2016-01-22 35 views
0

我正在尝试使用此枚举并添加新材料。 任何未被移除的东西在其他地方都有很强的依赖性,即使如此,根据mod作者的说法,这几乎是Java字节的限制,所以没有太多的工作空间。在运行时创建并覆盖Java Enum对象[GregTech/minecraft]

GregoriousT提到“有一种方法,Overmind使用Reflection来攻击Enum添加他自己的东西,不知道他是如何做到的,也不知道如果你问他他需要多长时间来回复。

枚举我们在谈论: http://pastebin.com/g0aJ2Qjd

所以我只是问,我怎么会去吗?

这是我当前尝试在客户端崩溃之前抛出[FML]: Variable m:1|newInstance|public java.lang.Object sun.reflect.DelegatingConstructorAccessorImpl.newInstance(java.lang.Object[]) throws java.lang.InstantiationException,java.lang.IllegalArgumentException,java.lang.reflect.InvocationTargetException|false 的原因。 (日志为方便阅读移除代码)

当前的尝试:

public class MaterialsNew { 

public static void getGregMaterials() throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, SecurityException{ 
Utils.LOG_WARNING("Stepping through the process of Greg's materials."); 

    Constructor<?> con = Materials.class.getDeclaredConstructors()[0]; 
java.lang.reflect.Method[] methods = con.getClass().getDeclaredMethods(); 
for (java.lang.reflect.Method m1 : methods) { 
    if (m1.getName().equals("acquireConstructorAccessor")) { 
     m1.setAccessible(true); 
     m1.invoke(con, new Object[0]);} 
} 
Field[] fields = con.getClass().getDeclaredFields(); 
Object ca = null; 
for (Field f : fields) { 
    if (f.getName().equals("constructorAccessor")) { 
    f.setAccessible(true); 
    ca = f.get(con); 
    } 
} 
Method m = ca.getClass().getMethod("newInstance", new Class[] { Object[].class }); 
m.setAccessible(true); 
Materials v = (Materials) m.invoke(ca, new Object[] { new Object[] { "NEWMATERIAL", Integer.MAX_VALUE } }); 
System.out.println(v.getClass() + ":" + v.name() + ":" + v.ordinal());}} 

任何帮助或建议表示赞赏,他们在球员在锻造IRC是真的不知道任何。

+0

我怀疑你可以用简单的反射来做到这一点。但问题是,你真的需要破解'enum'类型还是只需要实现接口'IColorModulationContainer'和'ISubTagContainer'? – Holger

+0

除此之外,您应该以可读的方式格式化源代码,并停止在每条语句之间使用日志语句来污染代码。这是非常难以阅读的。 – Holger

+0

除非它包含在材料枚举中,否则它是没有加载或甚至没有处理的无用代码。这就是为什么在运行时修改它是唯一真正的选项AFAIK。实际上,考虑到以前做过这个的人是Forge程序员的主要人员之一,但我没有想到这完全在我的能力范围之内。 我知道这不是一个标准的用例,它不符合枚举的要点,但有时你只需要扩展某人的工作。 (我很欢迎试试为什么不这样做) – Draknyte1

回答

1

JVMs应该阻止这种鬼鬼祟祟的enum实例创建。所以你必须使用一个很快就可能解决的漏洞,或者深入到JRE中,以至于稍有改变都可能会破坏它。

这里是一个与Oracle的当前JRE 8,也许JRE 7,以及工作的窍门,并出奇的简单:

import java.lang.invoke.MethodHandle; 
import java.lang.invoke.MethodHandles; 
import java.lang.reflect.Constructor; 
import java.util.EnumSet; 

public class EnumHack { 
    public static void main(String[] args) throws Throwable { 
     Constructor<Thread.State> c 
      = Thread.State.class.getDeclaredConstructor(String.class, int.class); 
     c.setAccessible(true); 
     MethodHandle h=MethodHandles.lookup().unreflectConstructor(c); 
     Thread.State state=(Thread.State)h.invokeExact("FLYING", 42); 
     System.out.println("created Thread.State "+state+"("+state.ordinal()+')'); 
     System.out.println(EnumSet.allOf(Thread.State.class).contains(state)); 
    } 
} 

但是,不要指望这个解决方案将持续...