Actually return transformed byte source

This commit is contained in:
IzzelAliz 2021-02-20 17:17:00 +08:00
parent 2a01f3230a
commit 5dd94c727d
2 changed files with 33 additions and 14 deletions

View File

@ -162,7 +162,7 @@ public class ArclightRedirectAdapter implements PluginTransformer {
for (AbstractInsnNode insnNode : methodNode.instructions) { for (AbstractInsnNode insnNode : methodNode.instructions) {
if (insnNode instanceof MethodInsnNode) { if (insnNode instanceof MethodInsnNode) {
MethodInsnNode from = (MethodInsnNode) insnNode; MethodInsnNode from = (MethodInsnNode) insnNode;
process(from, methodNode.instructions, remapper); process(from, methodNode.instructions, remapper, classNode);
} else if (insnNode.getOpcode() == Opcodes.INVOKEDYNAMIC) { } else if (insnNode.getOpcode() == Opcodes.INVOKEDYNAMIC) {
InvokeDynamicInsnNode invokeDynamic = (InvokeDynamicInsnNode) insnNode; InvokeDynamicInsnNode invokeDynamic = (InvokeDynamicInsnNode) insnNode;
Object[] bsmArgs = invokeDynamic.bsmArgs; Object[] bsmArgs = invokeDynamic.bsmArgs;
@ -193,7 +193,7 @@ public class ArclightRedirectAdapter implements PluginTransformer {
return handle; return handle;
} }
private static void process(MethodInsnNode node, InsnList insnList, ClassLoaderRemapper remapper) { private static void process(MethodInsnNode node, InsnList insnList, ClassLoaderRemapper remapper, ClassNode classNode) {
String key = node.name + node.desc; String key = node.name + node.desc;
Collection<Product2<String, MethodInsnNode>> modifyArgsCol = METHOD_MODIFY.get(key); Collection<Product2<String, MethodInsnNode>> modifyArgsCol = METHOD_MODIFY.get(key);
for (Product2<String, MethodInsnNode> modifyArgs : modifyArgsCol) { for (Product2<String, MethodInsnNode> modifyArgs : modifyArgsCol) {
@ -205,7 +205,7 @@ public class ArclightRedirectAdapter implements PluginTransformer {
} else { } else {
handlerNode = modifyArgs._2; handlerNode = modifyArgs._2;
} }
processModify(node, insnList, handlerNode); processModify(node, insnList, handlerNode, classNode);
return; return;
} }
} }
@ -233,13 +233,19 @@ public class ArclightRedirectAdapter implements PluginTransformer {
insnList.set(node, handlerNode); insnList.set(node, handlerNode);
} }
private static void processModify(MethodInsnNode node, InsnList insnList, MethodInsnNode handlerNode) { private static void processModify(MethodInsnNode node, InsnList insnList, MethodInsnNode handlerNode, ClassNode classNode) {
InsnList list = new InsnList(); InsnList list = new InsnList();
list.add(handlerNode); list.add(handlerNode);
Type methodType = Type.getMethodType(node.desc); Type methodType = Type.getMethodType(node.desc);
Type[] types = methodType.getArgumentTypes(); Type[] types = methodType.getArgumentTypes();
if (node.getOpcode() != Opcodes.INVOKESTATIC) { if (node.getOpcode() != Opcodes.INVOKESTATIC) {
types = ArrayUtil.prepend(types, Type.getObjectType(node.owner), Type[]::new); Type selfType;
if (node.getOpcode() == Opcodes.INVOKESPECIAL) {
selfType = Type.getObjectType(classNode.name);
} else {
selfType = Type.getObjectType(node.owner);
}
types = ArrayUtil.prepend(types, selfType, Type[]::new);
} }
if (types.length == 1) { if (types.length == 1) {
if (node.desc.startsWith("()")) { if (node.desc.startsWith("()")) {

View File

@ -1,19 +1,20 @@
package io.izzel.arclight.common.mod.util.remapper.resource; package io.izzel.arclight.common.mod.util.remapper.resource;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import cpw.mods.modlauncher.ClassTransformer;
import cpw.mods.modlauncher.TransformingClassLoader;
import io.izzel.arclight.api.Unsafe; import io.izzel.arclight.api.Unsafe;
import io.izzel.arclight.common.mod.util.remapper.ArclightRemapper; import io.izzel.arclight.common.mod.util.remapper.ArclightRemapper;
import io.izzel.arclight.common.mod.util.remapper.GlobalClassRepo; import io.izzel.arclight.common.mod.util.remapper.GlobalClassRepo;
import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.ClassNode;
import org.spongepowered.asm.service.MixinService;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.net.URLStreamHandler; import java.net.URLStreamHandler;
@ -28,6 +29,21 @@ public class RemapSourceHandler extends URLStreamHandler {
private static class RemapSourceConnection extends URLConnection { private static class RemapSourceConnection extends URLConnection {
private static final MethodHandle MH_TRANSFORM;
static {
try {
ClassLoader classLoader = RemapSourceConnection.class.getClassLoader();
Field classTransformer = TransformingClassLoader.class.getDeclaredField("classTransformer");
classTransformer.setAccessible(true);
ClassTransformer tranformer = (ClassTransformer) classTransformer.get(classLoader);
Method transform = tranformer.getClass().getDeclaredMethod("transform", byte[].class, String.class, String.class);
MH_TRANSFORM = Unsafe.lookup().unreflect(transform).bindTo(tranformer);
} catch (Throwable t) {
throw new IllegalStateException("Unknown modlauncher version", t);
}
}
private byte[] array; private byte[] array;
protected RemapSourceConnection(URL url) { protected RemapSourceConnection(URL url) {
@ -38,13 +54,10 @@ public class RemapSourceHandler extends URLStreamHandler {
public void connect() throws IOException { public void connect() throws IOException {
byte[] bytes = ByteStreams.toByteArray(url.openStream()); byte[] bytes = ByteStreams.toByteArray(url.openStream());
String className = new ClassReader(bytes).getClassName(); String className = new ClassReader(bytes).getClassName();
if (className.startsWith("net/minecraft/")) { if (className.startsWith("net/minecraft/") || className.equals("com/mojang/brigadier/tree/CommandNode")) {
try { try {
ClassNode classNode = MixinService.getService().getBytecodeProvider().getClassNode(className); bytes = (byte[]) MH_TRANSFORM.invokeExact(bytes, className.replace('/', '.'), "source");
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); } catch (Throwable e) {
classNode.accept(cw);
bytes = cw.toByteArray();
} catch (ClassNotFoundException e) {
throw new IOException(e); throw new IOException(e);
} }
} }