Hello!
I try to modify 2 functions: getSkinUrl and getCapeUrl with ASM in order to create my own skin system. In this way i can do event in my server. Tank's to this code I have managed to delete the content of function and i have add a invocation to a static method. But I want return the result and I don't know how do this!
package pickandcraftSkin;
import static org.objectweb.asm.Opcodes.ALOAD;
import static org.objectweb.asm.Opcodes.INVOKESTATIC;
import java.util.Iterator;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.VarInsnNode;
public class EDClassTransformer implements net.minecraft.launchwrapper.IClassTransformer {
@Override
public byte[] transform(String arg0, String arg1, byte[] arg2) {
if (arg0.equals("beu")) {
System.out.println("********* INSIDE OBFUSCATED AbstractClientPlayer TRANSFORMER ABOUT TO PATCH: " + arg0);
return patchClassASM(arg0, arg2, true);
}
if (arg0.equals("net.minecraft.client.entity.AbstractClientPlayer")) {
System.out.println("********* INSIDE AbstractClientPlayer TRANSFORMER ABOUT TO PATCH: " + arg0);
return patchClassASM(arg0, arg2, false);
}
return arg2;
}
public byte[] patchClassASM(String name, byte[] bytes, boolean obfuscated) {
String targetMethodName = "";
if(obfuscated == true)
targetMethodName ="d";
else
targetMethodName ="getSkinUrl";
//set up ASM class manipulation stuff. Consult the ASM docs for details
ClassNode classNode = new ClassNode();
ClassReader classReader = new ClassReader(bytes);
classReader.accept(classNode, 0);
//Now we loop over all of the methods declared inside the Explosion class until we get to the targetMethodName "doExplosionB"
// find method to inject into
@SuppressWarnings("unchecked")
Iterator<MethodNode> methods = classNode.methods.iterator();
while(methods.hasNext())
{
MethodNode m = methods.next();
System.out.println("********* Method Name: "+m.name + " Desc:" + m.desc);
//Check if this is doExplosionB and it's method signature is (Z)V which means that it accepts a boolean (Z) and returns a void (V)
if ((m.name.equals(targetMethodName) && m.desc.equals("(Ljava/lang/String;)Ljava/lang/String;")))
{
System.out.println("********* Inside target method!");
//on supprime tous les noeuds
AbstractInsnNode targetNode = null;
@SuppressWarnings("unchecked")
Iterator<AbstractInsnNode> iter = m.instructions.iterator();
int index = -1;
while (iter.hasNext()) {
index++;
targetNode = iter.next();
m.instructions.remove(targetNode);
}
InsnList toInject = new InsnList();
toInject.add(new VarInsnNode(ALOAD, 0));
toInject.add(new MethodInsnNode(INVOKESTATIC, "pickandcraftSkin/PlayerCustom", "getURLSkincustom", "(Ljava/lang/String;)Ljava/lang/String;"));
// inject new instruction list into method instruction list
m.instructions.insert(toInject);
System.out.println("Patching Complete!");
break;
}
}
//ASM specific for cleaning up and returning the final bytes for JVM processing.
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
classNode.accept(writer);
return writer.toByteArray();
}
}