Jump to content

[1.7.10] ASM transforming causes ArrayIndexOutOfBoundsException


StarSheep

Recommended Posts

What I'm trying to do is adding a hooks for changing sky color without creating a new biome.

(I'm new to ASM, I used this tutorial : http://www.minecraftforum.net/forums/mapping-and-modding/mapping-and-modding-tutorials/1571568-tutorial-1-6-2-changing-vanilla-without-editing)

 

The crash:

 

java.lang.NoClassDefFoundError: net/minecraftforge/client/ForgeHooksClient

at net.minecraft.client.Minecraft.startGame(Minecraft.java:474)

at net.minecraft.client.Minecraft.run(Minecraft.java:931)

at net.minecraft.client.main.Main.main(Main.java:164)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

at java.lang.reflect.Method.invoke(Unknown Source)

at net.minecraft.launchwrapper.Launch.launch(Launch.java:135)

at net.minecraft.launchwrapper.Launch.main(Launch.java:28)

at net.minecraftforge.gradle.GradleStartCommon.launch(GradleStartCommon.java:78)

at GradleStart.main(GradleStart.java:45)

Caused by: java.lang.ClassNotFoundException: net.minecraftforge.client.ForgeHooksClient

at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:191)

at java.lang.ClassLoader.loadClass(Unknown Source)

at java.lang.ClassLoader.loadClass(Unknown Source)

... 11 more

Caused by: java.lang.ArrayIndexOutOfBoundsException: -1

at org.objectweb.asm.Frame.merge(Frame.java:1311)

at org.objectweb.asm.MethodWriter.visitMaxs(MethodWriter.java:1475)

at org.objectweb.asm.tree.MethodNode.accept(MethodNode.java:834)

at org.objectweb.asm.tree.MethodNode.accept(MethodNode.java:726)

at org.objectweb.asm.tree.ClassNode.accept(ClassNode.java:412)

at com.starsheep.colorevents.ColorTransformer.transformClientHooks(ColorTransformer.java:114)

at com.starsheep.colorevents.ColorTransformer.transform(ColorTransformer.java:43)

at net.minecraft.launchwrapper.LaunchClassLoader.runTransformers(LaunchClassLoader.java:279)

at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:176)

... 13 more

 

 

A detailed walkthrough of the error, its code path and all known details is as follows:

---------------------------------------------------------------------------------------

 

-- Head --

Stacktrace:

at net.minecraft.client.Minecraft.startGame(Minecraft.java:474)

 

-- Initialization --

Details:

Stacktrace:

at net.minecraft.client.Minecraft.run(Minecraft.java:931)

at net.minecraft.client.main.Main.main(Main.java:164)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

at java.lang.reflect.Method.invoke(Unknown Source)

at net.minecraft.launchwrapper.Launch.launch(Launch.java:135)

at net.minecraft.launchwrapper.Launch.main(Launch.java:28)

at net.minecraftforge.gradle.GradleStartCommon.launch(GradleStartCommon.java:78)

at GradleStart.main(GradleStart.java:45)

 

 

The code:

 

package com.starsheep.colorevents;

 

import static org.objectweb.asm.Opcodes.*;

 

import net.minecraft.launchwrapper.IClassTransformer;

 

import org.objectweb.asm.ClassReader;

import org.objectweb.asm.ClassWriter;

import org.objectweb.asm.Type;

import org.objectweb.asm.commons.LocalVariablesSorter;

import org.objectweb.asm.tree.AbstractInsnNode;

import org.objectweb.asm.tree.ClassNode;

import org.objectweb.asm.tree.FieldInsnNode;

import org.objectweb.asm.tree.InsnList;

import org.objectweb.asm.tree.InsnNode;

import org.objectweb.asm.tree.IntInsnNode;

import org.objectweb.asm.tree.MethodInsnNode;

import org.objectweb.asm.tree.MethodNode;

import org.objectweb.asm.tree.VarInsnNode;

 

