Diff
checker
文本
文本
圖像
文檔
Excel
文件夾
Legal
Enterprise
桌面版
定價
登入
下載 Diffchecker 桌面版
比較文本
尋找兩個文字檔案之間的差異
工具
歷史
即時編輯器
摺疊未變更行
關閉換行
檢視
拆分
統一
比對精度
智能
單詞
字符
語法突出顯示
選擇語法
忽略
文字轉換
前往第一個差異
編輯輸入
Diffchecker Desktop
執行Diffchecker最安全的方式。取得Diffchecker桌面應用程式:您的差異永遠不會離開您的電腦!
取得桌面版
Untitled diff
建立於
9 年前
差異永不過期
清除
匯出
分享
解釋
0 刪除
行
總計
刪除
字符
總計
刪除
要繼續使用此功能,請升級到
Diff
checker
Pro
查看價格
375 行
全部複製
5 新增
行
總計
新增
字符
總計
新增
要繼續使用此功能,請升級到
Diff
checker
Pro
查看價格
377 行
全部複製
/*
/*
* 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();
}
}
}
}
}
}
已保存差異
原始文本
開啟檔案
/* * 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.common.util; import java.lang.reflect.*; import java.util.*; import com.google.common.collect.Lists; import net.minecraftforge.fml.common.EnhancedRuntimeException; import net.minecraftforge.fml.common.FMLLog; import net.minecraft.block.BlockPressurePlate.Sensitivity; import net.minecraft.block.material.Material; import net.minecraft.enchantment.EnumEnchantmentType; import net.minecraft.entity.EnumCreatureAttribute; import net.minecraft.entity.EnumCreatureType; import net.minecraft.entity.item.EntityPainting.EnumArt; import net.minecraft.entity.player.EntityPlayer.SleepResult; import net.minecraft.item.EnumAction; import net.minecraft.item.EnumRarity; import net.minecraft.item.Item.ToolMaterial; import net.minecraft.item.ItemArmor.ArmorMaterial; import net.minecraft.util.SoundEvent; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.text.TextFormatting; import net.minecraft.world.EnumSkyBlock; import net.minecraft.world.gen.structure.StructureStrongholdPieces.Stronghold.Door; import net.minecraftforge.classloading.FMLForgePlugin; public class EnumHelper { private static Object reflectionFactory = null; private static Method newConstructorAccessor = null; private static Method newInstance = null; private static Method newFieldAccessor = null; private static Method fieldAccessorSet = null; private static boolean isSetup = false; //Some enums are decompiled with extra arguments, so lets check for that private static Class<?>[][] commonTypes = { {EnumAction.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}, {EnumCreatureAttribute.class}, {EnumCreatureType.class, Class.class, int.class, Material.class, boolean.class, boolean.class}, {Door.class}, {EnumEnchantmentType.class}, {Sensitivity.class}, {RayTraceResult.Type.class}, {EnumSkyBlock.class, int.class}, {SleepResult.class}, {ToolMaterial.class, int.class, int.class, float.class, float.class, int.class}, {EnumRarity.class, TextFormatting.class, String.class} }; public static EnumAction addAction(String name) { return addEnum(EnumAction.class, name); } 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); } 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); } public static EnumCreatureAttribute addCreatureAttribute(String name) { return addEnum(EnumCreatureAttribute.class, name); } 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); } public static Door addDoor(String name) { return addEnum(Door.class, name); } public static EnumEnchantmentType addEnchantmentType(String name) { return addEnum(EnumEnchantmentType.class, name); } public static Sensitivity addSensitivity(String name) { return addEnum(Sensitivity.class, name); } public static RayTraceResult.Type addMovingObjectType(String name) { return addEnum(RayTraceResult.Type.class, name); } public static EnumSkyBlock addSkyBlock(String name, int lightValue) { return addEnum(EnumSkyBlock.class, name, lightValue); } public static SleepResult addStatus(String name) { return addEnum(SleepResult.class, name); } 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); } public static EnumRarity addRarity(String name, TextFormatting color, String displayName) { return addEnum(EnumRarity.class, name, color, displayName); } private static void setup() { if (isSetup) { return; } try { Method getReflectionFactory = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("getReflectionFactory"); reflectionFactory = getReflectionFactory.invoke(null); newConstructorAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newConstructorAccessor", Constructor.class); newInstance = Class.forName("sun.reflect.ConstructorAccessor").getDeclaredMethod("newInstance", Object[].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); } catch (Exception e) { e.printStackTrace(); } isSetup = true; } /* * 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. * Found at: http://niceideas.ch/roller2/badtrash/entry/java_create_enum_instances_dynamically */ private static Object getConstructorAccessor(Class<?> enumClass, Class<?>[] additionalParameterTypes) throws Exception { Class<?>[] parameterTypes = new Class[additionalParameterTypes.length + 2]; parameterTypes[0] = String.class; parameterTypes[1] = int.class; System.arraycopy(additionalParameterTypes, 0, parameterTypes, 2, additionalParameterTypes.length); 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 { Object[] params = new Object[additionalValues.length + 2]; params[0] = value; params[1] = ordinal; System.arraycopy(additionalValues, 0, params, 2, additionalValues.length); return enumClass.cast(newInstance.invoke(getConstructorAccessor(enumClass, additionalTypes), new Object[] {params})); } public static void setFailsafeFieldValue(Field field, Object target, Object value) throws Exception { field.setAccessible(true); Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); Object fieldAccessor = newFieldAccessor.invoke(reflectionFactory, field, false); fieldAccessorSet.invoke(fieldAccessor, target, value); } private static void blankField(Class<?> enumClass, String fieldName) throws Exception { for (Field field : Class.class.getDeclaredFields()) { if (field.getName().contains(fieldName)) { field.setAccessible(true); setFailsafeFieldValue(field, enumClass, null); break; } } } private static void cleanEnumCache(Class<?> enumClass) throws Exception { blankField(enumClass, "enumConstantDirectory"); blankField(enumClass, "enumConstants"); } private static <T extends Enum<? >> T addEnum(Class<T> enumType, String enumName, Object... paramValues) { setup(); return addEnum(commonTypes, enumType, enumName, paramValues); } protected static <T extends Enum<? >> T addEnum(Class<?>[][] map, Class<T> enumType, String enumName, Object... paramValues) { for (Class<?>[] lookup : map) { if (lookup[0] == enumType) { Class<?>[] paramTypes = new Class<?>[lookup.length - 1]; if (paramTypes.length > 0) { System.arraycopy(lookup, 1, paramTypes, 0, paramTypes.length); } return addEnum(enumType, enumName, paramTypes, paramValues); } } return null; } //Tests an enum is compatible with these args, throws an error if not. public static void testEnum(Class<? extends Enum<?>> enumType, Class<?>[] paramTypes) { addEnum(true, enumType, null, paramTypes, (Object[])null); } public static <T extends Enum<? >> T addEnum(Class<T> enumType, String enumName, Class<?>[] paramTypes, Object... paramValues) { return addEnum(false, enumType, enumName, paramTypes, paramValues); } @SuppressWarnings({ "unchecked", "serial" }) private static <T extends Enum<? >> T addEnum(boolean test, final Class<T> enumType, String enumName, final Class<?>[] paramTypes, Object[] paramValues) { if (!isSetup) { setup(); } Field valuesField = null; Field[] fields = enumType.getDeclaredFields(); for (Field field : fields) { String name = field.getName(); if (name.equals("$VALUES") || name.equals("ENUM$VALUES")) //Added 'ENUM$VALUES' because Eclipse's internal compiler doesn't follow standards { valuesField = field; break; } } int flags = (FMLForgePlugin.RUNTIME_DEOBF ? Modifier.PUBLIC : Modifier.PRIVATE) | Modifier.STATIC | Modifier.FINAL | 0x1000 /*SYNTHETIC*/; if (valuesField == null) { String valueType = String.format("[L%s;", enumType.getName().replace('.', '/')); for (Field field : fields) { if ((field.getModifiers() & flags) == flags && field.getType().getName().replace('.', '/').equals(valueType)) //Apparently some JVMs return .'s and some don't.. { valuesField = field; break; } } } if (valuesField == null) { final List<String> lines = Lists.newArrayList(); 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("Flags: %s", String.format("%16s", Integer.toBinaryString(flags)).replace(' ', '0'))); lines.add( "Fields:"); for (Field field : fields) { String mods = String.format("%16s", Integer.toBinaryString(field.getModifiers())).replace(' ', '0'); lines.add(String.format(" %s %s: %s", mods, field.getName(), field.getType().getName())); } for (String line : lines) FMLLog.severe(line); if (test) { throw new EnhancedRuntimeException("Could not find $VALUES field for enum: " + enumType.getName()) { @Override protected void printStackTrace(WrappedPrintStream stream) { for (String line : lines) stream.println(line); } }; } return null; } if (test) { Object ctr = null; Exception ex = null; try { ctr = getConstructorAccessor(enumType, paramTypes); } catch (Exception e) { ex = e; } if (ctr == null || ex != null) { throw new EnhancedRuntimeException(String.format("Could not find constructor for Enum %s", enumType.getName()), ex) { private String toString(Class<?>[] cls) { StringBuilder b = new StringBuilder(); for (int x = 0; x < cls.length; x++) { b.append(cls[x].getName()); if (x != cls.length - 1) b.append(", "); } return b.toString(); } @Override protected void printStackTrace(WrappedPrintStream stream) { stream.println("Target Arguments:"); stream.println(" java.lang.String, int, " + toString(paramTypes)); stream.println("Found Constructors:"); for (Constructor<?> ctr : enumType.getDeclaredConstructors()) { stream.println(" " + toString(ctr.getParameterTypes())); } } }; } return null; } valuesField.setAccessible(true); try { T[] previousValues = (T[])valuesField.get(enumType); List<T> values = new ArrayList<T>(Arrays.asList(previousValues)); T newValue = makeEnum(enumType, enumName, values.size(), paramTypes, paramValues); values.add(newValue); setFailsafeFieldValue(valuesField, null, values.toArray((T[]) Array.newInstance(enumType, 0))); cleanEnumCache(enumType); return newValue; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e.getMessage(), e); } } static { if (!isSetup) { setup(); } } }
更改後文本
開啟檔案
/* * 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.common.util; import java.lang.reflect.*; import java.util.*; import com.google.common.base.Predicate; import com.google.common.collect.Lists; import net.minecraftforge.fml.common.EnhancedRuntimeException; import net.minecraftforge.fml.common.FMLLog; import net.minecraft.block.BlockPressurePlate.Sensitivity; import net.minecraft.block.material.Material; import net.minecraft.enchantment.EnumEnchantmentType; import net.minecraft.entity.EnumCreatureAttribute; import net.minecraft.entity.EnumCreatureType; import net.minecraft.entity.item.EntityPainting.EnumArt; import net.minecraft.entity.player.EntityPlayer.SleepResult; import net.minecraft.item.EnumAction; import net.minecraft.item.EnumRarity; import net.minecraft.item.Item; import net.minecraft.item.Item.ToolMaterial; import net.minecraft.item.ItemArmor.ArmorMaterial; import net.minecraft.util.SoundEvent; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.text.TextFormatting; import net.minecraft.world.EnumSkyBlock; import net.minecraft.world.gen.structure.StructureStrongholdPieces.Stronghold.Door; import net.minecraftforge.classloading.FMLForgePlugin; public class EnumHelper { private static Object reflectionFactory = null; private static Method newConstructorAccessor = null; private static Method newInstance = null; private static Method newFieldAccessor = null; private static Method fieldAccessorSet = null; private static boolean isSetup = false; //Some enums are decompiled with extra arguments, so lets check for that private static Class<?>[][] commonTypes = { {EnumAction.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}, {EnumCreatureAttribute.class}, {EnumCreatureType.class, Class.class, int.class, Material.class, boolean.class, boolean.class}, {Door.class}, {EnumEnchantmentType.class, Predicate.class}, {Sensitivity.class}, {RayTraceResult.Type.class}, {EnumSkyBlock.class, int.class}, {SleepResult.class}, {ToolMaterial.class, int.class, int.class, float.class, float.class, int.class}, {EnumRarity.class, TextFormatting.class, String.class} }; public static EnumAction addAction(String name) { return addEnum(EnumAction.class, name); } 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); } 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); } public static EnumCreatureAttribute addCreatureAttribute(String name) { return addEnum(EnumCreatureAttribute.class, name); } 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); } public static Door addDoor(String name) { return addEnum(Door.class, name); } public static EnumEnchantmentType addEnchantmentType(String name, Predicate<Item> delegate) { return addEnum(EnumEnchantmentType.class, name, delegate); } public static Sensitivity addSensitivity(String name) { return addEnum(Sensitivity.class, name); } public static RayTraceResult.Type addMovingObjectType(String name) { return addEnum(RayTraceResult.Type.class, name); } public static EnumSkyBlock addSkyBlock(String name, int lightValue) { return addEnum(EnumSkyBlock.class, name, lightValue); } public static SleepResult addStatus(String name) { return addEnum(SleepResult.class, name); } 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); } public static EnumRarity addRarity(String name, TextFormatting color, String displayName) { return addEnum(EnumRarity.class, name, color, displayName); } private static void setup() { if (isSetup) { return; } try { Method getReflectionFactory = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("getReflectionFactory"); reflectionFactory = getReflectionFactory.invoke(null); newConstructorAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newConstructorAccessor", Constructor.class); newInstance = Class.forName("sun.reflect.ConstructorAccessor").getDeclaredMethod("newInstance", Object[].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); } catch (Exception e) { e.printStackTrace(); } isSetup = true; } /* * 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. * Found at: http://niceideas.ch/roller2/badtrash/entry/java_create_enum_instances_dynamically */ private static Object getConstructorAccessor(Class<?> enumClass, Class<?>[] additionalParameterTypes) throws Exception { Class<?>[] parameterTypes = new Class[additionalParameterTypes.length + 2]; parameterTypes[0] = String.class; parameterTypes[1] = int.class; System.arraycopy(additionalParameterTypes, 0, parameterTypes, 2, additionalParameterTypes.length); 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 { Object[] params = new Object[additionalValues.length + 2]; params[0] = value; params[1] = ordinal; System.arraycopy(additionalValues, 0, params, 2, additionalValues.length); return enumClass.cast(newInstance.invoke(getConstructorAccessor(enumClass, additionalTypes), new Object[] {params})); } public static void setFailsafeFieldValue(Field field, Object target, Object value) throws Exception { field.setAccessible(true); Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); Object fieldAccessor = newFieldAccessor.invoke(reflectionFactory, field, false); fieldAccessorSet.invoke(fieldAccessor, target, value); } private static void blankField(Class<?> enumClass, String fieldName) throws Exception { for (Field field : Class.class.getDeclaredFields()) { if (field.getName().contains(fieldName)) { field.setAccessible(true); setFailsafeFieldValue(field, enumClass, null); break; } } } private static void cleanEnumCache(Class<?> enumClass) throws Exception { blankField(enumClass, "enumConstantDirectory"); blankField(enumClass, "enumConstants"); } private static <T extends Enum<? >> T addEnum(Class<T> enumType, String enumName, Object... paramValues) { setup(); return addEnum(commonTypes, enumType, enumName, paramValues); } protected static <T extends Enum<? >> T addEnum(Class<?>[][] map, Class<T> enumType, String enumName, Object... paramValues) { for (Class<?>[] lookup : map) { if (lookup[0] == enumType) { Class<?>[] paramTypes = new Class<?>[lookup.length - 1]; if (paramTypes.length > 0) { System.arraycopy(lookup, 1, paramTypes, 0, paramTypes.length); } return addEnum(enumType, enumName, paramTypes, paramValues); } } return null; } //Tests an enum is compatible with these args, throws an error if not. public static void testEnum(Class<? extends Enum<?>> enumType, Class<?>[] paramTypes) { addEnum(true, enumType, null, paramTypes, (Object[])null); } public static <T extends Enum<? >> T addEnum(Class<T> enumType, String enumName, Class<?>[] paramTypes, Object... paramValues) { return addEnum(false, enumType, enumName, paramTypes, paramValues); } @SuppressWarnings({ "unchecked", "serial" }) private static <T extends Enum<? >> T addEnum(boolean test, final Class<T> enumType, String enumName, final Class<?>[] paramTypes, Object[] paramValues) { if (!isSetup) { setup(); } Field valuesField = null; Field[] fields = enumType.getDeclaredFields(); for (Field field : fields) { String name = field.getName(); if (name.equals("$VALUES") || name.equals("ENUM$VALUES")) //Added 'ENUM$VALUES' because Eclipse's internal compiler doesn't follow standards { valuesField = field; break; } } int flags = (FMLForgePlugin.RUNTIME_DEOBF ? Modifier.PUBLIC : Modifier.PRIVATE) | Modifier.STATIC | Modifier.FINAL | 0x1000 /*SYNTHETIC*/; if (valuesField == null) { String valueType = String.format("[L%s;", enumType.getName().replace('.', '/')); for (Field field : fields) { if ((field.getModifiers() & flags) == flags && field.getType().getName().replace('.', '/').equals(valueType)) //Apparently some JVMs return .'s and some don't.. { valuesField = field; break; } } } if (valuesField == null) { final List<String> lines = Lists.newArrayList(); 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("Flags: %s", String.format("%16s", Integer.toBinaryString(flags)).replace(' ', '0'))); lines.add( "Fields:"); for (Field field : fields) { String mods = String.format("%16s", Integer.toBinaryString(field.getModifiers())).replace(' ', '0'); lines.add(String.format(" %s %s: %s", mods, field.getName(), field.getType().getName())); } for (String line : lines) FMLLog.severe(line); if (test) { throw new EnhancedRuntimeException("Could not find $VALUES field for enum: " + enumType.getName()) { @Override protected void printStackTrace(WrappedPrintStream stream) { for (String line : lines) stream.println(line); } }; } return null; } if (test) { Object ctr = null; Exception ex = null; try { ctr = getConstructorAccessor(enumType, paramTypes); } catch (Exception e) { ex = e; } if (ctr == null || ex != null) { throw new EnhancedRuntimeException(String.format("Could not find constructor for Enum %s", enumType.getName()), ex) { private String toString(Class<?>[] cls) { StringBuilder b = new StringBuilder(); for (int x = 0; x < cls.length; x++) { b.append(cls[x].getName()); if (x != cls.length - 1) b.append(", "); } return b.toString(); } @Override protected void printStackTrace(WrappedPrintStream stream) { stream.println("Target Arguments:"); stream.println(" java.lang.String, int, " + toString(paramTypes)); stream.println("Found Constructors:"); for (Constructor<?> ctr : enumType.getDeclaredConstructors()) { stream.println(" " + toString(ctr.getParameterTypes())); } } }; } return null; } valuesField.setAccessible(true); try { T[] previousValues = (T[])valuesField.get(enumType); List<T> values = new ArrayList<T>(Arrays.asList(previousValues)); T newValue = makeEnum(enumType, enumName, values.size(), paramTypes, paramValues); values.add(newValue); setFailsafeFieldValue(valuesField, null, values.toArray((T[]) Array.newInstance(enumType, 0))); cleanEnumCache(enumType); return newValue; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e.getMessage(), e); } } static { if (!isSetup) { setup(); } } }
尋找差異