I’m currently developing a java add-on for a minecraft client called "LabyMod". Because Labymod did not create all events I need I'm trying to create the missing event myself. For this I need to modify a class via asm but every time I make the modifications to this class I get the following error:
SEVERE: Unable to launch
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at net.minecraft.launchwrapper.Launch.launch(Launch.java:131)
at net.minecraft.launchwrapper.Launch.main(Launch.java:27)
Caused by: java.lang.VerifyError: Bad local variable type
Exception Details:
Location:
aip.a(Laed;Lakb;)Ljava/util/List; @1909: aload_0
Reason:
Type top (current frame, locals[0]) is not assignable to reference type
Current Frame:
bci: @1909
flags: { }
locals: { top, top, top, 'java/util/ArrayList' }
stack: { 'java/util/ArrayList' }
You can view my code here, all class and method names I transform are right because if I remove both "ALOAD" (and remove the required parameters of course) it works
public byte[] transform(String name, String transformedName, byte[] basicClass) {
if (implementation == null) {
return basicClass;
}
if (transformedName.equals(implementation.getTooltipClassName()) || transformedName.length() > 0) {
ClassNode classNode = new ClassNode();
ClassReader classReader = new ClassReader(basicClass);
classReader.accept(classNode, 0);
methodFor: for (MethodNode methodNode : classNode.methods) {
if (methodNode.name.equals(implementation.getTooltipMethodName())) {
if (methodNode.desc.equals(implementation.getTooltipMethodDesc())) {
System.out.println("M:" + methodNode.name);
System.out.println("D: " + methodNode.desc);
for (int i = 0; i < methodNode.instructions.size(); i++) {
AbstractInsnNode node = methodNode.instructions.get(i);
if (node.getOpcode() == Opcodes.ARETURN) {
System.out.println("Method found");
AbstractInsnNode eventHook = new MethodInsnNode(Opcodes.INVOKESTATIC,
"org/forengoetter/eventhandler/EventAdapter", "onItemTooltip",
implementation.getTooltipEventMethodDesc(), false);
AbstractInsnNode loadHook = new VarInsnNode(Opcodes.ALOAD, 0);
AbstractInsnNode loadHookAdvanced = new VarInsnNode(Opcodes.ALOAD, 2);
methodNode.instructions.insertBefore(node, loadHook);
System.out.println("hook1");
methodNode.instructions.insertBefore(node, loadHookAdvanced);
System.out.println("hook2");
methodNode.instructions.insertBefore(node, eventHook);
System.out.println("hook3");
break methodFor;
}
}
}
}
}
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
classNode.accept(classWriter);
return classWriter.toByteArray();
}
return basicClass;
}
this is the method which should be called:
public static List<String> onItemTooltip(List<String> toolTip, ItemStack itemStack, ITooltipFlag advanced) {
ItemTooltipEvent event = new ItemTooltipEvent(itemStack, toolTip, advanced.isAdvanced());
// FOG.getInstance().getEventBus().post(event);
event.toolTip.add("this is a test");
return event.toolTip;
}
and this is the signature of this method I'm using in the asm transformation (Ljava/util/List;Laip;Lakb;)Ljava/util/List; (the signature is obfuscated because of minecraft, but the class names are right, I've checked it several times)
I hope somebody can help me.