Krenair

Untitled

Dec 5th, 2011
157
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 6.70 KB | None | 0 0
  1. package net.minecraft.src;
  2.  
  3. import java.lang.reflect.*;
  4. import java.util.*;
  5.  
  6. public class mod_Test extends BaseMod {
  7.     /*
  8.      * Found at: http://niceideas.ch/roller2/badtrash/entry/java_create_enum_instances_dynamically
  9.      * Updated to compile properly in eclipse/Java 1.6/1.7
  10.      */
  11.     private static enum TestEnum {
  12.         a,
  13.         b,
  14.         c;
  15.     };
  16.     @Override
  17.     public String getVersion() {
  18.         return "Test";
  19.     }
  20.  
  21.     @Override
  22.     public void load() {
  23.         addEnum(TestEnum.class, "d");
  24.         addEnum(TestEnum.class, "e");
  25.         addEnum(TestEnum.class, "f");
  26.        
  27.         EnumArmorMaterial armor = addArmorMaterial("Piggy", 1337, new int[]{1, 3, 2, 1}, 1000);
  28.         EnumToolMaterial tool = addToolMaterial("Piggy", 0, 59, 2.0F, 0, 15);
  29.         System.out.println(Arrays.deepToString(TestEnum.values()));
  30.         System.out.println(Arrays.deepToString(EnumArmorMaterial.values()));
  31.         System.out.println(Arrays.deepToString(EnumToolMaterial.values()));
  32.     }
  33.    
  34.     public EnumArmorMaterial addArmorMaterial(String name, int durability, int[] reductionAmounts, int enchantability)
  35.     {
  36.         if (!isSetup)
  37.         {
  38.             setup();
  39.         }
  40.        
  41.         if (isJad)
  42.         {
  43.             return addEnum(EnumArmorMaterial.class, name,
  44.                 new Class[] { String.class, int.class, int.class,  int[].class,      int.class      },
  45.                 new Object[]{ name,         0,         durability, reductionAmounts, enchantability });
  46.         }
  47.         else
  48.         {
  49.             return addEnum(EnumArmorMaterial.class, name,
  50.                 new Class[] { int.class,  int[].class,      int.class      },
  51.                 new Object[]{ durability, reductionAmounts, enchantability }); 
  52.         }
  53.     }
  54.     public EnumToolMaterial addToolMaterial(String name, int harvestLevel, int maxUses, float efficiency, int damage, int enchantability)
  55.     {
  56.         if (!isSetup)
  57.         {
  58.             setup();
  59.         }
  60.        
  61.         if (isJad)
  62.         {
  63.             return addEnum(EnumToolMaterial.class, name,
  64.                 new Class[] { String.class, int.class, int.class,    int.class, float.class,  int.class, int.class      },
  65.                 new Object[]{ name,         0,         harvestLevel, maxUses,   efficiency,   damage,    enchantability });
  66.         }
  67.         else
  68.         {
  69.             return addEnum(EnumToolMaterial.class, name,
  70.                 new Class[] { int.class,    int.class, float.class,  int.class, int.class       },
  71.                 new Object[]{ harvestLevel, maxUses,   efficiency,   damage,    enchantability  });
  72.         }
  73.     }
  74.    
  75.     private Object reflectionFactory      = null;
  76.     private Method newConstructorAccessor = null;
  77.     private Method newInstance            = null;
  78.     private Method newFieldAccessor       = null;
  79.     private Method fieldAccessorSet       = null;
  80.     private boolean isJad                 = false;
  81.     private boolean isSetup               = false;
  82.    
  83.     private void setup()
  84.     {
  85.         if (isSetup)
  86.         {
  87.             return;
  88.         }
  89.        
  90.         try {
  91.             //Jad is stupid, decompiles the enums wrong, so it has redundant String,int params.
  92.             EnumArmorMaterial.class.getDeclaredConstructor(String.class, int.class, String.class, int.class, int.class, int[].class, int.class);
  93.             isJad = true;
  94.         }
  95.         catch (Exception e)
  96.         {
  97.             //Nom nom nom
  98.         }
  99.  
  100.         try {
  101.             Method getReflectionFactory = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("getReflectionFactory");
  102.             reflectionFactory      = getReflectionFactory.invoke(null);
  103.             newConstructorAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newConstructorAccessor", Constructor.class);
  104.             newInstance            = Class.forName("sun.reflect.ConstructorAccessor").getDeclaredMethod("newInstance", Object[].class);
  105.             newFieldAccessor       = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newFieldAccessor", Field.class, boolean.class);
  106.             fieldAccessorSet       = Class.forName("sun.reflect.FieldAccessor").getDeclaredMethod("set", Object.class, Object.class);          
  107.         } catch (Exception e) {
  108.             e.printStackTrace();
  109.         }
  110.        
  111.         isSetup = true;
  112.     }
  113.    
  114.     private Object getConstructorAccessor(Class<?> enumClass, Class<?>[] additionalParameterTypes) throws Exception {
  115.         Class<?>[] parameterTypes = new Class[additionalParameterTypes.length + 2];
  116.         parameterTypes[0] = String.class;
  117.         parameterTypes[1] = int.class;
  118.         System.arraycopy(additionalParameterTypes, 0, parameterTypes, 2, additionalParameterTypes.length);
  119.         return newConstructorAccessor.invoke(reflectionFactory, enumClass.getDeclaredConstructor(parameterTypes));
  120.     }
  121.    
  122.     private <T extends Enum<?>> T makeEnum(Class<T> enumClass, String value, int ordinal, Class<?>[] additionalTypes, Object[] additionalValues) throws Exception {
  123.         Object[] parms = new Object[additionalValues.length + 2];
  124.         parms[0] = value;
  125.         parms[1] = Integer.valueOf(ordinal);
  126.         System.arraycopy(additionalValues, 0, parms, 2, additionalValues.length);
  127.         return enumClass.cast(newInstance.invoke(getConstructorAccessor(enumClass, additionalTypes), new Object[]{parms}));
  128.     }
  129.  
  130.     private void setFailsafeFieldValue(Field field, Object target, Object value) throws Exception {
  131.         field.setAccessible(true);
  132.         Field modifiersField = Field.class.getDeclaredField("modifiers");
  133.         modifiersField.setAccessible(true);
  134.         modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
  135.         Object fieldAccessor = newFieldAccessor.invoke(reflectionFactory, field, false);
  136.         fieldAccessorSet.invoke(fieldAccessor, target, value);
  137.     }
  138.    
  139.     private void blankField(Class<?> enumClass, String fieldName) throws Exception {
  140.         for (Field field : Class.class.getDeclaredFields()) {
  141.             if (field.getName().contains(fieldName)) {
  142.                 field.setAccessible(true);
  143.                 setFailsafeFieldValue(field, enumClass, null);
  144.                 break;
  145.             }
  146.         }
  147.     }
  148.    
  149.     private void cleanEnumCache(Class<?> enumClass) throws Exception {
  150.         blankField(enumClass, "enumConstantDirectory");
  151.         blankField(enumClass, "enumConstants");
  152.     }
  153.  
  154.     public <T extends Enum<?>> T addEnum(Class<T> enumType, String enumName) {
  155.         return addEnum(enumType, enumName, new Class<?>[]{}, new Object[]{});
  156.     }
  157.    
  158.     @SuppressWarnings("unchecked")
  159.     public <T extends Enum<?>> T addEnum(Class<T> enumType, String enumName, Class<?>[] paramTypes, Object[] paramValues) {
  160.         if (!isSetup)
  161.         {
  162.             setup();
  163.         }
  164.        
  165.         Field valuesField = null;
  166.         Field[] fields = enumType.getDeclaredFields();
  167.         for (Field field : fields) {
  168.             if (field.getName().contains("$VALUES")) {
  169.                 valuesField = field;
  170.                 break;
  171.             }
  172.         }
  173.         valuesField.setAccessible(true);
  174.  
  175.         try {
  176.             T[] previousValues = (T[])valuesField.get(enumType);
  177.             List<T> values = new ArrayList<T>(Arrays.asList(previousValues));
  178.             T newValue = (T)makeEnum(enumType, enumName, values.size(), paramTypes, paramValues);
  179.             values.add(newValue);
  180.             setFailsafeFieldValue(valuesField, null, values.toArray((T[]) Array.newInstance(enumType, 0)));
  181.             cleanEnumCache(enumType);
  182.            
  183.             return newValue;
  184.         } catch (Exception e) {
  185.             e.printStackTrace();
  186.             throw new RuntimeException(e.getMessage(), e);
  187.         }
  188.     }
  189. }
  190.  
Advertisement
Add Comment
Please, Sign In to add comment