public class ColorTransformer implements IClassTransformer {

 

@Override

public byte[] transform(String name, String transformedName, byte[] bytes)

{

if(name.equals("net.minecraftforge.client.ForgeHooksClient"))

{

System.out.println("Going To Transform: " + name);

return transformClientHooks(bytes);

}

return bytes;

}

 

private byte[] transformClientHooks(byte[] bytes)

{

ClassNode classNode = new ClassNode();

ClassReader classReader = new ClassReader(bytes);

classReader.accept(classNode, 0);

 

MethodNode method = ASMHelper.findMethod(classNode.methods, new String[] {"getSkyBlendColour"}, "(Lnet/minecraft/world/World;III)I");

LocalVariablesSorter sorter = new LocalVariablesSorter(method.access, method.desc, method);

 

InsnList toFind = new InsnList();

 

toFind.add(new VarInsnNode(ILOAD, 7));

toFind.add(new VarInsnNode(ILOAD, 10));

toFind.add(new InsnNode(IDIV));

toFind.add(new IntInsnNode(SIPUSH, 255));

toFind.add(new InsnNode(IAND));

toFind.add(new IntInsnNode(BIPUSH, 16));

toFind.add(new InsnNode(ISHL));

toFind.add(new VarInsnNode(ILOAD, 8));

toFind.add(new VarInsnNode(ILOAD, 10));

toFind.add(new InsnNode(IDIV));

toFind.add(new IntInsnNode(SIPUSH, 255));

toFind.add(new InsnNode(IAND));

toFind.add(new IntInsnNode(BIPUSH, 8));

toFind.add(new InsnNode(ISHL));

toFind.add(new InsnNode(IOR));

toFind.add(new VarInsnNode(ILOAD, 9));

toFind.add(new VarInsnNode(ILOAD, 10));

toFind.add(new InsnNode(IDIV));

toFind.add(new IntInsnNode(SIPUSH, 255));

toFind.add(new InsnNode(IAND));

toFind.add(new InsnNode(IOR));

toFind.add(new VarInsnNode(ISTORE, 11)); //int multiplier = (r / divider & 255) << 16 | (g / divider & 255) << 8 | b / divider & 255;

 

AbstractInsnNode node = ASMHelper.findFirst(toFind, method.instructions);

 

InsnList toInject = new InsnList();

 

int fieldEvent = sorter.newLocal(Type.getType(EventSkyColor.class));

toInject.add(new InsnNode(DUP));

toInject.add(new VarInsnNode(ILOAD, 7));

toInject.add(new VarInsnNode(ILOAD, 8));

toInject.add(new VarInsnNode(ILOAD, 9));

toInject.add(new MethodInsnNode(INVOKESPECIAL, "com/starsheep/colorevents/EventSkyColor", "<init>", "(III)V", false));

toInject.add(new VarInsnNode(ASTORE, fieldEvent)); //EventSkyColor event = new EventSkyColor(red, green, blue);

 

toInject.add(new FieldInsnNode(GETSTATIC, "net/minecraftforge/common/MinecraftForge", "EVENT_BUS", "Lcpw/mods/fml/common/eventhandler/EventBus;"));

toInject.add(new VarInsnNode(ALOAD, fieldEvent));

toInject.add(new FieldInsnNode(INVOKEVIRTUAL, "cpw/mods/fml/common/eventhandler/EventBus", "post", "(Lcpw/mods/fml/common/eventhandler/Event;)Z"));

toInject.add(new InsnNode(POP)); //MinecraftForge.EVENT_BUS.post(event);

 

toInject.add(new VarInsnNode(ALOAD, fieldEvent));

toInject.add(new FieldInsnNode(GETFIELD, "com/starsheep/colorevents/EventSkyColor", "red", "I"));

toInject.add(new VarInsnNode(ASTORE, 7)); // red = event.red;

 

toInject.add(new VarInsnNode(ALOAD, fieldEvent));

toInject.add(new FieldInsnNode(GETFIELD, "com/starsheep/colorevents/EventSkyColor", "green", "I"));

toInject.add(new VarInsnNode(ASTORE, 8)); // green = event.green;

 

toInject.add(new VarInsnNode(ALOAD, fieldEvent));

toInject.add(new FieldInsnNode(GETFIELD, "com/starsheep/colorevents/EventSkyColor", "blue", "I"));

toInject.add(new VarInsnNode(ASTORE, 9)); //blue = event.blue;

 

method.instructions.insertBefore(node, toInject);

 

ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);

classNode.accept(writer);

return writer.toByteArray();

}

}

 

 

 

