Fix up blockstate rebuild. Closes #2221. Also fix formatting. IDEA has differences. Solved now.
This commit is contained in:
parent
02e9b9d99c
commit
21173c3b65
|
@ -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<I> extends RegistryNamespacedDefaultedByKey<ResourceLocation,I> {
|
||||
public class FMLControlledNamespacedRegistry<I> extends RegistryNamespacedDefaultedByKey<ResourceLocation, I>
|
||||
{
|
||||
public static final boolean DEBUG = Boolean.parseBoolean(System.getProperty("fml.debugRegistryEntries", "false"));
|
||||
private final Class<I> superType;
|
||||
private final boolean isDelegated;
|
||||
|
@ -43,7 +40,7 @@ public class FMLControlledNamespacedRegistry<I> 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 <ResourceLocation, ResourceLocation> aliases = Maps.newHashMap();
|
||||
private final Map<ResourceLocation, ResourceLocation> 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<I> extends RegistryNamespacedDefaul
|
|||
private final Set<Integer> blockedIds = Sets.newHashSet();
|
||||
|
||||
private final BitSet availabilityMap;
|
||||
|
||||
private final AddCallback<I> addCallback;
|
||||
|
||||
public interface AddCallback<T>
|
||||
{
|
||||
public void onAdd(T obj, int id);
|
||||
}
|
||||
|
||||
FMLControlledNamespacedRegistry(ResourceLocation defaultKey, int maxIdValue, int minIdValue, Class<I> type, boolean isDelegated)
|
||||
{
|
||||
this(defaultKey, maxIdValue, minIdValue, type, isDelegated, null);
|
||||
}
|
||||
|
||||
FMLControlledNamespacedRegistry(ResourceLocation defaultKey, int maxIdValue, int minIdValue, Class<I> type, boolean isDelegated, AddCallback<I> callback)
|
||||
{
|
||||
super(defaultKey);
|
||||
this.superType = type;
|
||||
|
@ -67,16 +77,22 @@ public class FMLControlledNamespacedRegistry<I> 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<I> 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<I> extends RegistryNamespacedDefaul
|
|||
@SuppressWarnings("unchecked")
|
||||
void set(FMLControlledNamespacedRegistry<I> 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<I> 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<I> extends RegistryNamespacedDefaul
|
|||
|
||||
/**
|
||||
* Fetch the object identified by the specified name or the default object.
|
||||
*
|
||||
* <p/>
|
||||
* 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<I> extends RegistryNamespacedDefaul
|
|||
|
||||
/**
|
||||
* Fetch the object identified by the specified id or the default object.
|
||||
*
|
||||
* <p/>
|
||||
* 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<I> extends RegistryNamespacedDefaul
|
|||
|
||||
/**
|
||||
* Get the id for the specified object.
|
||||
*
|
||||
* <p/>
|
||||
* Don't hold onto the id across the world, it's being dynamically re-mapped as needed.
|
||||
*
|
||||
* <p/>
|
||||
* 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<I> 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<I> extends RegistryNamespacedDefaul
|
|||
|
||||
/**
|
||||
* Determine if the registry has an entry for the specified name.
|
||||
*
|
||||
* <p/>
|
||||
* Aliased names will be resolved as well.
|
||||
*
|
||||
* @param name Object name to check.
|
||||
|
@ -269,7 +321,10 @@ public class FMLControlledNamespacedRegistry<I> 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<I> extends RegistryNamespacedDefaul
|
|||
|
||||
/**
|
||||
* Get the id for the specified object.
|
||||
*
|
||||
* <p/>
|
||||
* Don't hold onto the id across the world, it's being dynamically re-mapped as needed.
|
||||
*
|
||||
* <p/>
|
||||
* 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<I> 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<I> extends RegistryNamespacedDefaul
|
|||
idMapping.put(getNameForObject(thing), getId(thing));
|
||||
}
|
||||
}
|
||||
|
||||
public void serializeAliases(Map<ResourceLocation, ResourceLocation> map)
|
||||
{
|
||||
map.putAll(this.aliases);
|
||||
|
@ -325,15 +384,21 @@ public class FMLControlledNamespacedRegistry<I> 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<I> 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<I> 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<I> extends RegistryNamespacedDefaul
|
|||
{
|
||||
aliases.put(from, to);
|
||||
if (DEBUG)
|
||||
{
|
||||
FMLLog.finer("Registry alias: %s -> %s", from, to);
|
||||
}
|
||||
}
|
||||
|
||||
Map<ResourceLocation,Integer> getEntriesNotIn(FMLControlledNamespacedRegistry<I> registry)
|
||||
Map<ResourceLocation, Integer> getEntriesNotIn(FMLControlledNamespacedRegistry<I> registry)
|
||||
{
|
||||
Map<ResourceLocation,Integer> ret = new HashMap<ResourceLocation, Integer>();
|
||||
Map<ResourceLocation, Integer> ret = new HashMap<ResourceLocation, Integer>();
|
||||
|
||||
for (I thing : this.typeSafeIterable())
|
||||
{
|
||||
|
@ -418,7 +490,9 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespacedDefaul
|
|||
void dump(ResourceLocation registryName)
|
||||
{
|
||||
if (!DEBUG)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<Integer> ids = new ArrayList<Integer>();
|
||||
|
||||
|
@ -442,13 +516,26 @@ public class FMLControlledNamespacedRegistry<I> 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<I> extends RegistryNamespacedDefaul
|
|||
return optionalDefaultObject;
|
||||
}
|
||||
|
||||
public RegistryDelegate<I> getDelegate(I thing, Class<I> clazz) {
|
||||
public RegistryDelegate<I> getDelegate(I thing, Class<I> clazz)
|
||||
{
|
||||
return new RegistryDelegate.Delegate<I>(thing, clazz);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Delegate<I> getExistingDelegate(I thing) {
|
||||
try {
|
||||
return (Delegate<I>) delegateAccessor.get(thing);
|
||||
} catch (IllegalAccessException e) {
|
||||
public Delegate<I> getExistingDelegate(I thing)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (Delegate<I>)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<I> 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<I> 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<I> extends RegistryNamespacedDefaul
|
|||
@Override
|
||||
public Iterator<I> iterator()
|
||||
{
|
||||
return Iterators.concat(super.iterator(),getPersistentSubstitutions().values().iterator());
|
||||
return Iterators.concat(super.iterator(), getPersistentSubstitutions().values().iterator());
|
||||
}
|
||||
|
||||
|
||||
|
||||
FMLControlledNamespacedRegistry<I> makeShallowCopy() {
|
||||
FMLControlledNamespacedRegistry<I> makeShallowCopy()
|
||||
{
|
||||
return new FMLControlledNamespacedRegistry<I>(optionalDefaultKey, maxId, minId, superType, isDelegated);
|
||||
}
|
||||
|
||||
void resetSubstitutionDelegates()
|
||||
{
|
||||
if (!isDelegated) return;
|
||||
for (I obj: typeSafeIterable()) {
|
||||
if (!isDelegated)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (I obj : typeSafeIterable())
|
||||
{
|
||||
Delegate<I> delegate = getExistingDelegate(obj);
|
||||
delegate.changeReference(obj);
|
||||
}
|
||||
|
@ -546,49 +646,62 @@ public class FMLControlledNamespacedRegistry<I> extends RegistryNamespacedDefaul
|
|||
@SuppressWarnings("unchecked")
|
||||
public <T> FMLControlledNamespacedRegistry<T> asType(Class<? extends T> type)
|
||||
{
|
||||
return (FMLControlledNamespacedRegistry<T>) this;
|
||||
return (FMLControlledNamespacedRegistry<T>)this;
|
||||
}
|
||||
|
||||
public void serializeBlockList(Set<Integer> blocked) {
|
||||
public void serializeBlockList(Set<Integer> blocked)
|
||||
{
|
||||
blocked.addAll(this.blockedIds);
|
||||
}
|
||||
|
||||
public Set<? extends ResourceLocation> getActiveSubstitutions() {
|
||||
public Set<? extends ResourceLocation> getActiveSubstitutions()
|
||||
{
|
||||
return activeSubstitutions.keySet();
|
||||
}
|
||||
|
||||
public void loadAliases(Map<ResourceLocation, ResourceLocation> aliases) {
|
||||
for (Map.Entry<ResourceLocation, ResourceLocation> alias : aliases.entrySet()) {
|
||||
public void loadAliases(Map<ResourceLocation, ResourceLocation> aliases)
|
||||
{
|
||||
for (Map.Entry<ResourceLocation, ResourceLocation> alias : aliases.entrySet())
|
||||
{
|
||||
addAlias(alias.getKey(), alias.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public void loadSubstitutions(Set<ResourceLocation> substitutions) {
|
||||
for (ResourceLocation rl : substitutions) {
|
||||
public void loadSubstitutions(Set<ResourceLocation> substitutions)
|
||||
{
|
||||
for (ResourceLocation rl : substitutions)
|
||||
{
|
||||
activateSubstitution(rl);
|
||||
}
|
||||
}
|
||||
|
||||
public void loadBlocked(Set<Integer> blocked) {
|
||||
for (Integer id : blocked) {
|
||||
public void loadBlocked(Set<Integer> blocked)
|
||||
{
|
||||
for (Integer id : blocked)
|
||||
{
|
||||
blockedIds.add(id);
|
||||
availabilityMap.set(id);
|
||||
}
|
||||
}
|
||||
|
||||
public void loadIds(Map<ResourceLocation, Integer> ids, Map<ResourceLocation, Integer> missingIds, Map<ResourceLocation, Integer[]> remappedIds, FMLControlledNamespacedRegistry<I> currentRegistry, ResourceLocation registryName) {
|
||||
for (Map.Entry<ResourceLocation, Integer> entry : ids.entrySet()) {
|
||||
public void loadIds(Map<ResourceLocation, Integer> ids, Map<ResourceLocation, Integer> missingIds, Map<ResourceLocation, Integer[]> remappedIds, FMLControlledNamespacedRegistry<I> currentRegistry, ResourceLocation registryName)
|
||||
{
|
||||
for (Map.Entry<ResourceLocation, Integer> 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<I> extends RegistryNamespacedDefaul
|
|||
}
|
||||
}
|
||||
|
||||
public void blockId(int id) {
|
||||
public void blockId(int id)
|
||||
{
|
||||
blockedIds.add(id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Block> getBlockRegistry() {
|
||||
public static FMLControlledNamespacedRegistry<Block> getBlockRegistry()
|
||||
{
|
||||
return getMain().iBlockRegistry;
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,8 @@ public class GameData {
|
|||
*
|
||||
* @return Item Registry.
|
||||
*/
|
||||
public static FMLControlledNamespacedRegistry<Item> getItemRegistry() {
|
||||
public static FMLControlledNamespacedRegistry<Item> 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<Block> iBlockRegistry = PersistentRegistryManager.createRegistry(PersistentRegistryManager.BLOCKS, Block.class, new ResourceLocation("minecraft:air"), MAX_BLOCK_ID, MIN_BLOCK_ID, true);
|
||||
private final FMLControlledNamespacedRegistry<Block> iBlockRegistry = PersistentRegistryManager.createRegistry(PersistentRegistryManager.BLOCKS, Block.class, new ResourceLocation("minecraft:air"), MAX_BLOCK_ID, MIN_BLOCK_ID, true, BlockStateCapture.INSTANCE);
|
||||
private final FMLControlledNamespacedRegistry<Item> 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, Item> 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<IBlockState> BLOCKSTATE_TO_ID = new ClearableObjectIntIdentityMap<IBlockState>();
|
||||
|
||||
//Internal: DO NOT USE, will change without warning.
|
||||
public static ObjectIntIdentityMap getBlockStateIDMap() {
|
||||
public static ClearableObjectIntIdentityMap<IBlockState> getBlockStateIDMap()
|
||||
{
|
||||
return BLOCKSTATE_TO_ID;
|
||||
}
|
||||
|
||||
//Lets us clear the map so we can rebuild it.
|
||||
private static class ClearableObjectIntIdentityMap<I> extends ObjectIntIdentityMap<I> {
|
||||
private void clear() {
|
||||
static class ClearableObjectIntIdentityMap<I> extends ObjectIntIdentityMap<I>
|
||||
{
|
||||
void clear()
|
||||
{
|
||||
this.identityMap.clear();
|
||||
this.objectList.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public <T> RegistryDelegate<T> makeDelegate(T obj, Class<T> rootClass) {
|
||||
public <T> RegistryDelegate<T> makeDelegate(T obj, Class<T> rootClass)
|
||||
{
|
||||
return PersistentRegistryManager.makeDelegate(obj, rootClass);
|
||||
}
|
||||
|
||||
private static class BlockStateCapture implements FMLControlledNamespacedRegistry.AddCallback<Block>
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<IWorldGenerator> 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<IWorldGenerator> list = Lists.newArrayList(worldGenerators);
|
||||
Collections.sort(list, new Comparator<IWorldGenerator>() {
|
||||
Collections.sort(list, new Comparator<IWorldGenerator>()
|
||||
{
|
||||
@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<? extends ItemBlock> 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<? extends ItemBlock> 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<? extends TileEntity> tileEntityClass, String id, String... alternatives)
|
||||
{
|
||||
TileEntity.addMapping(tileEntityClass, id);
|
||||
Map<String,Class<?>> teMappings = ObfuscationReflectionHelper.getPrivateValue(TileEntity.class, null, "field_" + "145855_i", "nameToClassMap");
|
||||
for (String s: alternatives)
|
||||
Map<String, Class<?>> 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.
|
||||
*
|
||||
* <p/>
|
||||
* 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.
|
||||
*
|
||||
* <p/>
|
||||
* 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.
|
||||
*
|
||||
* <p/>
|
||||
* 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
|
||||
*
|
||||
* <p/>
|
||||
* 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;
|
||||
|
|
|
@ -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<ResourceLocation,FMLControlledNamespacedRegistry<?>> registries = HashBiMap.create();
|
||||
private final BiMap<Class<?>,ResourceLocation> registrySuperTypes = HashBiMap.create();
|
||||
private final BiMap<ResourceLocation, FMLControlledNamespacedRegistry<?>> registries = HashBiMap.create();
|
||||
private final BiMap<Class<?>, ResourceLocation> registrySuperTypes = HashBiMap.create();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
<T> FMLControlledNamespacedRegistry<T> getRegistry(ResourceLocation key, Class<T> regType)
|
||||
{
|
||||
return (FMLControlledNamespacedRegistry<T>) registries.get(key);
|
||||
return (FMLControlledNamespacedRegistry<T>)registries.get(key);
|
||||
}
|
||||
|
||||
<T> FMLControlledNamespacedRegistry<T> getOrShallowCopyRegistry(ResourceLocation key, Class<T> regType, FMLControlledNamespacedRegistry<T> other)
|
||||
{
|
||||
if (!registries.containsKey(key)) {
|
||||
if (!registries.containsKey(key))
|
||||
{
|
||||
registries.put(key, other.makeShallowCopy());
|
||||
registrySuperTypes.put(regType, key);
|
||||
}
|
||||
return getRegistry(key, regType);
|
||||
}
|
||||
|
||||
private <T> FMLControlledNamespacedRegistry<T> createRegistry(ResourceLocation registryName, Class<T> type, ResourceLocation defaultObjectKey, int minId, int maxId, boolean isDelegated) {
|
||||
private <T> FMLControlledNamespacedRegistry<T> createRegistry(ResourceLocation registryName, Class<T> registryType, ResourceLocation optionalDefaultKey, int minId, int maxId, boolean hasDelegates)
|
||||
{
|
||||
return this.createRegistry(registryName, registryType, optionalDefaultKey, minId, maxId, hasDelegates, null);
|
||||
}
|
||||
|
||||
private <T> FMLControlledNamespacedRegistry<T> createRegistry(ResourceLocation registryName, Class<T> type, ResourceLocation defaultObjectKey, int minId, int maxId, boolean isDelegated, FMLControlledNamespacedRegistry.AddCallback<T> addCallback)
|
||||
{
|
||||
Set<Class<?>> parents = Sets.newHashSet();
|
||||
findSuperTypes(type, parents);
|
||||
SetView<Class<?>> 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<T> fmlControlledNamespacedRegistry = new FMLControlledNamespacedRegistry<T>(defaultObjectKey, maxId, minId, type, isDelegated);
|
||||
FMLControlledNamespacedRegistry<T> fmlControlledNamespacedRegistry = new FMLControlledNamespacedRegistry<T>(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<Class<?>> 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 <T> FMLControlledNamespacedRegistry<T> getRegistry(Class<T> rootClass) {
|
||||
public <T> FMLControlledNamespacedRegistry<T> getRegistry(Class<T> 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 <T> FMLControlledNamespacedRegistry<T> createRegistry(ResourceLocation registryName, Class<T> registryType, ResourceLocation optionalDefaultKey, int maxId, int minId, boolean hasDelegates) {
|
||||
return PersistentRegistry.ACTIVE.createRegistry(registryName,registryType,optionalDefaultKey,minId, maxId, hasDelegates);
|
||||
public static <T> FMLControlledNamespacedRegistry<T> createRegistry(ResourceLocation registryName, Class<T> registryType, ResourceLocation optionalDefaultKey, int maxId, int minId, boolean hasDelegates, FMLControlledNamespacedRegistry.AddCallback<T> addCallback)
|
||||
{
|
||||
return PersistentRegistry.ACTIVE.createRegistry(registryName, registryType, optionalDefaultKey, minId, maxId, hasDelegates, addCallback);
|
||||
}
|
||||
|
||||
public static <T> FMLControlledNamespacedRegistry<T> createRegistry(ResourceLocation registryName, Class<T> registryType, ResourceLocation optionalDefaultKey, int maxId, int minId, boolean hasDelegates)
|
||||
{
|
||||
return PersistentRegistry.ACTIVE.createRegistry(registryName, registryType, optionalDefaultKey, minId, maxId, hasDelegates);
|
||||
}
|
||||
|
||||
public static List<String> injectSnapshot(GameDataSnapshot snapshot, boolean injectFrozenData, boolean isLocalWorld) {
|
||||
public static List<String> 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<ResourceLocation, Map<ResourceLocation,Integer[]>> remaps = Maps.newHashMap();
|
||||
final LinkedHashMap<ResourceLocation, Map<ResourceLocation,Integer>> missing = Maps.newLinkedHashMap();
|
||||
final Map<ResourceLocation, Map<ResourceLocation, Integer[]>> remaps = Maps.newHashMap();
|
||||
final LinkedHashMap<ResourceLocation, Map<ResourceLocation, Integer>> 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<ResourceLocation, GameDataSnapshot.Entry> snapshotEntry : snapshot.entries.entrySet())
|
||||
{
|
||||
|
@ -119,13 +155,17 @@ public class PersistentRegistryManager
|
|||
// If we have missed data, fire the missing mapping event
|
||||
List<String> 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<ResourceLocation, FMLControlledNamespacedRegistry<?>> r : PersistentRegistry.ACTIVE.registries.entrySet()) {
|
||||
for (Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>> 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<ResourceLocation, FMLControlledNamespacedRegistry<?>> r : PersistentRegistry.ACTIVE.registries.entrySet()) {
|
||||
for (Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>> 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<Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>>, Void> operation) {
|
||||
private static void forAllRegistries(PersistentRegistry registrySet, Function<Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>>, Void> operation)
|
||||
{
|
||||
for (Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>> r : registrySet.registries.entrySet())
|
||||
{
|
||||
operation.apply(r);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> void loadRegistry(ResourceLocation registryName, PersistentRegistry from, PersistentRegistry to, Class<T> regType) {
|
||||
private static <T> void loadRegistry(ResourceLocation registryName, PersistentRegistry from, PersistentRegistry to, Class<T> regType)
|
||||
{
|
||||
FMLControlledNamespacedRegistry<T> fromRegistry = from.getRegistry(registryName, regType);
|
||||
FMLControlledNamespacedRegistry<T> toRegistry = to.getOrShallowCopyRegistry(registryName, regType, fromRegistry);
|
||||
toRegistry.set(fromRegistry);
|
||||
}
|
||||
|
||||
private static <T> void loadFrozenDataToStagingRegistry(Map<ResourceLocation, Map<ResourceLocation, Integer[]>> remaps, ResourceLocation registryName, Class<T> regType) {
|
||||
private static <T> void loadFrozenDataToStagingRegistry(Map<ResourceLocation, Map<ResourceLocation, Integer[]>> remaps, ResourceLocation registryName, Class<T> regType)
|
||||
{
|
||||
FMLControlledNamespacedRegistry<T> newRegistry = PersistentRegistry.STAGING.getRegistry(registryName, regType);
|
||||
FMLControlledNamespacedRegistry<T> frozenRegistry = PersistentRegistry.FROZEN.getRegistry(registryName, regType);
|
||||
newRegistry.loadIds(frozenRegistry.getEntriesNotIn(newRegistry), Maps.<ResourceLocation, Integer>newLinkedHashMap(), remaps.get(registryName), frozenRegistry, registryName);
|
||||
}
|
||||
|
||||
private static <T> void loadPersistentDataToStagingRegistry(boolean injectFrozenData, Map<ResourceLocation, Map<ResourceLocation, Integer[]>> remaps, LinkedHashMap<ResourceLocation, Map<ResourceLocation, Integer>> missing, Map.Entry<ResourceLocation, GameDataSnapshot.Entry> snapEntry, Class<T> regType) {
|
||||
private static <T> void loadPersistentDataToStagingRegistry(boolean injectFrozenData, Map<ResourceLocation, Map<ResourceLocation, Integer[]>> remaps, LinkedHashMap<ResourceLocation, Map<ResourceLocation, Integer>> missing, Map.Entry<ResourceLocation, GameDataSnapshot.Entry> snapEntry, Class<T> regType)
|
||||
{
|
||||
ResourceLocation registryName = snapEntry.getKey();
|
||||
FMLControlledNamespacedRegistry<T> 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<ResourceLocation, FMLControlledNamespacedRegistry<?>> r : PersistentRegistry.ACTIVE.registries.entrySet()) {
|
||||
for (Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>> 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<ResourceLocation, FMLControlledNamespacedRegistry<?>> r : PersistentRegistry.ACTIVE.registries.entrySet()) {
|
||||
for (Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>> 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<String> processIdRematches(Iterable<FMLMissingMappingsEvent.MissingMapping> missedMappings, boolean isLocalWorld, Map<ResourceLocation, Integer[]> remapBlocks, Map<ResourceLocation, Integer[]> remapItems) {
|
||||
public static List<String> processIdRematches(Iterable<FMLMissingMappingsEvent.MissingMapping> missedMappings, boolean isLocalWorld, Map<ResourceLocation, Integer[]> remapBlocks, Map<ResourceLocation, Integer[]> remapItems)
|
||||
{
|
||||
List<String> failed = Lists.newArrayList();
|
||||
List<String> ignored = Lists.newArrayList();
|
||||
List<String> 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<Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>>, Void>() {
|
||||
forAllRegistries(PersistentRegistry.ACTIVE, new Function<Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>>, Void>()
|
||||
{
|
||||
@Override
|
||||
public Void apply(Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>> input) {
|
||||
public Void apply(Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>> 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<ResourceLocation, Integer> ids;
|
||||
public final Set<ResourceLocation> substitutions;
|
||||
public final Map<ResourceLocation, ResourceLocation> aliases;
|
||||
public final Set<Integer> blocked;
|
||||
|
||||
public Entry() {
|
||||
public Entry()
|
||||
{
|
||||
this(new HashMap<ResourceLocation, Integer>(), new HashSet<ResourceLocation>(), new HashMap<ResourceLocation, ResourceLocation>(), new HashSet<Integer>());
|
||||
}
|
||||
|
||||
public Entry(Map<ResourceLocation, Integer> ids, Set<ResourceLocation> substitutions, Map<ResourceLocation, ResourceLocation> aliases, Set<Integer> blocked) {
|
||||
public Entry(Map<ResourceLocation, Integer> ids, Set<ResourceLocation> substitutions, Map<ResourceLocation, ResourceLocation> aliases, Set<Integer> 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<ResourceLocation, Entry> entries = Maps.newHashMap();
|
||||
}
|
||||
|
||||
public static <T> RegistryDelegate<T> makeDelegate(T obj, Class<T> rootClass) {
|
||||
public static <T> RegistryDelegate<T> makeDelegate(T obj, Class<T> rootClass)
|
||||
{
|
||||
return PersistentRegistry.ACTIVE.getRegistry(rootClass).getDelegate(obj, rootClass);
|
||||
}
|
||||
|
||||
|
||||
private static class DumpRegistryFunction implements Function<Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>>, Void> {
|
||||
private static class DumpRegistryFunction implements Function<Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>>, Void>
|
||||
{
|
||||
static final DumpRegistryFunction OPERATION = new DumpRegistryFunction();
|
||||
|
||||
@Override
|
||||
public Void apply(Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>> input) {
|
||||
public Void apply(Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>> input)
|
||||
{
|
||||
input.getValue().dump(input.getKey());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
private static class ValidateRegistryFunction implements Function<Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>>, Void> {
|
||||
|
||||
private static class ValidateRegistryFunction implements Function<Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>>, Void>
|
||||
{
|
||||
static final ValidateRegistryFunction OPERATION = new ValidateRegistryFunction();
|
||||
|
||||
@Override
|
||||
public Void apply(Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>> input) {
|
||||
public Void apply(Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>> input)
|
||||
{
|
||||
input.getValue().validateContent(input.getKey());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
private static class ResetDelegatesFunction implements Function<Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>>, Void> {
|
||||
|
||||
private static class ResetDelegatesFunction implements Function<Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>>, Void>
|
||||
{
|
||||
static final ResetDelegatesFunction OPERATION = new ResetDelegatesFunction();
|
||||
|
||||
@Override
|
||||
public Void apply(Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>> input) {
|
||||
public Void apply(Map.Entry<ResourceLocation, FMLControlledNamespacedRegistry<?>> input)
|
||||
{
|
||||
input.getValue().resetSubstitutionDelegates();
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -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<StructureComponent> 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<StructureComponent> 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<VillagerProfession> professions = PersistentRegistryManager.createRegistry(new ResourceLocation("minecraft:villagerprofessions"), VillagerProfession.class, null, 1024, 0, true);
|
||||
private FMLControlledNamespacedRegistry<VillagerProfession> 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))
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue