net.lyonlancer5.mcmp.karasu.asm.KarasuTransformer.java Source code

Java tutorial

Introduction

Here is the source code for net.lyonlancer5.mcmp.karasu.asm.KarasuTransformer.java

Source

/***************************************************************************\
* Copyright 2016 [Lyonlancer5]                                              *
*                                                                           *
* Licensed under the Apache License, Version 2.0 (the "License");           *
* you may not use this file except in compliance with the License.          *
* You may obtain a copy of the License at                                   *
*                                                                           *
*     http://www.apache.org/licenses/LICENSE-2.0                            *
*                                                                           *
* Unless required by applicable law or agreed to in writing, software       *
* distributed under the License is distributed on an "AS IS" BASIS,         *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
* See the License for the specific language governing permissions and       *
* limitations under the License.                                            *
\***************************************************************************/
package net.lyonlancer5.mcmp.karasu.asm;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
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.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.VarInsnNode;

import net.lyonlancer5.mcmp.karasu.util.Constants;
import net.minecraft.launchwrapper.IClassTransformer;

public class KarasuTransformer implements IClassTransformer {

    public byte[] transform(String name, String transformedName, byte[] bytes) {
        int index = transformedName.contains("EntityLivingBase") ? 0 : -1;
        return index != -1 ? transform(index, bytes) : bytes;
    }

    private static byte[] transform(int index, byte[] classBeingTransformed) {
        try {
            ClassNode e = new ClassNode();
            ClassReader classReader = new ClassReader(classBeingTransformed);
            classReader.accept(e, 0);
            switch (index) {
            case 0:
                transformEntityLivingBase(e);
            default:
                ClassWriter classWriter = new ClassWriter(1);
                e.accept(classWriter);
                return classWriter.toByteArray();
            }
        } catch (Exception var6) {
            var6.printStackTrace();
            return classBeingTransformed;
        }
    }

    private static void transformEntityLivingBase(ClassNode classNode) {
        Constants.LOGGER.info("======== Project Karasu ~ Water Walking Enchantment Patch ========");
        Constants.LOGGER.info("Patching net.minecraft.entity.EntityLivingBase");

        for (MethodNode method : classNode.methods) {
            if (method.desc.equals("(FF)V")) {

                AbstractInsnNode movefNode = null;
                AbstractInsnNode motionxNode = null;
                AbstractInsnNode motionzNode = null;
                AbstractInsnNode motionyNode = null;
                AbstractInsnNode[] moveList = method.instructions.toArray();
                int var11 = moveList.length;

                for (int var12 = 0; var12 < var11; ++var12) {
                    AbstractInsnNode instruction = moveList[var12];
                    if (instruction.getOpcode() == Opcodes.ALOAD) {
                        if (((VarInsnNode) instruction).var == 0 && instruction.getNext().getOpcode() == Opcodes.DUP
                                && motionxNode == null) {
                            motionxNode = instruction;
                        } else if (((VarInsnNode) instruction).var == 0
                                && instruction.getNext().getOpcode() == Opcodes.DUP && motionyNode == null) {
                            motionyNode = instruction;
                        } else if (((VarInsnNode) instruction).var == 0
                                && instruction.getNext().getOpcode() == Opcodes.DUP && motionzNode == null) {
                            motionzNode = instruction;
                        } else if (movefNode == null && ((VarInsnNode) instruction).var == 0
                                && instruction.getNext().getOpcode() == Opcodes.FLOAD
                                && ((VarInsnNode) instruction.getNext()).var == 1) {
                            movefNode = instruction;
                        }
                    }
                }

                int var14;
                InsnList var15;

                if (method.name.equals("e")) {
                    Constants.LOGGER.info("Found matching method: " + method.name + " " + method.desc + " - (Obf)");
                    if (motionxNode != null) {
                        for (var14 = 0; var14 < 6; ++var14) {
                            motionxNode = motionxNode.getNext();
                            method.instructions.remove(motionxNode.getPrevious());
                        }
                        Constants.LOGGER.info("Patching sv.w");
                        var15 = new InsnList();
                        var15.add(new VarInsnNode(Opcodes.ALOAD, 0));
                        var15.add(new InsnNode(Opcodes.DUP));
                        var15.add(new FieldInsnNode(Opcodes.GETFIELD, "net/minecraft/entity/EntityLivingBase", "w",
                                "D"));
                        var15.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
                                "net/lyonlancer5/mcmp/karasu/asm/KarasuFeatherMetadata", "modifyHorizontalVel",
                                "()D", false));
                        var15.add(new InsnNode(Opcodes.DMUL));
                        var15.add(new FieldInsnNode(Opcodes.PUTFIELD, "net/minecraft/entity/EntityLivingBase", "w",
                                "D"));
                        method.instructions.insertBefore(motionxNode, var15);
                        Constants.LOGGER.info("Patched sv.w");
                    }

                    if (motionzNode != null) {
                        for (var14 = 0; var14 < 6; ++var14) {
                            motionzNode = motionzNode.getNext();
                            method.instructions.remove(motionzNode.getPrevious());
                        }

                        Constants.LOGGER.info("Patching sv.y");
                        var15 = new InsnList();
                        var15.add(new VarInsnNode(Opcodes.ALOAD, 0));
                        var15.add(new InsnNode(Opcodes.DUP));
                        var15.add(new FieldInsnNode(Opcodes.GETFIELD, "net/minecraft/entity/EntityLivingBase", "y",
                                "D"));
                        var15.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
                                "net/lyonlancer5/mcmp/karasu/asm/KarasuFeatherMetadata", "modifyHorizontalVel",
                                "()D", false));
                        var15.add(new InsnNode(Opcodes.DMUL));
                        var15.add(new FieldInsnNode(Opcodes.PUTFIELD, "net/minecraft/entity/EntityLivingBase", "y",
                                "D"));
                        method.instructions.insertBefore(motionzNode, var15);
                        Constants.LOGGER.info("Patched sv.y");
                    }

