diff --git a/src/main/java/net/runelite/deob/Method.java b/src/main/java/net/runelite/deob/Method.java index c0e7a28766..e5c3c4bf5e 100644 --- a/src/main/java/net/runelite/deob/Method.java +++ b/src/main/java/net/runelite/deob/Method.java @@ -24,6 +24,8 @@ public class Method public static final short ACC_FINAL = 0x10; public static final short ACC_SYNCHRONIZED = 0x20; public static final short ACC_ABSTRACT = 0x400; + + public static final short ACCESS_MODIFIERS = ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED; private Methods methods; @@ -145,6 +147,11 @@ public class Method { return (accessFlags & ACC_PRIVATE) != 0; } + + public void setPrivate() + { + accessFlags = (short) ((accessFlags & ~ACCESS_MODIFIERS) | ACC_PRIVATE); + } public Exceptions getExceptions() { diff --git a/src/main/java/net/runelite/deob/injection/InjectReplace.java b/src/main/java/net/runelite/deob/injection/InjectReplace.java index fd308932ed..ad461c4cb1 100644 --- a/src/main/java/net/runelite/deob/injection/InjectReplace.java +++ b/src/main/java/net/runelite/deob/injection/InjectReplace.java @@ -19,8 +19,10 @@ import net.runelite.deob.attributes.code.instructions.DLoad; import net.runelite.deob.attributes.code.instructions.FLoad; import net.runelite.deob.attributes.code.instructions.ILoad; import net.runelite.deob.attributes.code.instructions.InvokeSpecial; +import net.runelite.deob.attributes.code.instructions.InvokeVirtual; import net.runelite.deob.attributes.code.instructions.LLoad; import net.runelite.deob.attributes.code.instructions.New; +import net.runelite.deob.attributes.code.instructions.Pop; import net.runelite.deob.attributes.code.instructions.Return; import net.runelite.deob.signature.Type; @@ -85,6 +87,8 @@ public class InjectReplace replaceNew(classToInject); } + + private static final String INITFN = "init"; private void injectConstructors(ClassFile classToInject) { @@ -92,9 +96,38 @@ public class InjectReplace Methods methods = classToInject.getMethods(); Methods vanillaMethods = vanilla.getMethods(); - for (Method m : new ArrayList<>(methods.getMethods())) + boolean seen = false; + for (Method m : methods.getMethods()) if (m.getName().equals("")) - methods.removeMethod(m); + { + assert seen == false; // only one ctor allowed + seen = true; + + Code code = m.getCode(); + Instructions instructions = code.getInstructions(); + + m.setName(INITFN); // magic + + // replace invokespecial call + + for (Instruction i : instructions.getInstructions()) + { + if (!(i instanceof InvokeSpecial)) + continue; + + InvokeSpecial is = (InvokeSpecial) i; + net.runelite.deob.pool.Method method = (net.runelite.deob.pool.Method) is.getMethod(); + assert method.getNameAndType().getDescriptor().size() == 0; // Replace classes must extend Object so this must be Object.init() + + instructions.replace(i, new Pop(instructions)); // pop this + + break; + } + + m.setPrivate(); + + // now we'll just add a call to init in the constructors + } // Add constructors for (Method m : vanillaMethods.getMethods()) @@ -154,6 +187,15 @@ public class InjectReplace } ins.add(new InvokeSpecial(instructions, m.getPoolMethod())); + + // invoke our init func if it exists + Method initfn = methods.findMethod(INITFN); + if (initfn != null) + { + ins.add(new ALoad(instructions, 0)); // this + ins.add(new InvokeVirtual(instructions, initfn.getPoolMethod())); + } + ins.add(new Return(instructions, InstructionType.RETURN)); methods.addMethod(constructor); @@ -293,6 +335,7 @@ public class InjectReplace if (i instanceof New) { New n = (New) i; + if (!n.getNewClass().equals(vanilla.getPoolClass())) continue;