Another pass at substitutions - now capable of fixing up ItemBlock to point at the right block when a block is substituted, should also handle substituting itemblocks. There's some hackery in the way we have to change the value of ItemBlock.block, but it's not too egregious in my opinion.
This commit is contained in:
parent
53b43a6e1f
commit
4dcee246d5
12 changed files with 328 additions and 87 deletions
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.registry;
|
package net.minecraftforge.fml.common.registry;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -31,7 +30,6 @@ import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
import com.google.common.base.Throwables;
|
|
||||||
import com.google.common.collect.BiMap;
|
import com.google.common.collect.BiMap;
|
||||||
import com.google.common.collect.HashBiMap;
|
import com.google.common.collect.HashBiMap;
|
||||||
import com.google.common.collect.Iterators;
|
import com.google.common.collect.Iterators;
|
||||||
|
@ -90,7 +88,9 @@ public class FMLControlledNamespacedRegistry<I extends IForgeRegistryEntry<I>> e
|
||||||
|
|
||||||
private final CreateCallback<I> createCallback;
|
private final CreateCallback<I> createCallback;
|
||||||
|
|
||||||
FMLControlledNamespacedRegistry(ResourceLocation defaultKey, int minIdValue, int maxIdValue, Class<I> type, AddCallback<I> addCallback, ClearCallback<I> clearCallback, CreateCallback<I> createCallback)
|
private final SubstitutionCallback<I> substitutionCallback;
|
||||||
|
|
||||||
|
FMLControlledNamespacedRegistry(ResourceLocation defaultKey, int minIdValue, int maxIdValue, Class<I> type, BiMap<ResourceLocation, ? extends IForgeRegistry<?>> registries, AddCallback<I> addCallback, ClearCallback<I> clearCallback, CreateCallback<I> createCallback, SubstitutionCallback<I> substitutionCallback)
|
||||||
{
|
{
|
||||||
super(defaultKey);
|
super(defaultKey);
|
||||||
this.superType = type;
|
this.superType = type;
|
||||||
|
@ -102,9 +102,10 @@ public class FMLControlledNamespacedRegistry<I extends IForgeRegistryEntry<I>> e
|
||||||
this.addCallback = addCallback;
|
this.addCallback = addCallback;
|
||||||
this.clearCallback = clearCallback;
|
this.clearCallback = clearCallback;
|
||||||
this.createCallback = createCallback;
|
this.createCallback = createCallback;
|
||||||
|
this.substitutionCallback = substitutionCallback;
|
||||||
if (createCallback != null)
|
if (createCallback != null)
|
||||||
{
|
{
|
||||||
createCallback.onCreate(slaves);
|
createCallback.onCreate(slaves, registries);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +169,9 @@ public class FMLControlledNamespacedRegistry<I extends IForgeRegistryEntry<I>> e
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException("incompatible registry");
|
throw new IllegalArgumentException("incompatible registry");
|
||||||
}
|
}
|
||||||
|
final Map<ResourceLocation, Object> slaves = Maps.newHashMap(this.slaves);
|
||||||
|
slaves.put(PersistentRegistryManager.SUBSTITUTION_ORIGINALS, substitutionOriginals);
|
||||||
|
if (this.clearCallback!=null) this.clearCallback.onClear(this, slaves);
|
||||||
this.optionalDefaultKey = otherRegistry.optionalDefaultKey;
|
this.optionalDefaultKey = otherRegistry.optionalDefaultKey;
|
||||||
this.maxId = otherRegistry.maxId;
|
this.maxId = otherRegistry.maxId;
|
||||||
this.minId = otherRegistry.minId;
|
this.minId = otherRegistry.minId;
|
||||||
|
@ -187,7 +190,10 @@ public class FMLControlledNamespacedRegistry<I extends IForgeRegistryEntry<I>> e
|
||||||
{
|
{
|
||||||
addObjectRaw(otherRegistry.getId(thing), otherRegistry.getNameForObject(thing), thing);
|
addObjectRaw(otherRegistry.getId(thing), otherRegistry.getNameForObject(thing), thing);
|
||||||
}
|
}
|
||||||
this.activeSubstitutions.putAll(otherRegistry.activeSubstitutions);
|
for (ResourceLocation resloc : otherRegistry.activeSubstitutions.keySet())
|
||||||
|
{
|
||||||
|
activateSubstitution(resloc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// public api
|
// public api
|
||||||
|
@ -611,6 +617,7 @@ public class FMLControlledNamespacedRegistry<I extends IForgeRegistryEntry<I>> e
|
||||||
addObjectRaw(id, nameToReplace, sub);
|
addObjectRaw(id, nameToReplace, sub);
|
||||||
// Track the original in the substitution originals collection
|
// Track the original in the substitution originals collection
|
||||||
substitutionOriginals.put(nameToReplace, original);
|
substitutionOriginals.put(nameToReplace, original);
|
||||||
|
if (substitutionCallback!=null) substitutionCallback.onSubstituteActivated(slaves, original, sub, nameToReplace);
|
||||||
return original;
|
return original;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -668,9 +675,9 @@ public class FMLControlledNamespacedRegistry<I extends IForgeRegistryEntry<I>> e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FMLControlledNamespacedRegistry<I> makeShallowCopy()
|
FMLControlledNamespacedRegistry<I> makeShallowCopy(BiMap<ResourceLocation, ? extends IForgeRegistry<?>> registries)
|
||||||
{
|
{
|
||||||
return new FMLControlledNamespacedRegistry<I>(optionalDefaultKey, minId, maxId, superType, addCallback, clearCallback, createCallback);
|
return new FMLControlledNamespacedRegistry<I>(optionalDefaultKey, minId, maxId, superType, registries, addCallback, clearCallback, createCallback, substitutionCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void resetSubstitutionDelegates()
|
void resetSubstitutionDelegates()
|
||||||
|
@ -756,12 +763,17 @@ public class FMLControlledNamespacedRegistry<I extends IForgeRegistryEntry<I>> e
|
||||||
remappedIds.put(itemName, new Integer[] {currId, newId});
|
remappedIds.put(itemName, new Integer[] {currId, newId});
|
||||||
}
|
}
|
||||||
I obj = currentRegistry.getRaw(itemName);
|
I obj = currentRegistry.getRaw(itemName);
|
||||||
|
I sub = obj;
|
||||||
// If we have an object in the originals set, we use that for initial adding - substitute activation will readd the substitute if neceessary later
|
// If we have an object in the originals set, we use that for initial adding - substitute activation will readd the substitute if neceessary later
|
||||||
if (currentRegistry.substitutionOriginals.containsKey(itemName))
|
if (currentRegistry.substitutionOriginals.containsKey(itemName))
|
||||||
{
|
{
|
||||||
obj = currentRegistry.substitutionOriginals.get(itemName);
|
obj = currentRegistry.substitutionOriginals.get(itemName);
|
||||||
}
|
}
|
||||||
add(newId, itemName, obj);
|
add(newId, itemName, obj);
|
||||||
|
if (currentRegistry.substitutionOriginals.containsKey(itemName) && substitutionCallback != null)
|
||||||
|
{
|
||||||
|
substitutionCallback.onSubstituteActivated(slaves, sub, obj, itemName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Minecraft Forge
|
||||||
|
* Copyright (c) 2016.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation version 2.1
|
||||||
|
* of the License.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.minecraftforge.fml.common.registry;
|
||||||
|
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class for setting final fields.
|
||||||
|
*/
|
||||||
|
class FinalFieldHelper
|
||||||
|
{
|
||||||
|
private static Field modifiersField;
|
||||||
|
private static Object reflectionFactory;
|
||||||
|
private static Method newFieldAccessor;
|
||||||
|
private static Method fieldAccessorSet;
|
||||||
|
static Field makeWritable(Field f) throws Exception
|
||||||
|
{
|
||||||
|
if (modifiersField == null)
|
||||||
|
{
|
||||||
|
Method getReflectionFactory = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("getReflectionFactory");
|
||||||
|
reflectionFactory = getReflectionFactory.invoke(null);
|
||||||
|
newFieldAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newFieldAccessor", Field.class, boolean.class);
|
||||||
|
fieldAccessorSet = Class.forName("sun.reflect.FieldAccessor").getDeclaredMethod("set", Object.class, Object.class);
|
||||||
|
modifiersField = Field.class.getDeclaredField("modifiers");
|
||||||
|
modifiersField.setAccessible(true);
|
||||||
|
}
|
||||||
|
modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void setField(Field field, Object instance, Object thing) throws Exception
|
||||||
|
{
|
||||||
|
Object fieldAccessor = newFieldAccessor.invoke(reflectionFactory, field, false);
|
||||||
|
fieldAccessorSet.invoke(fieldAccessor, instance, thing);
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,8 +19,10 @@
|
||||||
|
|
||||||
package net.minecraftforge.fml.common.registry;
|
package net.minecraftforge.fml.common.registry;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
import com.google.common.collect.HashBiMap;
|
import com.google.common.collect.HashBiMap;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.state.IBlockState;
|
import net.minecraft.block.state.IBlockState;
|
||||||
|
@ -32,13 +34,13 @@ import net.minecraft.potion.PotionType;
|
||||||
import net.minecraft.util.ObjectIntIdentityMap;
|
import net.minecraft.util.ObjectIntIdentityMap;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.SoundEvent;
|
import net.minecraft.util.SoundEvent;
|
||||||
import net.minecraft.util.registry.RegistryNamespaced;
|
|
||||||
import net.minecraft.world.biome.Biome;
|
import net.minecraft.world.biome.Biome;
|
||||||
import net.minecraftforge.fml.common.FMLLog;
|
import net.minecraftforge.fml.common.FMLLog;
|
||||||
import net.minecraftforge.fml.common.Loader;
|
import net.minecraftforge.fml.common.Loader;
|
||||||
import net.minecraftforge.fml.common.ModContainer;
|
import net.minecraftforge.fml.common.ModContainer;
|
||||||
|
|
||||||
import com.google.common.collect.BiMap;
|
import com.google.common.collect.BiMap;
|
||||||
|
import net.minecraftforge.fml.relauncher.ReflectionHelper;
|
||||||
import org.apache.logging.log4j.Level;
|
import org.apache.logging.log4j.Level;
|
||||||
|
|
||||||
public class GameData
|
public class GameData
|
||||||
|
@ -63,16 +65,28 @@ public class GameData
|
||||||
|
|
||||||
private static final GameData mainData = new GameData();
|
private static final GameData mainData = new GameData();
|
||||||
|
|
||||||
|
private static Field blockField;
|
||||||
|
|
||||||
public GameData()
|
public GameData()
|
||||||
{
|
{
|
||||||
iBlockRegistry = PersistentRegistryManager.createRegistry(PersistentRegistryManager.BLOCKS, Block.class, new ResourceLocation("minecraft:air"), MIN_BLOCK_ID, MAX_BLOCK_ID, true, BlockCallbacks.INSTANCE, BlockCallbacks.INSTANCE, BlockCallbacks.INSTANCE);
|
iBlockRegistry = PersistentRegistryManager.createRegistry(PersistentRegistryManager.BLOCKS, Block.class, new ResourceLocation("minecraft:air"), MIN_BLOCK_ID, MAX_BLOCK_ID, true, BlockCallbacks.INSTANCE, BlockCallbacks.INSTANCE, BlockCallbacks.INSTANCE, BlockCallbacks.INSTANCE);
|
||||||
iItemRegistry = PersistentRegistryManager.createRegistry(PersistentRegistryManager.ITEMS, Item.class, null, MIN_ITEM_ID, MAX_ITEM_ID, true, ItemCallbacks.INSTANCE, ItemCallbacks.INSTANCE, ItemCallbacks.INSTANCE);
|
iItemRegistry = PersistentRegistryManager.createRegistry(PersistentRegistryManager.ITEMS, Item.class, null, MIN_ITEM_ID, MAX_ITEM_ID, true, ItemCallbacks.INSTANCE, ItemCallbacks.INSTANCE, ItemCallbacks.INSTANCE, ItemCallbacks.INSTANCE);
|
||||||
iPotionRegistry = PersistentRegistryManager.createRegistry(PersistentRegistryManager.POTIONS, Potion.class, null, MIN_POTION_ID, MAX_POTION_ID, false, PotionCallbacks.INSTANCE, PotionCallbacks.INSTANCE, PotionCallbacks.INSTANCE);
|
iPotionRegistry = PersistentRegistryManager.createRegistry(PersistentRegistryManager.POTIONS, Potion.class, null, MIN_POTION_ID, MAX_POTION_ID, false, PotionCallbacks.INSTANCE, PotionCallbacks.INSTANCE, PotionCallbacks.INSTANCE, null);
|
||||||
iBiomeRegistry = PersistentRegistryManager.createRegistry(PersistentRegistryManager.BIOMES, Biome.class, null, MIN_BIOME_ID, MAX_BIOME_ID, false, BiomeCallbacks.INSTANCE, BiomeCallbacks.INSTANCE, BiomeCallbacks.INSTANCE);
|
iBiomeRegistry = PersistentRegistryManager.createRegistry(PersistentRegistryManager.BIOMES, Biome.class, null, MIN_BIOME_ID, MAX_BIOME_ID, false, BiomeCallbacks.INSTANCE, BiomeCallbacks.INSTANCE, BiomeCallbacks.INSTANCE, null);
|
||||||
iSoundEventRegistry = PersistentRegistryManager.createRegistry(PersistentRegistryManager.SOUNDEVENTS, SoundEvent.class, null, MIN_SOUND_ID, MAX_SOUND_ID, false, null, null, null);
|
iSoundEventRegistry = PersistentRegistryManager.createRegistry(PersistentRegistryManager.SOUNDEVENTS, SoundEvent.class, null, MIN_SOUND_ID, MAX_SOUND_ID, false, null, null, null, null);
|
||||||
ResourceLocation WATER = new ResourceLocation("water");
|
ResourceLocation WATER = new ResourceLocation("water");
|
||||||
iPotionTypeRegistry = PersistentRegistryManager.createRegistry(PersistentRegistryManager.POTIONTYPES, PotionType.class, WATER, MIN_POTIONTYPE_ID, MAX_POTIONTYPE_ID, false, null, null, null);
|
iPotionTypeRegistry = PersistentRegistryManager.createRegistry(PersistentRegistryManager.POTIONTYPES, PotionType.class, WATER, MIN_POTIONTYPE_ID, MAX_POTIONTYPE_ID, false, null, null, null, null);
|
||||||
iEnchantmentRegistry = PersistentRegistryManager.createRegistry(PersistentRegistryManager.ENCHANTMENTS, Enchantment.class, null, MIN_ENCHANTMENT_ID, MAX_ENCHANTMENT_ID, false, null, null, null);
|
iEnchantmentRegistry = PersistentRegistryManager.createRegistry(PersistentRegistryManager.ENCHANTMENTS, Enchantment.class, null, MIN_ENCHANTMENT_ID, MAX_ENCHANTMENT_ID, false, null, null, null, null);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
blockField = FinalFieldHelper.makeWritable(ReflectionHelper.findField(ItemBlock.class, "block", "field_150939" + "_a"));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
FMLLog.log(Level.FATAL, e, "Cannot access the 'block' field from ItemBlock, this is fatal!");
|
||||||
|
throw Throwables.propagate(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// internal registry objects
|
// internal registry objects
|
||||||
private final FMLControlledNamespacedRegistry<Block> iBlockRegistry;
|
private final FMLControlledNamespacedRegistry<Block> iBlockRegistry;
|
||||||
|
@ -193,22 +207,12 @@ public class GameData
|
||||||
if (type == GameRegistry.Type.BLOCK)
|
if (type == GameRegistry.Type.BLOCK)
|
||||||
{
|
{
|
||||||
iBlockRegistry.addSubstitutionAlias(Loader.instance().activeModContainer().getModId(), nameToSubstitute, (Block)toReplace);
|
iBlockRegistry.addSubstitutionAlias(Loader.instance().activeModContainer().getModId(), nameToSubstitute, (Block)toReplace);
|
||||||
Block orig = iBlockRegistry.activateSubstitution(nameToSubstitute);
|
iBlockRegistry.activateSubstitution(nameToSubstitute);
|
||||||
if (blockItemMap.containsKey(orig))
|
|
||||||
{
|
|
||||||
Item i = blockItemMap.get(orig);
|
|
||||||
blockItemMap.forcePut((Block)toReplace,i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (type == GameRegistry.Type.ITEM)
|
else if (type == GameRegistry.Type.ITEM)
|
||||||
{
|
{
|
||||||
iItemRegistry.addSubstitutionAlias(Loader.instance().activeModContainer().getModId(), nameToSubstitute, (Item)toReplace);
|
iItemRegistry.addSubstitutionAlias(Loader.instance().activeModContainer().getModId(), nameToSubstitute, (Item)toReplace);
|
||||||
Item orig = iItemRegistry.activateSubstitution(nameToSubstitute);
|
iItemRegistry.activateSubstitution(nameToSubstitute);
|
||||||
if (blockItemMap.containsValue(orig))
|
|
||||||
{
|
|
||||||
Block b = blockItemMap.inverse().get(orig);
|
|
||||||
blockItemMap.forcePut(b, (Item)toReplace);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,7 +281,7 @@ public class GameData
|
||||||
return PersistentRegistryManager.makeDelegate(obj, rootClass);
|
return PersistentRegistryManager.makeDelegate(obj, rootClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class BlockCallbacks implements IForgeRegistry.AddCallback<Block>,IForgeRegistry.ClearCallback<Block>,IForgeRegistry.CreateCallback<Block>
|
private static class BlockCallbacks implements IForgeRegistry.AddCallback<Block>,IForgeRegistry.ClearCallback<Block>,IForgeRegistry.CreateCallback<Block>, IForgeRegistry.SubstitutionCallback<Block>
|
||||||
{
|
{
|
||||||
static final BlockCallbacks INSTANCE = new BlockCallbacks();
|
static final BlockCallbacks INSTANCE = new BlockCallbacks();
|
||||||
|
|
||||||
|
@ -297,23 +301,64 @@ public class GameData
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public void onClear(Map<ResourceLocation, ?> slaveset)
|
public void onClear(IForgeRegistry<Block> registry, Map<ResourceLocation, ?> slaveset)
|
||||||
{
|
{
|
||||||
ClearableObjectIntIdentityMap<IBlockState> blockstateMap = (ClearableObjectIntIdentityMap<IBlockState>)slaveset.get(BLOCKSTATE_TO_ID);
|
ClearableObjectIntIdentityMap<IBlockState> blockstateMap = (ClearableObjectIntIdentityMap<IBlockState>)slaveset.get(BLOCKSTATE_TO_ID);
|
||||||
blockstateMap.clear();
|
blockstateMap.clear();
|
||||||
|
final Map<ResourceLocation, Block> originals = (Map<ResourceLocation, Block>)slaveset.get(PersistentRegistryManager.SUBSTITUTION_ORIGINALS);
|
||||||
|
final BiMap<Block, Item> blockItemMap = (BiMap<Block, Item>)slaveset.get(BLOCK_TO_ITEM);
|
||||||
|
for (Item it : blockItemMap.values())
|
||||||
|
{
|
||||||
|
if (it instanceof ItemBlock) {
|
||||||
|
ItemBlock itemBlock = (ItemBlock)it;
|
||||||
|
final ResourceLocation registryKey = registry.getKey(itemBlock.block);
|
||||||
|
if (!originals.containsKey(registryKey)) continue;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FinalFieldHelper.setField(blockField, itemBlock, originals.get(registryKey));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw Throwables.propagate(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Map<ResourceLocation, ?> slaveset)
|
public void onCreate(Map<ResourceLocation, ?> slaveset, BiMap<ResourceLocation, ? extends IForgeRegistry<?>> registries)
|
||||||
{
|
{
|
||||||
final ClearableObjectIntIdentityMap<Block> idMap = new ClearableObjectIntIdentityMap<Block>();
|
final ClearableObjectIntIdentityMap<Block> idMap = new ClearableObjectIntIdentityMap<Block>();
|
||||||
((Map<ResourceLocation,Object>)slaveset).put(BLOCKSTATE_TO_ID, idMap);
|
((Map<ResourceLocation,Object>)slaveset).put(BLOCKSTATE_TO_ID, idMap);
|
||||||
|
final HashBiMap<Block, Item> map = HashBiMap.create();
|
||||||
|
((Map<ResourceLocation,Object>)slaveset).put(BLOCK_TO_ITEM, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSubstituteActivated(Map<ResourceLocation, ?> slaveset, Block original, Block replacement, ResourceLocation name)
|
||||||
|
{
|
||||||
|
final BiMap<Block, Item> blockItemMap = (BiMap<Block, Item>)slaveset.get(BLOCK_TO_ITEM);
|
||||||
|
if (blockItemMap.containsKey(original))
|
||||||
|
{
|
||||||
|
Item i = blockItemMap.get(original);
|
||||||
|
if (i instanceof ItemBlock)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FinalFieldHelper.setField(blockField, i, replacement);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw Throwables.propagate(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
blockItemMap.forcePut(replacement,i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ItemCallbacks implements IForgeRegistry.AddCallback<Item>,IForgeRegistry.ClearCallback<Item>,IForgeRegistry.CreateCallback<Item>
|
private static class ItemCallbacks implements IForgeRegistry.AddCallback<Item>,IForgeRegistry.ClearCallback<Item>,IForgeRegistry.CreateCallback<Item>, IForgeRegistry.SubstitutionCallback<Item>
|
||||||
{
|
{
|
||||||
static final ItemCallbacks INSTANCE = new ItemCallbacks();
|
static final ItemCallbacks INSTANCE = new ItemCallbacks();
|
||||||
|
|
||||||
|
@ -324,13 +369,14 @@ public class GameData
|
||||||
{
|
{
|
||||||
ItemBlock itemBlock = (ItemBlock)item;
|
ItemBlock itemBlock = (ItemBlock)item;
|
||||||
@SuppressWarnings("unchecked") BiMap<Block, Item> blockToItem = (BiMap<Block, Item>)slaves.get(BLOCK_TO_ITEM);
|
@SuppressWarnings("unchecked") BiMap<Block, Item> blockToItem = (BiMap<Block, Item>)slaves.get(BLOCK_TO_ITEM);
|
||||||
blockToItem.forcePut(itemBlock.getBlock().delegate.get(), item);
|
final Block block = itemBlock.getBlock().delegate.get();
|
||||||
|
blockToItem.forcePut(block, item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public void onClear(Map<ResourceLocation, ?> slaveset)
|
public void onClear(IForgeRegistry<Item> registry, Map<ResourceLocation, ?> slaveset)
|
||||||
{
|
{
|
||||||
Map<Block,Item> map = (Map<Block, Item>)slaveset.get(BLOCK_TO_ITEM);
|
Map<Block,Item> map = (Map<Block, Item>)slaveset.get(BLOCK_TO_ITEM);
|
||||||
map.clear();
|
map.clear();
|
||||||
|
@ -338,10 +384,17 @@ public class GameData
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Map<ResourceLocation, ?> slaveset)
|
public void onCreate(Map<ResourceLocation, ?> slaveset, BiMap<ResourceLocation, ? extends IForgeRegistry<?>> registries)
|
||||||
{
|
{
|
||||||
final HashBiMap<Block, Item> map = HashBiMap.create();
|
// We share the blockItem map between items and blocks registries
|
||||||
((Map<ResourceLocation,Object>)slaveset).put(BLOCK_TO_ITEM, map);
|
final BiMap blockItemMap = (BiMap<Block, Item>)registries.get(PersistentRegistryManager.BLOCKS).getSlaveMap(BLOCK_TO_ITEM, BiMap.class);
|
||||||
|
((Map<ResourceLocation,Object>)slaveset).put(BLOCK_TO_ITEM, blockItemMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSubstituteActivated(Map<ResourceLocation, ?> slaveset, Item original, Item replacement, ResourceLocation name)
|
||||||
|
{
|
||||||
|
final BiMap<Block, Item> blockItemMap = (BiMap<Block, Item>)slaveset.get(BLOCK_TO_ITEM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,13 +408,13 @@ public class GameData
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClear(Map<ResourceLocation, ?> slaveset)
|
public void onClear(IForgeRegistry<Potion> registry, Map<ResourceLocation, ?> slaveset)
|
||||||
{
|
{
|
||||||
// no op for the minute?
|
// no op for the minute?
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Map<ResourceLocation, ?> slaveset)
|
public void onCreate(Map<ResourceLocation, ?> slaveset, BiMap<ResourceLocation, ? extends IForgeRegistry<?>> registries)
|
||||||
{
|
{
|
||||||
// no op for the minute?
|
// no op for the minute?
|
||||||
}
|
}
|
||||||
|
@ -371,18 +424,18 @@ public class GameData
|
||||||
static final BiomeCallbacks INSTANCE = new BiomeCallbacks();
|
static final BiomeCallbacks INSTANCE = new BiomeCallbacks();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAdd(Biome potion, int id, Map<ResourceLocation, ?> slaves) {
|
public void onAdd(Biome biome, int id, Map<ResourceLocation, ?> slaves) {
|
||||||
// no op for the minute?
|
// no op for the minute?
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClear(Map<ResourceLocation, ?> slaveset)
|
public void onClear(IForgeRegistry<Biome> registry, Map<ResourceLocation, ?> slaveset)
|
||||||
{
|
{
|
||||||
// no op for the minute?
|
// no op for the minute?
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Map<ResourceLocation, ?> slaveset)
|
public void onCreate(Map<ResourceLocation, ?> slaveset, BiMap<ResourceLocation, ? extends IForgeRegistry<?>> registries)
|
||||||
{
|
{
|
||||||
// no op for the minute?
|
// no op for the minute?
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.google.common.collect.BiMap;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,7 +63,7 @@ public interface IForgeRegistry<V extends IForgeRegistryEntry<V>> extends Iterab
|
||||||
* Callback fired when objects are added to the registry. This will fire when the registry is rebuilt
|
* Callback fired when objects are added to the registry. This will fire when the registry is rebuilt
|
||||||
* on the client side from a server side synchronization, or when a world is loaded.
|
* on the client side from a server side synchronization, or when a world is loaded.
|
||||||
*/
|
*/
|
||||||
interface AddCallback<V>
|
interface AddCallback<V extends IForgeRegistryEntry<V>>
|
||||||
{
|
{
|
||||||
void onAdd(V obj, int id, Map<ResourceLocation, ?> slaveset);
|
void onAdd(V obj, int id, Map<ResourceLocation, ?> slaveset);
|
||||||
}
|
}
|
||||||
|
@ -71,16 +72,21 @@ public interface IForgeRegistry<V extends IForgeRegistryEntry<V>> extends Iterab
|
||||||
* Callback fired when the registry is cleared. This is done before a registry is reloaded from client
|
* Callback fired when the registry is cleared. This is done before a registry is reloaded from client
|
||||||
* or server.
|
* or server.
|
||||||
*/
|
*/
|
||||||
interface ClearCallback<V>
|
interface ClearCallback<V extends IForgeRegistryEntry<V>>
|
||||||
{
|
{
|
||||||
void onClear(Map<ResourceLocation, ?> slaveset);
|
void onClear(IForgeRegistry<V> is, Map<ResourceLocation, ?> slaveset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback fired when a registry instance is created. Populate slave maps here.
|
* Callback fired when a registry instance is created. Populate slave maps here.
|
||||||
*/
|
*/
|
||||||
interface CreateCallback<V>
|
interface CreateCallback<V extends IForgeRegistryEntry<V>>
|
||||||
{
|
{
|
||||||
void onCreate(Map<ResourceLocation, ?> slaveset);
|
void onCreate(Map<ResourceLocation, ?> slaveset, BiMap<ResourceLocation, ? extends IForgeRegistry<?>> registries);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SubstitutionCallback<V extends IForgeRegistryEntry<V>>
|
||||||
|
{
|
||||||
|
void onSubstituteActivated(Map<ResourceLocation, ?> slaveset, V original, V replacement, ResourceLocation name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,28 +87,11 @@ class ObjectHolderRef {
|
||||||
{
|
{
|
||||||
throw new IllegalStateException(String.format("The ObjectHolder annotation cannot apply to a field that is not an Item or Block (found : %s at %s.%s)", field.getType().getName(), field.getClass().getName(), field.getName()));
|
throw new IllegalStateException(String.format("The ObjectHolder annotation cannot apply to a field that is not an Item or Block (found : %s at %s.%s)", field.getType().getName(), field.getClass().getName(), field.getName()));
|
||||||
}
|
}
|
||||||
makeWritable(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Field modifiersField;
|
|
||||||
private static Object reflectionFactory;
|
|
||||||
private static Method newFieldAccessor;
|
|
||||||
private static Method fieldAccessorSet;
|
|
||||||
private static void makeWritable(Field f)
|
|
||||||
{
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (modifiersField == null)
|
FinalFieldHelper.makeWritable(field);
|
||||||
{
|
}
|
||||||
Method getReflectionFactory = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("getReflectionFactory");
|
catch (Exception e)
|
||||||
reflectionFactory = getReflectionFactory.invoke(null);
|
|
||||||
newFieldAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newFieldAccessor", Field.class, boolean.class);
|
|
||||||
fieldAccessorSet = Class.forName("sun.reflect.FieldAccessor").getDeclaredMethod("set", Object.class, Object.class);
|
|
||||||
modifiersField = Field.class.getDeclaredField("modifiers");
|
|
||||||
modifiersField.setAccessible(true);
|
|
||||||
}
|
|
||||||
modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL);
|
|
||||||
} catch (Exception e)
|
|
||||||
{
|
{
|
||||||
throw Throwables.propagate(e);
|
throw Throwables.propagate(e);
|
||||||
}
|
}
|
||||||
|
@ -145,8 +128,7 @@ class ObjectHolderRef {
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Object fieldAccessor = newFieldAccessor.invoke(reflectionFactory, field, false);
|
FinalFieldHelper.setField(field, null, thing);
|
||||||
fieldAccessorSet.invoke(fieldAccessor, null, thing);
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -84,13 +84,13 @@ public class PersistentRegistryManager
|
||||||
{
|
{
|
||||||
if (!registries.containsKey(key))
|
if (!registries.containsKey(key))
|
||||||
{
|
{
|
||||||
registries.put(key, other.makeShallowCopy());
|
registries.put(key, other.makeShallowCopy(registries));
|
||||||
registrySuperTypes.put(regType, key);
|
registrySuperTypes.put(regType, key);
|
||||||
}
|
}
|
||||||
return getRegistry(key, regType);
|
return getRegistry(key, regType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T extends IForgeRegistryEntry<T>> FMLControlledNamespacedRegistry<T> createRegistry(ResourceLocation registryName, Class<T> type, ResourceLocation defaultObjectKey, int minId, int maxId, IForgeRegistry.AddCallback<T> addCallback, IForgeRegistry.ClearCallback<T> clearCallback, IForgeRegistry.CreateCallback<T> createCallback)
|
private <T extends IForgeRegistryEntry<T>> FMLControlledNamespacedRegistry<T> createRegistry(ResourceLocation registryName, Class<T> type, ResourceLocation defaultObjectKey, int minId, int maxId, IForgeRegistry.AddCallback<T> addCallback, IForgeRegistry.ClearCallback<T> clearCallback, IForgeRegistry.CreateCallback<T> createCallback, IForgeRegistry.SubstitutionCallback<T> substitutionCallback)
|
||||||
{
|
{
|
||||||
Set<Class<?>> parents = Sets.newHashSet();
|
Set<Class<?>> parents = Sets.newHashSet();
|
||||||
findSuperTypes(type, parents);
|
findSuperTypes(type, parents);
|
||||||
|
@ -101,7 +101,7 @@ public class PersistentRegistryManager
|
||||||
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);
|
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");
|
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, minId, maxId, type, addCallback, clearCallback, createCallback);
|
FMLControlledNamespacedRegistry<T> fmlControlledNamespacedRegistry = new FMLControlledNamespacedRegistry<T>(defaultObjectKey, minId, maxId, type, registries, addCallback, clearCallback, createCallback, substitutionCallback);
|
||||||
registries.put(registryName, fmlControlledNamespacedRegistry);
|
registries.put(registryName, fmlControlledNamespacedRegistry);
|
||||||
registrySuperTypes.put(type, registryName);
|
registrySuperTypes.put(type, registryName);
|
||||||
return getRegistry(registryName, type);
|
return getRegistry(registryName, type);
|
||||||
|
@ -152,10 +152,11 @@ public class PersistentRegistryManager
|
||||||
public static final ResourceLocation SOUNDEVENTS = new ResourceLocation("minecraft:soundevents");
|
public static final ResourceLocation SOUNDEVENTS = new ResourceLocation("minecraft:soundevents");
|
||||||
public static final ResourceLocation POTIONTYPES = new ResourceLocation("minecraft:potiontypes");
|
public static final ResourceLocation POTIONTYPES = new ResourceLocation("minecraft:potiontypes");
|
||||||
public static final ResourceLocation ENCHANTMENTS = new ResourceLocation("minecraft:enchantments");
|
public static final ResourceLocation ENCHANTMENTS = new ResourceLocation("minecraft:enchantments");
|
||||||
|
static final ResourceLocation SUBSTITUTION_ORIGINALS = new ResourceLocation("fml:suboriginals");
|
||||||
|
|
||||||
public static <T extends IForgeRegistryEntry<T>> FMLControlledNamespacedRegistry<T> createRegistry(ResourceLocation registryName, Class<T> registryType, ResourceLocation optionalDefaultKey, int minId, int maxId, boolean hasDelegates, IForgeRegistry.AddCallback<T> addCallback, IForgeRegistry.ClearCallback<T> clearCallback, IForgeRegistry.CreateCallback<T> createCallback)
|
public static <T extends IForgeRegistryEntry<T>> FMLControlledNamespacedRegistry<T> createRegistry(ResourceLocation registryName, Class<T> registryType, ResourceLocation optionalDefaultKey, int minId, int maxId, boolean hasDelegates, IForgeRegistry.AddCallback<T> addCallback, IForgeRegistry.ClearCallback<T> clearCallback, IForgeRegistry.CreateCallback<T> createCallback, IForgeRegistry.SubstitutionCallback<T> substitutionCallback)
|
||||||
{
|
{
|
||||||
return PersistentRegistry.ACTIVE.createRegistry(registryName, registryType, optionalDefaultKey, minId, maxId, addCallback, clearCallback, createCallback);
|
return PersistentRegistry.ACTIVE.createRegistry(registryName, registryType, optionalDefaultKey, minId, maxId, addCallback, clearCallback, createCallback, substitutionCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
|
|
|
@ -132,7 +132,7 @@ public class VillagerRegistry
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasInit = false;
|
private boolean hasInit = false;
|
||||||
private FMLControlledNamespacedRegistry<VillagerProfession> professions = PersistentRegistryManager.createRegistry(PROFESSIONS, VillagerProfession.class, null, 0, 1024, true, null, null, null);
|
private FMLControlledNamespacedRegistry<VillagerProfession> professions = PersistentRegistryManager.createRegistry(PROFESSIONS, VillagerProfession.class, null, 0, 1024, true, null, null, null, null);
|
||||||
public IForgeRegistry<VillagerProfession> getRegistry() { return this.professions; }
|
public IForgeRegistry<VillagerProfession> getRegistry() { return this.professions; }
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -39,9 +39,9 @@ public class FreezingTests
|
||||||
{
|
{
|
||||||
Loader.instance();
|
Loader.instance();
|
||||||
System.setProperty("fml.queryResult", "confirm");
|
System.setProperty("fml.queryResult", "confirm");
|
||||||
registry = PersistentRegistryManager.createRegistry(resloc, RTest.class, null, 0, 255, false, null, null, null);
|
registry = PersistentRegistryManager.createRegistry(resloc, RTest.class, null, 0, 255, false, null, null, null, null);
|
||||||
PersistentRegistryManager.createRegistry(PersistentRegistryManager.BLOCKS, Block.class, null, 0, 255, false, null, null, null);
|
PersistentRegistryManager.createRegistry(PersistentRegistryManager.BLOCKS, Block.class, null, 0, 255, false, null, null, null, null);
|
||||||
PersistentRegistryManager.createRegistry(PersistentRegistryManager.ITEMS, Item.class, null, 0, 255, false, null, null, null);
|
PersistentRegistryManager.createRegistry(PersistentRegistryManager.ITEMS, Item.class, null, 0, 255, false, null, null, null, null);
|
||||||
r1 = new RTest("test1");
|
r1 = new RTest("test1");
|
||||||
r2 = new RTest("test2");
|
r2 = new RTest("test2");
|
||||||
r3 = new RTest("test3");
|
r3 = new RTest("test3");
|
||||||
|
@ -58,9 +58,9 @@ public class FreezingTests
|
||||||
ss.entries.put(resloc, new PersistentRegistryManager.GameDataSnapshot.Entry(PersistentRegistryManager.PersistentRegistry.ACTIVE.getRegistry(RTest.class)));
|
ss.entries.put(resloc, new PersistentRegistryManager.GameDataSnapshot.Entry(PersistentRegistryManager.PersistentRegistry.ACTIVE.getRegistry(RTest.class)));
|
||||||
PersistentRegistryManager.PersistentRegistry.ACTIVE.clean();
|
PersistentRegistryManager.PersistentRegistry.ACTIVE.clean();
|
||||||
PersistentRegistryManager.PersistentRegistry.FROZEN.clean();
|
PersistentRegistryManager.PersistentRegistry.FROZEN.clean();
|
||||||
registry = PersistentRegistryManager.createRegistry(resloc, RTest.class, null, 0, 255, false, null, null, null);
|
registry = PersistentRegistryManager.createRegistry(resloc, RTest.class, null, 0, 255, false, null, null, null, null);
|
||||||
PersistentRegistryManager.createRegistry(PersistentRegistryManager.BLOCKS, Block.class, null, 0, 255, false, null, null, null);
|
PersistentRegistryManager.createRegistry(PersistentRegistryManager.BLOCKS, Block.class, null, 0, 255, false, null, null, null, null);
|
||||||
PersistentRegistryManager.createRegistry(PersistentRegistryManager.ITEMS, Item.class, null, 0, 255, false, null, null, null);
|
PersistentRegistryManager.createRegistry(PersistentRegistryManager.ITEMS, Item.class, null, 0, 255, false, null, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
package net.minecraftforge.fml.common.registry;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.BlockDirt;
|
||||||
|
import net.minecraft.init.Blocks;
|
||||||
|
import net.minecraft.init.Bootstrap;
|
||||||
|
import net.minecraft.item.Item;
|
||||||
|
import net.minecraft.item.ItemBlock;
|
||||||
|
import net.minecraft.item.ItemMultiTexture;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraftforge.fml.common.DummyModContainer;
|
||||||
|
import net.minecraftforge.fml.common.Loader;
|
||||||
|
import net.minecraftforge.fml.common.ModMetadata;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Substitution test harness - tests that substitutions behave correctly
|
||||||
|
*/
|
||||||
|
@RunWith(ForgeTestRunner.class)
|
||||||
|
public class ItemBlockSubstitutionRemoveRestoreTest
|
||||||
|
{
|
||||||
|
private ResourceLocation myDirt = new ResourceLocation("minecraft:dirt");
|
||||||
|
private static class ItemMyDirt extends ItemMultiTexture
|
||||||
|
{
|
||||||
|
public ItemMyDirt() {
|
||||||
|
super(Blocks.DIRT, Blocks.DIRT, new Function<ItemStack, String>()
|
||||||
|
{
|
||||||
|
@Nullable
|
||||||
|
public String apply(@Nullable ItemStack p_apply_1_)
|
||||||
|
{
|
||||||
|
return BlockDirt.DirtType.byMetadata(p_apply_1_.getMetadata()).getUnlocalizedName();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static ItemMyDirt myDirtInstance;
|
||||||
|
private static Item originalDirt;
|
||||||
|
@BeforeClass
|
||||||
|
public static void setup()
|
||||||
|
{
|
||||||
|
Loader.instance();
|
||||||
|
Bootstrap.register();
|
||||||
|
myDirtInstance = new ItemMyDirt();
|
||||||
|
Loader.instance().setupTestHarness(new DummyModContainer(new ModMetadata() {{
|
||||||
|
modId = "test";
|
||||||
|
}}));
|
||||||
|
originalDirt = new ItemStack(Blocks.DIRT).getItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSubstitutionRemovalAndRestore() throws Exception
|
||||||
|
{
|
||||||
|
GameRegistry.addSubstitutionAlias("minecraft:dirt", GameRegistry.Type.ITEM, myDirtInstance);
|
||||||
|
PersistentRegistryManager.freezeData();
|
||||||
|
ObjectHolderRegistry.INSTANCE.applyObjectHolders();
|
||||||
|
|
||||||
|
final FMLControlledNamespacedRegistry<Item> itemRegistry = (FMLControlledNamespacedRegistry<Item>)PersistentRegistryManager.findRegistryByType(Item.class);
|
||||||
|
|
||||||
|
// TEST 1: Does my substitute take effect? The substitute should be found in the registry
|
||||||
|
ItemBlock dirtitem = (ItemBlock)itemRegistry.getValue(myDirt);
|
||||||
|
assertEquals("ItemBlock points at my block", myDirtInstance, dirtitem);
|
||||||
|
|
||||||
|
// TEST 2: Does the substitute get removed when told by remote operation? The substitute should NOT be found in the registry
|
||||||
|
final PersistentRegistryManager.GameDataSnapshot snapshot = PersistentRegistryManager.takeSnapshot();
|
||||||
|
snapshot.entries.get(PersistentRegistryManager.ITEMS).substitutions.clear();
|
||||||
|
PersistentRegistryManager.injectSnapshot(snapshot, false, false);
|
||||||
|
ObjectHolderRegistry.INSTANCE.applyObjectHolders();
|
||||||
|
|
||||||
|
dirtitem = (ItemBlock)itemRegistry.getValue(myDirt);
|
||||||
|
assertEquals("ItemBlock points at vanilla block", originalDirt, dirtitem);
|
||||||
|
assertNotEquals("ItemBlock points at my block", myDirtInstance, dirtitem);
|
||||||
|
|
||||||
|
// TEST 3: Does the substitute get restored when reverting to frozen state? The substitute should be found in the registry again
|
||||||
|
PersistentRegistryManager.revertToFrozen();
|
||||||
|
ObjectHolderRegistry.INSTANCE.applyObjectHolders();
|
||||||
|
dirtitem = (ItemBlock)itemRegistry.getValue(myDirt);
|
||||||
|
assertEquals("ItemBlock points at my block", myDirtInstance, dirtitem);
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ import org.junit.runners.Suite;
|
||||||
* Run the full suite of tests
|
* Run the full suite of tests
|
||||||
*/
|
*/
|
||||||
@RunWith(Suite.class)
|
@RunWith(Suite.class)
|
||||||
@Suite.SuiteClasses({VanillaRegistryTests.class, FreezingTests.class, SubstitutionRemoveRestoreTest.class, SubstitutionInjectionTest.class, DummyBlockReplacementTest.class})
|
@Suite.SuiteClasses({VanillaRegistryTests.class, FreezingTests.class, SubstitutionRemoveRestoreTest.class, SubstitutionInjectionTest.class, DummyBlockReplacementTest.class, BlockStateMappingsTest.class})
|
||||||
public class RegistryTestSuite
|
public class RegistryTestSuite
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@ import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockDirt;
|
import net.minecraft.block.BlockDirt;
|
||||||
import net.minecraft.init.Blocks;
|
import net.minecraft.init.Blocks;
|
||||||
import net.minecraft.init.Bootstrap;
|
import net.minecraft.init.Bootstrap;
|
||||||
|
import net.minecraft.item.Item;
|
||||||
|
import net.minecraft.item.ItemBlock;
|
||||||
import net.minecraft.stats.StatList;
|
import net.minecraft.stats.StatList;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraftforge.fml.common.DummyModContainer;
|
import net.minecraftforge.fml.common.DummyModContainer;
|
||||||
|
@ -15,6 +17,7 @@ import org.junit.runner.RunWith;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotEquals;
|
import static org.junit.Assert.assertNotEquals;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Substitution test harness - tests that substitutions behave correctly
|
* Substitution test harness - tests that substitutions behave correctly
|
||||||
|
@ -40,24 +43,44 @@ public class SubstitutionInjectionTest
|
||||||
@Test
|
@Test
|
||||||
public void testSubstitutionInjection() throws Exception
|
public void testSubstitutionInjection() throws Exception
|
||||||
{
|
{
|
||||||
|
final FMLControlledNamespacedRegistry<Block> blockRegistry = (FMLControlledNamespacedRegistry<Block>)PersistentRegistryManager.findRegistryByType(Block.class);
|
||||||
|
final FMLControlledNamespacedRegistry<Item> itemRegistry = (FMLControlledNamespacedRegistry<Item>)PersistentRegistryManager.findRegistryByType(Item.class);
|
||||||
|
|
||||||
// Capture snapshot prior to registering the substitution - this is a world state "pre-substitute"
|
// Capture snapshot prior to registering the substitution - this is a world state "pre-substitute"
|
||||||
final PersistentRegistryManager.GameDataSnapshot snapshot = PersistentRegistryManager.takeSnapshot();
|
final PersistentRegistryManager.GameDataSnapshot snapshot = PersistentRegistryManager.takeSnapshot();
|
||||||
|
|
||||||
|
Block fnd = blockRegistry.getValue(myDirt);
|
||||||
|
Block currDirt = Blocks.DIRT;
|
||||||
|
// TEST 0: Verify that input state is correct
|
||||||
|
assertEquals("Got vanilla dirt ", currDirt, fnd);
|
||||||
|
|
||||||
|
// TEST 0a: Validate that the ItemBlock for Dirt points at vanilla dirt
|
||||||
|
ItemBlock dirtitem = (ItemBlock)itemRegistry.getValue(myDirt);
|
||||||
|
assertEquals("ItemBlock points at my block", currDirt, dirtitem.block);
|
||||||
|
|
||||||
GameRegistry.addSubstitutionAlias("minecraft:dirt", GameRegistry.Type.BLOCK, toSub);
|
GameRegistry.addSubstitutionAlias("minecraft:dirt", GameRegistry.Type.BLOCK, toSub);
|
||||||
PersistentRegistryManager.freezeData();
|
PersistentRegistryManager.freezeData();
|
||||||
ObjectHolderRegistry.INSTANCE.applyObjectHolders();
|
ObjectHolderRegistry.INSTANCE.applyObjectHolders();
|
||||||
// This should not throw an exception
|
// This should not throw an exception
|
||||||
StatList.reinit();
|
try
|
||||||
|
{
|
||||||
final FMLControlledNamespacedRegistry<Block> blockRegistry = (FMLControlledNamespacedRegistry<Block>)PersistentRegistryManager.findRegistryByType(Block.class);
|
StatList.reinit();
|
||||||
|
} catch (Exception e)
|
||||||
|
{
|
||||||
|
fail("Caught exception");
|
||||||
|
}
|
||||||
|
|
||||||
// TEST 1: Does my substitute take effect? The substitute should be found in the registry
|
// TEST 1: Does my substitute take effect? The substitute should be found in the registry
|
||||||
Block fnd = blockRegistry.getValue(myDirt);
|
fnd = blockRegistry.getValue(myDirt);
|
||||||
Block currDirt = Blocks.DIRT;
|
currDirt = Blocks.DIRT;
|
||||||
assertEquals("Got my dirt substitute - Blocks", toSub, currDirt);
|
assertEquals("Got my dirt substitute - Blocks", toSub, currDirt);
|
||||||
assertEquals("Got my dirt substitute - Blocks and registry", currDirt, fnd);
|
assertEquals("Got my dirt substitute - Blocks and registry", currDirt, fnd);
|
||||||
assertEquals("Got my dirt substitute - registry", toSub, fnd);
|
assertEquals("Got my dirt substitute - registry", toSub, fnd);
|
||||||
|
|
||||||
|
// TEST 1a: Validate that the ItemBlock for Dirt now points at my dirt
|
||||||
|
dirtitem = (ItemBlock)itemRegistry.getValue(myDirt);
|
||||||
|
assertEquals("ItemBlock points at my block", toSub, dirtitem.block);
|
||||||
|
|
||||||
// TEST 2: Does the substitute get injected when told by loading operation? The substitute should be found in the registry
|
// TEST 2: Does the substitute get injected when told by loading operation? The substitute should be found in the registry
|
||||||
PersistentRegistryManager.injectSnapshot(snapshot, true, true);
|
PersistentRegistryManager.injectSnapshot(snapshot, true, true);
|
||||||
ObjectHolderRegistry.INSTANCE.applyObjectHolders();
|
ObjectHolderRegistry.INSTANCE.applyObjectHolders();
|
||||||
|
@ -67,6 +90,9 @@ public class SubstitutionInjectionTest
|
||||||
assertEquals("Got my dirt substitute - Blocks and registry", currDirt, fnd);
|
assertEquals("Got my dirt substitute - Blocks and registry", currDirt, fnd);
|
||||||
assertEquals("Got my dirt substitute - registry", toSub, fnd);
|
assertEquals("Got my dirt substitute - registry", toSub, fnd);
|
||||||
|
|
||||||
|
dirtitem = (ItemBlock)itemRegistry.getValue(myDirt);
|
||||||
|
assertEquals("ItemBlock points at my block", toSub, dirtitem.block);
|
||||||
|
|
||||||
// TEST 3: Does the substitute get restored when reverting to frozen state? The substitute should be found in the registry again
|
// TEST 3: Does the substitute get restored when reverting to frozen state? The substitute should be found in the registry again
|
||||||
PersistentRegistryManager.revertToFrozen();
|
PersistentRegistryManager.revertToFrozen();
|
||||||
ObjectHolderRegistry.INSTANCE.applyObjectHolders();
|
ObjectHolderRegistry.INSTANCE.applyObjectHolders();
|
||||||
|
@ -75,5 +101,7 @@ public class SubstitutionInjectionTest
|
||||||
assertEquals("Got my dirt substitute - Blocks", toSub, currDirt);
|
assertEquals("Got my dirt substitute - Blocks", toSub, currDirt);
|
||||||
assertEquals("Got my dirt substitute - Blocks and registry", currDirt, fnd);
|
assertEquals("Got my dirt substitute - Blocks and registry", currDirt, fnd);
|
||||||
assertEquals("Got my dirt substitute - registry", toSub, fnd);
|
assertEquals("Got my dirt substitute - registry", toSub, fnd);
|
||||||
|
dirtitem = (ItemBlock)itemRegistry.getValue(myDirt);
|
||||||
|
assertEquals("ItemBlock points at my block", toSub, dirtitem.block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@ import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockDirt;
|
import net.minecraft.block.BlockDirt;
|
||||||
import net.minecraft.init.Blocks;
|
import net.minecraft.init.Blocks;
|
||||||
import net.minecraft.init.Bootstrap;
|
import net.minecraft.init.Bootstrap;
|
||||||
|
import net.minecraft.item.Item;
|
||||||
|
import net.minecraft.item.ItemBlock;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraftforge.fml.common.DummyModContainer;
|
import net.minecraftforge.fml.common.DummyModContainer;
|
||||||
import net.minecraftforge.fml.common.Loader;
|
import net.minecraftforge.fml.common.Loader;
|
||||||
|
@ -44,6 +46,7 @@ public class SubstitutionRemoveRestoreTest
|
||||||
ObjectHolderRegistry.INSTANCE.applyObjectHolders();
|
ObjectHolderRegistry.INSTANCE.applyObjectHolders();
|
||||||
|
|
||||||
final FMLControlledNamespacedRegistry<Block> blockRegistry = (FMLControlledNamespacedRegistry<Block>)PersistentRegistryManager.findRegistryByType(Block.class);
|
final FMLControlledNamespacedRegistry<Block> blockRegistry = (FMLControlledNamespacedRegistry<Block>)PersistentRegistryManager.findRegistryByType(Block.class);
|
||||||
|
final FMLControlledNamespacedRegistry<Item> itemRegistry = (FMLControlledNamespacedRegistry<Item>)PersistentRegistryManager.findRegistryByType(Item.class);
|
||||||
|
|
||||||
// TEST 1: Does my substitute take effect? The substitute should be found in the registry
|
// TEST 1: Does my substitute take effect? The substitute should be found in the registry
|
||||||
Block fnd = blockRegistry.getValue(myDirt);
|
Block fnd = blockRegistry.getValue(myDirt);
|
||||||
|
@ -52,6 +55,9 @@ public class SubstitutionRemoveRestoreTest
|
||||||
assertEquals("Got my dirt substitute - Blocks and registry", currDirt, fnd);
|
assertEquals("Got my dirt substitute - Blocks and registry", currDirt, fnd);
|
||||||
assertEquals("Got my dirt substitute - registry", toSub, fnd);
|
assertEquals("Got my dirt substitute - registry", toSub, fnd);
|
||||||
|
|
||||||
|
ItemBlock dirtitem = (ItemBlock)itemRegistry.getValue(myDirt);
|
||||||
|
assertEquals("ItemBlock points at my block", toSub, dirtitem.block);
|
||||||
|
|
||||||
// TEST 2: Does the substitute get removed when told by remote operation? The substitute should NOT be found in the registry
|
// TEST 2: Does the substitute get removed when told by remote operation? The substitute should NOT be found in the registry
|
||||||
final PersistentRegistryManager.GameDataSnapshot snapshot = PersistentRegistryManager.takeSnapshot();
|
final PersistentRegistryManager.GameDataSnapshot snapshot = PersistentRegistryManager.takeSnapshot();
|
||||||
snapshot.entries.get(PersistentRegistryManager.BLOCKS).substitutions.clear();
|
snapshot.entries.get(PersistentRegistryManager.BLOCKS).substitutions.clear();
|
||||||
|
@ -63,6 +69,10 @@ public class SubstitutionRemoveRestoreTest
|
||||||
assertEquals("Got my dirt substitute - Blocks and registry", currDirt, fnd);
|
assertEquals("Got my dirt substitute - Blocks and registry", currDirt, fnd);
|
||||||
assertNotEquals("Got my dirt substitute - registry", toSub, fnd);
|
assertNotEquals("Got my dirt substitute - registry", toSub, fnd);
|
||||||
|
|
||||||
|
dirtitem = (ItemBlock)itemRegistry.getValue(myDirt);
|
||||||
|
assertEquals("ItemBlock points at vanilla block", currDirt, dirtitem.block);
|
||||||
|
assertNotEquals("ItemBlock points at my block", toSub, dirtitem.block);
|
||||||
|
|
||||||
// TEST 3: Does the substitute get restored when reverting to frozen state? The substitute should be found in the registry again
|
// TEST 3: Does the substitute get restored when reverting to frozen state? The substitute should be found in the registry again
|
||||||
PersistentRegistryManager.revertToFrozen();
|
PersistentRegistryManager.revertToFrozen();
|
||||||
ObjectHolderRegistry.INSTANCE.applyObjectHolders();
|
ObjectHolderRegistry.INSTANCE.applyObjectHolders();
|
||||||
|
@ -71,5 +81,8 @@ public class SubstitutionRemoveRestoreTest
|
||||||
assertEquals("Got my dirt substitute - Blocks", toSub, currDirt);
|
assertEquals("Got my dirt substitute - Blocks", toSub, currDirt);
|
||||||
assertEquals("Got my dirt substitute - Blocks and registry", currDirt, fnd);
|
assertEquals("Got my dirt substitute - Blocks and registry", currDirt, fnd);
|
||||||
assertEquals("Got my dirt substitute - registry", toSub, fnd);
|
assertEquals("Got my dirt substitute - registry", toSub, fnd);
|
||||||
|
|
||||||
|
dirtitem = (ItemBlock)itemRegistry.getValue(myDirt);
|
||||||
|
assertEquals("ItemBlock points at my block", toSub, dirtitem.block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue