diff --git a/src/main/java/net/minecraftforge/fml/common/registry/FMLControlledNamespacedRegistry.java b/src/main/java/net/minecraftforge/fml/common/registry/FMLControlledNamespacedRegistry.java index 9f1fd475e7..e35847845b 100644 --- a/src/main/java/net/minecraftforge/fml/common/registry/FMLControlledNamespacedRegistry.java +++ b/src/main/java/net/minecraftforge/fml/common/registry/FMLControlledNamespacedRegistry.java @@ -9,28 +9,25 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.Callable; import com.google.common.base.Throwables; -import com.google.common.collect.*; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.Iterators; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import org.apache.commons.lang3.Validate; import org.apache.logging.log4j.Level; -import net.minecraft.block.Block; -import net.minecraft.item.Item; -import net.minecraft.item.ItemBanner; -import net.minecraft.item.ItemBlock; import net.minecraft.util.ObjectIntIdentityMap; -import net.minecraft.util.RegistryNamespaced; import net.minecraft.util.RegistryNamespacedDefaultedByKey; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.common.FMLLog; import net.minecraftforge.fml.common.functions.GenericIterableFactory; import net.minecraftforge.fml.common.registry.RegistryDelegate.Delegate; -import com.google.common.base.Function; - -public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaultedByKey { +public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaultedByKey +{ public static final boolean DEBUG = Boolean.parseBoolean(System.getProperty("fml.debugRegistryEntries", "false")); private final Class superType; private final boolean isDelegated; @@ -43,7 +40,7 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul * Aliases are resource location to resource location pointers, allowing for alternative names to be supplied * pointing at the same thing. They are used to allow programmatic migration of an ID. */ - private final Map aliases = Maps.newHashMap(); + private final Map aliases = Maps.newHashMap(); /** * Persistent substitutions are the mechanism to allow mods to override specific behaviours with new behaviours. */ @@ -58,7 +55,20 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul private final Set blockedIds = Sets.newHashSet(); private final BitSet availabilityMap; + + private final AddCallback addCallback; + + public interface AddCallback + { + public void onAdd(T obj, int id); + } + FMLControlledNamespacedRegistry(ResourceLocation defaultKey, int maxIdValue, int minIdValue, Class type, boolean isDelegated) + { + this(defaultKey, maxIdValue, minIdValue, type, isDelegated, null); + } + + FMLControlledNamespacedRegistry(ResourceLocation defaultKey, int maxIdValue, int minIdValue, Class type, boolean isDelegated, AddCallback callback) { super(defaultKey); this.superType = type; @@ -67,16 +77,22 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul this.minId = minIdValue; this.availabilityMap = new BitSet(maxIdValue + 1); this.isDelegated = isDelegated; - if (this.isDelegated) { - try { + if (this.isDelegated) + { + try + { this.delegateAccessor = type.getField("delegate"); - } catch (NoSuchFieldException e) { + } catch (NoSuchFieldException e) + { FMLLog.log(Level.ERROR, e, "Delegate class identified with missing delegate field"); throw Throwables.propagate(e); } - } else { + } + else + { this.delegateAccessor = null; } + this.addCallback = callback; } void validateContent(ResourceLocation registryName) @@ -88,21 +104,45 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul boolean isSubstituted = activeSubstitutions.containsKey(name); // name lookup failed -> obj is not in the obj<->name map - if (name == null) throw new IllegalStateException(String.format("Registry entry for %s %s, id %d, doesn't yield a name.", registryName, obj, id)); + if (name == null) + { + throw new IllegalStateException(String.format("Registry entry for %s %s, id %d, doesn't yield a name.", registryName, obj, id)); + } // id lookup failed -> obj is not in the obj<->id map - if (!isSubstituted && id < 0) throw new IllegalStateException(String.format("Registry entry for %s %s, name %s, doesn't yield an id.", registryName, obj, name)); + if (!isSubstituted && id < 0) + { + throw new IllegalStateException(String.format("Registry entry for %s %s, name %s, doesn't yield an id.", registryName, obj, name)); + } // id is too high - if (id > maxId) throw new IllegalStateException(String.format("Registry entry for %s %s, name %s uses the too large id %d.", registryName, obj, name, id)); + if (id > maxId) + { + throw new IllegalStateException(String.format("Registry entry for %s %s, name %s uses the too large id %d.", registryName, obj, name, id)); + } // the rest of the tests don't really work for substituted items or blocks - if (isSubstituted) continue; + if (isSubstituted) + { + continue; + } // id -> obj lookup is inconsistent - if (getRaw(id) != obj) throw new IllegalStateException(String.format("Registry entry for id %d, name %s, doesn't yield the expected %s %s.", id, name, registryName, obj)); + if (getRaw(id) != obj) + { + throw new IllegalStateException(String.format("Registry entry for id %d, name %s, doesn't yield the expected %s %s.", id, name, registryName, obj)); + } // name -> obj lookup is inconsistent - if (getRaw(name) != obj ) throw new IllegalStateException(String.format("Registry entry for name %s, id %d, doesn't yield the expected %s %s.", name, id, registryName, obj)); + if (getRaw(name) != obj) + { + throw new IllegalStateException(String.format("Registry entry for name %s, id %d, doesn't yield the expected %s %s.", name, id, registryName, obj)); + } // name -> id lookup is inconsistent - if (getId(name) != id) throw new IllegalStateException(String.format("Registry entry for name %s doesn't yield the expected id %d.", name, id)); + if (getId(name) != id) + { + throw new IllegalStateException(String.format("Registry entry for name %s doesn't yield the expected id %d.", name, id)); + } // entry is blocked, thus should be empty - if (blockedIds.contains(id)) throw new IllegalStateException(String.format("Registry entry for %s %s, id %d, name %s, marked as dangling.", registryName, obj, id, name)); + if (blockedIds.contains(id)) + { + throw new IllegalStateException(String.format("Registry entry for %s %s, id %d, name %s, marked as dangling.", registryName, obj, id, name)); + } } } @@ -110,7 +150,10 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul @SuppressWarnings("unchecked") void set(FMLControlledNamespacedRegistry otherRegistry) { - if (this.superType != otherRegistry.superType) throw new IllegalArgumentException("incompatible registry"); + if (this.superType != otherRegistry.superType) + { + throw new IllegalArgumentException("incompatible registry"); + } this.optionalDefaultKey = otherRegistry.optionalDefaultKey; this.maxId = otherRegistry.maxId; @@ -155,8 +198,14 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul public void putObject(ResourceLocation name, I thing) { - if (name == null) throw new NullPointerException("Can't use a null-name for the registry."); - if (thing == null) throw new NullPointerException("Can't add null-object to the registry."); + if (name == null) + { + throw new NullPointerException("Can't use a null-name for the registry."); + } + if (thing == null) + { + throw new NullPointerException("Can't add null-object to the registry."); + } ResourceLocation existingName = getNameForObject(thing); @@ -177,7 +226,7 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul /** * Fetch the object identified by the specified name or the default object. - * + *

* For blocks the default object is the air block, for items it's null. * * @param name Unique name identifying the object. @@ -192,7 +241,7 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul /** * Fetch the object identified by the specified id or the default object. - * + *

* For blocks the default object is the air block, for items it's null. * * @param id ID identifying the object. @@ -207,9 +256,9 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul /** * Get the id for the specified object. - * + *

* Don't hold onto the id across the world, it's being dynamically re-mapped as needed. - * + *

* Usually the name should be used instead of the id, if using the Block/Item object itself is * not suitable for the task. * @@ -246,7 +295,10 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul { name = aliases.get(name); - if (name != null) return getRaw(name); + if (name != null) + { + return getRaw(name); + } } return ret; @@ -254,7 +306,7 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul /** * Determine if the registry has an entry for the specified name. - * + *

* Aliased names will be resolved as well. * * @param name Object name to check. @@ -269,7 +321,10 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul { name = aliases.get(name); - if (name != null) return containsKey(name); + if (name != null) + { + return containsKey(name); + } } return ret; @@ -277,9 +332,9 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul /** * Get the id for the specified object. - * + *

* Don't hold onto the id across the world, it's being dynamically re-mapped as needed. - * + *

* Usually the name should be used instead of the id, if using the Block/Item object itself is * not suitable for the task. * @@ -289,7 +344,10 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul public int getId(ResourceLocation itemName) { I obj = getRaw(itemName); - if (obj == null) return -1; + if (obj == null) + { + return -1; + } return getId(obj); } @@ -312,6 +370,7 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul idMapping.put(getNameForObject(thing), getId(thing)); } } + public void serializeAliases(Map map) { map.putAll(this.aliases); @@ -325,15 +384,21 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul /** * Add the specified object to the registry. * - * @param id ID to use if available, auto-assigned otherwise. - * @param name Name to use, prefixed by the mod id. + * @param id ID to use if available, auto-assigned otherwise. + * @param name Name to use, prefixed by the mod id. * @param thing Object to add. * @return ID eventually allocated. */ int add(int id, ResourceLocation name, I thing) { - if (name == null) throw new NullPointerException(String.format("Can't use a null-name for the registry, object %s.", thing)); - if (thing == null) throw new NullPointerException(String.format("Can't add null-object to the registry, name %s.", name)); + if (name == null) + { + throw new NullPointerException(String.format("Can't use a null-name for the registry, object %s.", thing)); + } + if (thing == null) + { + throw new NullPointerException(String.format("Can't add null-object to the registry, name %s.", name)); + } if (optionalDefaultKey != null && optionalDefaultKey.equals(name) && this.optionalDefaultObject == null) { this.optionalDefaultObject = thing; @@ -376,7 +441,10 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul { I oldThing = thing; thing = activeSubstitutions.get(name); - if (DEBUG) FMLLog.getLogger().log(Level.DEBUG, "Active substitution: {} {}@{} -> {}@{}",name, oldThing.getClass().getName(), System.identityHashCode(oldThing), thing.getClass().getName(), System.identityHashCode(thing)); + if (DEBUG) + { + FMLLog.getLogger().log(Level.DEBUG, "Active substitution: {} {}@{} -> {}@{}", name, oldThing.getClass().getName(), System.identityHashCode(oldThing), thing.getClass().getName(), System.identityHashCode(thing)); + } } @@ -386,7 +454,9 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul getExistingDelegate(thing).setResourceName(name); } if (DEBUG) + { FMLLog.finer("Registry add: %s %d %s (req. id %d)", name, idToUse, thing, id); + } return idToUse; } @@ -394,12 +464,14 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul { aliases.put(from, to); if (DEBUG) + { FMLLog.finer("Registry alias: %s -> %s", from, to); + } } - Map getEntriesNotIn(FMLControlledNamespacedRegistry registry) + Map getEntriesNotIn(FMLControlledNamespacedRegistry registry) { - Map ret = new HashMap(); + Map ret = new HashMap(); for (I thing : this.typeSafeIterable()) { @@ -418,7 +490,9 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul void dump(ResourceLocation registryName) { if (!DEBUG) + { return; + } List ids = new ArrayList(); @@ -442,13 +516,26 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul */ private void addObjectRaw(int id, ResourceLocation name, I thing) { - if (name == null) throw new NullPointerException("The name to be added to the registry is null. This can only happen with a corrupted registry state. Reflection/ASM hackery? Registry bug?"); - if (thing == null) throw new NullPointerException("The object to be added to the registry is null. This can only happen with a corrupted registry state. Reflection/ASM hackery? Registry bug?"); - if (!superType.isInstance(thing)) throw new IllegalArgumentException("The object to be added to the registry is not of the right type. Reflection/ASM hackery? Registry bug?"); + if (name == null) + { + throw new NullPointerException("The name to be added to the registry is null. This can only happen with a corrupted registry state. Reflection/ASM hackery? Registry bug?"); + } + if (thing == null) + { + throw new NullPointerException("The object to be added to the registry is null. This can only happen with a corrupted registry state. Reflection/ASM hackery? Registry bug?"); + } + if (!superType.isInstance(thing)) + { + throw new IllegalArgumentException("The object to be added to the registry is not of the right type. Reflection/ASM hackery? Registry bug?"); + } underlyingIntegerMap.put(thing, id); // obj <-> id super.putObject(name, thing); // name <-> obj availabilityMap.set(id); + if (addCallback != null) + { + addCallback.onAdd(thing, id); + } } public I getDefaultValue() @@ -456,19 +543,24 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul return optionalDefaultObject; } - public RegistryDelegate getDelegate(I thing, Class clazz) { + public RegistryDelegate getDelegate(I thing, Class clazz) + { return new RegistryDelegate.Delegate(thing, clazz); } @SuppressWarnings("unchecked") - public Delegate getExistingDelegate(I thing) { - try { - return (Delegate) delegateAccessor.get(thing); - } catch (IllegalAccessException e) { + public Delegate getExistingDelegate(I thing) + { + try + { + return (Delegate)delegateAccessor.get(thing); + } catch (IllegalAccessException e) + { FMLLog.log(Level.ERROR, e, "Illegal attempt to access delegate"); throw Throwables.propagate(e); } } + void activateSubstitution(ResourceLocation nameToReplace) { if (getPersistentSubstitutions().containsKey(nameToReplace)) @@ -480,7 +572,8 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul } } - void addSubstitutionAlias(String modId, ResourceLocation nameToReplace, I replacement) throws ExistingSubstitutionException { + void addSubstitutionAlias(String modId, ResourceLocation nameToReplace, I replacement) throws ExistingSubstitutionException + { if (getPersistentSubstitutions().containsKey(nameToReplace) || getPersistentSubstitutions().containsValue(replacement)) { FMLLog.severe("The substitution of %s has already occurred. You cannot duplicate substitutions", nameToReplace); @@ -515,8 +608,11 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul public void validateKey() { if (this.optionalDefaultKey != null) + { Validate.notNull(this.optionalDefaultObject); + } } + /* * This iterator is used by some regular MC methods to visit all blocks, we need to include substitutions * Compare #typeSafeIterable() @@ -525,19 +621,23 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul @Override public Iterator iterator() { - return Iterators.concat(super.iterator(),getPersistentSubstitutions().values().iterator()); + return Iterators.concat(super.iterator(), getPersistentSubstitutions().values().iterator()); } - - FMLControlledNamespacedRegistry makeShallowCopy() { + FMLControlledNamespacedRegistry makeShallowCopy() + { return new FMLControlledNamespacedRegistry(optionalDefaultKey, maxId, minId, superType, isDelegated); } void resetSubstitutionDelegates() { - if (!isDelegated) return; - for (I obj: typeSafeIterable()) { + if (!isDelegated) + { + return; + } + for (I obj : typeSafeIterable()) + { Delegate delegate = getExistingDelegate(obj); delegate.changeReference(obj); } @@ -546,49 +646,62 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul @SuppressWarnings("unchecked") public FMLControlledNamespacedRegistry asType(Class type) { - return (FMLControlledNamespacedRegistry) this; + return (FMLControlledNamespacedRegistry)this; } - public void serializeBlockList(Set blocked) { + public void serializeBlockList(Set blocked) + { blocked.addAll(this.blockedIds); } - public Set getActiveSubstitutions() { + public Set getActiveSubstitutions() + { return activeSubstitutions.keySet(); } - public void loadAliases(Map aliases) { - for (Map.Entry alias : aliases.entrySet()) { + public void loadAliases(Map aliases) + { + for (Map.Entry alias : aliases.entrySet()) + { addAlias(alias.getKey(), alias.getValue()); } } - public void loadSubstitutions(Set substitutions) { - for (ResourceLocation rl : substitutions) { + public void loadSubstitutions(Set substitutions) + { + for (ResourceLocation rl : substitutions) + { activateSubstitution(rl); } } - public void loadBlocked(Set blocked) { - for (Integer id : blocked) { + public void loadBlocked(Set blocked) + { + for (Integer id : blocked) + { blockedIds.add(id); availabilityMap.set(id); } } - public void loadIds(Map ids, Map missingIds, Map remappedIds, FMLControlledNamespacedRegistry currentRegistry, ResourceLocation registryName) { - for (Map.Entry entry : ids.entrySet()) { + public void loadIds(Map ids, Map missingIds, Map remappedIds, FMLControlledNamespacedRegistry currentRegistry, ResourceLocation registryName) + { + for (Map.Entry entry : ids.entrySet()) + { ResourceLocation itemName = entry.getKey(); int newId = entry.getValue(); int currId = currentRegistry.getId(itemName); - if (currId == -1) { + if (currId == -1) + { FMLLog.info("Found a missing id from the world %s", itemName); missingIds.put(entry.getKey(), newId); continue; // no block/item -> nothing to add - } else if (currId != newId) { + } + else if (currId != newId) + { FMLLog.fine("Fixed %s id mismatch %s: %d (init) -> %d (map).", registryName, itemName, currId, newId); - remappedIds.put(itemName, new Integer[]{currId, newId}); + remappedIds.put(itemName, new Integer[] {currId, newId}); } I obj = currentRegistry.getRaw(itemName); @@ -596,7 +709,8 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul } } - public void blockId(int id) { + public void blockId(int id) + { blockedIds.add(id); } } diff --git a/src/main/java/net/minecraftforge/fml/common/registry/GameData.java b/src/main/java/net/minecraftforge/fml/common/registry/GameData.java index c96a942e0a..71e8d7e090 100644 --- a/src/main/java/net/minecraftforge/fml/common/registry/GameData.java +++ b/src/main/java/net/minecraftforge/fml/common/registry/GameData.java @@ -14,6 +14,8 @@ package net.minecraftforge.fml.common.registry; import java.util.Map; +import com.google.common.collect.Maps; + import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.item.Item; @@ -22,12 +24,9 @@ import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.common.FMLLog; import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.ModContainer; -import net.minecraftforge.fml.common.registry.GameRegistry.Type; -import net.minecraftforge.fml.common.registry.GameRegistry.UniqueIdentifier; -import com.google.common.collect.Maps; - -public class GameData { +public class GameData +{ static final int MIN_BLOCK_ID = 0; static final int MAX_BLOCK_ID = 4095; static final int MIN_ITEM_ID = 4096; @@ -41,7 +40,8 @@ public class GameData { * * @return Block Registry. */ - public static FMLControlledNamespacedRegistry getBlockRegistry() { + public static FMLControlledNamespacedRegistry getBlockRegistry() + { return getMain().iBlockRegistry; } @@ -50,7 +50,8 @@ public class GameData { * * @return Item Registry. */ - public static FMLControlledNamespacedRegistry getItemRegistry() { + public static FMLControlledNamespacedRegistry getItemRegistry() + { return getMain().iItemRegistry; } @@ -59,45 +60,59 @@ public class GameData { ***************************************************/ - static Item findItem(String modId, String name) { + static Item findItem(String modId, String name) + { return getMain().iItemRegistry.getObject(new ResourceLocation(modId, name)); } - static Block findBlock(String modId, String name) { + static Block findBlock(String modId, String name) + { return getMain().iBlockRegistry.getObject(new ResourceLocation(modId, name)); } - static UniqueIdentifier getUniqueName(Block block) { - if (block == null) return null; + static GameRegistry.UniqueIdentifier getUniqueName(Block block) + { + if (block == null) + { + return null; + } Object name = getMain().iBlockRegistry.getNameForObject(block); - return new UniqueIdentifier(name); + return new GameRegistry.UniqueIdentifier(name); } - static UniqueIdentifier getUniqueName(Item item) { - if (item == null) return null; + static GameRegistry.UniqueIdentifier getUniqueName(Item item) + { + if (item == null) + { + return null; + } Object name = getMain().iItemRegistry.getNameForObject(item); - return new UniqueIdentifier(name); + return new GameRegistry.UniqueIdentifier(name); } - protected static GameData getMain() { + protected static GameData getMain() + { return mainData; } // internal registry objects - private final FMLControlledNamespacedRegistry iBlockRegistry = PersistentRegistryManager.createRegistry(PersistentRegistryManager.BLOCKS, Block.class, new ResourceLocation("minecraft:air"), MAX_BLOCK_ID, MIN_BLOCK_ID, true); + private final FMLControlledNamespacedRegistry iBlockRegistry = PersistentRegistryManager.createRegistry(PersistentRegistryManager.BLOCKS, Block.class, new ResourceLocation("minecraft:air"), MAX_BLOCK_ID, MIN_BLOCK_ID, true, BlockStateCapture.INSTANCE); private final FMLControlledNamespacedRegistry iItemRegistry = PersistentRegistryManager.createRegistry(PersistentRegistryManager.ITEMS, Item.class, null, MAX_ITEM_ID, MIN_ITEM_ID, true); int registerItem(Item item, String name) // from GameRegistry { int index = name.indexOf(':'); if (index != -1) + { FMLLog.bigWarning("Dangerous extra prefix %s for name %s, invalid registry invocation/invalid name?", name.substring(0, index), name); + } ResourceLocation rl = addPrefix(name); return registerItem(item, rl, -1); } - private int registerItem(Item item, ResourceLocation name, int idHint) { + private int registerItem(Item item, ResourceLocation name, int idHint) + { return iItemRegistry.add(idHint, name, item); } @@ -105,20 +120,17 @@ public class GameData { { int index = name.indexOf(':'); if (index != -1) + { FMLLog.bigWarning("Dangerous alternative prefix %s for name %s, invalid registry invocation/invalid name?", name.substring(0, index), name); + } ResourceLocation rl = addPrefix(name); return registerBlock(block, rl, -1); } - private int registerBlock(Block block, ResourceLocation name, int idHint) { - int blockId = iBlockRegistry.add(idHint, name, block); - - for (IBlockState state : block.getBlockState().getValidStates()) { - GameData.BLOCKSTATE_TO_ID.put(state, blockId << 4 | block.getMetaFromState(state)); - } - - return blockId; + private int registerBlock(Block block, ResourceLocation name, int idHint) + { + return iBlockRegistry.add(idHint, name, block); } /** @@ -133,33 +145,41 @@ public class GameData { * @param name name to prefix. * @return prefixed name. */ - private ResourceLocation addPrefix(String name) { + private ResourceLocation addPrefix(String name) + { int index = name.lastIndexOf(':'); String oldPrefix = index == -1 ? "" : name.substring(0, index); String prefix; ModContainer mc = Loader.instance().activeModContainer(); - if (mc != null) { + if (mc != null) + { prefix = mc.getModId(); - } else // no mod container, assume minecraft + } + else // no mod container, assume minecraft { prefix = "minecraft"; } - if (!oldPrefix.equals(prefix) && oldPrefix.length() > 0) { + if (!oldPrefix.equals(prefix) && oldPrefix.length() > 0) + { prefix = oldPrefix; } - return new ResourceLocation(prefix,name); + return new ResourceLocation(prefix, name); } - void registerSubstitutionAlias(String name, Type type, Object toReplace) throws ExistingSubstitutionException { + void registerSubstitutionAlias(String name, GameRegistry.Type type, Object toReplace) throws ExistingSubstitutionException + { ResourceLocation nameToSubstitute = new ResourceLocation(Loader.instance().activeModContainer().getModId(), name); - if (type == Type.BLOCK) { - iBlockRegistry.addSubstitutionAlias(Loader.instance().activeModContainer().getModId(), nameToSubstitute, (Block) toReplace); + if (type == GameRegistry.Type.BLOCK) + { + iBlockRegistry.addSubstitutionAlias(Loader.instance().activeModContainer().getModId(), nameToSubstitute, (Block)toReplace); iBlockRegistry.activateSubstitution(nameToSubstitute); - } else if (type == Type.ITEM) { - iItemRegistry.addSubstitutionAlias(Loader.instance().activeModContainer().getModId(), nameToSubstitute, (Item) toReplace); + } + else if (type == GameRegistry.Type.ITEM) + { + iItemRegistry.addSubstitutionAlias(Loader.instance().activeModContainer().getModId(), nameToSubstitute, (Item)toReplace); iItemRegistry.activateSubstitution(nameToSubstitute); } } @@ -167,26 +187,45 @@ public class GameData { private static Map BLOCK_TO_ITEM = Maps.newHashMap(); //Internal: DO NOT USE, will change without warning. - public static Map getBlockItemMap() { + public static Map getBlockItemMap() + { return BLOCK_TO_ITEM; } private static ClearableObjectIntIdentityMap BLOCKSTATE_TO_ID = new ClearableObjectIntIdentityMap(); //Internal: DO NOT USE, will change without warning. - public static ObjectIntIdentityMap getBlockStateIDMap() { + public static ClearableObjectIntIdentityMap getBlockStateIDMap() + { return BLOCKSTATE_TO_ID; } //Lets us clear the map so we can rebuild it. - private static class ClearableObjectIntIdentityMap extends ObjectIntIdentityMap { - private void clear() { + static class ClearableObjectIntIdentityMap extends ObjectIntIdentityMap + { + void clear() + { this.identityMap.clear(); this.objectList.clear(); } } - public RegistryDelegate makeDelegate(T obj, Class rootClass) { + public RegistryDelegate makeDelegate(T obj, Class rootClass) + { return PersistentRegistryManager.makeDelegate(obj, rootClass); } + + private static class BlockStateCapture implements FMLControlledNamespacedRegistry.AddCallback + { + static final BlockStateCapture INSTANCE = new BlockStateCapture(); + + @Override + public void onAdd(Block block, int blockId) + { + for (IBlockState state : block.getBlockState().getValidStates()) + { + GameData.BLOCKSTATE_TO_ID.put(state, blockId << 4 | block.getMetaFromState(state)); + } + } + } } \ No newline at end of file diff --git a/src/main/java/net/minecraftforge/fml/common/registry/GameRegistry.java b/src/main/java/net/minecraftforge/fml/common/registry/GameRegistry.java index 99b5bca706..837f2ab7e6 100644 --- a/src/main/java/net/minecraftforge/fml/common/registry/GameRegistry.java +++ b/src/main/java/net/minecraftforge/fml/common/registry/GameRegistry.java @@ -25,6 +25,17 @@ import java.util.Map; import java.util.Random; import java.util.Set; +import com.google.common.base.Objects; +import com.google.common.base.Strings; +import com.google.common.base.Throwables; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.ObjectArrays; +import com.google.common.collect.Sets; +import com.google.common.primitives.Ints; +import org.apache.logging.log4j.Level; + import net.minecraft.block.Block; import net.minecraft.item.Item; import net.minecraft.item.ItemBlock; @@ -48,18 +59,6 @@ import net.minecraftforge.fml.common.LoaderException; import net.minecraftforge.fml.common.LoaderState; import net.minecraftforge.fml.common.ObfuscationReflectionHelper; -import org.apache.logging.log4j.Level; - -import com.google.common.base.Objects; -import com.google.common.base.Strings; -import com.google.common.base.Throwables; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.ObjectArrays; -import com.google.common.collect.Sets; -import com.google.common.primitives.Ints; - public class GameRegistry { private static Set worldGenerators = Sets.newHashSet(); @@ -70,9 +69,9 @@ public class GameRegistry /** * Register a world generator - something that inserts new block types into the world * - * @param generator the generator + * @param generator the generator * @param modGenerationWeight a weight to assign to this generator. Heavy weights tend to sink to the bottom of - * list of world generators (i.e. they run later) + * list of world generators (i.e. they run later) */ public static void registerWorldGenerator(IWorldGenerator generator, int modGenerationWeight) { @@ -88,11 +87,11 @@ public class GameRegistry * Callback hook for world gen - if your mod wishes to add extra mod related generation to the world * call this * - * @param chunkX Chunk X coordinate - * @param chunkZ Chunk Z coordinate - * @param world World we're generating into + * @param chunkX Chunk X coordinate + * @param chunkZ Chunk Z coordinate + * @param world World we're generating into * @param chunkGenerator The chunk generator - * @param chunkProvider The chunk provider + * @param chunkProvider The chunk provider */ public static void generateWorld(int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) { @@ -116,7 +115,8 @@ public class GameRegistry private static void computeSortedGeneratorList() { ArrayList list = Lists.newArrayList(worldGenerators); - Collections.sort(list, new Comparator() { + Collections.sort(list, new Comparator() + { @Override public int compare(IWorldGenerator o1, IWorldGenerator o2) { @@ -139,8 +139,9 @@ public class GameRegistry /** * Register the specified Item with a mod specific name : overrides the standard type based name - * @param item The item to register - * @param name The mod-unique name to register it as - null will remove a custom name + * + * @param item The item to register + * @param name The mod-unique name to register it as - null will remove a custom name * @param modId deprecated, unused */ public static Item registerItem(Item item, String name, String modId) @@ -156,9 +157,9 @@ public class GameRegistry * referenced. * * @param nameToSubstitute The name to link to (this is the NEW block or item) - * @param type The type (Block or Item) - * @param object a NEW instance that is type compatible with the existing instance - * @throws ExistingSubstitutionException if someone else has already registered an alias either from or to one of the names + * @param type The type (Block or Item) + * @param object a NEW instance that is type compatible with the existing instance + * @throws ExistingSubstitutionException if someone else has already registered an alias either from or to one of the names * @throws IncompatibleSubstitutionException if the substitution is incompatible */ public static void addSubstitutionAlias(String nameToSubstitute, GameRegistry.Type type, Object object) throws ExistingSubstitutionException @@ -168,8 +169,9 @@ public class GameRegistry /** * Register a block with the specified mod specific name + * * @param block The block to register - * @param name The mod-unique name to register it as, will get prefixed by your modid. + * @param name The mod-unique name to register it as, will get prefixed by your modid. */ public static Block registerBlock(Block block, String name) { @@ -178,20 +180,22 @@ public class GameRegistry /** * Register a block with the world, with the specified item class and block name - * @param block The block to register + * + * @param block The block to register * @param itemclass The item type to register with it : null registers a block without associated item. - * @param name The mod-unique name to register it as, will get prefixed by your modid. + * @param name The mod-unique name to register it as, will get prefixed by your modid. */ public static Block registerBlock(Block block, Class itemclass, String name) { - return registerBlock(block, itemclass, name, new Object[]{}); + return registerBlock(block, itemclass, name, new Object[] {}); } /** * Register a block with the world, with the specified item class, block name and owning modId - * @param block The block to register - * @param itemclass The item type to register with it : null registers a block without associated item. - * @param name The mod-unique name to register it as, will get prefixed by your modid. + * + * @param block The block to register + * @param itemclass The item type to register with it : null registers a block without associated item. + * @param name The mod-unique name to register it as, will get prefixed by your modid. * @param itemCtorArgs Arguments to pass (after the required {@code Block} parameter) to the ItemBlock constructor (optional). */ @SuppressWarnings("unchecked") @@ -211,7 +215,7 @@ public class GameRegistry ctorArgClasses[0] = Block.class; for (int idx = 1; idx < ctorArgClasses.length; idx++) { - ctorArgClasses[idx] = itemCtorArgs[idx-1].getClass(); + ctorArgClasses[idx] = itemCtorArgs[idx - 1].getClass(); } Constructor itemCtor = itemclass.getConstructor(ctorArgClasses); i = itemCtor.newInstance(ObjectArrays.concat(block, itemCtorArgs)); @@ -224,8 +228,7 @@ public class GameRegistry GameData.getBlockItemMap().put(block, i); } return block; - } - catch (Exception e) + } catch (Exception e) { FMLLog.log(Level.ERROR, e, "Caught an exception during block registration"); throw new LoaderException(e); @@ -277,14 +280,14 @@ public class GameRegistry * This method allows for you to "rename" the 'id' of the tile entity. * * @param tileEntityClass The tileEntity class to register - * @param id The primary ID, this will be the ID that the tileentity saves as - * @param alternatives A list of alternative IDs that will also map to this class. These will never save, but they will load + * @param id The primary ID, this will be the ID that the tileentity saves as + * @param alternatives A list of alternative IDs that will also map to this class. These will never save, but they will load */ public static void registerTileEntityWithAlternatives(Class tileEntityClass, String id, String... alternatives) { TileEntity.addMapping(tileEntityClass, id); - Map> teMappings = ObfuscationReflectionHelper.getPrivateValue(TileEntity.class, null, "field_" + "145855_i", "nameToClassMap"); - for (String s: alternatives) + Map> teMappings = ObfuscationReflectionHelper.getPrivateValue(TileEntity.class, null, "field_" + "145855_i", "nameToClassMap"); + for (String s : alternatives) { if (!teMappings.containsKey(s)) { @@ -297,6 +300,7 @@ public class GameRegistry { fuelHandlers.add(handler); } + public static int getFuelValue(ItemStack itemStack) { int fuelValue = 0; @@ -309,8 +313,9 @@ public class GameRegistry /** * Look up a mod block in the global "named item list" + * * @param modId The modid owning the block - * @param name The name of the block itself + * @param name The name of the block itself * @return The block or null if not found */ public static Block findBlock(String modId, String name) @@ -320,8 +325,9 @@ public class GameRegistry /** * Look up a mod item in the global "named item list" + * * @param modId The modid owning the item - * @param name The name of the item itself + * @param name The name of the item itself * @return The item or null if not found */ public static Item findItem(String modId, String name) @@ -337,6 +343,7 @@ public class GameRegistry { public final String modId; public final String name; + UniqueIdentifier(String modId, String name) { this.modId = modId; @@ -361,7 +368,7 @@ public class GameRegistry else if (obj instanceof ResourceLocation) { this.modId = ((ResourceLocation)obj).getResourceDomain(); - this.name = ((ResourceLocation)obj).getResourcePath(); + this.name = ((ResourceLocation)obj).getResourcePath(); } else { @@ -372,9 +379,15 @@ public class GameRegistry @Override public boolean equals(Object obj) { - if (obj == null) return false; - if (obj.getClass() != this.getClass()) return false; - final UniqueIdentifier other = (UniqueIdentifier) obj; + if (obj == null) + { + return false; + } + if (obj.getClass() != this.getClass()) + { + return false; + } + final UniqueIdentifier other = (UniqueIdentifier)obj; return Objects.equal(modId, other.modId) && Objects.equal(name, other.name); } @@ -391,13 +404,15 @@ public class GameRegistry } } - public enum Type { + public enum Type + { BLOCK, ITEM; } + /** * Look up the mod identifier data for a block. - * + *

* Note: uniqueness and persistence is only guaranteed by mods using the game registry * correctly. * @@ -409,9 +424,10 @@ public class GameRegistry { return GameData.getUniqueName(block); } + /** * Look up the mod identifier data for an item. - * + *

* Note: uniqueness and persistence is only guaranteed by mods using the game registry * correctly. * @@ -425,15 +441,14 @@ public class GameRegistry } - /** * ObjectHolder can be used to automatically populate public static final fields with entries * from the registry. These values can then be referred within mod code directly. - * */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.FIELD}) - public @interface ObjectHolder { + public @interface ObjectHolder + { /** * If used on a class, this represents a modid only. * If used on a field, it represents a name, which can be abbreviated or complete. @@ -449,7 +464,7 @@ public class GameRegistry * {@link ItemStack} instances, referring a specific item, potentially configured with NBT. * These values can then be used in things like recipes and other places where ItemStacks * might be required. - * + *

* If the item is not found, the field will be populated with null. */ @Retention(RetentionPolicy.RUNTIME) @@ -458,12 +473,14 @@ public class GameRegistry { /** * The registry name of the item being looked up. + * * @return The registry name */ public String value(); /** * The metadata or damage value for the itemstack, defaults to 0. + * * @return the metadata value */ public int meta() default 0; @@ -478,26 +495,31 @@ public class GameRegistry /** * Makes an {@link ItemStack} based on the itemName reference, with supplied meta, stackSize and nbt, if possible - * + *

* Will return null if the item doesn't exist (because it's not from a loaded mod for example) * Will throw a {@link RuntimeException} if the nbtString is invalid for use in an {@link ItemStack} * - * @param itemName a registry name reference - * @param meta the meta + * @param itemName a registry name reference + * @param meta the meta * @param stackSize the stack size * @param nbtString an nbt stack as a string, will be processed by {@link JsonToNBT} * @return a new itemstack */ public static ItemStack makeItemStack(String itemName, int meta, int stackSize, String nbtString) { - if (itemName == null) throw new IllegalArgumentException("The itemName cannot be null"); + if (itemName == null) + { + throw new IllegalArgumentException("The itemName cannot be null"); + } Item item = GameData.getItemRegistry().getObject(new ResourceLocation(itemName)); - if (item == null) { + if (item == null) + { FMLLog.getLogger().log(Level.TRACE, "Unable to find item with name {}", itemName); return null; } - ItemStack is = new ItemStack(item,1,meta); - if (!Strings.isNullOrEmpty(nbtString)) { + ItemStack is = new ItemStack(item, 1, meta); + if (!Strings.isNullOrEmpty(nbtString)) + { NBTBase nbttag = null; try { @@ -507,11 +529,14 @@ public class GameRegistry FMLLog.getLogger().log(Level.WARN, "Encountered an exception parsing ItemStack NBT string {}", nbtString, e); throw Throwables.propagate(e); } - if (!(nbttag instanceof NBTTagCompound)) { + if (!(nbttag instanceof NBTTagCompound)) + { FMLLog.getLogger().log(Level.WARN, "Unexpected NBT string - multiple values {}", nbtString); throw new RuntimeException("Invalid NBT JSON"); - } else { - is.setTagCompound((NBTTagCompound) nbttag); + } + else + { + is.setTagCompound((NBTTagCompound)nbttag); } } return is; diff --git a/src/main/java/net/minecraftforge/fml/common/registry/PersistentRegistryManager.java b/src/main/java/net/minecraftforge/fml/common/registry/PersistentRegistryManager.java index 7667a84e31..138cfd882f 100644 --- a/src/main/java/net/minecraftforge/fml/common/registry/PersistentRegistryManager.java +++ b/src/main/java/net/minecraftforge/fml/common/registry/PersistentRegistryManager.java @@ -1,61 +1,82 @@ package net.minecraftforge.fml.common.registry; import java.io.IOException; -import java.util.*; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; import com.google.common.base.Function; -import com.google.common.collect.*; -import net.minecraft.block.Block; -import net.minecraft.item.Item; -import net.minecraftforge.fml.common.*; -import net.minecraftforge.fml.common.event.FMLMissingMappingsEvent; -import org.apache.logging.log4j.Level; - +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import com.google.common.collect.Sets.SetView; +import net.minecraft.block.Block; +import net.minecraft.item.Item; import net.minecraft.util.ResourceLocation; - -import javax.annotation.Nullable; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.FMLLog; +import net.minecraftforge.fml.common.Loader; +import net.minecraftforge.fml.common.StartupQuery; +import net.minecraftforge.fml.common.ZipperUtil; +import net.minecraftforge.fml.common.event.FMLMissingMappingsEvent; /** * Persistent registry manager. Manages the registries loading from disk, and from network. Handles staging * registry data before loading uniformly into the active registry, and keeps a frozen registry instance * for reversion after connection. + * * @author cpw */ public class PersistentRegistryManager { - private enum PersistentRegistry { + private enum PersistentRegistry + { ACTIVE, FROZEN, STAGING; - private final BiMap> registries = HashBiMap.create(); - private final BiMap,ResourceLocation> registrySuperTypes = HashBiMap.create(); + private final BiMap> registries = HashBiMap.create(); + private final BiMap, ResourceLocation> registrySuperTypes = HashBiMap.create(); @SuppressWarnings("unchecked") FMLControlledNamespacedRegistry getRegistry(ResourceLocation key, Class regType) { - return (FMLControlledNamespacedRegistry) registries.get(key); + return (FMLControlledNamespacedRegistry)registries.get(key); } FMLControlledNamespacedRegistry getOrShallowCopyRegistry(ResourceLocation key, Class regType, FMLControlledNamespacedRegistry other) { - if (!registries.containsKey(key)) { + if (!registries.containsKey(key)) + { registries.put(key, other.makeShallowCopy()); registrySuperTypes.put(regType, key); } return getRegistry(key, regType); } - private FMLControlledNamespacedRegistry createRegistry(ResourceLocation registryName, Class type, ResourceLocation defaultObjectKey, int minId, int maxId, boolean isDelegated) { + private FMLControlledNamespacedRegistry createRegistry(ResourceLocation registryName, Class registryType, ResourceLocation optionalDefaultKey, int minId, int maxId, boolean hasDelegates) + { + return this.createRegistry(registryName, registryType, optionalDefaultKey, minId, maxId, hasDelegates, null); + } + + private FMLControlledNamespacedRegistry createRegistry(ResourceLocation registryName, Class type, ResourceLocation defaultObjectKey, int minId, int maxId, boolean isDelegated, FMLControlledNamespacedRegistry.AddCallback addCallback) + { Set> parents = Sets.newHashSet(); findSuperTypes(type, parents); SetView> overlappedTypes = Sets.intersection(parents, registrySuperTypes.keySet()); - if (!overlappedTypes.isEmpty()) { + if (!overlappedTypes.isEmpty()) + { Class foundType = overlappedTypes.iterator().next(); FMLLog.severe("Found existing registry of type %1s named %2s, you cannot create a new registry (%3s) with type %4s, as %4s has a parent of that type", foundType, registrySuperTypes.get(foundType), registryName, type); throw new IllegalArgumentException("Duplicate registry parent type found - you can only have one registry for a particular super type"); } - FMLControlledNamespacedRegistry fmlControlledNamespacedRegistry = new FMLControlledNamespacedRegistry(defaultObjectKey, maxId, minId, type, isDelegated); + FMLControlledNamespacedRegistry fmlControlledNamespacedRegistry = new FMLControlledNamespacedRegistry(defaultObjectKey, maxId, minId, type, isDelegated, addCallback); registries.put(registryName, fmlControlledNamespacedRegistry); registrySuperTypes.put(type, registryName); return getRegistry(registryName, type); @@ -63,31 +84,37 @@ public class PersistentRegistryManager private void findSuperTypes(Class type, Set> types) { - if (type == null || type == Object.class) { + if (type == null || type == Object.class) + { return; } types.add(type); - for (Class interfac : type.getInterfaces()) { + for (Class interfac : type.getInterfaces()) + { findSuperTypes(interfac, types); } - findSuperTypes(type.getSuperclass(),types); + findSuperTypes(type.getSuperclass(), types); } - void clean() { + void clean() + { registries.clear(); registrySuperTypes.clear(); } - boolean isPopulated() { + boolean isPopulated() + { return !registries.isEmpty(); } - boolean containsRegistry(FMLControlledNamespacedRegistry registry) { + boolean containsRegistry(FMLControlledNamespacedRegistry registry) + { return registries.containsValue(registry); } - public FMLControlledNamespacedRegistry getRegistry(Class rootClass) { + public FMLControlledNamespacedRegistry getRegistry(Class rootClass) + { ResourceLocation rl = registrySuperTypes.get(rootClass); return getRegistry(rl, rootClass); } @@ -96,20 +123,29 @@ public class PersistentRegistryManager public static final ResourceLocation BLOCKS = new ResourceLocation("minecraft:blocks"); public static final ResourceLocation ITEMS = new ResourceLocation("minecraft:items"); - public static FMLControlledNamespacedRegistry createRegistry(ResourceLocation registryName, Class registryType, ResourceLocation optionalDefaultKey, int maxId, int minId, boolean hasDelegates) { - return PersistentRegistry.ACTIVE.createRegistry(registryName,registryType,optionalDefaultKey,minId, maxId, hasDelegates); + public static FMLControlledNamespacedRegistry createRegistry(ResourceLocation registryName, Class registryType, ResourceLocation optionalDefaultKey, int maxId, int minId, boolean hasDelegates, FMLControlledNamespacedRegistry.AddCallback addCallback) + { + return PersistentRegistry.ACTIVE.createRegistry(registryName, registryType, optionalDefaultKey, minId, maxId, hasDelegates, addCallback); } + public static FMLControlledNamespacedRegistry createRegistry(ResourceLocation registryName, Class registryType, ResourceLocation optionalDefaultKey, int maxId, int minId, boolean hasDelegates) + { + return PersistentRegistry.ACTIVE.createRegistry(registryName, registryType, optionalDefaultKey, minId, maxId, hasDelegates); + } - public static List injectSnapshot(GameDataSnapshot snapshot, boolean injectFrozenData, boolean isLocalWorld) { + public static List injectSnapshot(GameDataSnapshot snapshot, boolean injectFrozenData, boolean isLocalWorld) + { FMLLog.info("Injecting existing block and item data into this {} instance", FMLCommonHandler.instance().getEffectiveSide().isServer() ? "server" : "client"); - final Map> remaps = Maps.newHashMap(); - final LinkedHashMap> missing = Maps.newLinkedHashMap(); + final Map> remaps = Maps.newHashMap(); + final LinkedHashMap> missing = Maps.newLinkedHashMap(); forAllRegistries(PersistentRegistry.ACTIVE, ValidateRegistryFunction.OPERATION); forAllRegistries(PersistentRegistry.ACTIVE, DumpRegistryFunction.OPERATION); forAllRegistries(PersistentRegistry.ACTIVE, ResetDelegatesFunction.OPERATION); + // Empty the blockstate map before loading + GameData.getBlockStateIDMap().clear(); + // Load the snapshot into the "STAGING" registry for (Map.Entry snapshotEntry : snapshot.entries.entrySet()) { @@ -119,13 +155,17 @@ public class PersistentRegistryManager // If we have missed data, fire the missing mapping event List missedMappings = Loader.instance().fireMissingMappingEvent(missing.get(BLOCKS), missing.get(ITEMS), isLocalWorld, remaps.get(BLOCKS), remaps.get(ITEMS)); // If there's still missed mappings, we return, because that's an error - if (!missedMappings.isEmpty()) return missedMappings; + if (!missedMappings.isEmpty()) + { + return missedMappings; + } // If we're loading up the world from disk, we want to add in the new data that might have been provisioned by mods if (injectFrozenData) { // So we load it from the frozen persistent registry - for (Map.Entry> r : PersistentRegistry.ACTIVE.registries.entrySet()) { + for (Map.Entry> r : PersistentRegistry.ACTIVE.registries.entrySet()) + { loadFrozenDataToStagingRegistry(remaps, r.getKey(), PersistentRegistry.ACTIVE.registrySuperTypes.inverse().get(r.getKey())); } } @@ -134,7 +174,8 @@ public class PersistentRegistryManager forAllRegistries(PersistentRegistry.STAGING, ValidateRegistryFunction.OPERATION); // Load the STAGING registry into the ACTIVE registry - for (Map.Entry> r : PersistentRegistry.ACTIVE.registries.entrySet()) { + for (Map.Entry> r : PersistentRegistry.ACTIVE.registries.entrySet()) + { loadRegistry(r.getKey(), PersistentRegistry.STAGING, PersistentRegistry.ACTIVE, PersistentRegistry.ACTIVE.registrySuperTypes.inverse().get(r.getKey())); } @@ -151,29 +192,34 @@ public class PersistentRegistryManager return ImmutableList.of(); } - private static void forAllRegistries(PersistentRegistry registrySet, Function>, Void> operation) { + private static void forAllRegistries(PersistentRegistry registrySet, Function>, Void> operation) + { for (Map.Entry> r : registrySet.registries.entrySet()) { operation.apply(r); } } - private static void loadRegistry(ResourceLocation registryName, PersistentRegistry from, PersistentRegistry to, Class regType) { + private static void loadRegistry(ResourceLocation registryName, PersistentRegistry from, PersistentRegistry to, Class regType) + { FMLControlledNamespacedRegistry fromRegistry = from.getRegistry(registryName, regType); FMLControlledNamespacedRegistry toRegistry = to.getOrShallowCopyRegistry(registryName, regType, fromRegistry); toRegistry.set(fromRegistry); } - private static void loadFrozenDataToStagingRegistry(Map> remaps, ResourceLocation registryName, Class regType) { + private static void loadFrozenDataToStagingRegistry(Map> remaps, ResourceLocation registryName, Class regType) + { FMLControlledNamespacedRegistry newRegistry = PersistentRegistry.STAGING.getRegistry(registryName, regType); FMLControlledNamespacedRegistry frozenRegistry = PersistentRegistry.FROZEN.getRegistry(registryName, regType); newRegistry.loadIds(frozenRegistry.getEntriesNotIn(newRegistry), Maps.newLinkedHashMap(), remaps.get(registryName), frozenRegistry, registryName); } - private static void loadPersistentDataToStagingRegistry(boolean injectFrozenData, Map> remaps, LinkedHashMap> missing, Map.Entry snapEntry, Class regType) { + private static void loadPersistentDataToStagingRegistry(boolean injectFrozenData, Map> remaps, LinkedHashMap> missing, Map.Entry snapEntry, Class regType) + { ResourceLocation registryName = snapEntry.getKey(); FMLControlledNamespacedRegistry currentRegistry = PersistentRegistry.ACTIVE.getRegistry(registryName, regType); - if (currentRegistry == null) { + if (currentRegistry == null) + { FMLLog.severe("An unknown persistent registry type {} has been encountered. This Forge instance cannot understand it.", registryName); StartupQuery.abort(); } @@ -192,17 +238,23 @@ public class PersistentRegistryManager newRegistry.loadIds(snapshotEntry.ids, missing.get(registryName), remaps.get(registryName), currentRegistry, registryName); } - public static boolean isFrozen(FMLControlledNamespacedRegistry registry) { + public static boolean isFrozen(FMLControlledNamespacedRegistry registry) + { return PersistentRegistry.FROZEN.containsRegistry(registry); } - public static void revertToFrozen() { - if (!PersistentRegistry.FROZEN.isPopulated()) { + public static void revertToFrozen() + { + if (!PersistentRegistry.FROZEN.isPopulated()) + { FMLLog.warning("Can't revert to frozen GameData state without freezing first."); - } else { + } + else + { FMLLog.fine("Reverting to frozen data state."); } - for (Map.Entry> r : PersistentRegistry.ACTIVE.registries.entrySet()) { + for (Map.Entry> r : PersistentRegistry.ACTIVE.registries.entrySet()) + { loadRegistry(r.getKey(), PersistentRegistry.FROZEN, PersistentRegistry.ACTIVE, PersistentRegistry.ACTIVE.registrySuperTypes.inverse().get(r.getKey())); } // the id mapping has reverted, fire remap events for those that care about id changes @@ -211,15 +263,18 @@ public class PersistentRegistryManager ObjectHolderRegistry.INSTANCE.applyObjectHolders(); } - public static void freezeData() { + public static void freezeData() + { FMLLog.fine("Freezing block and item id maps"); - for (Map.Entry> r : PersistentRegistry.ACTIVE.registries.entrySet()) { + for (Map.Entry> r : PersistentRegistry.ACTIVE.registries.entrySet()) + { loadRegistry(r.getKey(), PersistentRegistry.ACTIVE, PersistentRegistry.FROZEN, PersistentRegistry.ACTIVE.registrySuperTypes.inverse().get(r.getKey())); } forAllRegistries(PersistentRegistry.FROZEN, ValidateRegistryFunction.OPERATION); } - public static List processIdRematches(Iterable missedMappings, boolean isLocalWorld, Map remapBlocks, Map remapItems) { + public static List processIdRematches(Iterable missedMappings, boolean isLocalWorld, Map remapBlocks, Map remapItems) + { List failed = Lists.newArrayList(); List ignored = Lists.newArrayList(); List warned = Lists.newArrayList(); @@ -227,64 +282,90 @@ public class PersistentRegistryManager final PersistentRegistry staging = PersistentRegistry.STAGING; final PersistentRegistry active = PersistentRegistry.ACTIVE; - for (FMLMissingMappingsEvent.MissingMapping remap : missedMappings) { + for (FMLMissingMappingsEvent.MissingMapping remap : missedMappings) + { FMLMissingMappingsEvent.Action action = remap.getAction(); - if (action == FMLMissingMappingsEvent.Action.REMAP) { + if (action == FMLMissingMappingsEvent.Action.REMAP) + { // block/item re-mapped, finish the registration with the new name/object, but the old id int currId = -1, newId = -1; ResourceLocation newName; - if (remap.type == GameRegistry.Type.BLOCK) { - currId = staging.getRegistry(BLOCKS, Block.class).getId((Block) remap.getTarget()); + if (remap.type == GameRegistry.Type.BLOCK) + { + currId = staging.getRegistry(BLOCKS, Block.class).getId((Block)remap.getTarget()); newName = active.getRegistry(BLOCKS, Block.class).getNameForObject((Block)remap.getTarget()); FMLLog.fine("The Block %s is being remapped to %s.", remap.name, newName); - newId = staging.getRegistry(BLOCKS,Block.class).add(remap.id, newName, (Block) remap.getTarget()); - staging.getRegistry(BLOCKS,Block.class).addAlias(remap.resourceLocation, newName); - } else if (remap.type == GameRegistry.Type.ITEM) { - currId = staging.getRegistry(ITEMS, Item.class).getId((Item) remap.getTarget()); + newId = staging.getRegistry(BLOCKS, Block.class).add(remap.id, newName, (Block)remap.getTarget()); + staging.getRegistry(BLOCKS, Block.class).addAlias(remap.resourceLocation, newName); + } + else if (remap.type == GameRegistry.Type.ITEM) + { + currId = staging.getRegistry(ITEMS, Item.class).getId((Item)remap.getTarget()); newName = active.getRegistry(ITEMS, Item.class).getNameForObject((Item)remap.getTarget()); FMLLog.fine("The Item %s is being remapped to %s.", remap.name, newName); - newId = staging.getRegistry(ITEMS,Item.class).add(remap.id, newName, (Item) remap.getTarget()); - staging.getRegistry(ITEMS,Item.class).addAlias(remap.resourceLocation, newName); - } else { + newId = staging.getRegistry(ITEMS, Item.class).add(remap.id, newName, (Item)remap.getTarget()); + staging.getRegistry(ITEMS, Item.class).addAlias(remap.resourceLocation, newName); + } + else + { // currently not remapping non-blocks and items continue; } - if (newId != remap.id) throw new IllegalStateException(); - - if (currId != newId) { - FMLLog.info("Fixed %s id mismatch %s: %d (init) -> %d (map).", remap.type == GameRegistry.Type.BLOCK ? "block" : "item", newName, currId, newId); - (remap.type == GameRegistry.Type.BLOCK ? remapBlocks : remapItems).put(newName, new Integer[]{currId, newId}); + if (newId != remap.id) + { + throw new IllegalStateException(); } - } else if (action == FMLMissingMappingsEvent.Action.BLOCKONLY) { + + if (currId != newId) + { + FMLLog.info("Fixed %s id mismatch %s: %d (init) -> %d (map).", remap.type == GameRegistry.Type.BLOCK ? "block" : "item", newName, currId, newId); + (remap.type == GameRegistry.Type.BLOCK ? remapBlocks : remapItems).put(newName, new Integer[] {currId, newId}); + } + } + else if (action == FMLMissingMappingsEvent.Action.BLOCKONLY) + { // Pulled out specifically so the block doesn't get reassigned a new ID just because it's // Item block has gone away FMLLog.fine("The ItemBlock %s is no longer present in the game. The residual block will remain", remap.name); - } else { + } + else + { // block item missing, warn as requested and block the id - if (action == FMLMissingMappingsEvent.Action.DEFAULT) { + if (action == FMLMissingMappingsEvent.Action.DEFAULT) + { defaulted.add(remap.name); - } else if (action == FMLMissingMappingsEvent.Action.IGNORE) { + } + else if (action == FMLMissingMappingsEvent.Action.IGNORE) + { ignored.add(remap.name); - } else if (action == FMLMissingMappingsEvent.Action.FAIL) { + } + else if (action == FMLMissingMappingsEvent.Action.FAIL) + { failed.add(remap.name); - } else if (action == FMLMissingMappingsEvent.Action.WARN) { + } + else if (action == FMLMissingMappingsEvent.Action.WARN) + { warned.add(remap.name); } // prevent the id from being reused later - if (remap.type == GameRegistry.Type.BLOCK) { + if (remap.type == GameRegistry.Type.BLOCK) + { staging.getRegistry(BLOCKS, Block.class).blockId(remap.id); - } else if (remap.type == GameRegistry.Type.ITEM) { + } + else if (remap.type == GameRegistry.Type.ITEM) + { staging.getRegistry(ITEMS, Item.class).blockId(remap.id); } } } - if (!defaulted.isEmpty()) { + if (!defaulted.isEmpty()) + { String text = "Forge Mod Loader detected missing blocks/items.\n\n" + "There are " + defaulted.size() + " missing blocks and items in this save.\n" + "If you continue the missing blocks/items will get removed.\n" + @@ -294,42 +375,57 @@ public class PersistentRegistryManager for (String s : defaulted) text += s + "\n"; boolean confirmed = StartupQuery.confirm(text); - if (!confirmed) StartupQuery.abort(); + if (!confirmed) + { + StartupQuery.abort(); + } - try { + try + { String skip = System.getProperty("fml.doNotBackup"); - if (skip == null || !"true".equals(skip)) { + if (skip == null || !"true".equals(skip)) + { ZipperUtil.backupWorld(); - } else { + } + else + { for (int x = 0; x < 10; x++) FMLLog.severe("!!!!!!!!!! UPDATING WORLD WITHOUT DOING BACKUP !!!!!!!!!!!!!!!!"); } - } catch (IOException e) { + } catch (IOException e) + { StartupQuery.notify("The world backup couldn't be created.\n\n" + e); StartupQuery.abort(); } warned.addAll(defaulted); } - if (!failed.isEmpty()) { + if (!failed.isEmpty()) + { FMLLog.severe("This world contains blocks and items that refuse to be remapped. The world will not be loaded"); return failed; } - if (!warned.isEmpty()) { + if (!warned.isEmpty()) + { FMLLog.warning("This world contains block and item mappings that may cause world breakage"); return failed; - } else if (!ignored.isEmpty()) { + } + else if (!ignored.isEmpty()) + { FMLLog.fine("There were %d missing mappings that have been ignored", ignored.size()); } return failed; } - public static GameDataSnapshot takeSnapshot() { + public static GameDataSnapshot takeSnapshot() + { final GameDataSnapshot snap = new GameDataSnapshot(); - forAllRegistries(PersistentRegistry.ACTIVE, new Function>, Void>() { + forAllRegistries(PersistentRegistry.ACTIVE, new Function>, Void>() + { @Override - public Void apply(Map.Entry> input) { + public Void apply(Map.Entry> input) + { snap.entries.put(input.getKey(), new GameDataSnapshot.Entry(input.getValue())); return null; } @@ -338,25 +434,30 @@ public class PersistentRegistryManager } - public static class GameDataSnapshot { - public static class Entry { + public static class GameDataSnapshot + { + public static class Entry + { public final Map ids; public final Set substitutions; public final Map aliases; public final Set blocked; - public Entry() { + public Entry() + { this(new HashMap(), new HashSet(), new HashMap(), new HashSet()); } - public Entry(Map ids, Set substitutions, Map aliases, Set blocked) { + public Entry(Map ids, Set substitutions, Map aliases, Set blocked) + { this.ids = ids; this.substitutions = substitutions; this.aliases = aliases; this.blocked = blocked; } - public Entry(FMLControlledNamespacedRegistry registry) { + public Entry(FMLControlledNamespacedRegistry registry) + { this.ids = Maps.newHashMap(); this.substitutions = Sets.newHashSet(); this.aliases = Maps.newHashMap(); @@ -372,34 +473,43 @@ public class PersistentRegistryManager public final Map entries = Maps.newHashMap(); } - public static RegistryDelegate makeDelegate(T obj, Class rootClass) { + public static RegistryDelegate makeDelegate(T obj, Class rootClass) + { return PersistentRegistry.ACTIVE.getRegistry(rootClass).getDelegate(obj, rootClass); } - private static class DumpRegistryFunction implements Function>, Void> { + private static class DumpRegistryFunction implements Function>, Void> + { static final DumpRegistryFunction OPERATION = new DumpRegistryFunction(); @Override - public Void apply(Map.Entry> input) { + public Void apply(Map.Entry> input) + { input.getValue().dump(input.getKey()); return null; } } - private static class ValidateRegistryFunction implements Function>, Void> { + + private static class ValidateRegistryFunction implements Function>, Void> + { static final ValidateRegistryFunction OPERATION = new ValidateRegistryFunction(); @Override - public Void apply(Map.Entry> input) { + public Void apply(Map.Entry> input) + { input.getValue().validateContent(input.getKey()); return null; } } - private static class ResetDelegatesFunction implements Function>, Void> { + + private static class ResetDelegatesFunction implements Function>, Void> + { static final ResetDelegatesFunction OPERATION = new ResetDelegatesFunction(); @Override - public Void apply(Map.Entry> input) { + public Void apply(Map.Entry> input) + { input.getValue().resetSubstitutionDelegates(); return null; } diff --git a/src/main/java/net/minecraftforge/fml/common/registry/VillagerRegistry.java b/src/main/java/net/minecraftforge/fml/common/registry/VillagerRegistry.java index 340c4e35cb..17c37c12cd 100644 --- a/src/main/java/net/minecraftforge/fml/common/registry/VillagerRegistry.java +++ b/src/main/java/net/minecraftforge/fml/common/registry/VillagerRegistry.java @@ -19,10 +19,18 @@ import java.util.Map; import java.util.Random; import java.util.Set; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import org.apache.commons.lang3.Validate; import net.minecraft.entity.passive.EntityVillager; -import net.minecraft.entity.passive.EntityVillager.*; +import net.minecraft.entity.passive.EntityVillager.EmeraldForItems; +import net.minecraft.entity.passive.EntityVillager.ITradeList; +import net.minecraft.entity.passive.EntityVillager.ItemAndEmeraldToItem; +import net.minecraft.entity.passive.EntityVillager.ListEnchantedBookForEmeralds; +import net.minecraft.entity.passive.EntityVillager.ListEnchantedItemForEmeralds; +import net.minecraft.entity.passive.EntityVillager.ListItemForEmeralds; +import net.minecraft.entity.passive.EntityVillager.PriceInfo; import net.minecraft.init.Blocks; import net.minecraft.init.Items; import net.minecraft.item.EnumDyeColor; @@ -38,14 +46,10 @@ import net.minecraftforge.fml.common.FMLLog; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; - /** * Registry for villager trading control * * @author cpw - * */ public class VillagerRegistry { @@ -66,7 +70,6 @@ public class VillagerRegistry * creation so you can insert your own new village pieces * * @author cpw - * */ public interface IVillageCreationHandler { @@ -86,6 +89,7 @@ public class VillagerRegistry /** * Build an instance of the village component {@link net.minecraft.world.gen.structure.StructureVillagePieces} + * * @param villagePiece * @param startPiece * @param pieces @@ -97,7 +101,7 @@ public class VillagerRegistry * @param p5 */ Village buildComponent(StructureVillagePieces.PieceWeight villagePiece, StructureVillagePieces.Start startPiece, List pieces, Random random, int p1, - int p2, int p3, EnumFacing facing, int p5); + int p2, int p3, EnumFacing facing, int p5); } public static VillagerRegistry instance() @@ -107,6 +111,7 @@ public class VillagerRegistry /** * Register your villager id + * * @param id */ @Deprecated // Doesn't work at all. @@ -119,6 +124,7 @@ public class VillagerRegistry } newVillagerIds.add(id); } + /** * Register a new skin for a villager type * @@ -184,7 +190,7 @@ public class VillagerRegistry } public static Village getVillageComponent(StructureVillagePieces.PieceWeight villagePiece, StructureVillagePieces.Start startPiece, List pieces, Random random, - int p1, int p2, int p3, EnumFacing facing, int p5) + int p1, int p2, int p3, EnumFacing facing, int p5) { return instance().villageCreationHandlers.get(villagePiece.villagePieceClass).buildComponent(villagePiece, startPiece, pieces, random, p1, p2, p3, facing, p5); } @@ -193,27 +199,30 @@ public class VillagerRegistry { register(prof, -1); } + private void register(VillagerProfession prof, int id) { professions.register(id, prof.name, prof); } private boolean hasInit = false; - private FMLControlledNamespacedRegistry professions = PersistentRegistryManager.createRegistry(new ResourceLocation("minecraft:villagerprofessions"), VillagerProfession.class, null, 1024, 0, true); + private FMLControlledNamespacedRegistry professions = PersistentRegistryManager.createRegistry(new ResourceLocation("minecraft:villagerprofessions"), VillagerProfession.class, null, 1024, 0, true, null); private void init() { if (hasInit) + { return; + } VillagerProfession prof = new VillagerProfession("minecraft:farmer", "minecraft:textures/entity/villager/farmer.png"); { register(prof, 0); - (new VillagerCareer(prof, "farmer" )).init(VanillaTrades.trades[0][0]); - (new VillagerCareer(prof, "fisherman" )).init(VanillaTrades.trades[0][1]); - (new VillagerCareer(prof, "shepherd" )).init(VanillaTrades.trades[0][2]); - (new VillagerCareer(prof, "fletcher" )).init(VanillaTrades.trades[0][3]); + (new VillagerCareer(prof, "farmer")).init(VanillaTrades.trades[0][0]); + (new VillagerCareer(prof, "fisherman")).init(VanillaTrades.trades[0][1]); + (new VillagerCareer(prof, "shepherd")).init(VanillaTrades.trades[0][2]); + (new VillagerCareer(prof, "fletcher")).init(VanillaTrades.trades[0][3]); } prof = new VillagerProfession("minecraft:librarian", "minecraft:textures/entity/villager/librarian.png"); { @@ -228,9 +237,9 @@ public class VillagerRegistry prof = new VillagerProfession("minecraft:smith", "minecraft:textures/entity/villager/smith.png"); { register(prof, 3); - (new VillagerCareer(prof, "armor" )).init(VanillaTrades.trades[3][0]); + (new VillagerCareer(prof, "armor")).init(VanillaTrades.trades[3][0]); (new VillagerCareer(prof, "weapon")).init(VanillaTrades.trades[3][1]); - (new VillagerCareer(prof, "tool" )).init(VanillaTrades.trades[3][2]); + (new VillagerCareer(prof, "tool")).init(VanillaTrades.trades[3][2]); } prof = new VillagerProfession("minecraft:butcher", "minecraft:textures/entity/villager/butcher.png"); { @@ -268,6 +277,7 @@ public class VillagerRegistry private VillagerProfession profession; private String name; private int id; + public VillagerCareer(VillagerProfession parent, String name) { this.profession = parent; @@ -283,8 +293,14 @@ public class VillagerRegistry @Override public boolean equals(Object o) { - if (o == this) return true; - if (!(o instanceof VillagerCareer)) return false; + if (o == this) + { + return true; + } + if (!(o instanceof VillagerCareer)) + { + return false; + } VillagerCareer oc = (VillagerCareer)o; return name.equals(oc.name) && profession == oc.profession; } @@ -294,7 +310,7 @@ public class VillagerRegistry * Hook called when spawning a Villager, sets it's profession to a random registered profession. * * @param entity The new entity - * @param rand The world's RNG + * @param rand The world's RNG */ public static void setRandomProfession(EntityVillager entity, Random rand) { @@ -312,196 +328,196 @@ public class VillagerRegistry //Moved to inner class to stop static initializer issues. //It is nasty I know but it's vanilla. private static final ITradeList[][][][] trades = - { - { { - { - new EmeraldForItems(Items.wheat, new PriceInfo(18, 22)), - new EmeraldForItems(Items.potato, new PriceInfo(15, 19)), - new EmeraldForItems(Items.carrot, new PriceInfo(15, 19)), - new ListItemForEmeralds(Items.bread, new PriceInfo(-4, -2)) - }, - { - new EmeraldForItems(Item.getItemFromBlock(Blocks.pumpkin), new PriceInfo(8, 13)), - new ListItemForEmeralds(Items.pumpkin_pie, new PriceInfo(-3, -2)) - }, - { - new EmeraldForItems(Item.getItemFromBlock(Blocks.melon_block), new PriceInfo(7, 12)), - new ListItemForEmeralds(Items.apple, new PriceInfo(-5, -7)) - }, - { - new ListItemForEmeralds(Items.cookie, new PriceInfo(-6, -10)), - new ListItemForEmeralds(Items.cake, new PriceInfo(1, 1)) - } - }, - { - { - new EmeraldForItems(Items.string, new PriceInfo(15, 20)), - new EmeraldForItems(Items.coal, new PriceInfo(16, 24)), - new ItemAndEmeraldToItem(Items.fish, new PriceInfo(6, 6), Items.cooked_fish, new PriceInfo(6, 6)) - }, - { - new ListEnchantedItemForEmeralds(Items.fishing_rod, new PriceInfo(7, 8)) - } - }, - { - { - new EmeraldForItems(Item.getItemFromBlock(Blocks.wool), new PriceInfo(16, 22)), - new ListItemForEmeralds(Items.shears, new PriceInfo(3, 4)) - }, - { - new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 0), new PriceInfo(1, 2)), - new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 1), new PriceInfo(1, 2)), - new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 2), new PriceInfo(1, 2)), - new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 3), new PriceInfo(1, 2)), - new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 4), new PriceInfo(1, 2)), - new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 5), new PriceInfo(1, 2)), - new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 6), new PriceInfo(1, 2)), - new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 7), new PriceInfo(1, 2)), - new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 8), new PriceInfo(1, 2)), - new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 9), new PriceInfo(1, 2)), - new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 10), new PriceInfo(1, 2)), - new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 11), new PriceInfo(1, 2)), - new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 12), new PriceInfo(1, 2)), - new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 13), new PriceInfo(1, 2)), - new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 14), new PriceInfo(1, 2)), - new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 15), new PriceInfo(1, 2)) - } - }, - { - { - new EmeraldForItems(Items.string, new PriceInfo(15, 20)), - new ListItemForEmeralds(Items.arrow, new PriceInfo(-12, -8)) - }, - { - new ListItemForEmeralds(Items.bow, new PriceInfo(2, 3)), - new ItemAndEmeraldToItem(Item.getItemFromBlock(Blocks.gravel), new PriceInfo(10, 10), Items.flint, new PriceInfo(6, 10)) - } - } - }, - { - { - { - new EmeraldForItems(Items.paper, new PriceInfo(24, 36)), - new ListEnchantedBookForEmeralds() - }, - { - new EmeraldForItems(Items.book, new PriceInfo(8, 10)), - new ListItemForEmeralds(Items.compass, new PriceInfo(10, 12)), - new ListItemForEmeralds(Item.getItemFromBlock(Blocks.bookshelf), new PriceInfo(3, 4)) - }, - { - new EmeraldForItems(Items.written_book, new PriceInfo(2, 2)), - new ListItemForEmeralds(Items.clock, new PriceInfo(10, 12)), - new ListItemForEmeralds(Item.getItemFromBlock(Blocks.glass), new PriceInfo(-5, -3)) - }, - { - new ListEnchantedBookForEmeralds() - }, - { - new ListEnchantedBookForEmeralds() - }, - { - new ListItemForEmeralds(Items.name_tag, new PriceInfo(20, 22)) - } - } - }, - { - { - { - new EmeraldForItems(Items.rotten_flesh, new PriceInfo(36, 40)), - new EmeraldForItems(Items.gold_ingot, new PriceInfo(8, 10)) - }, - { - new ListItemForEmeralds(Items.redstone, new PriceInfo(-4, -1)), - new ListItemForEmeralds(new ItemStack(Items.dye, 1, EnumDyeColor.BLUE.getDyeDamage()), - new PriceInfo(-2, -1)) - }, - { - new ListItemForEmeralds(Items.ender_eye, new PriceInfo(7, 11)), - new ListItemForEmeralds(Item.getItemFromBlock(Blocks.glowstone), new PriceInfo(-3, -1)) - }, - { - new ListItemForEmeralds(Items.experience_bottle, new PriceInfo(3, 11)) - } - } - }, - { - { - { - new EmeraldForItems(Items.coal, new PriceInfo(16, 24)), - new ListItemForEmeralds(Items.iron_helmet, new PriceInfo(4, 6)) - }, - { - new EmeraldForItems(Items.iron_ingot, new PriceInfo(7, 9)), - new ListItemForEmeralds(Items.iron_chestplate, new PriceInfo(10, 14)) - }, - { - new EmeraldForItems(Items.diamond, new PriceInfo(3, 4)), - new ListEnchantedItemForEmeralds(Items.diamond_chestplate, new PriceInfo(16, 19)) - }, - { - new ListItemForEmeralds(Items.chainmail_boots, new PriceInfo(5, 7)), - new ListItemForEmeralds(Items.chainmail_leggings, new PriceInfo(9, 11)), - new ListItemForEmeralds(Items.chainmail_helmet, new PriceInfo(5, 7)), - new ListItemForEmeralds(Items.chainmail_chestplate, new PriceInfo(11, 15)) - } - }, - { - { - new EmeraldForItems(Items.coal, new PriceInfo(16, 24)), - new ListItemForEmeralds(Items.iron_axe, new PriceInfo(6, 8)) - }, - { - new EmeraldForItems(Items.iron_ingot, new PriceInfo(7, 9)), - new ListEnchantedItemForEmeralds(Items.iron_sword, new PriceInfo(9, 10)) - }, - { - new EmeraldForItems(Items.diamond, new PriceInfo(3, 4)), - new ListEnchantedItemForEmeralds(Items.diamond_sword, new PriceInfo(12, 15)), - new ListEnchantedItemForEmeralds(Items.diamond_axe, new PriceInfo(9, 12)) - } - }, - { - { - new EmeraldForItems(Items.coal, new PriceInfo(16, 24)), - new ListEnchantedItemForEmeralds(Items.iron_shovel, new PriceInfo(5, 7)) - }, - { - new EmeraldForItems(Items.iron_ingot, new PriceInfo(7, 9)), - new ListEnchantedItemForEmeralds(Items.iron_pickaxe, new PriceInfo(9, 11)) - }, - { - new EmeraldForItems(Items.diamond, new PriceInfo(3, 4)), - new ListEnchantedItemForEmeralds(Items.diamond_pickaxe, new PriceInfo(12, 15)) - } - } - }, - { - { - { - new EmeraldForItems(Items.porkchop, new PriceInfo(14, 18)), - new EmeraldForItems(Items.chicken, new PriceInfo(14, 18)) - }, - { - new EmeraldForItems(Items.coal, new PriceInfo(16, 24)), - new ListItemForEmeralds(Items.cooked_porkchop, new PriceInfo(-7, -5)), - new ListItemForEmeralds(Items.cooked_chicken, new PriceInfo(-8, -6)) - } - }, - { - { - new EmeraldForItems(Items.leather, new PriceInfo(9, 12)), - new ListItemForEmeralds(Items.leather_leggings, new PriceInfo(2, 4)) - }, - { - new ListEnchantedItemForEmeralds(Items.leather_chestplate, new PriceInfo(7, 12)) - }, - { - new ListItemForEmeralds(Items.saddle, new PriceInfo(8, 10)) - } - } - } - }; + { + { + { + new EmeraldForItems(Items.wheat, new PriceInfo(18, 22)), + new EmeraldForItems(Items.potato, new PriceInfo(15, 19)), + new EmeraldForItems(Items.carrot, new PriceInfo(15, 19)), + new ListItemForEmeralds(Items.bread, new PriceInfo(-4, -2)) + }, + { + new EmeraldForItems(Item.getItemFromBlock(Blocks.pumpkin), new PriceInfo(8, 13)), + new ListItemForEmeralds(Items.pumpkin_pie, new PriceInfo(-3, -2)) + }, + { + new EmeraldForItems(Item.getItemFromBlock(Blocks.melon_block), new PriceInfo(7, 12)), + new ListItemForEmeralds(Items.apple, new PriceInfo(-5, -7)) + }, + { + new ListItemForEmeralds(Items.cookie, new PriceInfo(-6, -10)), + new ListItemForEmeralds(Items.cake, new PriceInfo(1, 1)) + } + }, + { + { + new EmeraldForItems(Items.string, new PriceInfo(15, 20)), + new EmeraldForItems(Items.coal, new PriceInfo(16, 24)), + new ItemAndEmeraldToItem(Items.fish, new PriceInfo(6, 6), Items.cooked_fish, new PriceInfo(6, 6)) + }, + { + new ListEnchantedItemForEmeralds(Items.fishing_rod, new PriceInfo(7, 8)) + } + }, + { + { + new EmeraldForItems(Item.getItemFromBlock(Blocks.wool), new PriceInfo(16, 22)), + new ListItemForEmeralds(Items.shears, new PriceInfo(3, 4)) + }, + { + new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 0), new PriceInfo(1, 2)), + new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 1), new PriceInfo(1, 2)), + new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 2), new PriceInfo(1, 2)), + new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 3), new PriceInfo(1, 2)), + new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 4), new PriceInfo(1, 2)), + new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 5), new PriceInfo(1, 2)), + new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 6), new PriceInfo(1, 2)), + new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 7), new PriceInfo(1, 2)), + new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 8), new PriceInfo(1, 2)), + new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 9), new PriceInfo(1, 2)), + new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 10), new PriceInfo(1, 2)), + new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 11), new PriceInfo(1, 2)), + new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 12), new PriceInfo(1, 2)), + new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 13), new PriceInfo(1, 2)), + new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 14), new PriceInfo(1, 2)), + new ListItemForEmeralds(new ItemStack(Blocks.wool, 1, 15), new PriceInfo(1, 2)) + } + }, + { + { + new EmeraldForItems(Items.string, new PriceInfo(15, 20)), + new ListItemForEmeralds(Items.arrow, new PriceInfo(-12, -8)) + }, + { + new ListItemForEmeralds(Items.bow, new PriceInfo(2, 3)), + new ItemAndEmeraldToItem(Item.getItemFromBlock(Blocks.gravel), new PriceInfo(10, 10), Items.flint, new PriceInfo(6, 10)) + } + } + }, + { + { + { + new EmeraldForItems(Items.paper, new PriceInfo(24, 36)), + new ListEnchantedBookForEmeralds() + }, + { + new EmeraldForItems(Items.book, new PriceInfo(8, 10)), + new ListItemForEmeralds(Items.compass, new PriceInfo(10, 12)), + new ListItemForEmeralds(Item.getItemFromBlock(Blocks.bookshelf), new PriceInfo(3, 4)) + }, + { + new EmeraldForItems(Items.written_book, new PriceInfo(2, 2)), + new ListItemForEmeralds(Items.clock, new PriceInfo(10, 12)), + new ListItemForEmeralds(Item.getItemFromBlock(Blocks.glass), new PriceInfo(-5, -3)) + }, + { + new ListEnchantedBookForEmeralds() + }, + { + new ListEnchantedBookForEmeralds() + }, + { + new ListItemForEmeralds(Items.name_tag, new PriceInfo(20, 22)) + } + } + }, + { + { + { + new EmeraldForItems(Items.rotten_flesh, new PriceInfo(36, 40)), + new EmeraldForItems(Items.gold_ingot, new PriceInfo(8, 10)) + }, + { + new ListItemForEmeralds(Items.redstone, new PriceInfo(-4, -1)), + new ListItemForEmeralds(new ItemStack(Items.dye, 1, EnumDyeColor.BLUE.getDyeDamage()), + new PriceInfo(-2, -1)) + }, + { + new ListItemForEmeralds(Items.ender_eye, new PriceInfo(7, 11)), + new ListItemForEmeralds(Item.getItemFromBlock(Blocks.glowstone), new PriceInfo(-3, -1)) + }, + { + new ListItemForEmeralds(Items.experience_bottle, new PriceInfo(3, 11)) + } + } + }, + { + { + { + new EmeraldForItems(Items.coal, new PriceInfo(16, 24)), + new ListItemForEmeralds(Items.iron_helmet, new PriceInfo(4, 6)) + }, + { + new EmeraldForItems(Items.iron_ingot, new PriceInfo(7, 9)), + new ListItemForEmeralds(Items.iron_chestplate, new PriceInfo(10, 14)) + }, + { + new EmeraldForItems(Items.diamond, new PriceInfo(3, 4)), + new ListEnchantedItemForEmeralds(Items.diamond_chestplate, new PriceInfo(16, 19)) + }, + { + new ListItemForEmeralds(Items.chainmail_boots, new PriceInfo(5, 7)), + new ListItemForEmeralds(Items.chainmail_leggings, new PriceInfo(9, 11)), + new ListItemForEmeralds(Items.chainmail_helmet, new PriceInfo(5, 7)), + new ListItemForEmeralds(Items.chainmail_chestplate, new PriceInfo(11, 15)) + } + }, + { + { + new EmeraldForItems(Items.coal, new PriceInfo(16, 24)), + new ListItemForEmeralds(Items.iron_axe, new PriceInfo(6, 8)) + }, + { + new EmeraldForItems(Items.iron_ingot, new PriceInfo(7, 9)), + new ListEnchantedItemForEmeralds(Items.iron_sword, new PriceInfo(9, 10)) + }, + { + new EmeraldForItems(Items.diamond, new PriceInfo(3, 4)), + new ListEnchantedItemForEmeralds(Items.diamond_sword, new PriceInfo(12, 15)), + new ListEnchantedItemForEmeralds(Items.diamond_axe, new PriceInfo(9, 12)) + } + }, + { + { + new EmeraldForItems(Items.coal, new PriceInfo(16, 24)), + new ListEnchantedItemForEmeralds(Items.iron_shovel, new PriceInfo(5, 7)) + }, + { + new EmeraldForItems(Items.iron_ingot, new PriceInfo(7, 9)), + new ListEnchantedItemForEmeralds(Items.iron_pickaxe, new PriceInfo(9, 11)) + }, + { + new EmeraldForItems(Items.diamond, new PriceInfo(3, 4)), + new ListEnchantedItemForEmeralds(Items.diamond_pickaxe, new PriceInfo(12, 15)) + } + } + }, + { + { + { + new EmeraldForItems(Items.porkchop, new PriceInfo(14, 18)), + new EmeraldForItems(Items.chicken, new PriceInfo(14, 18)) + }, + { + new EmeraldForItems(Items.coal, new PriceInfo(16, 24)), + new ListItemForEmeralds(Items.cooked_porkchop, new PriceInfo(-7, -5)), + new ListItemForEmeralds(Items.cooked_chicken, new PriceInfo(-8, -6)) + } + }, + { + { + new EmeraldForItems(Items.leather, new PriceInfo(9, 12)), + new ListItemForEmeralds(Items.leather_leggings, new PriceInfo(2, 4)) + }, + { + new ListEnchantedItemForEmeralds(Items.leather_chestplate, new PriceInfo(7, 12)) + }, + { + new ListItemForEmeralds(Items.saddle, new PriceInfo(8, 10)) + } + } + } + }; } }