Untitled diff

Created Diff never expires
3 removals
Words removed3
Total words1214
Words removed (%)0.25
375 lines
5 additions
Words added11
Total words1222
Words added (%)0.90
377 lines
/*
/*
* Minecraft Forge
* Minecraft Forge
* Copyright (c) 2016.
* Copyright (c) 2016.
*
*
* This library is free software; you can redistribute it and/or
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* License as published by the Free Software Foundation version 2.1
* of the License.
* of the License.
*
*
* This library is distributed in the hope that it will be useful,
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* Lesser General Public License for more details.
*
*
* You should have received a copy of the GNU Lesser General Public
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
*/


package net.minecraftforge.common.util;
package net.minecraftforge.common.util;


import java.lang.reflect.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.*;


import com.google.common.base.Predicate;
import com.google.common.collect.Lists;
import com.google.common.collect.Lists;


import net.minecraftforge.fml.common.EnhancedRuntimeException;
import net.minecraftforge.fml.common.EnhancedRuntimeException;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraft.block.BlockPressurePlate.Sensitivity;
import net.minecraft.block.BlockPressurePlate.Sensitivity;
import net.minecraft.block.material.Material;
import net.minecraft.block.material.Material;
import net.minecraft.enchantment.EnumEnchantmentType;
import net.minecraft.enchantment.EnumEnchantmentType;
import net.minecraft.entity.EnumCreatureAttribute;
import net.minecraft.entity.EnumCreatureAttribute;
import net.minecraft.entity.EnumCreatureType;
import net.minecraft.entity.EnumCreatureType;
import net.minecraft.entity.item.EntityPainting.EnumArt;
import net.minecraft.entity.item.EntityPainting.EnumArt;
import net.minecraft.entity.player.EntityPlayer.SleepResult;
import net.minecraft.entity.player.EntityPlayer.SleepResult;
import net.minecraft.item.EnumAction;
import net.minecraft.item.EnumAction;
import net.minecraft.item.EnumRarity;
import net.minecraft.item.EnumRarity;
import net.minecraft.item.Item;
import net.minecraft.item.Item.ToolMaterial;
import net.minecraft.item.Item.ToolMaterial;
import net.minecraft.item.ItemArmor.ArmorMaterial;
import net.minecraft.item.ItemArmor.ArmorMaterial;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.EnumSkyBlock;
import net.minecraft.world.EnumSkyBlock;
import net.minecraft.world.gen.structure.StructureStrongholdPieces.Stronghold.Door;
import net.minecraft.world.gen.structure.StructureStrongholdPieces.Stronghold.Door;
import net.minecraftforge.classloading.FMLForgePlugin;
import net.minecraftforge.classloading.FMLForgePlugin;


