All checks were successful
Build & Release Pack / build (push) Successful in 1m46s
NeoForge 1.21.1 (21.1.248) packwiz pack: client + server packs, story system (KubeJS/FTB Quests), patched World Portal & Create Ore Excavation, performance presets, and ops tooling. Clean-history import for v1.0.0.
78 lines
3.2 KiB
Java
78 lines
3.2 KiB
Java
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 <KubeJSExcavation.class-in> <class-out>");
|
|
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());
|
|
}
|
|
}
|