Hallo liebes Forum,
ich bin neu im Thema ASM und versuche mit dem folgenden Code eine unbekannte bzw vom Nutzer definierte menge an Variablen in meine Klasse "ItemList" hinzufügen zu lassen. Hierzu verwende ich for-loops und eine statische variable welche die Anzahl der hinzuzufügenden Felder enthält.
Die Methode wird direkt aus meiner "main" Methode aufgerufen. Leider werden die Bytecode Änderungen nicht übernommen. Generiert die Methode nur den Code und ich muss ihn noch irgendwie anwenden?
Vielen Dank im voraus für jede Hilfe!
ich bin neu im Thema ASM und versuche mit dem folgenden Code eine unbekannte bzw vom Nutzer definierte menge an Variablen in meine Klasse "ItemList" hinzufügen zu lassen. Hierzu verwende ich for-loops und eine statische variable welche die Anzahl der hinzuzufügenden Felder enthält.
Java:
protected static byte[] write() {
ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
MethodVisitor mv;
cw.visit(52, ACC_PUBLIC + ACC_SUPER, "de/blutmondgilde/ibocore/item/ItemList", null, "java/lang/Object", null);
cw.visitSource("ItemList.java", null);
cw.visitInnerClass("java/lang/invoke/MethodHandles$Lookup", "java/lang/invoke/MethodHandles", "Lookup", ACC_PUBLIC + ACC_FINAL + ACC_STATIC);
{
fv = cw.visitField(ACC_PRIVATE + ACC_FINAL + ACC_STATIC, "ITEM_REGISTRY", "Lnet/minecraftforge/registries/DeferredRegister;", "Lnet/minecraftforge/registries/DeferredRegister<Lnet/minecraft/item/Item;>;", null);
fv.visitEnd();
}
{
fv = cw.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, "TEST_ITEM", "Lnet/minecraftforge/fml/RegistryObject;", "Lnet/minecraftforge/fml/RegistryObject<Lnet/minecraft/item/Item;>;", null);
fv.visitEnd();
}
{
for (int i = 0; i < itemCount; i++) {
fv = cw.visitField(
ACC_PUBLIC + ACC_FINAL + ACC_STATIC,
ITEM_PREFIX + i,
"Lnet/minecraftforge/fml/RegistryObject;",
"Lnet/minecraftforge/fml/RegistryObject<Lnet/minecraft/item/Item;>;",
null);
fv.visitEnd();
}
}
{
mv = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
mv.visitCode();
Label l0 = new Label();
mv.visitLabel(l0);
mv.visitLineNumber(line++, l0);
mv.visitFieldInsn(GETSTATIC, "net/minecraftforge/registries/ForgeRegistries", "ITEMS", "Lnet/minecraftforge/registries/IForgeRegistry;");
mv.visitLdcInsn("ibocore");
mv.visitMethodInsn(INVOKESTATIC, "net/minecraftforge/registries/DeferredRegister", "create", "(Lnet/minecraftforge/registries/IForgeRegistry;Ljava/lang/String;)Lnet/minecraftforge/registries/DeferredRegister;", false);
mv.visitFieldInsn(PUTSTATIC, "de/blutmondgilde/ibocore/item/ItemList", "ITEM_REGISTRY", "Lnet/minecraftforge/registries/DeferredRegister;");
Label l1 = new Label();
mv.visitLabel(l1);
mv.visitLineNumber(line++, l1);
mv.visitFieldInsn(GETSTATIC, "de/blutmondgilde/ibocore/item/ItemList", "ITEM_REGISTRY", "Lnet/minecraftforge/registries/DeferredRegister;");
mv.visitLdcInsn("test_item");
mv.visitInvokeDynamicInsn("get", "()Ljava/util/function/Supplier;", new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"), new Object[]{Type.getType("()Ljava/lang/Object;"), new Handle(Opcodes.H_NEWINVOKESPECIAL, "de/blutmondgilde/ibocore/item/templates/DefaultItemTemplate", "<init>", "()V"), Type.getType("()Lnet/minecraft/item/Item;")});
mv.visitMethodInsn(INVOKEVIRTUAL, "net/minecraftforge/registries/DeferredRegister", "register", "(Ljava/lang/String;Ljava/util/function/Supplier;)Lnet/minecraftforge/fml/RegistryObject;", false);
mv.visitFieldInsn(PUTSTATIC, "de/blutmondgilde/ibocore/item/ItemList", "TEST_ITEM", "Lnet/minecraftforge/fml/RegistryObject;");
Label[] labels = new Label[itemCount + 1];
for (int i = 0; i < itemCount; i++) {
//Label
labels[i] = new Label();
mv.visitLabel(labels[i]);
mv.visitLineNumber(line++, labels[i]);
mv.visitFieldInsn(
GETSTATIC,
"de/blutmondgilde/ibocore/item/ItemList",
"ITEM_REGISTRY",
"Lnet/minecraftforge/registries/DeferredRegister;"
);
//Item Registry Name
mv.visitLdcInsn("generated_item_" + i);
mv.visitInvokeDynamicInsn(
"get",
"()Ljava/util/function/Supplier;",
new Handle(
Opcodes.H_INVOKESTATIC,
"java/lang/invoke/LambdaMetafactory",
"metafactory",
"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;"),
new Object[]{
Type.getType("()Ljava/lang/Object;"),
new Handle(Opcodes.H_NEWINVOKESPECIAL,
"de/blutmondgilde/ibocore/item/templates/DefaultItemTemplate",
"<init>", "()V"),
Type.getType("()Lnet/minecraft/item/Item;")
}
);
mv.visitMethodInsn(
INVOKEVIRTUAL,
"net/minecraftforge/registries/DeferredRegister",
"register",
"(Ljava/lang/String;Ljava/util/function/Supplier;)Lnet/minecraftforge/fml/RegistryObject;",
false
);
//Var Name
mv.visitFieldInsn(
PUTSTATIC,
"de/blutmondgilde/ibocore/item/ItemList",
ITEM_PREFIX + i,
"Lnet/minecraftforge/fml/RegistryObject;"
);
}
mv.visitInsn(RETURN);
mv.visitMaxs(3, 0);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
Label l0 = new Label();
mv.visitLabel(l0);
mv.visitLineNumber(12, l0);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
Label l1 = new Label();
mv.visitLabel(l1);
mv.visitLocalVariable("this", "Lde/blutmondgilde/ibocore/item/ItemList;", null, l0, l1, 0);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "register", "()V", null, null);
mv.visitCode();
Label l0 = new Label();
mv.visitLabel(l0);
mv.visitLineNumber(3 + line++, l0);
mv.visitFieldInsn(GETSTATIC, "de/blutmondgilde/ibocore/item/ItemList", "ITEM_REGISTRY", "Lnet/minecraftforge/registries/DeferredRegister;");
mv.visitMethodInsn(INVOKESTATIC, "net/minecraftforge/fml/javafmlmod/FMLJavaModLoadingContext", "get", "()Lnet/minecraftforge/fml/javafmlmod/FMLJavaModLoadingContext;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, "net/minecraftforge/fml/javafmlmod/FMLJavaModLoadingContext", "getModEventBus", "()Lnet/minecraftforge/eventbus/api/IEventBus;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, "net/minecraftforge/registries/DeferredRegister", "register", "(Lnet/minecraftforge/eventbus/api/IEventBus;)V", false);
Label l1 = new Label();
mv.visitLabel(l1);
mv.visitLineNumber(3 + line++, l1);
mv.visitLdcInsn("IBO-Core/Items");
mv.visitMethodInsn(INVOKESTATIC, "org/apache/logging/log4j/LogManager", "getLogger", "(Ljava/lang/String;)Lorg/apache/logging/log4j/Logger;", false);
mv.visitLdcInsn("Registered Items");
mv.visitMethodInsn(INVOKEINTERFACE, "org/apache/logging/log4j/Logger", "info", "(Ljava/lang/String;)V", true);
Label l2 = new Label();
mv.visitLabel(l2);
mv.visitLineNumber(3 + line++, l2);
mv.visitInsn(RETURN);
mv.visitMaxs(2, 0);
mv.visitEnd();
}
cw.visitEnd();
return cw.toByteArray();
}
Die Methode wird direkt aus meiner "main" Methode aufgerufen. Leider werden die Bytecode Änderungen nicht übernommen. Generiert die Methode nur den Code und ich muss ihn noch irgendwie anwenden?
Vielen Dank im voraus für jede Hilfe!