diff --git a/.travis.yml b/.travis.yml index 76201d94c3..9f3f35a358 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,13 @@ language: java sudo: false -dist: xenial +dist: trusty cache: directories: - $HOME/.m2 jdk: -- openjdk8 -- openjdk11 +- oraclejdk8 install: true script: ./travis/build.sh before_install: -- chmod +x ./travis/build.sh \ No newline at end of file +- chmod +x ./travis/build.sh + diff --git a/cache/src/test/java/net/runelite/cache/CacheProperties.java b/cache/src/test/java/net/runelite/cache/CacheProperties.java index 50da8759dc..5614563f72 100644 --- a/cache/src/test/java/net/runelite/cache/CacheProperties.java +++ b/cache/src/test/java/net/runelite/cache/CacheProperties.java @@ -30,7 +30,7 @@ import java.util.Properties; public class CacheProperties { - private static Properties getProperies() throws IOException + private static Properties getProperties() throws IOException { Properties properties = new Properties(); InputStream resourceAsStream = StoreLocation.class.getResourceAsStream("/cache.properties"); @@ -40,11 +40,11 @@ public class CacheProperties public static int getRsVersion() throws IOException { - return Integer.parseInt(getProperies().getProperty("rs.version")); + return Integer.parseInt(getProperties().getProperty("rs.version")); } public static int getCacheVersion() throws IOException { - return Integer.parseInt(getProperies().getProperty("cache.version")); + return Integer.parseInt(getProperties().getProperty("cache.version")); } } diff --git a/cache/src/test/java/net/runelite/cache/MapDumperTest.java b/cache/src/test/java/net/runelite/cache/MapDumperTest.java index 70d20dcb0f..8d1fffd7cb 100644 --- a/cache/src/test/java/net/runelite/cache/MapDumperTest.java +++ b/cache/src/test/java/net/runelite/cache/MapDumperTest.java @@ -165,7 +165,7 @@ public class MapDumperTest @Test @Ignore - public void dunpJson() throws IOException + public void dumpJson() throws IOException { File base = StoreLocation.LOCATION, outDir = folder.newFolder(); diff --git a/deobfuscator/src/main/java/net/runelite/asm/Method.java b/deobfuscator/src/main/java/net/runelite/asm/Method.java index bc2c8b305b..e8cbdef92b 100644 --- a/deobfuscator/src/main/java/net/runelite/asm/Method.java +++ b/deobfuscator/src/main/java/net/runelite/asm/Method.java @@ -203,9 +203,16 @@ public class Method return (accessFlags & ACC_STATIC) != 0; } - public void setStatic() + public void setStatic(boolean s) { - accessFlags |= ACC_STATIC; + if (s) + { + accessFlags |= ACC_STATIC; + } + else + { + accessFlags &= ~ACC_STATIC; + } } public boolean isSynchronized() diff --git a/deobfuscator/src/main/java/net/runelite/deob/Deob.java b/deobfuscator/src/main/java/net/runelite/deob/Deob.java index 8f37a9b167..e46bdfbe20 100644 --- a/deobfuscator/src/main/java/net/runelite/deob/Deob.java +++ b/deobfuscator/src/main/java/net/runelite/deob/Deob.java @@ -27,14 +27,10 @@ package net.runelite.deob; import com.google.common.base.Stopwatch; import java.io.File; import java.io.IOException; -import net.runelite.asm.ClassFile; import net.runelite.asm.ClassGroup; -import net.runelite.asm.Field; -import net.runelite.asm.Method; -import net.runelite.asm.Type; -import net.runelite.asm.attributes.Annotations; import net.runelite.asm.execution.Execution; import net.runelite.deob.deobfuscators.CastNull; +import net.runelite.deob.deobfuscators.StaticShouldBeInstance; import net.runelite.deob.deobfuscators.constparam.ConstantParameter; import net.runelite.deob.deobfuscators.EnumDeobfuscator; import net.runelite.deob.deobfuscators.FieldInliner; @@ -85,85 +81,70 @@ public class Deob ClassGroup group = JarUtil.loadJar(new File(args[0])); - for (ClassFile f : group.getClasses()) + if (args.length > 2 && args[2].equals("rl")) { - f.getAnnotations().clearAnnotations(); - for (Method m : f.getMethods()) - { - Annotations an = m.getAnnotations(); - an.clearAnnotations(); - } - for (Field fi : f.getFields()) - { - Annotations an = fi.getAnnotations(); - if (an.find(new Type("Ljavax/inject/Inject;")) == null) - { - an.clearAnnotations(); - } - else - { - logger.info("Class {}, field {} has inject", f.getClassName(), fi.getName()); - } - } + run(group, new StaticShouldBeInstance()); } + else + { + // remove except RuntimeException + run(group, new RuntimeExceptions()); - // remove except RuntimeException - run(group, new RuntimeExceptions()); + run(group, new ControlFlowDeobfuscator()); - run(group, new ControlFlowDeobfuscator()); + run(group, new RenameUnique()); - run(group, new RenameUnique()); + // remove unused methods - this leaves Code with no instructions, + // which is not valid, so unused methods is run after + run(group, new UnreachedCode()); + run(group, new UnusedMethods()); - // remove unused methods - this leaves Code with no instructions, - // which is not valid, so unused methods is run after - run(group, new UnreachedCode()); - run(group, new UnusedMethods()); + // remove illegal state exceptions, frees up some parameters + run(group, new IllegalStateExceptions()); - // remove illegal state exceptions, frees up some parameters - run(group, new IllegalStateExceptions()); + // remove constant logically dead parameters + run(group, new ConstantParameter()); - // remove constant logically dead parameters - run(group, new ConstantParameter()); + // remove unhit blocks + run(group, new UnreachedCode()); + run(group, new UnusedMethods()); - // remove unhit blocks - run(group, new UnreachedCode()); - run(group, new UnusedMethods()); + // remove unused parameters + run(group, new UnusedParameters()); - // remove unused parameters - run(group, new UnusedParameters()); + // remove unused fields + run(group, new UnusedFields()); - // remove unused fields - run(group, new UnusedFields()); + run(group, new FieldInliner()); - run(group, new FieldInliner()); + // order uses class name order for sorting fields/methods, + // so run it before removing classes below + run(group, new Order()); - // order uses class name order for sorting fields/methods, - // so run it before removing classes below - run(group, new Order()); + run(group, new UnusedClass()); - run(group, new UnusedClass()); + runMath(group); - runMath(group); + run(group, new ExprArgOrder()); - run(group, new ExprArgOrder()); + run(group, new Lvt()); - run(group, new Lvt()); + run(group, new CastNull()); - run(group, new CastNull()); + run(group, new EnumDeobfuscator()); - run(group, new EnumDeobfuscator()); + new OpcodesTransformer().transform(group); + //run(group, new PacketHandlerOrder()); + //run(group, new PacketWriteDeobfuscator()); - new OpcodesTransformer().transform(group); - //run(group, new PacketHandlerOrder()); - //run(group, new PacketWriteDeobfuscator()); + run(group, new MenuActionDeobfuscator()); - run(group, new MenuActionDeobfuscator()); - - new GetPathTransformer().transform(group); - new ClientErrorTransformer().transform(group); - new ReflectionTransformer().transform(group); - new MaxMemoryTransformer().transform(group); - //new RuneliteBufferTransformer().transform(group); + new GetPathTransformer().transform(group); + new ClientErrorTransformer().transform(group); + new ReflectionTransformer().transform(group); + new MaxMemoryTransformer().transform(group); + //new RuneliteBufferTransformer().transform(group); + } JarUtil.saveJar(group, new File(args[1])); diff --git a/deobfuscator/src/main/java/net/runelite/deob/deobfuscators/StaticShouldBeInstance.java b/deobfuscator/src/main/java/net/runelite/deob/deobfuscators/StaticShouldBeInstance.java new file mode 100644 index 0000000000..1cae903698 --- /dev/null +++ b/deobfuscator/src/main/java/net/runelite/deob/deobfuscators/StaticShouldBeInstance.java @@ -0,0 +1,171 @@ +package net.runelite.deob.deobfuscators; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import net.runelite.asm.ClassFile; +import net.runelite.asm.ClassGroup; +import net.runelite.asm.Field; +import net.runelite.asm.Type; +import net.runelite.asm.attributes.Annotations; +import net.runelite.asm.attributes.Code; +import net.runelite.asm.attributes.code.Instruction; +import net.runelite.asm.attributes.code.Instructions; +import net.runelite.asm.attributes.code.instruction.types.ReturnInstruction; +import net.runelite.asm.attributes.code.instructions.InvokeStatic; +import net.runelite.asm.attributes.code.instructions.InvokeVirtual; +import net.runelite.asm.pool.Method; +import net.runelite.asm.signature.Signature; +import net.runelite.deob.Deobfuscator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class StaticShouldBeInstance implements Deobfuscator +{ + private static final Logger logger = LoggerFactory.getLogger(StaticShouldBeInstance.class); + private static Map methods = new HashMap<>(); + + public void run(ClassGroup group) + { + int replacedCalls = 0; + int removedInstructions = 0; + int removedMethods = 0; + int removedAnnotations = 0; + List obfuscatedMethods = new ArrayList<>(); + + for (ClassFile cf : group.getClasses()) + { + // Remove unused annotations + Annotations a = cf.getAnnotations(); + removedAnnotations += a.getAnnotations().size(); + a.clearAnnotations(); + + Type type = new Type('L' + cf.getClassName() + ';'); + obfuscatedMethods.clear(); + + for (net.runelite.asm.Method m : cf.getMethods()) + { + // Remove unused annotations + a = m.getAnnotations(); + removedAnnotations += a.size(); + a.clearAnnotations(); + + if (m.isStatic() && m.getCode() != null) + { + if (checkIfObf(m, type, cf)) + { + removedMethods++; + obfuscatedMethods.add(m); + } + } + } + + + for (net.runelite.asm.Method m : obfuscatedMethods) + { + Signature sig = m.getDescriptor(); + Signature.Builder builder = new Signature.Builder(); + builder.setReturnType(sig.getReturnValue()); + if (sig.getArguments().size() > 1) + { + builder.addArguments(sig.getArguments().subList(1, sig.getArguments().size())); + } + + Signature toFind = builder.build(); + + net.runelite.asm.Method notStatic = cf.findMethod(m.getName(), toFind); + net.runelite.asm.pool.Method oldPool = m.getPoolMethod(); + cf.removeMethod(notStatic); + + m.setDescriptor(toFind); + m.setStatic(false); + Code c = m.getCode(); + Instructions ins = c.getInstructions(); + int startLength = ins.getInstructions().size(); + ListIterator it = ins.getInstructions().listIterator(); + assert it.hasNext(); + Instruction i = it.next(); + while (!(i instanceof ReturnInstruction)) + { + it.remove(); + i = it.next(); + } + it.remove(); + net.runelite.asm.pool.Method newPool = m.getPoolMethod(); + + methods.put(oldPool, newPool); + + removedInstructions += startLength - ins.getInstructions().size(); + } + + for (Field fi : cf.getFields()) + { + a = fi.getAnnotations(); + if (a.find(new Type("Ljavax/inject/Inject;")) == null) + { + removedAnnotations += a.size(); + a.clearAnnotations(); + } + else + { + logger.info("Class {}, field {} has inject", cf.getClassName(), fi.getName()); + } + } + } + + for (ClassFile cf : group.getClasses()) + { + for (net.runelite.asm.Method m : cf.getMethods()) + { + if (m.getCode() == null) + { + continue; + } + + Instructions ins = m.getCode().getInstructions(); + List instructions = ins.getInstructions(); + for (int i1 = 0, instructionsSize = instructions.size(); i1 < instructionsSize; i1++) + { + Instruction i = instructions.get(i1); + if (!(i instanceof InvokeStatic)) + { + continue; + } + + if (methods.containsKey(((InvokeStatic) i).getMethod())) + { + InvokeVirtual invoke = new InvokeVirtual(ins, methods.get(((InvokeStatic) i).getMethod())); + ins.replace(i, invoke); + replacedCalls++; + } + } + } + } + + logger.info("Made {} methods not static, removed {} instructions, replaced {} invokes, and removed {} annotations", removedMethods, removedInstructions, replacedCalls, removedAnnotations); + } + + private static boolean checkIfObf(net.runelite.asm.Method m, Type type, ClassFile cf) + { + Signature sig = m.getDescriptor(); + if (sig.getArguments().size() < 1 || !sig.getTypeOfArg(0).equals(type)) + { + return false; + } + + Signature.Builder builder = new Signature.Builder(); + builder.setReturnType(sig.getReturnValue()); + if (sig.getArguments().size() > 1) + { + builder.addArguments(sig.getArguments().subList(1, sig.getArguments().size())); + } + + Signature toFind = builder.build(); + + net.runelite.asm.Method notStatic = cf.findMethod(m.getName(), toFind); + + return notStatic != null; + } +} diff --git a/deobfuscator/src/main/java/net/runelite/deob/deobfuscators/transformers/OpcodesTransformer.java b/deobfuscator/src/main/java/net/runelite/deob/deobfuscators/transformers/OpcodesTransformer.java index 15f9eae248..d515c3bcd4 100644 --- a/deobfuscator/src/main/java/net/runelite/deob/deobfuscators/transformers/OpcodesTransformer.java +++ b/deobfuscator/src/main/java/net/runelite/deob/deobfuscators/transformers/OpcodesTransformer.java @@ -60,7 +60,7 @@ public class OpcodesTransformer implements Transformer if (clinit == null) { clinit = new Method(runeliteOpcodes, "", new Signature("()V")); - clinit.setStatic(); + clinit.setStatic(true); Code code = new Code(clinit); code.setMaxStack(1); clinit.setCode(code); diff --git a/deobfuscator/src/main/java/net/runelite/deob/updater/UpdateMappings.java b/deobfuscator/src/main/java/net/runelite/deob/updater/UpdateMappings.java index 0df369e8ad..db6ed0ef1c 100644 --- a/deobfuscator/src/main/java/net/runelite/deob/updater/UpdateMappings.java +++ b/deobfuscator/src/main/java/net/runelite/deob/updater/UpdateMappings.java @@ -26,19 +26,24 @@ package net.runelite.deob.updater; import java.io.File; import java.io.IOException; +import java.util.Map; import net.runelite.asm.ClassGroup; +import net.runelite.asm.Field; +import net.runelite.asm.Method; +import net.runelite.deob.deobfuscators.Renamer; import net.runelite.deob.deobfuscators.mapping.AnnotationIntegrityChecker; import net.runelite.deob.deobfuscators.mapping.AnnotationMapper; import net.runelite.deob.deobfuscators.mapping.Mapper; import net.runelite.deob.deobfuscators.mapping.ParallelExecutorMapping; import net.runelite.deob.util.JarUtil; +import net.runelite.deob.util.NameMappings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class UpdateMappings { private static final Logger logger = LoggerFactory.getLogger(UpdateMappings.class); - + private static boolean renameRL = true; private final ClassGroup group1, group2; public UpdateMappings(ClassGroup group1, ClassGroup group2) @@ -74,6 +79,32 @@ public class UpdateMappings pr.run(); } + public void updateRL() + { + Mapper mapper = new Mapper(group1, group2); + mapper.run(); + ParallelExecutorMapping mapping = mapper.getMapping(); + NameMappings names = new NameMappings(); + + for (Map.Entry e : mapping.getMap().entrySet()) + { + Object k = e.getKey(); + Object v = e.getValue(); + + if (k instanceof Field) + { + names.map(((Field) v).getPoolField(), ((Field) k).getName()); + } + else if (k instanceof Method) + { + names.map(((Method) v).getPoolMethod(), ((Method) k).getName()); + } + } + + Renamer renamer = new Renamer(names); + renamer.run(group2); + } + public void save(File out) throws IOException { JarUtil.saveJar(group2, out); @@ -90,7 +121,14 @@ public class UpdateMappings JarUtil.loadJar(new File(args[0])), JarUtil.loadJar(new File(args[1])) ); - u.update(); + if (renameRL) + { + u.updateRL(); + } + else + { + u.update(); + } u.save(new File(args[2])); } } diff --git a/deobfuscator/src/test/java/net/runelite/deob/ClassGroupFactory.java b/deobfuscator/src/test/java/net/runelite/deob/ClassGroupFactory.java index 6faef99743..3c2a5bebf9 100644 --- a/deobfuscator/src/test/java/net/runelite/deob/ClassGroupFactory.java +++ b/deobfuscator/src/test/java/net/runelite/deob/ClassGroupFactory.java @@ -39,7 +39,7 @@ public class ClassGroupFactory private static void addVoidMethod(ClassFile cf, String name) { Method method = new Method(cf, name, new Signature("()V")); - method.setStatic(); + method.setStatic(true); cf.addMethod(method); Code code = new Code(method); @@ -63,7 +63,7 @@ public class ClassGroupFactory cf.addField(field); Method method = new Method(cf, "func", new Signature("()V")); - method.setStatic(); + method.setStatic(true); cf.addMethod(method); Code code = new Code(method); @@ -71,7 +71,7 @@ public class ClassGroupFactory { method = new Method(cf, "func2", new Signature("(III)V")); - method.setStatic(); + method.setStatic(true); cf.addMethod(method); code = new Code(method); diff --git a/deobfuscator/src/test/java/net/runelite/deob/updater/UpdateMappingsTest.java b/deobfuscator/src/test/java/net/runelite/deob/updater/UpdateMappingsTest.java index 1eaf240b68..332e2e31b0 100644 --- a/deobfuscator/src/test/java/net/runelite/deob/updater/UpdateMappingsTest.java +++ b/deobfuscator/src/test/java/net/runelite/deob/updater/UpdateMappingsTest.java @@ -70,6 +70,7 @@ public class UpdateMappingsTest } @Test + @Ignore public void testRun() throws IOException { File client = new File(properties.getRsClient()); diff --git a/deobfuscator/src/test/java/net/runelite/runesuite/HookImporter.java b/deobfuscator/src/test/java/net/runelite/runesuite/HookImporter.java index 137260e925..c4a7892a1f 100644 --- a/deobfuscator/src/test/java/net/runelite/runesuite/HookImporter.java +++ b/deobfuscator/src/test/java/net/runelite/runesuite/HookImporter.java @@ -52,6 +52,7 @@ import net.runelite.deob.util.JarUtil; import net.runelite.deob.util.NameMappings; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -87,12 +88,13 @@ public class HookImporter @After public void after() throws IOException { - File out = new File("C:/Users/Lucas/Desktop/client.jar"); + File out = folder.newFile("client.jar"); JarUtil.saveJar(group, out); logger.info("Wrote to {}", out); } @Test + @Ignore public void importHooks() { int classes = 0, fields = 0, methods = 0, access = 0; diff --git a/deobfuscator/src/test/resources/deob-test.properties b/deobfuscator/src/test/resources/deob-test.properties index 125bd16ceb..e26a22a2b9 100644 --- a/deobfuscator/src/test/resources/deob-test.properties +++ b/deobfuscator/src/test/resources/deob-test.properties @@ -1,3 +1,3 @@ -rs.client=C:/Users/Lucas/Desktop/gamepack180_deob.jar +rs.client=${net.runelite.rs:rs-client:jar} rs.version=180 vanilla.client=${net.runelite.rs:vanilla:jar} \ No newline at end of file diff --git a/http-api/src/main/java/net/runelite/http/api/account/AccountClient.java b/http-api/src/main/java/net/runelite/http/api/account/AccountClient.java index 3f66167367..0a286cd70e 100644 --- a/http-api/src/main/java/net/runelite/http/api/account/AccountClient.java +++ b/http-api/src/main/java/net/runelite/http/api/account/AccountClient.java @@ -96,7 +96,7 @@ public class AccountClient } } - public boolean sesssionCheck() + public boolean sessionCheck() { HttpUrl url = RuneLiteAPI.getApiBase().newBuilder() .addPathSegment("account") diff --git a/injector-plugin/pom.xml b/injector-plugin/pom.xml index 4fcc212a47..38728b11e2 100644 --- a/injector-plugin/pom.xml +++ b/injector-plugin/pom.xml @@ -23,7 +23,8 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + 4.0.0 @@ -58,7 +59,7 @@ runescape-api ${project.version} - + org.apache.maven maven-plugin-api diff --git a/injector-plugin/src/main/java/net/runelite/injector/Inject.java b/injector-plugin/src/main/java/net/runelite/injector/Inject.java index af5322e60c..3e24a55374 100644 --- a/injector-plugin/src/main/java/net/runelite/injector/Inject.java +++ b/injector-plugin/src/main/java/net/runelite/injector/Inject.java @@ -47,23 +47,21 @@ import net.runelite.deob.DeobAnnotations; import net.runelite.deob.deobfuscators.arithmetic.DMath; import net.runelite.injector.raw.ClearColorBuffer; import net.runelite.injector.raw.DrawAfterWidgets; +import net.runelite.injector.raw.DrawMenu; import net.runelite.injector.raw.RasterizerHook; import net.runelite.injector.raw.RenderDraw; import net.runelite.injector.raw.ScriptVM; import net.runelite.mapping.Import; +import net.runelite.rs.api.RSClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import net.runelite.rs.api.RSClient; public class Inject { - private static final Logger logger = LoggerFactory.getLogger(Inject.class); - public static final java.lang.Class CLIENT_CLASS = RSClient.class; - public static final String API_PACKAGE_BASE = "net.runelite.rs.api.RS"; public static final String RL_API_PACKAGE_BASE = "net.runelite.api."; - + private static final Logger logger = LoggerFactory.getLogger(Inject.class); private final InjectHookMethod hookMethod = new InjectHookMethod(this); private final InjectGetter getters = new InjectGetter(this); @@ -71,6 +69,7 @@ public class Inject private final InjectInvoker invokes = new InjectInvoker(this); private final InjectConstruct construct = new InjectConstruct(this); + private final DrawMenu drawMenu = new DrawMenu(this); private final RasterizerHook rasterizerHook = new RasterizerHook(this); private final MixinInjector mixinInjector = new MixinInjector(this); private final DrawAfterWidgets drawAfterWidgets = new DrawAfterWidgets(this); @@ -87,34 +86,6 @@ public class Inject this.vanilla = vanilla; } - public Type getFieldType(Field f) - { - Type type = f.getType(); - - Annotation obfSignature = f.getAnnotations().find(DeobAnnotations.OBFUSCATED_SIGNATURE); - if (obfSignature != null) - { - //Annotation exists. Type was updated by us during deobfuscation - type = DeobAnnotations.getObfuscatedType(f); - } - - return type; - } - - public Signature getMethodSignature(Method m) - { - Signature signature = m.getDescriptor(); - - Annotation obfSignature = m.getAnnotations().find(DeobAnnotations.OBFUSCATED_SIGNATURE); - if (obfSignature != null) - { - //Annotation exists. Signature was updated by us during deobfuscation - signature = DeobAnnotations.getObfuscatedSignature(m); - } - - return signature; - } - /** * Convert a java.lang.Class to a Type * @@ -173,6 +144,34 @@ public class Inject return Type.getType("L" + c.getName().replace('.', '/') + ";", dimms); } + public Type getFieldType(Field f) + { + Type type = f.getType(); + + Annotation obfSignature = f.getAnnotations().find(DeobAnnotations.OBFUSCATED_SIGNATURE); + if (obfSignature != null) + { + //Annotation exists. Type was updated by us during deobfuscation + type = DeobAnnotations.getObfuscatedType(f); + } + + return type; + } + + public Signature getMethodSignature(Method m) + { + Signature signature = m.getDescriptor(); + + Annotation obfSignature = m.getAnnotations().find(DeobAnnotations.OBFUSCATED_SIGNATURE); + if (obfSignature != null) + { + //Annotation exists. Signature was updated by us during deobfuscation + signature = DeobAnnotations.getObfuscatedSignature(m); + } + + return signature; + } + /** * Build a Signature from a java method * @@ -284,7 +283,7 @@ public class Inject assert !f.isStatic(); // non static field exported on non exported interface - // logger.debug("Non static exported field {} on non exported interface", exportedName); + // logger.debug("Non static exported field {} on non exported interface", exportedName); continue; } @@ -303,7 +302,7 @@ public class Inject apiMethod = findImportMethodOnApi(targetApiClass, exportedName, false); if (apiMethod == null) { - // logger.debug("Unable to find import method on api class {} with imported name {}, not injecting getter", targetApiClass, exportedName); + //logger.debug("Unable to find import method on api class {} with imported name {}, not injecting getter", targetApiClass, exportedName); continue; } @@ -325,7 +324,7 @@ public class Inject invokes.process(m, other, implementingClass); } } - + logger.info("Injected {} getters, {} setters, {} invokers", getters.getInjectedGetters(), setters.getInjectedSetters(), invokes.getInjectedInvokers()); @@ -334,6 +333,7 @@ public class Inject scriptVM.inject(); clearColorBuffer.inject(); renderDraw.inject(); + drawMenu.inject(); } private java.lang.Class injectInterface(ClassFile cf, ClassFile other) @@ -514,10 +514,10 @@ public class Inject } } - // if (rlApiType == null) - // { - // throw new InjectionException("RS API type " + rsApiType + " does not extend RL API interface"); - // } + // if (rlApiType == null) + // { + // throw new InjectionException("RS API type " + rsApiType + " does not extend RL API interface"); + // } final java.lang.Class finalType = rlApiType == null ? rsApiType : rlApiType; @@ -539,7 +539,7 @@ public class Inject return Type.getType("L" + type.getInternalName().substring(API_PACKAGE_BASE.length()) + ";", type.getDimensions()); } - + ClassFile findVanillaForInterface(java.lang.Class clazz) { String className = clazz.getName().replace('.', '/'); diff --git a/injector-plugin/src/main/java/net/runelite/injector/InjectConstruct.java b/injector-plugin/src/main/java/net/runelite/injector/InjectConstruct.java index 295f636eaa..8a87451da6 100644 --- a/injector-plugin/src/main/java/net/runelite/injector/InjectConstruct.java +++ b/injector-plugin/src/main/java/net/runelite/injector/InjectConstruct.java @@ -54,7 +54,7 @@ public class InjectConstruct private final Inject inject; - public InjectConstruct(Inject inject) + InjectConstruct(Inject inject) { this.inject = inject; } @@ -99,7 +99,7 @@ public class InjectConstruct } } - public void injectConstruct(ClassFile targetClass, java.lang.reflect.Method apiMethod) throws InjectionException + void injectConstruct(ClassFile targetClass, java.lang.reflect.Method apiMethod) throws InjectionException { logger.info("Injecting construct for {}", apiMethod); @@ -115,19 +115,19 @@ public class InjectConstruct Signature sig = inject.javaMethodToSignature(apiMethod); Signature constructorSig = new Signature.Builder() - .addArguments(Stream.of(apiMethod.getParameterTypes()) - .map(arg -> - { - ClassFile vanilla = inject.findVanillaForInterface(arg); - if (vanilla != null) - { - return new Type("L" + vanilla.getName() + ";"); - } - return Inject.classToType(arg); - }) - .collect(Collectors.toList())) - .setReturnType(Type.VOID) - .build(); + .addArguments(Stream.of(apiMethod.getParameterTypes()) + .map(arg -> + { + ClassFile vanilla = inject.findVanillaForInterface(arg); + if (vanilla != null) + { + return new Type("L" + vanilla.getName() + ";"); + } + return Inject.classToType(arg); + }) + .collect(Collectors.toList())) + .setReturnType(Type.VOID) + .build(); Method vanillaConstructor = vanillaClass.findMethod("", constructorSig); if (vanillaConstructor == null) { diff --git a/injector-plugin/src/main/java/net/runelite/injector/InjectGetter.java b/injector-plugin/src/main/java/net/runelite/injector/InjectGetter.java index 3ac2752f6f..cd94ee80d8 100644 --- a/injector-plugin/src/main/java/net/runelite/injector/InjectGetter.java +++ b/injector-plugin/src/main/java/net/runelite/injector/InjectGetter.java @@ -44,20 +44,20 @@ import static org.objectweb.asm.Opcodes.ACC_PUBLIC; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class InjectGetter +class InjectGetter { private static final Logger logger = LoggerFactory.getLogger(InjectGetter.class); - + private final Inject inject; - + private int injectedGetters; - public InjectGetter(Inject inject) + InjectGetter(Inject inject) { this.inject = inject; } - - public void injectGetter(ClassFile clazz, java.lang.reflect.Method method, Field field, Number getter) + + void injectGetter(ClassFile clazz, java.lang.reflect.Method method, Field field, Number getter) { // clazz = class file we're injecting the method into. // method = api method (java reflect) that we're overriding @@ -148,7 +148,7 @@ public class InjectGetter ++injectedGetters; } - public int getInjectedGetters() + int getInjectedGetters() { return injectedGetters; } diff --git a/injector-plugin/src/main/java/net/runelite/injector/InjectHook.java b/injector-plugin/src/main/java/net/runelite/injector/InjectHook.java index a89c8019bf..19ae3a3df6 100644 --- a/injector-plugin/src/main/java/net/runelite/injector/InjectHook.java +++ b/injector-plugin/src/main/java/net/runelite/injector/InjectHook.java @@ -41,9 +41,11 @@ import net.runelite.asm.attributes.code.instruction.types.SetFieldInstruction; import net.runelite.asm.attributes.code.instructions.ArrayStore; import net.runelite.asm.attributes.code.instructions.CheckCast; import net.runelite.asm.attributes.code.instructions.Dup; +import net.runelite.asm.attributes.code.instructions.IMul; import net.runelite.asm.attributes.code.instructions.InvokeStatic; import net.runelite.asm.attributes.code.instructions.InvokeVirtual; import net.runelite.asm.attributes.code.instructions.LDC; +import net.runelite.asm.attributes.code.instructions.LMul; import net.runelite.asm.attributes.code.instructions.PutField; import net.runelite.asm.attributes.code.instructions.Swap; import net.runelite.asm.execution.Execution; @@ -53,28 +55,16 @@ import net.runelite.asm.signature.Signature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class InjectHook +class InjectHook { private static final Logger logger = LoggerFactory.getLogger(InjectHook.class); - - static class HookInfo - { - String fieldName; - String clazz; - Method method; - boolean before; - } - private static final String HOOK_METHOD_SIGNATURE = "(I)V"; - private static final String CLINIT = ""; - private final Inject inject; private final Map hooked = new HashMap<>(); - private int injectedHooks; - public InjectHook(Inject inject) + InjectHook(Inject inject) { this.inject = inject; } @@ -84,7 +74,7 @@ public class InjectHook hooked.put(field, hookInfo); } - public void run() + void run() { Execution e = new Execution(inject.getVanilla()); e.populateInitialMethods(); @@ -139,8 +129,7 @@ public class InjectHook StackContext objectStackContext = null; if (sfi instanceof PutField) { - StackContext objectStack = ic.getPops().get(1); // Object being set on - objectStackContext = objectStack; + objectStackContext = ic.getPops().get(1); } int idx = ins.getInstructions().indexOf(sfi); @@ -154,7 +143,7 @@ public class InjectHook } else { - // idx + 1 to insert after the set + // idx + 1 to insert after the set injectCallback(ins, idx + 1, hookInfo, null, objectStackContext); } } @@ -216,8 +205,7 @@ public class InjectHook StackContext objectStackContext = null; if (arrayReferencePushed.getInstruction().getType() == InstructionType.GETFIELD) { - StackContext objectReference = arrayReferencePushed.getPops().get(0); - objectStackContext = objectReference; + objectStackContext = arrayReferencePushed.getPops().get(0); } // inject hook after 'i' @@ -262,6 +250,21 @@ public class InjectHook ins.getInstructions().add(idx++, new Dup(ins)); // dup value idx = recursivelyPush(ins, idx, object); ins.getInstructions().add(idx++, new Swap(ins)); + if (hookInfo.getter != null) + { + assert hookInfo.getter instanceof Integer || hookInfo.getter instanceof Long; + + if (hookInfo.getter instanceof Integer) + { + ins.getInstructions().add(idx++, new LDC(ins, (int) hookInfo.getter)); + ins.getInstructions().add(idx++, new IMul(ins)); + } + else + { + ins.getInstructions().add(idx++, new LDC(ins, (long) hookInfo.getter)); + ins.getInstructions().add(idx++, new LMul(ins)); + } + } if (!value.type.equals(methodArgumentType)) { CheckCast checkCast = new CheckCast(ins); @@ -377,8 +380,17 @@ public class InjectHook } } - public int getInjectedHooks() + int getInjectedHooks() { return injectedHooks; } + + static class HookInfo + { + String fieldName; + String clazz; + Method method; + boolean before; + Number getter; + } } diff --git a/injector-plugin/src/main/java/net/runelite/injector/InjectHookMethod.java b/injector-plugin/src/main/java/net/runelite/injector/InjectHookMethod.java index 6c74fbc5fa..94303e81d3 100644 --- a/injector-plugin/src/main/java/net/runelite/injector/InjectHookMethod.java +++ b/injector-plugin/src/main/java/net/runelite/injector/InjectHookMethod.java @@ -49,18 +49,16 @@ import org.slf4j.LoggerFactory; public class InjectHookMethod { - private static final Logger logger = LoggerFactory.getLogger(InjectHookMethod.class); - public static final String HOOKS = "net/runelite/client/callback/Hooks"; - + private static final Logger logger = LoggerFactory.getLogger(InjectHookMethod.class); private final Inject inject; - public InjectHookMethod(Inject inject) + InjectHookMethod(Inject inject) { this.inject = inject; } - public void process(Method method) throws InjectionException + void process(Method method) throws InjectionException { Annotations an = method.getAnnotations(); if (an == null) @@ -115,7 +113,7 @@ public class InjectHookMethod Instructions instructions = vanillaMethod.getCode().getInstructions(); Signature.Builder builder = new Signature.Builder() - .setReturnType(Type.VOID); // Hooks always return void + .setReturnType(Type.VOID); // Hooks always return void for (Type type : deobMethod.getDescriptor().getArguments()) { @@ -164,11 +162,11 @@ public class InjectHookMethod { // Invoke callback invoke = new InvokeStatic(instructions, - new net.runelite.asm.pool.Method( - new net.runelite.asm.pool.Class(HOOKS), - hookName, - signature - ) + new net.runelite.asm.pool.Method( + new net.runelite.asm.pool.Class(HOOKS), + hookName, + signature + ) ); } else @@ -179,11 +177,11 @@ public class InjectHookMethod if (vanillaMethod.isStatic()) { invoke = new InvokeStatic(instructions, - new net.runelite.asm.pool.Method( - new net.runelite.asm.pool.Class("client"), // Static methods are in client - hookMethod.getName(), - signature - ) + new net.runelite.asm.pool.Method( + new net.runelite.asm.pool.Class("client"), // Static methods are in client + hookMethod.getName(), + signature + ) ); } else @@ -191,11 +189,11 @@ public class InjectHookMethod // otherwise invoke member function //instructions.addInstruction(insertPos++, new ALoad(instructions, 0)); invoke = new InvokeVirtual(instructions, - new net.runelite.asm.pool.Method( - new net.runelite.asm.pool.Class(vanillaMethod.getClassFile().getName()), - hookMethod.getName(), - signature - ) + new net.runelite.asm.pool.Method( + new net.runelite.asm.pool.Class(vanillaMethod.getClassFile().getName()), + hookMethod.getName(), + signature + ) ); } } diff --git a/injector-plugin/src/main/java/net/runelite/injector/InjectInvoker.java b/injector-plugin/src/main/java/net/runelite/injector/InjectInvoker.java index 1b59e63b4c..1153609b8e 100644 --- a/injector-plugin/src/main/java/net/runelite/injector/InjectInvoker.java +++ b/injector-plugin/src/main/java/net/runelite/injector/InjectInvoker.java @@ -51,7 +51,7 @@ import static org.objectweb.asm.Opcodes.ACC_PUBLIC; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class InjectInvoker +class InjectInvoker { private static final Logger logger = LoggerFactory.getLogger(InjectInvoker.class); @@ -59,7 +59,7 @@ public class InjectInvoker private int injectedInvokers; - public InjectInvoker(Inject inject) + InjectInvoker(Inject inject) { this.inject = inject; } @@ -67,13 +67,13 @@ public class InjectInvoker /** * Inject an invoker for a method * - * @param m Method in the deobfuscated client to inject an invoker for - * @param other Class in the vanilla client of the same class m is a - * member of + * @param m Method in the deobfuscated client to inject an invoker for + * @param other Class in the vanilla client of the same class m is a + * member of * @param implementingClass Java class for the API interface the class - * will implement + * will implement */ - public void process(Method m, ClassFile other, java.lang.Class implementingClass) + void process(Method m, ClassFile other, java.lang.Class implementingClass) { Annotations an = m.getAnnotations(); @@ -108,14 +108,14 @@ public class InjectInvoker assert !m.isStatic(); // non static exported method on non exported interface, weird. - // logger.debug("Non static exported method {} on non exported interface", exportedName); + // logger.debug("Non static exported method {} on non exported interface", exportedName); return; } java.lang.reflect.Method apiMethod = inject.findImportMethodOnApi(targetClassJava, exportedName, null); // api method to invoke 'otherm' if (apiMethod == null) { - // logger.debug("Unable to find api method on {} with imported name {}, not injecting invoker", targetClassJava, exportedName); + // logger.debug("Unable to find api method on {} with imported name {}, not injecting invoker", targetClassJava, exportedName); return; } @@ -284,7 +284,7 @@ public class InjectInvoker clazz.addMethod(invokerMethodSignature); } - public int getInjectedInvokers() + int getInjectedInvokers() { return injectedInvokers; } diff --git a/injector-plugin/src/main/java/net/runelite/injector/InjectMojo.java b/injector-plugin/src/main/java/net/runelite/injector/InjectMojo.java index 08ac162588..b7c22194fe 100644 --- a/injector-plugin/src/main/java/net/runelite/injector/InjectMojo.java +++ b/injector-plugin/src/main/java/net/runelite/injector/InjectMojo.java @@ -45,17 +45,14 @@ import org.apache.maven.plugins.annotations.Parameter; ) public class InjectMojo extends AbstractMojo { + private final Log log = getLog(); @Parameter(defaultValue = "${project.build.outputDirectory}") private File outputDirectory; - @Parameter(defaultValue = "./runescape-client/target/rs-client-${project.version}.jar", readonly = true, required = true) private String rsClientPath; - @Parameter(defaultValue = "${net.runelite.rs:vanilla:jar}", readonly = true, required = true) private String vanillaPath; - private final Log log = getLog(); - @Override public void execute() throws MojoExecutionException, MojoFailureException { diff --git a/injector-plugin/src/main/java/net/runelite/injector/InjectSetter.java b/injector-plugin/src/main/java/net/runelite/injector/InjectSetter.java index bcb8b1815d..58c225fa87 100644 --- a/injector-plugin/src/main/java/net/runelite/injector/InjectSetter.java +++ b/injector-plugin/src/main/java/net/runelite/injector/InjectSetter.java @@ -45,15 +45,15 @@ import static org.objectweb.asm.Opcodes.ACC_PUBLIC; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class InjectSetter +class InjectSetter { private static final Logger logger = LoggerFactory.getLogger(InjectSetter.class); private final Inject inject; - + private int injectedSetters; - public InjectSetter(Inject inject) + InjectSetter(Inject inject) { this.inject = inject; } @@ -61,15 +61,14 @@ public class InjectSetter /** * inject a setter into the vanilla classgroup * - * @param targetClass Class where to inject the setter (field's class, - * or client) + * @param targetClass Class where to inject the setter (field's class, + * or client) * @param targetApiClass API targetClass implements, which may have the - * setter declared - * @param field Field of vanilla that will be set - * @param exportedName exported name of field - * @param setter + * setter declared + * @param field Field of vanilla that will be set + * @param exportedName exported name of field */ - public void injectSetter(ClassFile targetClass, Class targetApiClass, Field field, String exportedName, Number setter) + void injectSetter(ClassFile targetClass, Class targetApiClass, Field field, String exportedName, Number setter) { java.lang.reflect.Method method = inject.findImportMethodOnApi(targetApiClass, exportedName, true); if (method == null) @@ -114,7 +113,7 @@ public class InjectSetter // load argument Type argumentType = sig.getTypeOfArg(0); ins.add(inject.createLoadForTypeIndex(instructions, argumentType, 1)); - + // cast argument to field type Type fieldType = field.getType(); if (!argumentType.equals(fieldType)) @@ -152,7 +151,7 @@ public class InjectSetter ins.add(new VReturn(instructions)); } - public int getInjectedSetters() + int getInjectedSetters() { return injectedSetters; } diff --git a/injector-plugin/src/main/java/net/runelite/injector/InjectUtil.java b/injector-plugin/src/main/java/net/runelite/injector/InjectUtil.java new file mode 100644 index 0000000000..e9a32a0bb0 --- /dev/null +++ b/injector-plugin/src/main/java/net/runelite/injector/InjectUtil.java @@ -0,0 +1,130 @@ +package net.runelite.injector; + +import net.runelite.asm.ClassFile; +import net.runelite.asm.Field; +import net.runelite.asm.Method; +import net.runelite.asm.signature.Signature; +import net.runelite.deob.DeobAnnotations; + +public class InjectUtil +{ + public static Method findStaticObMethod(Inject inject, String name) throws InjectionException + { + for (ClassFile c : inject.getVanilla().getClasses()) + { + for (Method m : c.getMethods()) + { + if (!m.getName().equals(name)) + { + continue; + } + return m; + } + } + + throw new InjectionException(String.format("Method \"%s\" could not be found.", name)); + } + + public static Method findMethod(Inject inject, String name) throws InjectionException + { + for (ClassFile c : inject.getDeobfuscated().getClasses()) + { + for (Method m : c.getMethods()) + { + if (!m.getName().equals(name)) + { + continue; + } + + String obfuscatedName = DeobAnnotations.getObfuscatedName(m.getAnnotations()); + Signature obfuscatedSignature = DeobAnnotations.getObfuscatedSignature(m); + + ClassFile c2 = inject.toObClass(c); + + return c2.findMethod(obfuscatedName, (obfuscatedSignature != null) ? obfuscatedSignature : m.getDescriptor()); + } + } + + throw new InjectionException("Couldn't find method " + name); + } + + public static Method findStaticMethod(Inject inject, String name) throws InjectionException + { + for (ClassFile c : inject.getDeobfuscated().getClasses()) + { + for (Method m : c.getMethods()) + { + if (!m.isStatic() || !m.getName().equals(name)) + { + continue; + } + + String obfuscatedName = DeobAnnotations.getObfuscatedName(m.getAnnotations()); + Signature obfuscatedSignature = DeobAnnotations.getObfuscatedSignature(m); + + ClassFile c2 = inject.toObClass(c); + + return c2.findMethod(obfuscatedName, (obfuscatedSignature != null) ? obfuscatedSignature : m.getDescriptor()); + } + } + + throw new InjectionException("Couldn't find static method " + name); + } + + + public static Field findObField(Inject inject, String name) throws InjectionException + { + for (ClassFile c : inject.getVanilla().getClasses()) + { + for (Field f : c.getFields()) + { + if (!f.getName().equals(name)) + { + continue; + } + return f; + } + } + + throw new InjectionException(String.format("Field \"%s\" could not be found.", name)); + } + + public static Field findDeobField(Inject inject, String name) throws InjectionException + { + for (ClassFile c : inject.getDeobfuscated().getClasses()) + { + for (Field f : c.getFields()) + { + if (!f.getName().equals(name)) + { + continue; + } + + String obfuscatedName = DeobAnnotations.getObfuscatedName(f.getAnnotations()); + + ClassFile c2 = inject.toObClass(c); + return c2.findField(obfuscatedName); + } + } + + throw new InjectionException(String.format("Mapped field \"%s\" could not be found.", name)); + } + + public static Field findDeobFieldButUseless(Inject inject, String name) throws InjectionException + { + for (ClassFile c : inject.getDeobfuscated().getClasses()) + { + for (Field f : c.getFields()) + { + if (!f.getName().equals(name)) + { + continue; + } + + return f; + } + } + + throw new InjectionException(String.format("Mapped field \"%s\" could not be found.", name)); + } +} diff --git a/injector-plugin/src/main/java/net/runelite/injector/Injector.java b/injector-plugin/src/main/java/net/runelite/injector/Injector.java index 60577cfbd4..9409b02075 100644 --- a/injector-plugin/src/main/java/net/runelite/injector/Injector.java +++ b/injector-plugin/src/main/java/net/runelite/injector/Injector.java @@ -39,17 +39,6 @@ public class Injector this.vanilla = vanilla; } - public void inject() throws InjectionException - { - Inject instance = new Inject(deobfuscated, vanilla); - instance.run(); - } - - public void save(File out) throws IOException - { - JarUtil.saveJar(vanilla, out); - } - public static void main(String[] args) throws IOException, InjectionException { if (args.length < 3) @@ -72,5 +61,16 @@ public class Injector u.save(new File(args[2])); } + public void inject() throws InjectionException + { + Inject instance = new Inject(deobfuscated, vanilla); + instance.run(); + } + + private void save(File out) throws IOException + { + JarUtil.saveJar(vanilla, out); + } + } diff --git a/injector-plugin/src/main/java/net/runelite/injector/InjectorValidator.java b/injector-plugin/src/main/java/net/runelite/injector/InjectorValidator.java index f4e2cad9b9..a49df63a3a 100644 --- a/injector-plugin/src/main/java/net/runelite/injector/InjectorValidator.java +++ b/injector-plugin/src/main/java/net/runelite/injector/InjectorValidator.java @@ -39,7 +39,7 @@ import org.slf4j.LoggerFactory; * * @author Adam */ -public class InjectorValidator +class InjectorValidator { private static final Logger logger = LoggerFactory.getLogger(InjectorValidator.class); @@ -49,12 +49,12 @@ public class InjectorValidator private int error, missing, okay; - public InjectorValidator(ClassGroup group) + InjectorValidator(ClassGroup group) { this.group = group; } - public void validate() + void validate() { for (ClassFile cf : group.getClasses()) { @@ -131,17 +131,17 @@ public class InjectorValidator } } - public int getError() + int getError() { return error; } - public int getMissing() + int getMissing() { return missing; } - public int getOkay() + int getOkay() { return okay; } diff --git a/injector-plugin/src/main/java/net/runelite/injector/MixinInjector.java b/injector-plugin/src/main/java/net/runelite/injector/MixinInjector.java index 9e4b64cacb..815b3699aa 100644 --- a/injector-plugin/src/main/java/net/runelite/injector/MixinInjector.java +++ b/injector-plugin/src/main/java/net/runelite/injector/MixinInjector.java @@ -87,7 +87,7 @@ public class MixinInjector // Use net.runelite.asm.pool.Field instead of Field because the pool version has hashcode implemented private final Map shadowFields = new HashMap<>(); - public MixinInjector(Inject inject) + MixinInjector(Inject inject) { this.inject = inject; } @@ -165,9 +165,6 @@ public class MixinInjector /** * Finds fields that are marked @Inject and inject them into the target - * - * @param mixinClasses - * @throws InjectionException */ private void injectFields(Map, List> mixinClasses) throws InjectionException { @@ -245,9 +242,6 @@ public class MixinInjector /** * Find fields which are marked @Shadow, and what they shadow - * - * @param mixinClasses - * @throws InjectionException */ private void findShadowFields(Map, List> mixinClasses) throws InjectionException { @@ -287,7 +281,7 @@ public class MixinInjector else { // Shadow a field already in the gamepack - Field shadowField = findDeobField(shadowName); + Field shadowField = InjectUtil.findDeobFieldButUseless(inject, shadowName); if (shadowField == null) { @@ -316,21 +310,6 @@ public class MixinInjector } } - private Field findDeobField(String name) - { - for (ClassFile cf : inject.getDeobfuscated().getClasses()) - { - for (Field f : cf.getFields()) - { - if (f.getName().equals(name) && f.isStatic()) - { - return f; - } - } - } - return null; - } - private void injectMethods(ClassFile mixinCf, ClassFile cf, Map shadowFields) throws InjectionException { @@ -404,7 +383,7 @@ public class MixinInjector care of the garbage parameter itself. */ boolean hasGarbageValue = method.getDescriptor().size() != obMethod.getDescriptor().size() - && deobMethod.getDescriptor().size() < obMethodSignature.size(); + && deobMethod.getDescriptor().size() < obMethodSignature.size(); copiedMethods.put(method.getPoolMethod(), new CopiedMethod(copy, hasGarbageValue)); logger.debug("Injected copy of {} to {}", obMethod, copy); @@ -577,7 +556,7 @@ public class MixinInjector if (!returnType.equals(deobReturnType)) { ClassFile deobReturnTypeClassFile = inject.getDeobfuscated() - .findClass(deobReturnType.getInternalName()); + .findClass(deobReturnType.getInternalName()); if (deobReturnTypeClassFile != null) { ClassFile obReturnTypeClass = inject.toObClass(deobReturnTypeClassFile); @@ -601,13 +580,13 @@ public class MixinInjector moveCode(obMethod, method.getCode()); boolean hasGarbageValue = method.getDescriptor().size() != obMethod.getDescriptor().size() - && deobMethod.getDescriptor().size() < obMethodSignature.size(); + && deobMethod.getDescriptor().size() < obMethodSignature.size(); if (hasGarbageValue) { int garbageIndex = obMethod.isStatic() - ? obMethod.getDescriptor().size() - 1 - : obMethod.getDescriptor().size(); + ? obMethod.getDescriptor().size() - 1 + : obMethod.getDescriptor().size(); /* If the mixin method doesn't have the garbage parameter, @@ -645,8 +624,8 @@ public class MixinInjector } private void setOwnersToTargetClass(ClassFile mixinCf, ClassFile cf, Method method, - Map shadowFields, - Map copiedMethods) + Map shadowFields, + Map copiedMethods) throws InjectionException { ListIterator iterator = method.getCode().getInstructions().getInstructions().listIterator(); @@ -901,7 +880,7 @@ public class MixinInjector if (targetField == null) { // first try non static fields, then static - targetField = findDeobField(hookName); + targetField = InjectUtil.findDeobFieldButUseless(inject, hookName); } if (targetField == null) @@ -909,6 +888,13 @@ public class MixinInjector throw new InjectionException("Field hook for nonexistent field " + hookName + " on " + method); } + Annotation an = targetField.getAnnotations().find(DeobAnnotations.OBFUSCATED_GETTER); + Number getter = null; + if (an != null) + { + getter = (Number) an.getElement().getValue(); + } + Field obField = inject.toObField(targetField); if (method.isStatic() != targetField.isStatic()) @@ -922,6 +908,7 @@ public class MixinInjector hookInfo.fieldName = hookName; hookInfo.method = method; hookInfo.before = before; + hookInfo.getter = getter; injectHook.hook(obField, hookInfo); } } diff --git a/injector-plugin/src/main/java/net/runelite/injector/raw/ClearColorBuffer.java b/injector-plugin/src/main/java/net/runelite/injector/raw/ClearColorBuffer.java index e1da299dd1..ac40a35e14 100644 --- a/injector-plugin/src/main/java/net/runelite/injector/raw/ClearColorBuffer.java +++ b/injector-plugin/src/main/java/net/runelite/injector/raw/ClearColorBuffer.java @@ -11,8 +11,8 @@ import net.runelite.asm.attributes.code.instructions.InvokeStatic; import net.runelite.asm.attributes.code.instructions.LDC; import net.runelite.asm.pool.Class; import net.runelite.asm.signature.Signature; -import net.runelite.deob.DeobAnnotations; import net.runelite.injector.Inject; +import net.runelite.injector.InjectUtil; import net.runelite.injector.InjectionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,7 +39,7 @@ public class ClearColorBuffer private void injectColorBufferHooks() throws InjectionException { - net.runelite.asm.pool.Method fillRectangle = findStaticMethod("Rasterizer2D_fillRectangle").getPoolMethod(); + net.runelite.asm.pool.Method fillRectangle = InjectUtil.findStaticMethod(inject, "Rasterizer2D_fillRectangle").getPoolMethod(); int count = 0; int replaced = 0; @@ -79,7 +79,7 @@ public class ClearColorBuffer if (current instanceof LDC && ((LDC) current).getConstantAsInt() == 0) { int varIdx = 0; - for (; ;) + for (; ; ) { current = it.previous(); if (current instanceof ILoad && ((ILoad) current).getVariableIndex() == 3 - varIdx) @@ -119,28 +119,4 @@ public class ClearColorBuffer } } } - - private Method findStaticMethod(String name) throws InjectionException - { - for (ClassFile c : inject.getDeobfuscated().getClasses()) - { - for (Method m : c.getMethods()) - { - if (!m.getName().equals(name)) - { - continue; - } - - String obfuscatedName = DeobAnnotations.getObfuscatedName(m.getAnnotations()); - Signature obfuscatedSignature = DeobAnnotations.getObfuscatedSignature(m); - - ClassFile c2 = inject.toObClass(c); - - return c2.findMethod(obfuscatedName, (obfuscatedSignature != null) ? obfuscatedSignature : m.getDescriptor()); - } - } - - throw new InjectionException("Couldn't find static method " + name); - } - } \ No newline at end of file diff --git a/injector-plugin/src/main/java/net/runelite/injector/raw/DrawAfterWidgets.java b/injector-plugin/src/main/java/net/runelite/injector/raw/DrawAfterWidgets.java index db239448bf..e2250b894e 100644 --- a/injector-plugin/src/main/java/net/runelite/injector/raw/DrawAfterWidgets.java +++ b/injector-plugin/src/main/java/net/runelite/injector/raw/DrawAfterWidgets.java @@ -38,9 +38,9 @@ import net.runelite.asm.attributes.code.instructions.GetStatic; import net.runelite.asm.attributes.code.instructions.IMul; import net.runelite.asm.attributes.code.instructions.InvokeStatic; import net.runelite.asm.signature.Signature; -import net.runelite.deob.DeobAnnotations; import net.runelite.injector.Inject; import static net.runelite.injector.InjectHookMethod.HOOKS; +import static net.runelite.injector.InjectUtil.findStaticMethod; import net.runelite.injector.InjectionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -107,7 +107,7 @@ public class DrawAfterWidgets boolean injected = false; - Method noClip = findStaticMethod("Rasterizer2D_resetClip"); // !!!!! + Method noClip = findStaticMethod(inject, "Rasterizer2D_resetClip"); // !!!!! if (noClip == null) { @@ -166,7 +166,7 @@ public class DrawAfterWidgets { // If we get here, we're either in the wrong method // or Jagex has removed the "if (535573958 * kl != -1)" - // logger.debug("Could not find the label for jumping to the " + noClip + " call in " + m); + // logger.debug("Could not find the label for jumping to the " + noClip + " call in " + m); continue; } @@ -261,27 +261,4 @@ public class DrawAfterWidgets throw new InjectionException("injectDrawAfterWidgets failed to inject!"); } } - - private Method findStaticMethod(String name) - { - for (ClassFile c : inject.getDeobfuscated().getClasses()) - { - for (Method m : c.getMethods()) - { - if (!m.getName().equals(name)) - { - continue; - } - - String obfuscatedName = DeobAnnotations.getObfuscatedName(m.getAnnotations()); - Signature obfuscatedSignature = DeobAnnotations.getObfuscatedSignature(m); - - ClassFile c2 = inject.toObClass(c); - - return c2.findMethod(obfuscatedName, (obfuscatedSignature != null) ? obfuscatedSignature : m.getDescriptor()); - } - } - - return null; - } } diff --git a/injector-plugin/src/main/java/net/runelite/injector/raw/DrawMenu.java b/injector-plugin/src/main/java/net/runelite/injector/raw/DrawMenu.java index 65cb9bdab4..b6634e68c5 100644 --- a/injector-plugin/src/main/java/net/runelite/injector/raw/DrawMenu.java +++ b/injector-plugin/src/main/java/net/runelite/injector/raw/DrawMenu.java @@ -1,193 +1,135 @@ -/* package net.runelite.injector.raw; -import com.google.common.base.Strings; -import java.util.HashSet; -import java.util.Set; +import java.util.ListIterator; import net.runelite.asm.ClassFile; import net.runelite.asm.Method; -import net.runelite.asm.Type; -import net.runelite.asm.attributes.Annotations; import net.runelite.asm.attributes.Code; -import net.runelite.asm.attributes.annotation.Annotation; import net.runelite.asm.attributes.code.Instruction; import net.runelite.asm.attributes.code.Instructions; import net.runelite.asm.attributes.code.Label; -import net.runelite.asm.attributes.code.instruction.types.ComparisonInstruction; import net.runelite.asm.attributes.code.instruction.types.JumpingInstruction; -import net.runelite.asm.attributes.code.instruction.types.ReturnInstruction; import net.runelite.asm.attributes.code.instructions.GetStatic; -import net.runelite.asm.attributes.code.instructions.IfACmpEq; -import net.runelite.asm.attributes.code.instructions.IfACmpNe; import net.runelite.asm.attributes.code.instructions.IfEq; import net.runelite.asm.attributes.code.instructions.IfNe; import net.runelite.asm.attributes.code.instructions.InvokeStatic; -import net.runelite.asm.execution.Execution; -import net.runelite.asm.execution.InstructionContext; import net.runelite.asm.pool.Class; import net.runelite.asm.pool.Field; import net.runelite.asm.signature.Signature; -import net.runelite.deob.DeobAnnotations; import net.runelite.injector.Inject; +import static net.runelite.injector.InjectUtil.findDeobField; +import static net.runelite.injector.InjectUtil.findStaticMethod; import net.runelite.injector.InjectionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class DrawMenu { + private final Logger log = LoggerFactory.getLogger(DrawMenu.class); private final Inject inject; - private static final Field isMenuOpen = new Field( - new Class("Client"), - "isMenuOpen", - Type.BOOLEAN - ); private static final net.runelite.asm.pool.Method hook = new net.runelite.asm.pool.Method( new Class("net.runelite.client.callback.Hooks"), "drawMenu", new Signature("()Z") ); + //Label Getstatic client.isMenuOpen + //Ifne -> Label Drawmenu + //Jump -> Label Drawtext + + //Label drawtext + //Ldc xxx + //Getstatic client. something with viewport size? + //Imul + //Iconst_m1 + //Ifne -> Label after draw menu <- info we need + //Getstatic / LDC (same getstatic and LDC before) + //Getstatic / LDC + public DrawMenu(Inject inject) { - this.inject =inject; + this.inject = inject; } public void inject() throws InjectionException { - Method drawLoggedIn = findDeobThing("drawLoggedIn", "Client", false); - Instructions ins = drawLoggedIn.getCode().getInstructions(); + Field isMenuOpen = findDeobField(inject, "isMenuOpen").getPoolField(); + net.runelite.asm.pool.Method topLeftText = findStaticMethod(inject, "drawMenuActionTextAt").getPoolMethod(); - int menuOpenIdx = -1; - Field field = toObField(isMenuOpen).getPoolField(); - - for (Instruction i : ins.getInstructions()) - { - if (!(i instanceof GetStatic)) - { - continue; - } - - if (((GetStatic) i).getField().equals(field)) - { - menuOpenIdx = ins.getInstructions().indexOf(i); - } - } - - if (menuOpenIdx == -1) - { - throw new InjectionException("Couldn't find the isMenuOpen check!"); - } - - // This is where the IFEQ or IFNE will be - final Instruction jump = ins.getInstructions().get(menuOpenIdx + 1); - // We want to inject if it's false so - if (jump instanceof IfEq) - { - // Not this one, but we gotta find out where the paths will intersect - Set