public class EnumHelper
public class EnumHelper
{
{
private static Object reflectionFactory = null;
private static Object reflectionFactory = null;
private static Method newConstructorAccessor = null;
private static Method newConstructorAccessor = null;
private static Method newInstance = null;
private static Method newInstance = null;
private static Method newFieldAccessor = null;
private static Method newFieldAccessor = null;
private static Method fieldAccessorSet = null;
private static Method fieldAccessorSet = null;
private static boolean isSetup = false;
private static boolean isSetup = false;


//Some enums are decompiled with extra arguments, so lets check for that
//Some enums are decompiled with extra arguments, so lets check for that
private static Class<?>[][] commonTypes =
private static Class<?>[][] commonTypes =
{
{
{EnumAction.class},
{EnumAction.class},
{ArmorMaterial.class, String.class, int.class, int[].class, int.class, SoundEvent.class, float.class},
{ArmorMaterial.class, String.class, int.class, int[].class, int.class, SoundEvent.class, float.class},
{EnumArt.class, String.class, int.class, int.class, int.class, int.class},
{EnumArt.class, String.class, int.class, int.class, int.class, int.class},
{EnumCreatureAttribute.class},
{EnumCreatureAttribute.class},
{EnumCreatureType.class, Class.class, int.class, Material.class, boolean.class, boolean.class},
{EnumCreatureType.class, Class.class, int.class, Material.class, boolean.class, boolean.class},
{Door.class},
{Door.class},
{EnumEnchantmentType.class},
{EnumEnchantmentType.class, Predicate.class},
{Sensitivity.class},
{Sensitivity.class},
{RayTraceResult.Type.class},
{RayTraceResult.Type.class},
{EnumSkyBlock.class, int.class},
{EnumSkyBlock.class, int.class},
{SleepResult.class},
{SleepResult.class},
{ToolMaterial.class, int.class, int.class, float.class, float.class, int.class},
{ToolMaterial.class, int.class, int.class, float.class, float.class, int.class},
{EnumRarity.class, TextFormatting.class, String.class}
{EnumRarity.class, TextFormatting.class, String.class}
};
};


public static EnumAction addAction(String name)
public static EnumAction addAction(String name)
{
{
return addEnum(EnumAction.class, name);
return addEnum(EnumAction.class, name);
}
}
public static ArmorMaterial addArmorMaterial(String name, String textureName, int durability, int[] reductionAmounts, int enchantability, SoundEvent soundOnEquip, float toughness)
public static ArmorMaterial addArmorMaterial(String name, String textureName, int durability, int[] reductionAmounts, int enchantability, SoundEvent soundOnEquip, float toughness)
{
{
return addEnum(ArmorMaterial.class, name, textureName, durability, reductionAmounts, enchantability, soundOnEquip, toughness);
return addEnum(ArmorMaterial.class, name, textureName, durability, reductionAmounts, enchantability, soundOnEquip, toughness);
}
}
public static EnumArt addArt(String name, String tile, int sizeX, int sizeY, int offsetX, int offsetY)
public static EnumArt addArt(String name, String tile, int sizeX, int sizeY, int offsetX, int offsetY)
{
{
return addEnum(EnumArt.class, name, tile, sizeX, sizeY, offsetX, offsetY);
return addEnum(EnumArt.class, name, tile, sizeX, sizeY, offsetX, offsetY);
}
}
public static EnumCreatureAttribute addCreatureAttribute(String name)
public static EnumCreatureAttribute addCreatureAttribute(String name)
{
{
return addEnum(EnumCreatureAttribute.class, name);
return addEnum(EnumCreatureAttribute.class, name);
}
}
public static EnumCreatureType addCreatureType(String name, Class<?> typeClass, int maxNumber, Material material, boolean peaceful, boolean animal)
public static EnumCreatureType addCreatureType(String name, Class<?> typeClass, int maxNumber, Material material, boolean peaceful, boolean animal)
{
{
return addEnum(EnumCreatureType.class, name, typeClass, maxNumber, material, peaceful, animal);
return addEnum(EnumCreatureType.class, name, typeClass, maxNumber, material, peaceful, animal);
}
}
public static Door addDoor(String name)
public static Door addDoor(String name)
{
{
return addEnum(Door.class, name);
return addEnum(Door.class, name);
}
}
public static EnumEnchantmentType addEnchantmentType(String name)
public static EnumEnchantmentType addEnchantmentType(String name, Predicate<Item> delegate)
{
{
return addEnum(EnumEnchantmentType.class, name);
return addEnum(EnumEnchantmentType.class, name, delegate);
}
}
public static Sensitivity addSensitivity(String name)
public static Sensitivity addSensitivity(String name)
{
{
return addEnum(Sensitivity.class, name);
return addEnum(Sensitivity.class, name);
}
}
public static RayTraceResult.Type addMovingObjectType(String name)
public static RayTraceResult.Type addMovingObjectType(String name)
{
{
return addEnum(RayTraceResult.Type.class, name);
return addEnum(RayTraceResult.Type.class, name);
}
}
public static EnumSkyBlock addSkyBlock(String name, int lightValue)
public static EnumSkyBlock addSkyBlock(String name, int lightValue)
{
{
return addEnum(EnumSkyBlock.class, name, lightValue);
return addEnum(EnumSkyBlock.class, name, lightValue);
}
}
public static SleepResult addStatus(String name)
public static SleepResult addStatus(String name)
{
{
return addEnum(SleepResult.class, name);
return addEnum(SleepResult.class, name);
}
}
public static ToolMaterial addToolMaterial(String name, int harvestLevel, int maxUses, float efficiency, float damage, int enchantability)
public static ToolMaterial addToolMaterial(String name, int harvestLevel, int maxUses, float efficiency, float damage, int enchantability)
{
{
return addEnum(ToolMaterial.class, name, harvestLevel, maxUses, efficiency, damage, enchantability);
return addEnum(ToolMaterial.class, name, harvestLevel, maxUses, efficiency, damage, enchantability);
}
}
public static EnumRarity addRarity(String name, TextFormatting color, String displayName)
public static EnumRarity addRarity(String name, TextFormatting color, String displayName)
{
{
return addEnum(EnumRarity.class, name, color, displayName);
return addEnum(EnumRarity.class, name, color, displayName);
}
}


private static void setup()
private static void setup()
{
{
if (isSetup)
if (isSetup)
{
{
return;
return;
}
}


try
try
{
{
Method getReflectionFactory = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("getReflectionFactory");
Method getReflectionFactory = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("getReflectionFactory");
reflectionFactory = getReflectionFactory.invoke(null);
reflectionFactory = getReflectionFactory.invoke(null);
newConstructorAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newConstructorAccessor", Constructor.class);
newConstructorAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newConstructorAccessor", Constructor.class);
newInstance = Class.forName("sun.reflect.ConstructorAccessor").getDeclaredMethod("newInstance", Object[].class);
newInstance = Class.forName("sun.reflect.ConstructorAccessor").getDeclaredMethod("newInstance", Object[].class);
newFieldAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newFieldAccessor", Field.class, boolean.class);
newFieldAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newFieldAccessor", Field.class, boolean.class);
fieldAccessorSet = Class.forName("sun.reflect.FieldAccessor").getDeclaredMethod("set", Object.class, Object.class);
fieldAccessorSet = Class.forName("sun.reflect.FieldAccessor").getDeclaredMethod("set", Object.class, Object.class);
}
}
catch (Exception e)
catch (Exception e)
{
{
e.printStackTrace();
e.printStackTrace();
}
}


isSetup = true;
isSetup = true;
}
}


/*
/*
* Everything below this is found at the site below, and updated to be able to compile in Eclipse/Java 1.6+
* Everything below this is found at the site below, and updated to be able to compile in Eclipse/Java 1.6+
* Also modified for use in decompiled code.
* Also modified for use in decompiled code.
* Found at: http://niceideas.ch/roller2/badtrash/entry/java_create_enum_instances_dynamically
* Found at: http://niceideas.ch/roller2/badtrash/entry/java_create_enum_instances_dynamically
*/
*/
private static Object getConstructorAccessor(Class<?> enumClass, Class<?>[] additionalParameterTypes) throws Exception
private static Object getConstructorAccessor(Class<?> enumClass, Class<?>[] additionalParameterTypes) throws Exception
{
{
Class<?>[] parameterTypes = new Class[additionalParameterTypes.length + 2];
Class<?>[] parameterTypes = new Class[additionalParameterTypes.length + 2];
parameterTypes[0] = String.class;
parameterTypes[0] = String.class;
parameterTypes[1] = int.class;
parameterTypes[1] = int.class;
System.arraycopy(additionalParameterTypes, 0, parameterTypes, 2, additionalParameterTypes.length);
System.arraycopy(additionalParameterTypes, 0, parameterTypes, 2, additionalParameterTypes.length);
return newConstructorAccessor.invoke(reflectionFactory, enumClass.getDeclaredConstructor(parameterTypes));
return newConstructorAccessor.invoke(reflectionFactory, enumClass.getDeclaredConstructor(parameterTypes));
}
}


private static < T extends Enum<? >> T makeEnum(Class<T> enumClass, String value, int ordinal, Class<?>[] additionalTypes, Object[] additionalValues) throws Exception
private static < T extends Enum<? >> T makeEnum(Class<T> enumClass, String value, int ordinal, Class<?>[] additionalTypes, Object[] additionalValues) throws Exception
{
{
Object[] params = new Object[additionalValues.length + 2];
Object[] params = new Object[additionalValues.length + 2];
params[0] = value;
params[0] = value;
params[1] = ordinal;
params[1] = ordinal;
System.arraycopy(additionalValues, 0, params, 2, additionalValues.length);
System.arraycopy(additionalValues, 0, params, 2, additionalValues.length);
return enumClass.cast(newInstance.invoke(getConstructorAccessor(enumClass, additionalTypes), new Object[] {params}));
return enumClass.cast(newInstance.invoke(getConstructorAccessor(enumClass, additionalTypes), new Object[] {params}));
}
}


public static void setFailsafeFieldValue(Field field, Object target, Object value) throws Exception
public static void setFailsafeFieldValue(Field field, Object target, Object value) throws Exception
{
{
field.setAccessible(true);
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
Object fieldAccessor = newFieldAccessor.invoke(reflectionFactory, field, false);
Object fieldAccessor = newFieldAccessor.invoke(reflectionFactory, field, false);
fieldAccessorSet.invoke(fieldAccessor, target, value);
fieldAccessorSet.invoke(fieldAccessor, target, value);
}
}


private static void blankField(Class<?> enumClass, String fieldName) throws Exception
private static void blankField(Class<?> enumClass, String fieldName) throws Exception
{
{
for (Field field : Class.class.getDeclaredFields())
for (Field field : Class.class.getDeclaredFields())
{
{
if (field.getName().contains(fieldName))
if (field.getName().contains(fieldName))
{
{
field.setAccessible(true);
field.setAccessible(true);
setFailsafeFieldValue(field, enumClass, null);
setFailsafeFieldValue(field, enumClass, null);
break;
break;
}
}
}
}
}
}


private static void cleanEnumCache(Class<?> enumClass) throws Exception
private static void cleanEnumCache(Class<?> enumClass) throws Exception
{
{
blankField(enumClass, "enumConstantDirectory");
blankField(enumClass, "enumConstantDirectory");
blankField(enumClass, "enumConstants");
blankField(enumClass, "enumConstants");
}
}


private static <T extends Enum<? >> T addEnum(Class<T> enumType, String enumName, Object... paramValues)
private static <T extends Enum<? >> T addEnum(Class<T> enumType, String enumName, Object... paramValues)
{
{
setup();
setup();
return addEnum(commonTypes, enumType, enumName, paramValues);
return addEnum(commonTypes, enumType, enumName, paramValues);
}
}


protected static <T extends Enum<? >> T addEnum(Class<?>[][] map, Class<T> enumType, String enumName, Object... paramValues)
protected static <T extends Enum<? >> T addEnum(Class<?>[][] map, Class<T> enumType, String enumName, Object... paramValues)
{
{
for (Class<?>[] lookup : map)
for (Class<?>[] lookup : map)
{
{
if (lookup[0] == enumType)
if (lookup[0] == enumType)
{
{
Class<?>[] paramTypes = new Class<?>[lookup.length - 1];
Class<?>[] paramTypes = new Class<?>[lookup.length - 1];
if (paramTypes.length > 0)
if (paramTypes.length > 0)
{
{
System.arraycopy(lookup, 1, paramTypes, 0, paramTypes.length);
System.arraycopy(lookup, 1, paramTypes, 0, paramTypes.length);
}
}
return addEnum(enumType, enumName, paramTypes, paramValues);
return addEnum(enumType, enumName, paramTypes, paramValues);
}
}
}
}
return null;
return null;
}
}


//Tests an enum is compatible with these args, throws an error if not.
//Tests an enum is compatible with these args, throws an error if not.
public static void testEnum(Class<? extends Enum<?>> enumType, Class<?>[] paramTypes)
public static void testEnum(Class<? extends Enum<?>> enumType, Class<?>[] paramTypes)
{
{
addEnum(true, enumType, null, paramTypes, (Object[])null);
addEnum(true, enumType, null, paramTypes, (Object[])null);
}
}


public static <T extends Enum<? >> T addEnum(Class<T> enumType, String enumName, Class<?>[] paramTypes, Object... paramValues)
public static <T extends Enum<? >> T addEnum(Class<T> enumType, String enumName, Class<?>[] paramTypes, Object... paramValues)
{
{
return addEnum(false, enumType, enumName, paramTypes, paramValues);
return addEnum(false, enumType, enumName, paramTypes, paramValues);
}
}


@SuppressWarnings({ "unchecked", "serial" })
@SuppressWarnings({ "unchecked", "serial" })
private static <T extends Enum<? >> T addEnum(boolean test, final Class<T> enumType, String enumName, final Class<?>[] paramTypes, Object[] paramValues)
private static <T extends Enum<? >> T addEnum(boolean test, final Class<T> enumType, String enumName, final Class<?>[] paramTypes, Object[] paramValues)
{
{
if (!isSetup)
if (!isSetup)
{
{
setup();
setup();
}
}


Field valuesField = null;
Field valuesField = null;
Field[] fields = enumType.getDeclaredFields();
Field[] fields = enumType.getDeclaredFields();


for (Field field : fields)
for (Field field : fields)
{
{
String name = field.getName();
String name = field.getName();
if (name.equals("$VALUES") || name.equals("ENUM$VALUES")) //Added 'ENUM$VALUES' because Eclipse's internal compiler doesn't follow standards
if (name.equals("$VALUES") || name.equals("ENUM$VALUES")) //Added 'ENUM$VALUES' because Eclipse's internal compiler doesn't follow standards
{
{
valuesField = field;
valuesField = field;
break;
break;
}
}
}
}


int flags = (FMLForgePlugin.RUNTIME_DEOBF ? Modifier.PUBLIC : Modifier.PRIVATE) | Modifier.STATIC | Modifier.FINAL | 0x1000 /*SYNTHETIC*/;
int flags = (FMLForgePlugin.RUNTIME_DEOBF ? Modifier.PUBLIC : Modifier.PRIVATE) | Modifier.STATIC | Modifier.FINAL | 0x1000 /*SYNTHETIC*/;
if (valuesField == null)
if (valuesField == null)
{
{
String valueType = String.format("[L%s;", enumType.getName().replace('.', '/'));
String valueType = String.format("[L%s;", enumType.getName().replace('.', '/'));


for (Field field : fields)
for (Field field : fields)
{
{
if ((field.getModifiers() & flags) == flags &&
if ((field.getModifiers() & flags) == flags &&
field.getType().getName().replace('.', '/').equals(valueType)) //Apparently some JVMs return .'s and some don't..
field.getType().getName().replace('.', '/').equals(valueType)) //Apparently some JVMs return .'s and some don't..
{
{
valuesField = field;
valuesField = field;
break;
break;
}
}
}
}
}
}


if (valuesField == null)
if (valuesField == null)
{
{
final List<String> lines = Lists.newArrayList();
final List<String> lines = Lists.newArrayList();
lines.add(String.format("Could not find $VALUES field for enum: %s", enumType.getName()));
lines.add(String.format("Could not find $VALUES field for enum: %s", enumType.getName()));
lines.add(String.format("Runtime Deobf: %s", FMLForgePlugin.RUNTIME_DEOBF));
lines.add(String.format("Runtime Deobf: %s", FMLForgePlugin.RUNTIME_DEOBF));
lines.add(String.format("Flags: %s", String.format("%16s", Integer.toBinaryString(flags)).replace(' ', '0')));
lines.add(String.format("Flags: %s", String.format("%16s", Integer.toBinaryString(flags)).replace(' ', '0')));
lines.add( "Fields:");
lines.add( "Fields:");
for (Field field : fields)
for (Field field : fields)
{
{
String mods = String.format("%16s", Integer.toBinaryString(field.getModifiers())).replace(' ', '0');
String mods = String.format("%16s", Integer.toBinaryString(field.getModifiers())).replace(' ', '0');
lines.add(String.format(" %s %s: %s", mods, field.getName(), field.getType().getName()));
lines.add(String.format(" %s %s: %s", mods, field.getName(), field.getType().getName()));
}
}


for (String line : lines)
for (String line : lines)
FMLLog.severe(line);
FMLLog.severe(line);


if (test)
if (test)
{
{
throw new EnhancedRuntimeException("Could not find $VALUES field for enum: " + enumType.getName())
throw new EnhancedRuntimeException("Could not find $VALUES field for enum: " + enumType.getName())
{
{
@Override
@Override
protected void printStackTrace(WrappedPrintStream stream)
protected void printStackTrace(WrappedPrintStream stream)
{
{
for (String line : lines)
for (String line : lines)
stream.println(line);
stream.println(line);
}
}
};
};
}
}
return null;
return null;
}
}


if (test)
if (test)
{
{
Object ctr = null;
Object ctr = null;
Exception ex = null;
Exception ex = null;
try
try
{
{
ctr = getConstructorAccessor(enumType, paramTypes);
ctr = getConstructorAccessor(enumType, paramTypes);
}
}
catch (Exception e)
catch (Exception e)
{
{
ex = e;
ex = e;
}
}
if (ctr == null || ex != null)
if (ctr == null || ex != null)
{
{
throw new EnhancedRuntimeException(String.format("Could not find constructor for Enum %s", enumType.getName()), ex)
throw new EnhancedRuntimeException(String.format("Could not find constructor for Enum %s", enumType.getName()), ex)
{
{
private String toString(Class<?>[] cls)
private String toString(Class<?>[] cls)
{
{
StringBuilder b = new StringBuilder();
StringBuilder b = new StringBuilder();
for (int x = 0; x < cls.length; x++)
for (int x = 0; x < cls.length; x++)
{
{
b.append(cls[x].getName());
b.append(cls[x].getName());
if (x != cls.length - 1)
if (x != cls.length - 1)
b.append(", ");
b.append(", ");
}
}
return b.toString();
return b.toString();
}
}
@Override
@Override
protected void printStackTrace(WrappedPrintStream stream)
protected void printStackTrace(WrappedPrintStream stream)
{
{
stream.println("Target Arguments:");
stream.println("Target Arguments:");
stream.println(" java.lang.String, int, " + toString(paramTypes));
stream.println(" java.lang.String, int, " + toString(paramTypes));
stream.println("Found Constructors:");
stream.println("Found Constructors:");
for (Constructor<?> ctr : enumType.getDeclaredConstructors())
for (Constructor<?> ctr : enumType.getDeclaredConstructors())
{
{
stream.println(" " + toString(ctr.getParameterTypes()));
stream.println(" " + toString(ctr.getParameterTypes()));
}
}
}
}
};
};
}
}
return null;
return null;
}
}


valuesField.setAccessible(true);
valuesField.setAccessible(true);


try
try
{
{
T[] previousValues = (T[])valuesField.get(enumType);
T[] previousValues = (T[])valuesField.get(enumType);
List<T> values = new ArrayList<T>(Arrays.asList(previousValues));
List<T> values = new ArrayList<T>(Arrays.asList(previousValues));
T newValue = makeEnum(enumType, enumName, values.size(), paramTypes, paramValues);
T newValue = makeEnum(enumType, enumName, values.size(), paramTypes, paramValues);
values.add(newValue);
values.add(newValue);
setFailsafeFieldValue(valuesField, null, values.toArray((T[]) Array.newInstance(enumType, 0)));
setFailsafeFieldValue(valuesField, null, values.toArray((T[]) Array.newInstance(enumType, 0)));
cleanEnumCache(enumType);
cleanEnumCache(enumType);


return newValue;
return newValue;
}
}
catch (Exception e)
catch (Exception e)
{
{
e.printStackTrace();
e.printStackTrace();
throw new RuntimeException(e.getMessage(), e);
throw new RuntimeException(e.getMessage(), e);
}
}
}
}


static
static
{
{
if (!isSetup)
if (!isSetup)
{
{
setup();
setup();
}
}
}
}
}
}