diff --git a/deob/src/main/java/dev/openrs2/deob/Deobfuscator.java b/deob/src/main/java/dev/openrs2/deob/Deobfuscator.java index 9b9ddad2a9..492fcd0834 100644 --- a/deob/src/main/java/dev/openrs2/deob/Deobfuscator.java +++ b/deob/src/main/java/dev/openrs2/deob/Deobfuscator.java @@ -15,6 +15,7 @@ import dev.openrs2.deob.transform.CanvasTransformer; import dev.openrs2.deob.transform.ClassForNameTransformer; import dev.openrs2.deob.transform.CounterTransformer; import dev.openrs2.deob.transform.ExceptionTracingTransformer; +import dev.openrs2.deob.transform.FieldOrderTransformer; import dev.openrs2.deob.transform.OpaquePredicateTransformer; import dev.openrs2.deob.transform.OriginalNameTransformer; import org.slf4j.Logger; @@ -27,7 +28,8 @@ public final class Deobfuscator { new OpaquePredicateTransformer(), new ExceptionTracingTransformer(), new CounterTransformer(), - new CanvasTransformer() + new CanvasTransformer(), + new FieldOrderTransformer() ); public static void main(String[] args) throws IOException { diff --git a/deob/src/main/java/dev/openrs2/deob/transform/FieldOrderTransformer.java b/deob/src/main/java/dev/openrs2/deob/transform/FieldOrderTransformer.java new file mode 100644 index 0000000000..a11e0acf10 --- /dev/null +++ b/deob/src/main/java/dev/openrs2/deob/transform/FieldOrderTransformer.java @@ -0,0 +1,52 @@ +package dev.openrs2.deob.transform; + +import java.util.HashMap; + +import dev.openrs2.asm.MemberDesc; +import dev.openrs2.asm.Transformer; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.FieldInsnNode; + +public final class FieldOrderTransformer extends Transformer { + private static final String CONSTRUCTOR = ""; + private static final String STATIC_CONSTRUCTOR = ""; + + private static void sortFields(ClassNode clazz, String ctorName, int opcode) { + clazz.methods.stream() + .filter(m -> m.name.equals(ctorName)) + .findFirst() + .ifPresent(ctor -> { + var fields = new HashMap(); + var index = 0; + + for (var insn = ctor.instructions.getFirst(); insn != null; insn = insn.getNext()) { + if (insn.getOpcode() != opcode) { + continue; + } + + var putfield = (FieldInsnNode) insn; + if (!putfield.owner.equals(clazz.name)) { + continue; + } + + var desc = new MemberDesc(putfield.name, putfield.desc); + if (!fields.containsKey(desc)) { + fields.put(desc, index++); + } + } + + clazz.fields.sort((a, b) -> { + var indexA = fields.getOrDefault(new MemberDesc(a.name, a.desc), -1); + var indexB = fields.getOrDefault(new MemberDesc(b.name, b.desc), -1); + return Integer.compare(indexA, indexB); + }); + }); + } + + @Override + public void transformClass(ClassNode clazz) { + sortFields(clazz, CONSTRUCTOR, Opcodes.PUTFIELD); + sortFields(clazz, STATIC_CONSTRUCTOR, Opcodes.PUTSTATIC); + } +}