Move generic logic from ResourcePackHookPatch to PatchUtil

This commit is contained in:
JFronny 2021-10-03 20:12:36 +02:00
parent ded7c20fdb
commit 9cad07b82d
No known key found for this signature in database
GPG Key ID: BEC5ACBBD4EE17E5
3 changed files with 74 additions and 47 deletions

View File

@ -1,15 +1,15 @@
package io.gitlab.jfronny.libjf.data.manipulation.impl;
import io.gitlab.jfronny.libjf.unsafe.asm.AsmConfig;
import io.gitlab.jfronny.libjf.unsafe.asm.AsmTransformer;
import io.gitlab.jfronny.libjf.unsafe.asm.patch.Patch;
import io.gitlab.jfronny.libjf.unsafe.asm.patch.PatchUtil;
import io.gitlab.jfronny.libjf.unsafe.asm.patch.modification.MethodModificationPatch;
import io.gitlab.jfronny.libjf.unsafe.asm.patch.targeting.InterfaceImplTargetPatch;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.*;
import org.objectweb.asm.tree.MethodNode;
import java.io.IOException;
import java.io.InputStream;
import java.util.Set;
public class ResourcePackHookPatch implements AsmConfig {
@ -17,7 +17,7 @@ public class ResourcePackHookPatch implements AsmConfig {
private static final String HOOK_IMPLEMENTATION = Type.getInternalName(ResourcePackHook.class);
@Override
public Set<String> skipClasses() {
return Set.of(getClass(TARGET_CLASS_INTERMEDIARY));
return Set.of(PatchUtil.getRemapped(TARGET_CLASS_INTERMEDIARY));
}
@Override
@ -46,50 +46,10 @@ public class ResourcePackHookPatch implements AsmConfig {
}
private void hookReturn(MethodNode method, String targetMethod, String targetType, String[] extraParamTypes) {
for (AbstractInsnNode node : method.instructions) {
if (node.getOpcode() == Opcodes.IRETURN || node.getOpcode() == Opcodes.ARETURN) {
method.instructions.insertBefore(node, buildInvoker(targetMethod, targetType, targetType, extraParamTypes));
}
}
PatchUtil.redirectReturn(method, TARGET_CLASS_INTERMEDIARY, HOOK_IMPLEMENTATION, targetMethod, targetType, extraParamTypes);
}
private void catchEx(MethodNode method, String targetMethod, String[] extraParamTypes) {
LabelNode start = new LabelNode();
LabelNode end = new LabelNode();
LabelNode handler = new LabelNode();
method.instructions.insertBefore(method.instructions.getFirst(), start);
method.instructions.insertBefore(method.instructions.getLast(), end);
method.instructions.add(handler);
method.instructions.add(buildInvoker(targetMethod, "Ljava/io/IOException;", "Ljava/io/InputStream;", extraParamTypes));
method.instructions.add(new InsnNode(Opcodes.ARETURN));
method.tryCatchBlocks.add(new TryCatchBlockNode(start, end, handler, Type.getInternalName(IOException.class)));
}
private InsnList buildInvoker(String targetMethod, String inType, String outType, String[] extraParamTypes) {
InsnList instructions = new InsnList();
instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
StringBuilder descriptor = new StringBuilder("(").append(inType);
descriptor.append('L').append(getClassInternal("net/minecraft/class_3262")).append(';');
for (int i = 0; i < extraParamTypes.length; i++) {
if (extraParamTypes[i].equals("I"))
instructions.add(new VarInsnNode(Opcodes.ILOAD, i + 1));
else
instructions.add(new VarInsnNode(Opcodes.ALOAD, i + 1));
if (extraParamTypes[i].length() == 1)
descriptor.append(extraParamTypes[i]);
else
descriptor.append('L').append(getClassInternal(extraParamTypes[i])).append(';');
}
descriptor.append(")").append(outType);
instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, HOOK_IMPLEMENTATION, targetMethod, descriptor.toString()));
return instructions;
}
private String getClassInternal(String name) {
return getClass(name.replace('/', '.')).replace('.', '/');
}
private String getClass(String name) {
return AsmTransformer.MAPPING_RESOLVER.mapClassName(AsmTransformer.INTERMEDIARY, name);
PatchUtil.redirectExceptions(method, TARGET_CLASS_INTERMEDIARY, HOOK_IMPLEMENTATION, Type.getInternalName(IOException.class), Type.getInternalName(InputStream.class), targetMethod, extraParamTypes);
}
}