ASMHelper (some parts are stolen from https://github.com/SanAndreasP/SAPManagerPack/blob/master/java/de/sanandrew/core/manpack/transformer/ASMHelper.java)

 

package com.starsheep.colorevents;

 

import java.util.Iterator;

import java.util.List;

 

import org.objectweb.asm.tree.*;

 

import static org.objectweb.asm.tree.AbstractInsnNode.*;

 

public class ASMHelper {

 

 

public static MethodNode findMethod(List<MethodNode> methods, String[] names, String desc)

{

Iterator<MethodNode> iterator = methods.iterator();

MethodNode method = null;

while(iterator.hasNext())

{

MethodNode m = iterator.next();

boolean flag = true;

for(String name : names)

{

if(m.name.equals(name)) flag = false;

}

if(flag) continue;

if(m.desc.equals("(Lnet/minecraft/world/World;III)I"))

{

System.out.println("Found Method: " + m.name);

method = m;

break;

}

}

return method;

}

 

public static AbstractInsnNode findFirst(InsnList key, InsnList fings)

{

Iterator<AbstractInsnNode> iterator = fings.iterator();

while(iterator.hasNext())

{

AbstractInsnNode n = iterator.next();

if(isInsnEqual(key, n))

{

return n;

}

}

return null;

}

 

public static AbstractInsnNode findLast(InsnList key, InsnList fings)

{

Iterator<AbstractInsnNode> iterator = fings.iterator();

int number = 0;

while(iterator.hasNext())

{

AbstractInsnNode n = iterator.next();

if(isInsnEqual(key, n))

{

return fings.get(number + key.size() - 1);

}

number++;

}

return null;

}

 

public static boolean isInsnEqual(InsnList key, AbstractInsnNode node)

{

Iterator<AbstractInsnNode> iterator = key.iterator();

while(iterator.hasNext())

{

AbstractInsnNode n = iterator.next();

if(!nodeEqual(node, n))

{

return false;

}

node = node.getNext();

}

return true;

}

 

public static boolean nodeEqual(AbstractInsnNode node1, AbstractInsnNode node2)

{

        if( node1.getType() != node2.getType() ) {

            return false;

        } else if( node1.getOpcode() != node2.getOpcode() ) {

            return false;

        }

 

        switch( node2.getType() )

        {

            case VAR_INSN :

                return varInsnEqual((VarInsnNode) node1, (VarInsnNode) node2);

            case TYPE_INSN :

                return typeInsnEqual((TypeInsnNode) node1, (TypeInsnNode) node2);

            case FIELD_INSN :

                return fieldInsnEqual((FieldInsnNode) node1, (FieldInsnNode) node2);

            case METHOD_INSN :

                return methodInsnEqual((MethodInsnNode) node1, (MethodInsnNode) node2);

            case LDC_INSN :

                return ldcInsnEqual((LdcInsnNode) node1, (LdcInsnNode) node2);

            case IINC_INSN :

                return iincInsnEqual((IincInsnNode) node1, (IincInsnNode) node2);

            case INT_INSN :

                return intInsnEqual((IntInsnNode) node1, (IntInsnNode) node2);

            default :

                return true;

        }

    }

 

public static boolean varInsnEqual(VarInsnNode insn1, VarInsnNode insn2)

{

        return insn1.var == -1 || insn2.var == -1 || insn1.var == insn2.var;

}

 

public static boolean typeInsnEqual(TypeInsnNode insn1, TypeInsnNode insn2)

{

        return insn1.desc.equals("~") || insn2.desc.equals("~") || insn1.desc.equals(insn2.desc);

}

 

public static boolean fieldInsnEqual(FieldInsnNode insn1, FieldInsnNode insn2)

{

      return insn1.owner.equals(insn2.owner) && insn1.name.equals(insn2.name) && insn1.desc.equals(insn2.desc);

}

 

public static boolean methodInsnEqual(MethodInsnNode insn1, MethodInsnNode insn2)

{

      return insn1.owner.equals(insn2.owner) && insn1.name.equals(insn2.name) && insn1.desc.equals(insn2.desc);

}

 

public static boolean ldcInsnEqual(LdcInsnNode insn1, LdcInsnNode insn2)

{

      return insn1.cst.equals("~") || insn2.cst.equals("~") || insn1.cst.equals(insn2.cst);

}

 

public static boolean iincInsnEqual(IincInsnNode node1, IincInsnNode node2)

{

    return node1.var == node2.var && node1.incr == node2.incr;

}

 

public static boolean intInsnEqual(IntInsnNode node1, IntInsnNode node2)

{

return node1.operand == -1 || node2.operand == -1 || node1.operand == node2.operand;

}

 

}

 

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.