package net.glowstone.io.structure; import net.glowstone.generator.structures.GlowStructurePiece; import net.glowstone.util.nbt.CompoundTag; import java.util.HashMap; import java.util.Map; /** * The class responsible for mapping structure piece types to their storage methods * and reading and writing structure piece data using those storage methods. */ public final class StructurePieceStorage { private StructurePieceStorage() { } /** * A table which maps structure pieces ids to compound readers. This is generally used * to map stored structure pieces to actual structure pieces. */ private static final Map<String, StructurePieceStore<?>> idTable = new HashMap<>(); /** * A table which maps structure pieces to stores. This is generally used to map * structure pieces being stored. */ private static final Map<Class<? extends GlowStructurePiece>, StructurePieceStore<?>> classTable = new HashMap<>(); /** * Populates the maps with stores. */ static { bind(new DesertTempleStore()); bind(new JungleTempleStore()); bind(new WitchHutStore()); } /** * Binds a store by adding entries for it to the tables. * @param store The store object. * @param <T> The type of structure piece. */ private static <T extends GlowStructurePiece> void bind(StructurePieceStore<T> store) { idTable.put(store.getId(), store); classTable.put(store.getType(), store); } /** * Load a structure piece from the given data tag. * @param compound The tag to load from. * @return The newly constructed structure piece. * @throws IllegalArgumentException if there is an error in the data. */ public static GlowStructurePiece loadStructurePiece(CompoundTag compound) { // look up the store by the tag's id if (!compound.isString("id")) { throw new IllegalArgumentException("StructurePiece has no type"); } StructurePieceStore<?> store = idTable.get(compound.getString("id")); if (store == null) { throw new IllegalArgumentException("Unknown structure piece type to load: \"" + compound.getString("id") + "\""); } return createStructurePiece(store, compound); } /** * Save a structure piece data to the given compound tag. * @param structurePiece The structure piece to save. * @param compound The target tag. */ public static void saveStructurePiece(GlowStructurePiece structurePiece, CompoundTag compound) { // look up the store for the structure piece StructurePieceStore<?> store = classTable.get(structurePiece.getClass()); if (store == null) { throw new IllegalArgumentException("Unknown structure piece type to save: \"" + structurePiece.getClass() + "\""); } compound.putString("id", store.getId()); getBaseStore(store).save(structurePiece, compound); } /** * Helper method to call StructurePieceStore methods for type safety. */ private static <T extends GlowStructurePiece> T createStructurePiece(StructurePieceStore<T> store, CompoundTag compound) { T structurePiece = store.createStructurePiece(); store.load(structurePiece, compound); return structurePiece; } /** * Unsafe-cast an unknown StructurePieceStore to the base type. */ @SuppressWarnings("unchecked") private static StructurePieceStore<GlowStructurePiece> getBaseStore(StructurePieceStore<?> store) { return ((StructurePieceStore<GlowStructurePiece>) store); } }