                    if (movefNode != null) {
                        for (var14 = 0; var14 < 14; ++var14) {
                            movefNode = movefNode.getNext();
                            method.instructions.remove(movefNode.getPrevious());
                        }

                        var15 = new InsnList();
                        var15.add(new VarInsnNode(Opcodes.ALOAD, 0));
                        var15.add(new VarInsnNode(Opcodes.FLOAD, 1));
                        var15.add(new VarInsnNode(Opcodes.FLOAD, 2));
                        var15.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
                                "net/lyonlancer5/mcmp/karasu/asm/KarasuFeatherMetadata", "modifyVerticalVel", "()F",
                                false));
                        var15.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "net/minecraft/entity/EntityLivingBase",
                                "a", "(FFF)V", false));
                        method.instructions.insertBefore(movefNode, var15);
                        Constants.LOGGER.info("Patching method -- sv.a (FFF)V");
                    }

                    Constants.LOGGER.info("Patch success!");
                    return;
                } else if (method.name.equals("moveEntityWithHeading")) {
                    Constants.LOGGER
                            .info("Found matching method: " + method.name + " " + method.desc + " - (Deobf)");
                    if (motionxNode != null) {
                        for (var14 = 0; var14 < 6; ++var14) {
                            motionxNode = motionxNode.getNext();
                            method.instructions.remove(motionxNode.getPrevious());
                        }

                        Constants.LOGGER.info("Patching EntityLivingBase.motionX");
                        var15 = new InsnList();
                        var15.add(new VarInsnNode(Opcodes.ALOAD, 0));
                        var15.add(new InsnNode(Opcodes.DUP));
                        var15.add(new FieldInsnNode(Opcodes.GETFIELD, "net/minecraft/entity/EntityLivingBase",
                                "motionX", "D"));
                        var15.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
                                "net/lyonlancer5/mcmp/karasu/asm/KarasuFeatherMetadata", "modifyHorizontalVel",
                                "()D", false));
                        var15.add(new InsnNode(Opcodes.DMUL));
                        var15.add(new FieldInsnNode(Opcodes.PUTFIELD, "net/minecraft/entity/EntityLivingBase",
                                "motionX", "D"));
                        method.instructions.insertBefore(motionxNode, var15);
                        Constants.LOGGER.info("Patched EntityLivingBase.motionX");
                    }

                    if (motionzNode != null) {
                        for (var14 = 0; var14 < 6; ++var14) {
                            motionzNode = motionzNode.getNext();
                            method.instructions.remove(motionzNode.getPrevious());
                        }

                        Constants.LOGGER.info("Patching EntityLivingBase.motionZ");
                        var15 = new InsnList();
                        var15.add(new VarInsnNode(Opcodes.ALOAD, 0));
                        var15.add(new InsnNode(Opcodes.DUP));
                        var15.add(new FieldInsnNode(Opcodes.GETFIELD, "net/minecraft/entity/EntityLivingBase",
                                "motionZ", "D"));
                        var15.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
                                "net/lyonlancer5/mcmp/karasu/asm/KarasuFeatherMetadata", "modifyHorizontalVel",
                                "()D", false));
                        var15.add(new InsnNode(Opcodes.DMUL));
                        var15.add(new FieldInsnNode(Opcodes.PUTFIELD, "net/minecraft/entity/EntityLivingBase",
                                "motionZ", "D"));
                        method.instructions.insertBefore(motionzNode, var15);
                        Constants.LOGGER.info("Patched EntityLivingBase.motionZ");
                    }

                    if (movefNode != null) {
                        for (var14 = 0; var14 < 14; ++var14) {
                            movefNode = movefNode.getNext();
                            method.instructions.remove(movefNode.getPrevious());
                        }

                        var15 = new InsnList();
                        var15.add(new VarInsnNode(Opcodes.ALOAD, 0));
                        var15.add(new VarInsnNode(Opcodes.FLOAD, 1));
                        var15.add(new VarInsnNode(Opcodes.FLOAD, 2));
                        var15.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
                                "net/lyonlancer5/mcmp/karasu/asm/KarasuFeatherMetadata", "modifyVerticalVel", "()F",
                                false));
                        var15.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "net/minecraft/entity/EntityLivingBase",
                                "moveFlying", "(FFF)V", false));
                        method.instructions.insertBefore(movefNode, var15);
                        Constants.LOGGER.info("Patched method - EntityLivingBase.moveFlying (FFF)V");
                    }

                    Constants.LOGGER.info("Patch success!");
                    return;
                } else if (method.name.equals("func_70612_e")) {
                    Constants.LOGGER.info("Found matching method: " + method.name + " " + method.desc + " - (srg)");
                    if (motionxNode != null) {
                        for (var14 = 0; var14 < 6; ++var14) {
                            motionxNode = motionxNode.getNext();
                            method.instructions.remove(motionxNode.getPrevious());
                        }

                        Constants.LOGGER.info("Patching EntityLivingBase.field_70159_w");
                        var15 = new InsnList();
                        var15.add(new VarInsnNode(Opcodes.ALOAD, 0));
                        var15.add(new InsnNode(Opcodes.DUP));
                        var15.add(new FieldInsnNode(Opcodes.GETFIELD, "net/minecraft/entity/EntityLivingBase",
                                "field_70159_w", "D"));
                        var15.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
                                "net/lyonlancer5/mcmp/karasu/asm/KarasuFeatherMetadata", "modifyHorizontalVel",
                                "()D", false));
                        var15.add(new InsnNode(Opcodes.DMUL));
                        var15.add(new FieldInsnNode(Opcodes.PUTFIELD, "net/minecraft/entity/EntityLivingBase",
                                "field_70159_w", "D"));
                        method.instructions.insertBefore(motionxNode, var15);
                        Constants.LOGGER.info("Patched EntityLivingBase.field_70159_w");
                    }

                    if (motionzNode != null) {
                        for (var14 = 0; var14 < 6; ++var14) {
                            motionzNode = motionzNode.getNext();
                            method.instructions.remove(motionzNode.getPrevious());
                        }

                        Constants.LOGGER.info("Patching EntityLivingBase.field_70179_y");
                        var15 = new InsnList();
                        var15.add(new VarInsnNode(Opcodes.ALOAD, 0));
                        var15.add(new InsnNode(Opcodes.DUP));
                        var15.add(new FieldInsnNode(Opcodes.GETFIELD, "net/minecraft/entity/EntityLivingBase",
                                "field_70179_y", "D"));
                        var15.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
                                "net/lyonlancer5/mcmp/karasu/asm/KarasuFeatherMetadata", "modifyHorizontalVel",
                                "()D", false));
                        var15.add(new InsnNode(Opcodes.DMUL));
                        var15.add(new FieldInsnNode(Opcodes.PUTFIELD, "net/minecraft/entity/EntityLivingBase",
                                "field_70179_y", "D"));
                        method.instructions.insertBefore(motionzNode, var15);
                        Constants.LOGGER.info("Patched EntityLivingBase.field_70179_y");
                    }

                    if (movefNode != null) {
                        for (var14 = 0; var14 < 14; ++var14) {
                            movefNode = movefNode.getNext();
                            method.instructions.remove(movefNode.getPrevious());
                        }

                        var15 = new InsnList();
                        var15.add(new VarInsnNode(Opcodes.ALOAD, 0));
                        var15.add(new VarInsnNode(Opcodes.FLOAD, 1));
                        var15.add(new VarInsnNode(Opcodes.FLOAD, 2));
                        var15.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
                                "net/lyonlancer5/mcmp/karasu/asm/KarasuFeatherMetadata", "modifyVerticalVel", "()F",
                                false));
                        var15.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "net/minecraft/entity/EntityLivingBase",
                                "func_70060_a", "(FFF)V", false));
                        method.instructions.insertBefore(movefNode, var15);
                        Constants.LOGGER.info("Patched method - EntityLivingBase.func_70060_a (FFF)V");
                    }

                    Constants.LOGGER.info("Patch success!");
                    return;
                }
            }
        }
        // #OVERKILL
        throw new RuntimeException("Patch FAILED -- No matching method found");

    }
}