View File

@ -58,7 +58,7 @@ public class AsmTransformer extends FabricMixinTransformerProxy {
return classBytes;
}
public boolean isClassUnmoddable(String className, AsmConfig config) {
public static boolean isClassUnmoddable(String className, AsmConfig config) {
if (className.replace('/', '.').startsWith("org.objectweb.asm")
//|| className.startsWith("net.fabricmc.loader")
//|| className.startsWith("io.gitlab.jfronny.libjf.unsafe.asm")

View File

@ -0,0 +1,67 @@
package io.gitlab.jfronny.libjf.unsafe.asm.patch;
import io.gitlab.jfronny.libjf.unsafe.asm.AsmTransformer;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.*;
public class PatchUtil {
public static String getRemappedInternal(String className) {
return getRemapped(className.replace('/', '.')).replace('.', '/');
}
public static String getRemapped(String className) {
return AsmTransformer.MAPPING_RESOLVER.mapClassName(AsmTransformer.INTERMEDIARY, className);
}
public static void redirectReturn(MethodNode method, String targetClass, String hookClass, String targetMethod, String targetType, String[] extraParamTypes) {
for (AbstractInsnNode node : method.instructions) {
if (node.getOpcode() == Opcodes.ARETURN
|| node.getOpcode() == Opcodes.IRETURN
|| node.getOpcode() == Opcodes.DRETURN
|| node.getOpcode() == Opcodes.FRETURN
|| node.getOpcode() == Opcodes.LRETURN) {
method.instructions.insertBefore(node, PatchUtil.buildParamPassingInvoker(targetClass, hookClass, targetMethod, targetType, targetType, extraParamTypes));
}
}
}
public static void redirectExceptions(MethodNode method, String targetClass, String hookClass, String exceptionType, String returnTypeNormal, String targetMethod, String[] extraParamTypes) {
LabelNode start = new LabelNode();
LabelNode end = new LabelNode();
LabelNode handler = new LabelNode();
method.instructions.insertBefore(method.instructions.getFirst(), start);
method.instructions.insertBefore(method.instructions.getLast(), end);
method.instructions.add(handler);
method.instructions.add(PatchUtil.buildParamPassingInvoker(targetClass,
hookClass,
targetMethod,
"L" + getRemappedInternal(exceptionType) + ";",
"L" + getRemappedInternal(returnTypeNormal) + ";",
extraParamTypes));
method.instructions.add(new InsnNode(Opcodes.ARETURN));
method.tryCatchBlocks.add(new TryCatchBlockNode(start, end, handler, exceptionType));
}
public static InsnList buildParamPassingInvoker(String targetClass, String hookClass, String targetMethod, String inType, String outType, String[] extraParamTypes) {
InsnList instructions = new InsnList();
instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
StringBuilder descriptor = new StringBuilder("(").append(inType);
descriptor.append('L').append(getRemappedInternal(targetClass)).append(';');
for (int i = 0; i < extraParamTypes.length; i++) {
instructions.add(new VarInsnNode(switch (extraParamTypes[i]) {
case "I" -> Opcodes.ILOAD;
case "D" -> Opcodes.DLOAD;
case "F" -> Opcodes.FLOAD;
case "L" -> Opcodes.LLOAD;
default -> Opcodes.ALOAD;
}, i + 1));
if (extraParamTypes[i].length() == 1)
descriptor.append(extraParamTypes[i]);
else
descriptor.append('L').append(PatchUtil.getRemappedInternal(extraParamTypes[i])).append(';');
}
descriptor.append(")").append(outType);
instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, hookClass, targetMethod, descriptor.toString()));
return instructions;
}
}