Skip to content

Instantly share code, notes, and snippets.

@zly2006
Created September 25, 2023 05:34
Show Gist options
  • Save zly2006/b8098e12c4a38f4c95644aae7ee30e23 to your computer and use it in GitHub Desktop.
Save zly2006/b8098e12c4a38f4c95644aae7ee30e23 to your computer and use it in GitHub Desktop.
package com.github.zly2006.reden.report;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.MethodNode;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.CodeSource;
public class MM implements PreLaunchEntrypoint {
static class FabricLoaderInjector {
private final ClassLoader knotClassLoader;
private final Method defMethod;
public FabricLoaderInjector(ClassLoader knotClassLoader) throws ClassNotFoundException, NoSuchMethodException {
this.knotClassLoader = knotClassLoader;
var kclClass = Class.forName("net.fabricmc.loader.impl.launch.knot.KnotClassLoader");
if (!kclClass.isInstance(knotClassLoader)) {
throw new IllegalArgumentException("knotClassLoader must be an instance of KnotClassLoader");
}
defMethod = kclClass.getMethod("defineClassFwd", String.class, byte[].class, int.class, int.class, CodeSource.class);
defMethod.setAccessible(true);
}
public Class<?> defineClass(String name, byte[] b, int off, int len, CodeSource cs) throws InvocationTargetException, IllegalAccessException {
return (Class<?>) defMethod.invoke(knotClassLoader, name, b, off, len, cs);
}
}
Class<ModInitializer> generateEntrypoint() {
return ModInitializer.class;
}
@Override
public void onPreLaunch() {
// Reflection!
ClassWriter classWriter = new ClassWriter(3);
ClassNode classNode = new ClassNode();
classNode.name = "com/github/zly2006/reden/generated/Hello";
classNode.signature = "Lcom/github/zly2006/reden/generated/Hello;";
MethodNode helloMethod = new MethodNode();
helloMethod.name = "hello";
helloMethod.desc = "()V";
helloMethod.signature = "()V";
helloMethod.instructions.add(new FieldInsnNode(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"));
classNode.methods.add(helloMethod);
String classSig = "com/github/zly2006/reden/generated/Hello";
classWriter.visit(61, Opcodes.ACC_PUBLIC, classSig, null, "java/lang/Object", new String[]{"net/fabricmc/api/ModInitializer"});
var ctor = classWriter.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
ctor.visitCode();
ctor.visitVarInsn(Opcodes.ALOAD, 0);
ctor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
ctor.visitInsn(Opcodes.RETURN);
ctor.visitMaxs(1, 1);
ctor.visitEnd();
var hello = classWriter.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "hello", "()V", null, null);
hello.visitCode();
hello.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
hello.visitLdcInsn("Hello ASM world!");
hello.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
hello.visitInsn(Opcodes.RETURN);
hello.visitMaxs(2, 1);
hello.visitEnd();
var initMod = classWriter.visitMethod(Opcodes.ACC_PUBLIC, "onInitialize", "()V", "", null);
initMod.visitCode();
initMod.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
initMod.visitLdcInsn("Hello Fabric, this is generated!");
initMod.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
initMod.visitInsn(Opcodes.RETURN);
initMod.visitMaxs(2, 1);
initMod.visitEnd();
classWriter.visitEnd();
try {
FabricLoaderInjector injector = new FabricLoaderInjector(getClass().getClassLoader());
byte[] byteArray = classWriter.toByteArray();
injector.defineClass("com.github.zly2006.reden.generated.Hello", byteArray, 0, byteArray.length, null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment