import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.FieldInsnNode; import org.objectweb.asm.tree.JumpInsnNode; import org.objectweb.asm.tree.LabelNode; import org.objectweb.asm.tree.MethodNode; import java.nio.file.Files; import java.nio.file.Paths; /** * Strips Create Ore Excavation's guarded ProcessingOutput type-wrapper registration * from KubeJSExcavation.registerTypeWrappers. * * Upstream guard: `if (!CreateOreExcavation.kubeJSCreate) register(ProcessingOutput, ...)` * — but kubeJSCreate is assigned in the @Mod constructor while KubeJS invokes plugin * callbacks during KubeJS's own construction. FML constructs independent mods on * parallel workers, so the flag may still be false when the callback runs → duplicate * wrapper vs kubejs-create → "Wrapper already exists!" crash (nondeterministic). * * This pack always ships kubejs-create, so COE never needs its own wrapper: remove * the whole guarded block (getstatic/ifne/…/invokevirtual) up to its branch-target * label. Later frames stay valid because operand stack at that label is unchanged. */ public class Patcher { public static void main(String[] args) throws Exception { if (args.length != 2) { System.err.println("usage: Patcher "); System.exit(2); } byte[] bytes = Files.readAllBytes(Paths.get(args[0])); ClassNode cn = new ClassNode(); new ClassReader(bytes).accept(cn, 0); boolean found = false; for (MethodNode mn : cn.methods) { if (!"registerTypeWrappers".equals(mn.name)) continue; found = true; AbstractInsnNode start = null; for (AbstractInsnNode n : mn.instructions) { if (n instanceof FieldInsnNode f && n.getOpcode() == Opcodes.GETSTATIC && "kubeJSCreate".equals(f.name)) { start = n; break; } } if (start == null) throw new IllegalStateException("kubeJSCreate guard not found"); AbstractInsnNode jump = start.getNext(); if (!(jump instanceof JumpInsnNode) || jump.getOpcode() != Opcodes.IFNE) { throw new IllegalStateException("expected IFNE after getstatic"); } LabelNode target = ((JumpInsnNode) jump).label; int removed = 0; AbstractInsnNode n = start; while (n != target) { AbstractInsnNode next = n.getNext(); mn.instructions.remove(n); n = next; removed++; if (n == null) throw new IllegalStateException("branch target not reached"); } System.out.println("patched " + cn.name + "." + mn.name + ": removed " + removed + " instructions up to branch target"); } if (!found) throw new IllegalStateException("registerTypeWrappers not found"); ClassWriter cw = new ClassWriter(0); cn.accept(cw); Files.write(Paths.get(args[1]), cw.toByteArray()); } }