package de.take_weiland.mods.commons.internal.transformers; import de.take_weiland.mods.commons.asm.MCPNames; import de.take_weiland.mods.commons.internal.ASMHooks; import net.minecraft.network.NetServerHandler; import net.minecraft.network.packet.Packet41EntityEffect; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Type; import static org.objectweb.asm.Opcodes.*; /** * @author diesieben07 */ public final class EntityTrackingHook extends MethodVisitor { private enum Stage { START, FOUND_NEW, FOUND_CSTR, FOUND_SEND_PACKET, FOUND_GOTO, DONE } private final String packetEntityEff = Type.getInternalName(Packet41EntityEffect.class); private final String netServerHandler = Type.getInternalName(NetServerHandler.class); private Stage stage = Stage.START; public EntityTrackingHook(MethodVisitor mv) { super(ASM4, mv); } @Override public void visitTypeInsn(int opcode, String type) { if (stage == Stage.START && opcode == NEW && type.equals(packetEntityEff)) { stage = Stage.FOUND_NEW; } super.visitTypeInsn(opcode, type); } @Override public void visitMethodInsn(int opcode, String owner, String name, String desc) { if (stage == Stage.FOUND_NEW && opcode == INVOKESPECIAL && owner.equals(packetEntityEff) && name.equals("<init>")) { stage = Stage.FOUND_CSTR; } else if (stage == Stage.FOUND_CSTR && opcode == INVOKEVIRTUAL && owner.equals(netServerHandler) && name.equals(MCPNames.method(MCPNames.M_SEND_PACKET_TO_PLAYER))) { stage = Stage.FOUND_SEND_PACKET; } super.visitMethodInsn(opcode, owner, name, desc); } @Override public void visitJumpInsn(int opcode, Label label) { if (stage == Stage.FOUND_SEND_PACKET && opcode == GOTO) { stage = Stage.FOUND_GOTO; } else if (stage == Stage.FOUND_GOTO && opcode == GOTO) { stage = Stage.DONE; super.visitVarInsn(ALOAD, 1); // load first arg, the player super.visitVarInsn(ALOAD, 0); // load this Type entityType = Type.getObjectType("net/minecraft/entity/Entity"); Type entityPlayerType = Type.getObjectType("net/minecraft/entity/player/EntityPlayer"); String owner = "net/minecraft/entity/EntityTrackerEntry"; String name = MCPNames.field(MCPNames.F_MY_ENTITY); String desc = entityType.getDescriptor(); super.visitFieldInsn(GETFIELD, owner, name, desc); String hookClazz = Type.getInternalName(ASMHooks.class); name = ASMHooks.ON_START_TRACKING; desc = Type.getMethodDescriptor(Type.VOID_TYPE, entityPlayerType, entityType); super.visitMethodInsn(INVOKESTATIC, hookClazz, name, desc); } super.visitJumpInsn(opcode, label); } }