package joshie.harvest.asm.transformers; 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.MethodInsnNode; import org.objectweb.asm.tree.MethodNode; import java.util.HashSet; import java.util.Set; /** Removes the call to wakePlayer, in onUpdate when * It is daytime. This is to allow the player to sleep at any time * of day that they wish, in order to pass the time quicker. */ public class PlayerWakeTransformer extends AbstractASM { @Override public boolean isClass(String name) { return name.equals("net.minecraft.entity.player.EntityPlayer") || name.equals("zs"); } @Override public boolean isVisitor() { return false; } private boolean isOnUpdate(String name, String descriptor) { return descriptor.equals("()V") && (name.equals("onUpdate") || name.equals("func_70071_h_") || name.equals("m")); } private boolean isWakeupPlayer(String name, String descriptor) { return descriptor.equals("(ZZZ)V") && (name.equals("wakeUpPlayer") || name.equals("func_70999_a") || name.equals("a")); } private boolean isDaytime(String name, String descriptor) { return descriptor.equals("()Z") && (name.equals("isDaytime") || name.equals("func_72935_r") || name.equals("B")); } @Override public byte[] transform(byte[] data) { ClassNode classNode = new ClassNode(); ClassReader classReader = new ClassReader(data); classReader.accept(classNode, 0); topLabel: for (MethodNode method : classNode.methods) { if (isOnUpdate(method.name, method.desc)) { for (int i = 0; i < method.instructions.size(); i++) { AbstractInsnNode node = method.instructions.get(i); if (node instanceof MethodInsnNode) { MethodInsnNode mNode = ((MethodInsnNode) node); if ((isWakeupPlayer(mNode.name, mNode.desc)) && method.instructions.get(i - 8) instanceof MethodInsnNode){ MethodInsnNode previous = ((MethodInsnNode)method.instructions.get(i - 8)); if (isDaytime(previous.name, previous.desc)) { Set<AbstractInsnNode> remove = new HashSet<>(); for (int j = 0; j <= 5; j++) { remove.add(method.instructions.get(i - j)); } for (AbstractInsnNode instruction : remove) { method.instructions.remove(instruction); } break topLabel; } } } } } } ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS); classNode.accept(writer); return writer.toByteArray(); } }