From c05ab91d68cfb0bbd3f1d1eedb732f175989e5a2 Mon Sep 17 00:00:00 2001 From: Sam Kirby Date: Sun, 7 Jun 2020 21:24:07 +0100 Subject: [PATCH] Primal's Steppe Wolves now fear fish This is to prevent further fish massacre --- .../core/SevPatchesLoadingPlugin.java | 8 ++ .../core/SevPatchesTransformer.java | 98 ++++++++++++++++++- 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/src/main/java/tv/darkosto/sevpatches/core/SevPatchesLoadingPlugin.java b/src/main/java/tv/darkosto/sevpatches/core/SevPatchesLoadingPlugin.java index 8152424..fd33f01 100644 --- a/src/main/java/tv/darkosto/sevpatches/core/SevPatchesLoadingPlugin.java +++ b/src/main/java/tv/darkosto/sevpatches/core/SevPatchesLoadingPlugin.java @@ -34,6 +34,10 @@ public class SevPatchesLoadingPlugin implements IFMLLoadingPlugin { public static String VEC_3I_DISTANCE_SQ; public static String VEC_3I_DISTANCE_SQ_DESC; + public static String INIT_ENTITY_AI; + public static String ENTITY_TASKS; + public static String ENTITY_TASKS_ADD_TASK; + public SevPatchesLoadingPlugin() { LOGGER.info("setting up mixin environment"); MixinBootstrap.init(); @@ -79,6 +83,10 @@ public void injectData(Map data) { SevPatchesLoadingPlugin.FIND_CHUNKS_FOR_SPAWNING_DESC = dev ? "(Lnet/minecraft/world/WorldServer;ZZZ)I" : "(Loo;ZZZ)I"; SevPatchesLoadingPlugin.VEC_3I_DISTANCE_SQ = dev ? "distanceSq" : "f"; SevPatchesLoadingPlugin.VEC_3I_DISTANCE_SQ_DESC = "(DDD)D"; + + SevPatchesLoadingPlugin.INIT_ENTITY_AI = dev ? "initEntityAI" : "func_184651_r"; + SevPatchesLoadingPlugin.ENTITY_TASKS = dev ? "tasks" : "field_70714_bg"; + SevPatchesLoadingPlugin.ENTITY_TASKS_ADD_TASK = dev ? "addTask" : "func_75776_a"; } @Override diff --git a/src/main/java/tv/darkosto/sevpatches/core/SevPatchesTransformer.java b/src/main/java/tv/darkosto/sevpatches/core/SevPatchesTransformer.java index 3499040..1c74bab 100644 --- a/src/main/java/tv/darkosto/sevpatches/core/SevPatchesTransformer.java +++ b/src/main/java/tv/darkosto/sevpatches/core/SevPatchesTransformer.java @@ -5,7 +5,21 @@ import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.*; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.AnnotationNode; +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.JumpInsnNode; +import org.objectweb.asm.tree.LabelNode; +import org.objectweb.asm.tree.LdcInsnNode; +import org.objectweb.asm.tree.LineNumberNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.TypeInsnNode; +import org.objectweb.asm.tree.VarInsnNode; import java.util.Arrays; import java.util.ListIterator; @@ -36,6 +50,8 @@ public byte[] transform(String name, String transformedName, byte[] basicClass) return this.fishAreFish(basicClass); case "nmd.primal.core.common.entities.living.EntityHammerHead": return this.nicerHammerHeads(basicClass); + case "nmd.primal.core.common.entities.living.EntityCanisCampestris": + return this.scaredyCat(basicClass); default: return basicClass; } @@ -60,6 +76,86 @@ private void setEventSubPriority(ClassNode input, String targetMethod, String pr } } + /** + * Make Primal's Steppe Wolves scared of fish + */ + private byte[] scaredyCat(byte[] basicClass) { + ClassReader classReader = new ClassReader(basicClass); + + ClassNode classNode = new ClassNode(); + classReader.accept(classNode, 0); + + MethodNode initEntityAI = null; + + for (MethodNode methodNode : classNode.methods) { + if (!methodNode.name.equals(SevPatchesLoadingPlugin.INIT_ENTITY_AI)) continue; + initEntityAI = methodNode; + break; + } + + if (initEntityAI == null) { + SevPatchesLoadingPlugin.LOGGER.warn("Did not find target method (scaredyCat)"); + return basicClass; + } + + InsnNode returnInsn = null; + + for (ListIterator it = initEntityAI.instructions.iterator(); it.hasNext(); ) { + AbstractInsnNode insnNode = it.next(); + + if (insnNode.getOpcode() == Opcodes.RETURN) { + returnInsn = (InsnNode) insnNode; + break; + } + } + + if (returnInsn == null) { + SevPatchesLoadingPlugin.LOGGER.warn("This method does not return?"); + return basicClass; + } + + InsnList scaredWolf = new InsnList(); + + scaredWolf.add(new VarInsnNode(Opcodes.ALOAD, 0)); + scaredWolf.add(new FieldInsnNode( + Opcodes.GETFIELD, + "nmd/primal/core/common/entities/living/EntityCanisCampestris", + SevPatchesLoadingPlugin.ENTITY_TASKS, + "Lnet/minecraft/entity/ai/EntityAITasks;" + )); + scaredWolf.add(new InsnNode(Opcodes.ICONST_1)); + scaredWolf.add(new TypeInsnNode( + Opcodes.NEW, + "net/minecraft/entity/ai/EntityAIAvoidEntity" + )); + scaredWolf.add(new InsnNode(Opcodes.DUP)); + scaredWolf.add(new VarInsnNode(Opcodes.ALOAD, 0)); + scaredWolf.add(new LdcInsnNode(Type.getObjectType("com/tmtravlr/jaff/entities/EntityFish"))); + scaredWolf.add(new LdcInsnNode(6.0F)); + scaredWolf.add(new InsnNode(Opcodes.DCONST_1)); + scaredWolf.add(new LdcInsnNode(1.2D)); + scaredWolf.add(new MethodInsnNode( + Opcodes.INVOKESPECIAL, + "net/minecraft/entity/ai/EntityAIAvoidEntity", + "", + "(Lnet/minecraft/entity/EntityCreature;Ljava/lang/Class;FDD)V", + false + )); + scaredWolf.add(new MethodInsnNode( + Opcodes.INVOKEVIRTUAL, + "net/minecraft/entity/ai/EntityAITasks", + SevPatchesLoadingPlugin.ENTITY_TASKS_ADD_TASK, + "(ILnet/minecraft/entity/ai/EntityAIBase;)V", + false + )); + + initEntityAI.instructions.insertBefore(returnInsn, scaredWolf); + + ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); + classNode.accept(classWriter); + return classWriter.toByteArray(); + } + /** * Prevent Primal's Hammerhead from murdering all the fish */