hellfirepvp.astralsorcery.core.ClassPatch.java Source code

Java tutorial

Introduction

Here is the source code for hellfirepvp.astralsorcery.core.ClassPatch.java

Source

/*******************************************************************************
 * HellFirePvP / Astral Sorcery 2017
 *
 * This project is licensed under GNU GENERAL PUBLIC LICENSE Version 3.
 * The source code is available on github: https://github.com/HellFirePvP/AstralSorcery
 * For further details, see the License file there.
 ******************************************************************************/

package hellfirepvp.astralsorcery.core;

import net.minecraftforge.fml.common.FMLLog;
import org.objectweb.asm.tree.*;

import javax.annotation.Nonnull;

/**
 * This class is part of the Astral Sorcery Mod
 * The complete source code for this mod can be found on github.
 * Class: ClassPatch
 * Created by HellFirePvP
 * Date: 04.08.2016 / 00:39
 */
public abstract class ClassPatch {

    public boolean writeAsClassFile = false;

    private final String className;//, classNameObf;

    public ClassPatch(String className) {
        this.className = className;
    }

    public void transform(ClassNode node) {
        try {
            patch(node);
        } catch (ASMTransformationException exc) {
            throw new ASMTransformationException("Failed to applyServer ASM Transformation ClassPatch "
                    + getClass().getSimpleName().toUpperCase(), exc);
        }
    }

    public abstract void patch(ClassNode cn);

    public String getClassName() {
        return className;
    }

    @Nonnull
    public MethodNode getMethodLazy(ClassNode cn, String deobf, String obf) {
        for (MethodNode m : cn.methods) {
            if (m.name.equals(obf) || m.name.equals(deobf)) {
                return m;
            }
        }
        FMLLog.info("[AstralTransformer] Find method will fail. Printing all methods as debug...");
        for (MethodNode found : cn.methods) {
            FMLLog.info("Method: mame=" + found.name + ", desc=" + found.desc + ", signature=" + found.signature);
        }
        throw new ASMTransformationException("Could not find method: " + deobf + "/" + obf);
    }

    @Nonnull
    public MethodNode getMethod(ClassNode cn, String deobf, String obf, String sig) {
        for (MethodNode m : cn.methods) {
            if ((m.name.equals(obf) || m.name.equals(deobf)) && m.desc.equals(sig)) {
                return m;
            }
        }
        FMLLog.info("[AstralTransformer] Find method will fail. Printing all methods as debug...");
        for (MethodNode found : cn.methods) {
            FMLLog.info("Method: mame=" + found.name + ", desc=" + found.desc + ", signature=" + found.signature);
        }
        throw new ASMTransformationException("Could not find method: " + deobf + "/" + obf);
    }

    @Nonnull
    public AbstractInsnNode findNthInstruction(MethodNode mn, int n, int opCode) {
        return findNthInstructionAfter(mn, n, 0, opCode);
    }

    @Nonnull
    public AbstractInsnNode findNthInstructionAfter(MethodNode mn, int n, int startingIndex, int opCode) {
        AbstractInsnNode node = findFirstInstructionAfter(mn, startingIndex, opCode);
        int currentIndex = mn.instructions.indexOf(node) + 1;
        for (int i = 0; i <= (n - 1); i++) {
            node = findFirstInstructionAfter(mn, currentIndex, opCode);
            currentIndex = mn.instructions.indexOf(node) + 1;
        }
        return node;
    }

    @Nonnull
    public AbstractInsnNode findFirstInstruction(MethodNode mn, int opCode) {
        return findFirstInstructionAfter(mn, 0, opCode);
    }

    @Nonnull
    public AbstractInsnNode findFirstInstructionAfter(MethodNode mn, int startingIndex, int opCode) {
        for (int i = startingIndex; i < mn.instructions.size(); i++) {
            AbstractInsnNode ain = mn.instructions.get(i);
            if (ain.getOpcode() == opCode)
                return ain;
        }
        throw new ASMTransformationException("Couldn't find Instruction with opcode " + opCode);
    }

    @Nonnull
    public static MethodInsnNode getFirstMethodCallAfter(MethodNode mn, String owner, String nameDeobf,
            String nameObf, String sig, int startingIndex) {
        for (int i = startingIndex; i < mn.instructions.size(); i++) {
            AbstractInsnNode ain = mn.instructions.get(i);
            if (ain instanceof MethodInsnNode) {
                MethodInsnNode min = (MethodInsnNode) ain;
                if (min.owner.equals(owner) && (min.name.equals(nameDeobf) || min.name.equals(nameObf))
                        && min.desc.equals(sig)) {
                    return min;
                }
            }
        }
        throw new ASMTransformationException("Couldn't find method Instruction: owner=" + owner + " nameDeobf="
                + nameDeobf + " nameObf=" + nameObf + " signature=" + sig);
    }

    @Nonnull
    public static MethodInsnNode getFirstMethodCall(MethodNode mn, String owner, String nameDeobf, String nameObf,
            String sig) {
        return getNthMethodCallAfter(mn, owner, nameDeobf, nameObf, sig, 0, 0);
    }

    @Nonnull
    public static MethodInsnNode getNthMethodCall(MethodNode mn, String owner, String nameDeobf, String nameObf,
            String sig, int n) {
        return getNthMethodCallAfter(mn, owner, nameDeobf, nameObf, sig, n, 0);
    }

    @Nonnull
    public static MethodInsnNode getNthMethodCallAfter(MethodNode mn, String owner, String nameDeobf,
            String nameObf, String sig, int n, int startingIndex) {
        MethodInsnNode node = getFirstMethodCallAfter(mn, owner, nameDeobf, nameObf, sig, startingIndex);
        int currentIndex = mn.instructions.indexOf(node) + 1;
        for (int i = 0; i <= (n - 1); i++) {
            node = getFirstMethodCallAfter(mn, owner, nameDeobf, nameObf, sig, currentIndex);
            currentIndex = mn.instructions.indexOf(node) + 1;
        }
        return node;
    }

    @Nonnull
    public static LabelNode getFirstLabelBefore(MethodNode mn, int startIndex) {
        for (int i = startIndex; i >= 0; i--) {
            AbstractInsnNode isn = mn.instructions.get(i);
            if (isn instanceof LabelNode)
                return (LabelNode) isn;
        }
        throw new ASMTransformationException("Couldn't find LabelNode before index " + startIndex);
    }

    @Nonnull
    public static LabelNode getNextLabelAfter(MethodNode mn, int startIndex) {
        for (int i = startIndex; i < mn.instructions.size(); i++) {
            AbstractInsnNode isn = mn.instructions.get(i);
            if (isn instanceof LabelNode)
                return (LabelNode) isn;
        }
        throw new ASMTransformationException("Couldn't find LabelNode after index " + startIndex);
    }

}