diff --git a/.gitignore b/.gitignore index 8b8e20e..91ea741 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,2 @@ -shortcut -assets build .gradle diff --git a/.gradle/8.2.1/checksums/checksums.lock b/.gradle/8.2.1/checksums/checksums.lock index 7b9893c..7cf831a 100644 Binary files a/.gradle/8.2.1/checksums/checksums.lock and b/.gradle/8.2.1/checksums/checksums.lock differ diff --git a/.gradle/8.2.1/checksums/sha1-checksums.bin b/.gradle/8.2.1/checksums/sha1-checksums.bin index 56f9343..179fc3f 100644 Binary files a/.gradle/8.2.1/checksums/sha1-checksums.bin and b/.gradle/8.2.1/checksums/sha1-checksums.bin differ diff --git a/.gradle/8.2.1/executionHistory/executionHistory.bin b/.gradle/8.2.1/executionHistory/executionHistory.bin index 5b70e66..cd66888 100644 Binary files a/.gradle/8.2.1/executionHistory/executionHistory.bin and b/.gradle/8.2.1/executionHistory/executionHistory.bin differ diff --git a/.gradle/8.2.1/executionHistory/executionHistory.lock b/.gradle/8.2.1/executionHistory/executionHistory.lock index b6474ae..2204291 100644 Binary files a/.gradle/8.2.1/executionHistory/executionHistory.lock and b/.gradle/8.2.1/executionHistory/executionHistory.lock differ diff --git a/.gradle/8.2.1/fileHashes/fileHashes.bin b/.gradle/8.2.1/fileHashes/fileHashes.bin index 8baa3f4..82c5b28 100644 Binary files a/.gradle/8.2.1/fileHashes/fileHashes.bin and b/.gradle/8.2.1/fileHashes/fileHashes.bin differ diff --git a/.gradle/8.2.1/fileHashes/fileHashes.lock b/.gradle/8.2.1/fileHashes/fileHashes.lock index 769ec57..6c0d03d 100644 Binary files a/.gradle/8.2.1/fileHashes/fileHashes.lock and b/.gradle/8.2.1/fileHashes/fileHashes.lock differ diff --git a/.gradle/8.2.1/fileHashes/resourceHashesCache.bin b/.gradle/8.2.1/fileHashes/resourceHashesCache.bin index e139db2..44622c4 100644 Binary files a/.gradle/8.2.1/fileHashes/resourceHashesCache.bin and b/.gradle/8.2.1/fileHashes/resourceHashesCache.bin differ diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock index 5761ada..962b27a 100644 Binary files a/.gradle/buildOutputCleanup/buildOutputCleanup.lock and b/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/.gradle/file-system.probe b/.gradle/file-system.probe index 20da51f..3f70b8b 100644 Binary files a/.gradle/file-system.probe and b/.gradle/file-system.probe differ diff --git a/src/main/java/com/zivilon/cinder_loe/CinderLoE.java b/src/main/java/com/zivilon/cinder_loe/CinderLoE.java index 3faead7..21f0f10 100644 --- a/src/main/java/com/zivilon/cinder_loe/CinderLoE.java +++ b/src/main/java/com/zivilon/cinder_loe/CinderLoE.java @@ -928,6 +928,8 @@ public class CinderLoE { CinderCore.registerItemFallback(Item.getIdFromItem(BreeOutriderSpawnEgg), Item.getIdFromItem(Items.spawn_egg), "cinder_loe", "1.1"); CinderCore.registerItemFallback(Item.getIdFromItem(SauronSpawnEgg), Item.getIdFromItem(Items.spawn_egg), "cinder_loe", "1.1"); + CinderCore.registerItemFallback(Item.getIdFromItem(utumnoSlaveSpawnEgg), Item.getIdFromItem(Items.spawn_egg), "cinder_loe", "1.2.1"); + CinderCore.registerItemFallback(Item.getIdFromItem(helmetLimwaith), Item.getIdFromItem(LOTRMod.helmetMoredain), "cinder_loe", "1.0"); CinderCore.registerItemFallback(Item.getIdFromItem(bodyLimwaith), Item.getIdFromItem(LOTRMod.bodyMoredain), "cinder_loe", "1.0"); CinderCore.registerItemFallback(Item.getIdFromItem(legsLimwaith), Item.getIdFromItem(LOTRMod.legsMoredain), "cinder_loe", "1.0"); @@ -994,6 +996,8 @@ public class CinderLoE { CinderCore.registerEntityFallback(BreeCaptain.class, LOTREntityBreeMan.class, "cinder_loe", "1.1"); CinderCore.registerEntityFallback(BreeSoldierBannerBearer.class, LOTREntityBreeMan.class, "cinder_loe", "1.1"); CinderCore.registerEntityFallback(BreeOutrider.class, LOTREntityBreeMan.class, "cinder_loe", "1.1"); + + CinderCore.registerCustomFallback(42, 16, "banner", "cinder_loe", "1.2"); } // Create unit trade entries here, out of the way of important code diff --git a/src/main/java/com/zivilon/cinder_loe/coremod/LOTRBannerAdder.java b/src/main/java/com/zivilon/cinder_loe/coremod/LOTRBannerAdder.java index 4f08720..e158c8d 100644 --- a/src/main/java/com/zivilon/cinder_loe/coremod/LOTRBannerAdder.java +++ b/src/main/java/com/zivilon/cinder_loe/coremod/LOTRBannerAdder.java @@ -25,12 +25,8 @@ public class LOTRBannerAdder implements IClassTransformer { public void registerBanners() { custom_banners = new ArrayList<>(); // Arguments: enum name, texture name, ID, faction name -// register("RED_DWARF", "redDwarf", 42, "DURINS_FOLK"); + register("RED_DWARF", "redDwarf", 42, "DURINS_FOLK"); // register("TEST", "test", 43, "GONDOR"); - - // NOT FUNCTIONAL, DO NOT REGISTER - // Non-compliant clients crash if original banner is unrecognized even if fallback is vanilla - // Most likely something in PacketEntityMetadata } @Override diff --git a/src/main/java/com/zivilon/cinder_loe/coremod/LOTRShieldAdder.java b/src/main/java/com/zivilon/cinder_loe/coremod/LOTRShieldAdder.java new file mode 100644 index 0000000..3143f28 --- /dev/null +++ b/src/main/java/com/zivilon/cinder_loe/coremod/LOTRShieldAdder.java @@ -0,0 +1,160 @@ +package com.zivilon.cinder_loe.coremod; + +import net.minecraft.launchwrapper.IClassTransformer; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.FieldNode; +import org.objectweb.asm.tree.InsnList; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.IntInsnNode; +import org.objectweb.asm.tree.TypeInsnNode; +import org.objectweb.asm.tree.InsnNode; +import org.objectweb.asm.tree.LdcInsnNode; +import org.objectweb.asm.tree.FieldInsnNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; + +import java.util.List; +import java.util.ArrayList; + +public class LOTRShieldAdder implements IClassTransformer { + public static List custom_banners = new ArrayList<>(); + + public void registerShields() { + custom_banners = new ArrayList<>(); + // Arguments: enum name, texture name, ID, faction name + register("RED_DWARF", "redDwarf", 42, "DURINS_FOLK"); +// register("TEST", "test", 43, "GONDOR"); + } + + @Override + public byte[] transform(String name, String transformedName, byte[] basicClass) { + if ("lotr.common.LOTRShields".equals(transformedName)) { + registerShields(); + + // Get class + ClassReader classReader = new ClassReader(basicClass); + ClassNode classNode = new ClassNode(); + classReader.accept(classNode, 0); + + + // Add the new enum constant + for (BannerInfo banner : custom_banners) { + FieldNode newEnumConstant = new FieldNode( + Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC + Opcodes.ACC_FINAL + Opcodes.ACC_ENUM, + banner.enum_name, + "Llotr/common/LOTRShields;", + null, + null + ); + classNode.fields.add(newEnumConstant); + } + + + // Locate + MethodNode clinit = null; + for (MethodNode method : classNode.methods) { + if ("".equals(method.name)) { + clinit = method; + break; + } + } + + InsnList insns = clinit.instructions; + AbstractInsnNode constructor_injection_point = null; + + for (int i = 0; i < insns.size(); i++) { + AbstractInsnNode insn = insns.get(i); + // Check if the instruction is a BIPUSH + if (insn.getOpcode() == Opcodes.BIPUSH) { + IntInsnNode intInsn = (IntInsnNode) insn; + // Check if the operand is 42, indicating the size of the $VALUES array + if (intInsn.operand == 42) { + // Found the instruction to modify + constructor_injection_point = insn; + // Modify the operand from 42 to 43 to account for the new enum constant + intInsn.operand = 42 + custom_banners.size(); + System.out.println("Enum array length set to " + intInsn.operand); + System.out.println("Banner list size: " + custom_banners.size()); + break; + } + } + } + + // Create the constructor instructions to add new banner + InsnList constructor_injection = new InsnList(); + for (BannerInfo banner : custom_banners) { + constructor_injection.add(new TypeInsnNode(Opcodes.NEW, "lotr/common/item/LOTRItemBanner$BannerType")); + constructor_injection.add(new InsnNode(Opcodes.DUP)); + System.out.println("Registering with enum " + banner.enum_name); + constructor_injection.add(new LdcInsnNode(banner.enum_name)); + System.out.println("Registering with identifier " + banner.identifier); + constructor_injection.add(new LdcInsnNode(banner.identifier)); + constructor_injection.add(new FieldInsnNode(Opcodes.GETSTATIC, "lotr/common/fac/LOTRFaction", banner.faction, "Llotr/common/fac/LOTRFaction;")); + constructor_injection.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "lotr/common/item/LOTRItemBanner$BannerType", "", "(Ljava/lang/String;IILjava/lang/String;Llotr/common/fac/LOTRFaction;)V", false)); + constructor_injection.add(new FieldInsnNode(Opcodes.PUTSTATIC, "lotr/common/item/LOTRItemBanner$BannerType", banner.enum_name, "Llotr/common/item/LOTRItemBanner$BannerType;")); + } + // Insert the new instructions + if (constructor_injection_point != null) { + insns.insertBefore(constructor_injection_point, constructor_injection); + } + + + // Modifying the $VALUES array + // Create new instruction list to be injected later + InsnList values_array_injection = new InsnList(); + + // Add instructions to the instruction list + for (BannerInfo banner : custom_banners) { + values_array_injection.add(new InsnNode(Opcodes.DUP)); + values_array_injection.add(new FieldInsnNode(Opcodes.GETSTATIC, "lotr/common/item/LOTRItemBanner$BannerType", banner.enum_name, "Llotr/common/item/LOTRItemBanner$BannerType;")); + values_array_injection.add(new InsnNode(Opcodes.AASTORE)); + } + + // Find the putstatic instruction for $VALUES + // This is where the fields are injected into a list, we want to inject our instructions before this + AbstractInsnNode values_injection_point = null; + + while (constructor_injection_point != null) { + constructor_injection_point = constructor_injection_point.getNext(); + if (constructor_injection_point.getOpcode() == Opcodes.PUTSTATIC) { + values_injection_point = constructor_injection_point; + break; + } + } + + // Insert the new instructions before the putstatic instruction + if (values_injection_point != null) { + insns.insertBefore(values_injection_point, values_array_injection); + } + + // Write the modified class back to a byte array + ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + classNode.accept(classWriter); + return classWriter.toByteArray(); // Return the modified class + } + return basicClass; // Return the unmodified class for all other classes + } + + public void register(String enum_name, String identifier, int ordinal, String faction) { + System.out.println("Registering banner " + enum_name + " " + identifier); + custom_banners.add(new BannerInfo(enum_name, identifier, ordinal, faction)); + } + + public class BannerInfo { + String enum_name; + String identifier; + int ordinal; + String faction; + + public BannerInfo(String enum_name, String identifier, int ordinal, String faction) { + this.enum_name = enum_name; + this.identifier = identifier; + this.ordinal = ordinal; + this.faction = faction; + } + } + +}