Last active
December 27, 2015 05:09
-
-
Save boq/7272206 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package cpw.mods.fml.common.asm.transformers; | |
import java.util.Map; | |
import java.util.Set; | |
import net.minecraft.launchwrapper.IClassTransformer; | |
import org.objectweb.asm.*; | |
import org.objectweb.asm.commons.Method; | |
import com.google.common.collect.ImmutableSet; | |
import com.google.common.collect.Maps; | |
public class TestTransformer implements IClassTransformer { | |
private final static String bedHookCls = "openblocks/BedHook"; | |
private static class HookMethodVisitor extends MethodVisitor { | |
private final String methodName; | |
public HookMethodVisitor(MethodVisitor mv, String methodName) { | |
super(Opcodes.ASM4, mv); | |
this.methodName = methodName; | |
} | |
@Override | |
public void visitCode() { | |
mv.visitCode(); | |
mv.visitVarInsn(Opcodes.ALOAD, 0); //EntityPlayer this | |
mv.visitMethodInsn(Opcodes.INVOKESTATIC, bedHookCls, "hook", "(Lnet/minecraft/entity/player/EntityPlayer;)Z"); | |
Label skipReturn = new Label(); | |
mv.visitJumpInsn(Opcodes.IFEQ, skipReturn); | |
mv.visitLdcInsn(true); | |
mv.visitInsn(Opcodes.IRETURN); | |
mv.visitLabel(skipReturn); | |
} | |
} | |
public class HookClassVistor extends ClassVisitor { | |
private final Set<Method> methods; | |
public HookClassVistor(ClassVisitor cv, Set<Method> methods) { | |
super(Opcodes.ASM4, cv); | |
this.methods = ImmutableSet.copyOf(methods); | |
} | |
@Override | |
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { | |
Method type = new Method(name, desc); | |
MethodVisitor parent = super.visitMethod(access, name, desc, signature, exceptions); | |
return methods.contains(type) ? new HookMethodVisitor(parent, name) : parent; | |
} | |
} | |
private Map<String, Set<Method>> classes = Maps.newHashMap(); | |
{ | |
classes.put("net.minecraft.entity.player.EntityPlayer", ImmutableSet.<Method>of(new Method("isInBed", "()Z"))); | |
} | |
@Override | |
public byte[] transform(String name, String transformedName, byte[] bytes) { | |
Set<Method> methodsToModify = classes.get(transformedName); | |
if (methodsToModify == null) | |
return bytes; | |
ClassReader cr = new ClassReader(bytes); | |
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); | |
HookClassVistor mod = new HookClassVistor(cw, methodsToModify); | |
cr.accept(mod, 0); | |
return cw.toByteArray(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment