Improve reflection helper methods (#4853)

This commit is contained in:
Ben Staddon authored and mezz committed 2018-11-23 15:37:53 -08:00
1 parent 896db6398f
commit d16472d0ba
13 files changed
+219 -61

No files matched your search

@@ -67,7 +67,6 @@ import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.item.Item;
import net.minecraft.launchwrapper.Launch;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.registry.IRegistry;
@@ -84,6 +83,7 @@ import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.ProgressManager;
import net.minecraftforge.fml.common.ProgressManager.ProgressBar;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
import net.minecraftforge.fml.relauncher.FMLLaunchHandler;
import net.minecraftforge.registries.IRegistryDelegate;
import org.apache.commons.lang3.tuple.Pair;
@@ -128,7 +128,7 @@ public final class ModelLoader extends ModelBakery
return isLoading;
}
private final boolean enableVerboseMissingInfo = (Boolean)Launch.blackboard.get("fml.deobfuscatedEnvironment") || Boolean.parseBoolean(System.getProperty("forge.verboseMissingModelLogging", "false"));
private final boolean enableVerboseMissingInfo = FMLLaunchHandler.isDeobfuscatedEnvironment() || Boolean.parseBoolean(System.getProperty("forge.verboseMissingModelLogging", "false"));
private final int verboseMissingInfoCount = Integer.parseInt(System.getProperty("forge.verboseMissingModelLoggingCount", "5"));
public ModelLoader(IResourceManager manager, TextureMap map, BlockModelShapes shapes)
@@ -146,11 +146,11 @@ import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.LoaderState;
import net.minecraftforge.fml.common.ModContainer;
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
import net.minecraftforge.fml.common.eventhandler.Event;
import net.minecraftforge.fml.common.network.handshake.NetworkDispatcher;
import net.minecraftforge.fml.common.network.handshake.NetworkDispatcher.ConnectionType;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
import net.minecraftforge.fml.relauncher.ReflectionHelper;
import net.minecraftforge.registries.IForgeRegistry;
import net.minecraftforge.registries.RegistryManager;
@@ -270,19 +270,19 @@ public class ForgeHooks
}
toolInit = true;
Set<Block> blocks = ReflectionHelper.getPrivateValue(ItemPickaxe.class, null, 0);
Set<Block> blocks = ObfuscationReflectionHelper.getPrivateValue(ItemPickaxe.class, null, "field_150915"+"_c");
for (Block block : blocks)
{
block.setHarvestLevel("pickaxe", 0);
}
blocks = ReflectionHelper.getPrivateValue(ItemSpade.class, null, 0);
blocks = ObfuscationReflectionHelper.getPrivateValue(ItemSpade.class, null, "field_150916"+"_c");
for (Block block : blocks)
{
block.setHarvestLevel("shovel", 0);
}
blocks = ReflectionHelper.getPrivateValue(ItemAxe.class, null, 0);
blocks = ObfuscationReflectionHelper.getPrivateValue(ItemAxe.class, null, "field_150917"+"_c");
for (Block block : blocks)
{
block.setHarvestLevel("axe", 0);
@@ -330,7 +330,6 @@ public class ForgeHooks
return new ItemStack(Items.WHEAT_SEEDS, 1 + rand.nextInt(fortune * 2 + 1));
}
});
initTools();
}
/**
@@ -395,7 +395,7 @@ public class ForgeEventFactory
public static void firePlayerLoadingEvent(EntityPlayer player, IPlayerFileData playerFileData, String uuidString)
{
SaveHandler sh = (SaveHandler) playerFileData;
File dir = ObfuscationReflectionHelper.getPrivateValue(SaveHandler.class, sh, "playersDirectory", "field_"+"75771_c");
File dir = ObfuscationReflectionHelper.getPrivateValue(SaveHandler.class, sh, "field_"+"75771_c");
MinecraftForge.EVENT_BUS.post(new PlayerEvent.LoadFromFile(player, dir, uuidString));
}
@@ -961,7 +961,7 @@ public class FMLClientHandler implements IFMLSidedHandler
Logger logger = LogManager.getLogger("FML.TEXTURE_ERRORS");
logger.error(Strings.repeat("+=", 25));
logger.error("The following texture errors were found.");
Map<String,FallbackResourceManager> resManagers = ObfuscationReflectionHelper.getPrivateValue(SimpleReloadableResourceManager.class, (SimpleReloadableResourceManager)Minecraft.getMinecraft().getResourceManager(), "domainResourceManagers", "field_110548"+"_a");
Map<String,FallbackResourceManager> resManagers = ObfuscationReflectionHelper.getPrivateValue(SimpleReloadableResourceManager.class, (SimpleReloadableResourceManager)Minecraft.getMinecraft().getResourceManager(), "field_110548"+"_a");
for (String resourceDomain : badTextureDomains)
{
Set<ResourceLocation> missing = missingTextures.get(resourceDomain);
@@ -976,7 +976,7 @@ public class FMLClientHandler implements IFMLSidedHandler
}
else
{
List<IResourcePack> resPacks = ObfuscationReflectionHelper.getPrivateValue(FallbackResourceManager.class, fallbackResourceManager, "resourcePacks","field_110540"+"_a");
List<IResourcePack> resPacks = ObfuscationReflectionHelper.getPrivateValue(FallbackResourceManager.class, fallbackResourceManager, "field_110540"+"_a");
logger.error(" domain {} has {} location{}:",resourceDomain, resPacks.size(), resPacks.size() != 1 ? "s" :"");
for (IResourcePack resPack : resPacks)
{
@@ -988,7 +988,7 @@ public class FMLClientHandler implements IFMLSidedHandler
else if (resPack instanceof AbstractResourcePack)
{
AbstractResourcePack resourcePack = (AbstractResourcePack) resPack;
File resPath = ObfuscationReflectionHelper.getPrivateValue(AbstractResourcePack.class, resourcePack, "resourcePackFile","field_110597"+"_b");
File resPath = ObfuscationReflectionHelper.getPrivateValue(AbstractResourcePack.class, resourcePack, "field_110597"+"_b");
logger.error(" resource pack at path {}",resPath.getPath());
}
else
@@ -507,7 +507,7 @@ public class FMLCommonHandler
MinecraftServer server = getMinecraftServerInstance();
Loader.instance().serverStopped();
// FORCE the internal server to stop: hello optifine workaround!
if (server!=null) ObfuscationReflectionHelper.setPrivateValue(MinecraftServer.class, server, false, "field_71316"+"_v", "u", "serverStopped");
if (server!=null) ObfuscationReflectionHelper.setPrivateValue(MinecraftServer.class, server, false, "field_71316"+"_v");
// allow any pending exit to continue, clear exitLatch
CountDownLatch latch = exitLatch;
@@ -19,14 +19,18 @@
package net.minecraftforge.fml.common;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import net.minecraftforge.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper;
import net.minecraftforge.fml.relauncher.ReflectionHelper;
import net.minecraftforge.fml.relauncher.ReflectionHelper.UnableToAccessFieldException;
import net.minecraftforge.fml.relauncher.ReflectionHelper.UnableToFindFieldException;
import org.objectweb.asm.Type;
import org.apache.logging.log4j.Level;
import javax.annotation.Nullable;
/**
* Some reflection helper code.
@@ -36,6 +40,7 @@ import org.apache.logging.log4j.Level;
*/
public class ObfuscationReflectionHelper
{
@Deprecated // TODO: remove
public static <T, E> T getPrivateValue(Class<? super E> classToAccess, E instance, int fieldIndex)
{
try
@@ -49,6 +54,7 @@ public class ObfuscationReflectionHelper
}
}
@Deprecated // TODO: remove
public static String[] remapFieldNames(String className, String... fieldNames)
{
String internalClassName = FMLDeobfuscatingRemapper.INSTANCE.unmap(className.replace('.', '/'));
@@ -61,6 +67,22 @@ public class ObfuscationReflectionHelper
return mappedNames;
}
private static String remapFieldName(Class<?> clazz, String fieldName)
{
String internalClassName = FMLDeobfuscatingRemapper.INSTANCE.unmap(Type.getInternalName(clazz));
return FMLDeobfuscatingRemapper.INSTANCE.mapFieldName(internalClassName, fieldName, null);
}
private static String remapMethodName(Class<?> clazz, String methodName, Class<?> returnType, Class<?>... parameterTypes)
{
String internalClassName = FMLDeobfuscatingRemapper.INSTANCE.unmap(Type.getInternalName(clazz));
Type[] params = Arrays.stream(parameterTypes).map(Type::getType).toArray(Type[]::new);
String desc = Type.getMethodDescriptor(Type.getType(returnType), params);
return FMLDeobfuscatingRemapper.INSTANCE.mapMethodName(internalClassName, methodName, desc);
}
/** @deprecated use {@link #getPrivateValue(Class, Object, String)} */
@Deprecated // TODO: remove
public static <T, E> T getPrivateValue(Class<? super E> classToAccess, E instance, String... fieldNames)
{
try
@@ -79,6 +101,12 @@ public class ObfuscationReflectionHelper
}
}
public static <T, E> T getPrivateValue(Class<? super E> classToAccess, @Nullable E instance, String srgName)
{
return ReflectionHelper.getPrivateValue(classToAccess, instance, remapFieldName(classToAccess, srgName), null);
}
@Deprecated // TODO: remove
public static <T, E> void setPrivateValue(Class<? super T> classToAccess, T instance, E value, int fieldIndex)
{
try
@@ -92,6 +120,8 @@ public class ObfuscationReflectionHelper
}
}
/** @deprecated use {@link #setPrivateValue(Class, Object, Object, String)} */
@Deprecated // TODO: remove
public static <T, E> void setPrivateValue(Class<? super T> classToAccess, T instance, E value, String... fieldNames)
{
try
@@ -109,4 +139,58 @@ public class ObfuscationReflectionHelper
throw e;
}
}
public static <T, E> void setPrivateValue(Class<? super T> classToAccess, @Nullable T instance, @Nullable E value, String srgName)
{
ReflectionHelper.setPrivateValue(classToAccess, instance, value, remapFieldName(classToAccess, srgName), null);
}
/**
* Finds a field with the specified name in the given class and makes it accessible.
* Note: for performance, store the returned value and avoid calling this repeatedly.
* <p>
* Throws an exception if the field is not found.
*
* @param clazz The class to find the field on.
* @param srgName The obfuscated name of the field to find.
*
* @return The field with the specified name in the given class.
*/
public static Field findField(Class<?> clazz, String srgName)
{
return ReflectionHelper.findField(clazz, remapFieldName(clazz, srgName), null);
}
/**
* Finds a method with the specified name and parameters in the given class and makes it accessible.
* Note: for performance, store the returned value and avoid calling this repeatedly.
* <p>
* Throws an exception if the method is not found.
*
* @param clazz The class to find the method on.
* @param srgName The obfuscated name of the method to find.
* @param returnType The return type of the method to find.
* @param parameterTypes The parameter types of the method to find.
*
* @return The method with the specified name and type signature in the given class.
*/
public static Method findMethod(Class<?> clazz, String srgName, Class<?> returnType, Class<?>... parameterTypes)
{
String mappedName = remapMethodName(clazz, srgName, returnType, parameterTypes);
return ReflectionHelper.findMethod(clazz, mappedName, null, parameterTypes);
}
/**
* Finds a constructor in the specified class that has matching parameter types.
*
* @param klass The class to find the constructor in
* @param parameterTypes The parameter types of the constructor.
* @param <T> The type
*
* @return The constructor
*/
public static <T> Constructor<T> findConstructor(Class<T> klass, Class<?>... parameterTypes)
{
return ReflectionHelper.findConstructor(klass, parameterTypes);
}
}
@@ -33,9 +33,9 @@ import java.util.jar.JarOutputStream;
import java.util.jar.Pack200;
import java.util.regex.Pattern;
import net.minecraft.launchwrapper.Launch;
import net.minecraft.launchwrapper.LaunchClassLoader;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.relauncher.FMLLaunchHandler;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.repackage.com.nothome.delta.GDiffPatcher;
import LZMA.LzmaInputStream;
@@ -172,7 +172,7 @@ public class ClassPatchManager {
InputStream binpatchesCompressed = getClass().getResourceAsStream("/binpatches.pack.lzma");
if (binpatchesCompressed==null)
{
if (!((Boolean) Launch.blackboard.get("fml.deobfuscatedEnvironment")))
if (!FMLLaunchHandler.isDeobfuscatedEnvironment())
{
FMLLog.log.fatal("The binary patch set is missing, things are not going to work!");
}
@@ -31,7 +31,8 @@ import net.minecraft.world.biome.Biome;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.ModContainer;
import net.minecraftforge.fml.relauncher.ReflectionHelper;
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
import net.minecraftforge.fml.relauncher.ReflectionHelper.UnknownConstructorException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
@@ -250,7 +251,7 @@ public final class EntityEntryBuilder<E extends Entity>
* @throws IllegalStateException If the entity id has not been provided
* @throws IllegalStateException If the entity name has not been provided
* @throws IllegalStateException If spawns have been provided for a non {@link EntityLiving}
* @throws ReflectionHelper.UnknownConstructorException If a {@link #factory} has not been provided
* @throws UnknownConstructorException If a {@link #factory} has not been provided
* and {@link #entity} does not have a constructor accepting {@link World}
*/
@Nonnull
@@ -293,7 +294,7 @@ public final class EntityEntryBuilder<E extends Entity>
ConstructorFactory(final Class<? extends E> entity)
{
this.constructor = ReflectionHelper.findConstructor(entity, World.class);
this.constructor = ObfuscationReflectionHelper.findConstructor(entity, World.class);
}
@Override
@@ -76,13 +76,14 @@ public class CoreModManager {
private static List<String> ignoredModFiles = Lists.newArrayList();
private static Map<String, List<String>> transformers = Maps.newHashMap();
private static List<FMLPluginWrapper> loadPlugins;
private static boolean deobfuscatedEnvironment;
private static FMLTweaker tweaker;
private static File mcDir;
private static List<String> candidateModFiles = Lists.newArrayList();
private static List<String> accessTransformers = Lists.newArrayList();
private static Set<String> rootNames = Sets.newHashSet();
static boolean deobfuscatedEnvironment;
static
{
for(String cls : rootPlugins)
@@ -135,5 +135,8 @@ public class FMLLaunchHandler
INSTANCE.injectPostfixTransformers();
}
public static boolean isDeobfuscatedEnvironment()
{
return CoreModManager.deobfuscatedEnvironment;
}
}
@@ -19,8 +19,8 @@
package net.minecraftforge.fml.relauncher;
import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import net.minecraft.launchwrapper.Launch;
import org.apache.commons.lang3.StringUtils;
import javax.annotation.Nonnull;
@@ -29,65 +29,79 @@ import javax.annotation.Nullable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.StringJoiner;
/**
* Some reflection helper code.
*
* @author cpw
* This is in FML's coremod land.
* It's split in two because the two classes need to exist in separate classloaders.
* Modders shouldn't be using this class anyways.
*
* Use {@link net.minecraftforge.fml.common.ObfuscationReflectionHelper}
* when dealing with obfuscated fields or methods.
*
* @author cpw
* @deprecated not for external use
*/
@Deprecated // TODO: remove/relocate/replace
public class ReflectionHelper
{
public static class UnableToFindMethodException extends RuntimeException
{
private static final long serialVersionUID = 1L;
//private String[] methodNames;
@Deprecated // TODO: remove
public UnableToFindMethodException(String[] methodNames, Exception failed)
{
super(failed);
//this.methodNames = methodNames;
}
public UnableToFindMethodException(Throwable failed)
{
super(failed);
}
}
public static class UnableToFindClassException extends RuntimeException
{
private static final long serialVersionUID = 1L;
//private String[] classNames;
public UnableToFindClassException(String[] classNames, @Nullable Exception err)
{
super(err);
//this.classNames = classNames;
}
}
public static class UnableToAccessFieldException extends RuntimeException
{
private static final long serialVersionUID = 1L;
//private String[] fieldNameList;
@Deprecated // TODO: remove
public UnableToAccessFieldException(String[] fieldNames, Exception e)
{
super(e);
//this.fieldNameList = fieldNames;
}
public UnableToAccessFieldException(Exception e)
{
super(e);
}
}
public static class UnableToFindFieldException extends RuntimeException
{
private static final long serialVersionUID = 1L;
//private String[] fieldNameList;
@Deprecated // TODO: remove
public UnableToFindFieldException(String[] fieldNameList, Exception e)
{
super(e);
//this.fieldNameList = fieldNameList;
}
public UnableToFindFieldException(Exception e)
{
super(e);
}
}
@@ -99,6 +113,8 @@ public class ReflectionHelper
}
}
/** @deprecated use {@link #findField(Class, String, String)} */
@Deprecated // TODO: remove
public static Field findField(Class<?> clazz, String... fieldNames)
{
Exception failed = null;
@@ -118,7 +134,41 @@ public class ReflectionHelper
throw new UnableToFindFieldException(fieldNames, failed);
}
/**
* Finds a field with the specified name in the given class and makes it accessible.
* Note: for performance, store the returned value and avoid calling this repeatedly.
* <p>
* Throws an exception if the field is not found.
*
* @param clazz The class to find the field on.
* @param fieldName The name of the field to find (used in developer environments, i.e. "maxStackSize").
* @param fieldObfName The obfuscated name of the field to find (used in obfuscated environments, i.e. "field_77777_bU").
* If the name you are looking for is on a class that is never obfuscated, this should be null.
*
* @return The field with the specified name in the given class.
*/
@Nonnull
public static Field findField(@Nonnull Class<?> clazz, @Nonnull String fieldName, @Nullable String fieldObfName)
{
Preconditions.checkNotNull(clazz);
Preconditions.checkArgument(StringUtils.isNotEmpty(fieldName), "Field name cannot be empty");
String nameToFind = FMLLaunchHandler.isDeobfuscatedEnvironment() ? fieldName : MoreObjects.firstNonNull(fieldObfName, fieldName);
try
{
Field f = clazz.getDeclaredField(nameToFind);
f.setAccessible(true);
return f;
}
catch (Exception e)
{
throw new UnableToFindFieldException(e);
}
}
@SuppressWarnings("unchecked")
@Deprecated // TODO: remove
public static <T, E> T getPrivateValue(Class <? super E > classToAccess, @Nullable E instance, int fieldIndex)
{
try
@@ -129,11 +179,13 @@ public class ReflectionHelper
}
catch (Exception e)
{
throw new UnableToAccessFieldException(new String[0], e);
throw new UnableToAccessFieldException(e);
}
}
/** @deprecated use {@link #getPrivateValue(Class, Object, String, String )} */
@SuppressWarnings("unchecked")
@Deprecated // TODO: remove
public static <T, E> T getPrivateValue(Class <? super E > classToAccess, E instance, String... fieldNames)
{
try
@@ -146,6 +198,20 @@ public class ReflectionHelper
}
}
@SuppressWarnings("unchecked")
public static <T, E> T getPrivateValue(Class<? super E> classToAccess, @Nullable E instance, String fieldName, @Nullable String fieldObfName)
{
try
{
return (T) findField(classToAccess, fieldName, fieldObfName).get(instance);
}
catch (Exception e)
{
throw new UnableToAccessFieldException(e);
}
}
@Deprecated // TODO: remove
public static <T, E> void setPrivateValue(Class <? super T > classToAccess, T instance, E value, int fieldIndex)
{
try
@@ -156,10 +222,12 @@ public class ReflectionHelper
}
catch (Exception e)
{
throw new UnableToAccessFieldException(new String[0] , e);
throw new UnableToAccessFieldException(e);
}
}
/** @deprecated use {@link #setPrivateValue(Class, Object, Object, String, String)} */
@Deprecated // TODO: remove
public static <T, E> void setPrivateValue(Class <? super T > classToAccess, T instance, E value, String... fieldNames)
{
try
@@ -172,6 +240,18 @@ public class ReflectionHelper
}
}
public static <T, E> void setPrivateValue(Class<? super T> classToAccess, @Nullable T instance, @Nullable E value, String fieldName, @Nullable String fieldObfName)
{
try
{
findField(classToAccess, fieldName, fieldObfName).set(instance, value);
}
catch (Exception e)
{
throw new UnableToAccessFieldException(e);
}
}
@SuppressWarnings("unchecked")
public static Class<? super Object> getClass(ClassLoader loader, String... classNames)
{
@@ -210,15 +290,7 @@ public class ReflectionHelper
Preconditions.checkNotNull(clazz);
Preconditions.checkArgument(StringUtils.isNotEmpty(methodName), "Method name cannot be empty");
String nameToFind;
if (methodObfName == null || (Boolean) Launch.blackboard.get("fml.deobfuscatedEnvironment"))
{
nameToFind = methodName;
}
else
{
nameToFind = methodObfName;
}
String nameToFind = FMLLaunchHandler.isDeobfuscatedEnvironment() ? methodName : MoreObjects.firstNonNull(methodObfName, methodName);
try
{
@@ -249,27 +321,25 @@ public class ReflectionHelper
Preconditions.checkNotNull(klass, "class");
Preconditions.checkNotNull(parameterTypes, "parameter types");
final Constructor<T> constructor;
try
{
constructor = klass.getDeclaredConstructor(parameterTypes);
Constructor<T> constructor = klass.getDeclaredConstructor(parameterTypes);
constructor.setAccessible(true);
return constructor;
}
catch (final NoSuchMethodException e)
{
final StringBuilder desc = new StringBuilder();
desc.append(klass.getSimpleName()).append('(');
for (int i = 0, length = parameterTypes.length; i < length; i++)
desc.append(klass.getSimpleName());
StringJoiner joiner = new StringJoiner(", ", "(", ")");
for (Class<?> type : parameterTypes)
{
desc.append(parameterTypes[i].getName());
if (i > length)
{
desc.append(',').append(' ');
}
joiner.add(type.getSimpleName());
}
desc.append(')');
desc.append(joiner);
throw new UnknownConstructorException("Could not find constructor '" + desc.toString() + "' in " + klass);
}
return constructor;
}
}
@@ -26,7 +26,6 @@ import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import net.minecraft.launchwrapper.Launch;
import net.minecraft.network.INetHandler;
import net.minecraft.network.NetHandlerPlayServer;
import net.minecraft.network.NetworkManager;
@@ -45,6 +44,7 @@ import net.minecraftforge.fml.common.ModContainer;
import net.minecraftforge.fml.common.StartupQuery;
import net.minecraftforge.fml.common.eventhandler.EventBus;
import net.minecraftforge.fml.common.network.FMLNetworkEvent;
import net.minecraftforge.fml.relauncher.FMLLaunchHandler;
import net.minecraftforge.fml.relauncher.Side;
import com.google.common.collect.ImmutableList;
@@ -243,7 +243,7 @@ public class FMLServerHandler implements IFMLSidedHandler
ZipFile zip = null;
try
{
if (source.isDirectory() && (Boolean) Launch.blackboard.get("fml.deobfuscatedEnvironment"))
if (source.isDirectory() && FMLLaunchHandler.isDeobfuscatedEnvironment())
{
File f = new File(source.toURI().resolve(langFile).getPath());
if (!f.exists())
@@ -19,6 +19,7 @@
package net.minecraftforge.registries;
import java.lang.reflect.Method;
import java.util.BitSet;
import java.util.Collection;
import java.util.Collections;
@@ -26,20 +27,18 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.commons.lang3.Validate;
import java.util.Set;
import com.google.common.base.Preconditions;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
@@ -56,7 +55,6 @@ import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.InjectedModContainer;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.ModContainer;
import net.minecraftforge.fml.relauncher.ReflectionHelper;
public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRegistryInternal<V>, IForgeRegistryModifiable<V>
{
@@ -431,7 +429,9 @@ public class ForgeRegistry<V extends IForgeRegistryEntry<V>> implements IForgeRe
{
try
{
ReflectionHelper.findMethod(BitSet.class, "trimToSize", null).invoke(this.availabilityMap);
Method method = BitSet.class.getDeclaredMethod("trimToSize");
method.setAccessible(true);
method.invoke(this.availabilityMap);
}
catch (Exception e)
{