From 6a73c6f8e6cffccfba5fe8a288afc034479ec4c6 Mon Sep 17 00:00:00 2001 From: zeruth Date: Sun, 21 Apr 2019 00:16:50 -0400 Subject: [PATCH] ClientTransform Adds all protected menu transforms necessary for blackjacking! Eat shit upstream :) --- .../kittennotifier/KittenNotifierConfig.java | 6 - .../kittennotifier/KittenNotifierPlugin.java | 30 +- .../client/rs/bytecode/ByteCodePatcher.java | 291 +++++++++--------- .../transformers/ClientTransform.java | 194 ++++++++++++ 4 files changed, 359 insertions(+), 162 deletions(-) create mode 100644 runelite-client/src/main/java/net/runelite/client/rs/bytecode/transformers/ClientTransform.java diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/kittennotifier/KittenNotifierConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/kittennotifier/KittenNotifierConfig.java index e9d28f6b26..b4d567b16a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/kittennotifier/KittenNotifierConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/kittennotifier/KittenNotifierConfig.java @@ -18,10 +18,4 @@ public interface KittenNotifierConfig extends Config{ hidden = true ) default boolean catOwned() { return false; } - @ConfigItem( - keyName = "catOwned", - name = "", - description = "" - ) - void catOwned(Boolean bool); } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/kittennotifier/KittenNotifierPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/kittennotifier/KittenNotifierPlugin.java index 45ef04e0d2..584cbcde8c 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/kittennotifier/KittenNotifierPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/kittennotifier/KittenNotifierPlugin.java @@ -2,6 +2,7 @@ package net.runelite.client.plugins.kittennotifier; import com.google.inject.Provides; import net.runelite.api.ChatMessageType; import net.runelite.api.events.ChatMessage; +import net.runelite.api.events.GameTick; import net.runelite.api.events.NpcActionChanged; import net.runelite.api.events.NpcSpawned; import net.runelite.client.Notifier; @@ -20,6 +21,8 @@ import javax.inject.Inject; type = "utility" ) public class KittenNotifierPlugin extends Plugin{ + + public boolean catOwned = false; @Inject private Notifier notifier; @Inject @@ -51,36 +54,33 @@ public class KittenNotifierPlugin extends Plugin{ } } @Subscribe - public void onNpcActionChanged(NpcActionChanged event) { - if (event.getNpcComposition()!=null) + public void onGameTick(GameTick event) { if (!config.catOwned()) { for (NPC npc : client.getNpcs()) { - if (npc.getInteracting() != null) { - if (npc.getName().equals("Cat") && !config.catOwned()) { - // If this if statement is included in previous it could null. + if (npc.getInteracting()!=null) if (npc.getInteracting().getName().contentEquals(client.getLocalPlayer().getName())) { - config.catOwned(true); - notifier.notify("Your kitten has grown into a cat."); + if (npc.getName().equals("Cat") && !config.catOwned()) { + // If this if statement is included in previous it could null. + catOwned = true; + notifier.notify("Your kitten has grown into a cat."); } } } } - } } @Subscribe public void onNpcSpawned(NpcSpawned event) { NPC cat = event.getNpc(); - if (cat.getName() != null) { - if (cat.getName().equalsIgnoreCase("Kitten")) { - if (cat.getInteracting().getName().contentEquals(client.getLocalPlayer().getName())) { - config.catOwned(false); + if (cat.getInteracting()!=null) + if (cat.getInteracting().getName().equalsIgnoreCase(client.getLocalPlayer().getName())) { + if (cat.getName().contains("itten") && !config.catOwned()) { + catOwned = false; } } - else if (cat.getName().contentEquals("Cat")) { + else if (cat.getName().equals("Cat")) { if (cat.getInteracting().getName().equalsIgnoreCase(client.getLocalPlayer().getName())) { - config.catOwned(true); + catOwned = true; } } } - } } diff --git a/runelite-client/src/main/java/net/runelite/client/rs/bytecode/ByteCodePatcher.java b/runelite-client/src/main/java/net/runelite/client/rs/bytecode/ByteCodePatcher.java index b75a8c9631..1ab7c2da3e 100644 --- a/runelite-client/src/main/java/net/runelite/client/rs/bytecode/ByteCodePatcher.java +++ b/runelite-client/src/main/java/net/runelite/client/rs/bytecode/ByteCodePatcher.java @@ -8,22 +8,19 @@ import javassist.NotFoundException; import net.runelite.client.RuneLite; import net.runelite.client.rs.ClientLoader; import net.runelite.client.rs.bytecode.transformers.ActorTransform; +import net.runelite.client.rs.bytecode.transformers.ClientTransform; import net.runelite.client.rs.bytecode.transformers.PlayerTransform; import net.runelite.client.rs.bytecode.transformers.ProjectileTransform; import net.runelite.http.api.RuneLiteAPI; import org.xeustechnologies.jcl.JarClassLoader; import java.io.BufferedInputStream; -import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.io.Writer; -import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.net.URISyntaxException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; @@ -33,154 +30,166 @@ import java.util.jar.JarInputStream; public class ByteCodePatcher { - public static List modifiedClasses = new ArrayList<>(); - public static Hooks hooks = new Hooks(); - public static String clientInstance; - public static JarClassLoader jcl = new JarClassLoader(); - public static ClassPool classPool = null; - public static ClassLoader cl = ClassLoader.getSystemClassLoader(); + public static List modifiedClasses = new ArrayList<>(); + public static Hooks hooks = new Hooks(); + public static String clientInstance; + public static JarClassLoader jcl = new JarClassLoader(); + public static ClassPool classPool = null; + public static ClassLoader cl = ClassLoader.getSystemClassLoader(); - public static void applyHooks(File jf, Hooks hooks) { - try { - URLClassLoader child = new URLClassLoader( - new URL[] {jf.toURI().toURL()}, - cl - ); - try { - Class actorClass = Class.forName(hooks.actorClass, false, child); - transformActor(actorClass); - Class projectileClass = Class.forName(hooks.projectileClass, false, child); - transformProjectile(projectileClass); - Class playerClass = Class.forName(hooks.playerClass, false, child); - transformPlayer(playerClass); - ByteCodeUtils.updateHijackedJar(); - } catch (Exception e) { - e.printStackTrace(); - } + public static void applyHooks(File jf, Hooks hooks) { + try { + URLClassLoader child = new URLClassLoader( + new URL[] {jf.toURI().toURL()}, + cl + ); + try { + Class actorClass = Class.forName(hooks.actorClass, false, child); + transformActor(actorClass); + Class projectileClass = Class.forName(hooks.projectileClass, false, child); + transformProjectile(projectileClass); + Class playerClass = Class.forName(hooks.playerClass, false, child); + transformPlayer(playerClass); - } catch (Exception e) { - e.printStackTrace(); - } - } + //experimental + Class clientClass = Class.forName("client", false, child); + transformBlackjack(clientClass); - public static void findHooks(String jf) { - try { - classPool = new ClassPool(true); - classPool.appendClassPath(RuneLite.RUNELITE_DIR+"/injectedClient-"+ RuneLiteAPI.getVersion() +"-.jar"); - } catch (NotFoundException e) { - e.printStackTrace(); - } + ByteCodeUtils.updateHijackedJar(); + } catch (Exception e) { + e.printStackTrace(); + } - try { - jcl.add(new FileInputStream(jf)); - try (JarInputStream in = new JarInputStream(new BufferedInputStream(new FileInputStream(jf)))) { - JarEntry entry; - while ((entry = in.getNextJarEntry()) != null) { - if (entry.getName().endsWith(".class")) { - checkClasses(new File(jf), entry); - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - Gson gson = new GsonBuilder().setPrettyPrinting().create(); - try { - Writer writer = new FileWriter(ClientLoader.hooksFile); - gson.toJson(hooks, writer); - writer.flush(); - writer.close(); - } catch (IOException e) { - e.printStackTrace(); - } - ByteCodeUtils.updateHijackedJar(); - } + } catch (Exception e) { + e.printStackTrace(); + } + } - public static void checkClasses(File jf, JarEntry entry) { - try { - URLClassLoader child = new URLClassLoader( - new URL[] {jf.toURI().toURL()}, - cl - ); - try { - Class classToLoad = Class.forName(entry.getName().replace(".class", ""), false, child); - checkActor(classToLoad); - checkProjectile(classToLoad); - checkPlayer(classToLoad); - } catch (Exception e) { - e.printStackTrace(); - } + public static void findHooks(String jf) { + try { + classPool = new ClassPool(true); + classPool.appendClassPath(RuneLite.RUNELITE_DIR+"/injectedClient-"+ RuneLiteAPI.getVersion() +"-.jar"); + } catch (NotFoundException e) { + e.printStackTrace(); + } - } catch (Exception e) { - e.printStackTrace(); - System.out.println("Class not found: "+entry.getName()); - } - } + try { + jcl.add(new FileInputStream(jf)); + try (JarInputStream in = new JarInputStream(new BufferedInputStream(new FileInputStream(jf)))) { + JarEntry entry; + while ((entry = in.getNextJarEntry()) != null) { + if (entry.getName().endsWith(".class")) { + checkClasses(new File(jf), entry); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + try { + Writer writer = new FileWriter(ClientLoader.hooksFile); + gson.toJson(hooks, writer); + writer.flush(); + writer.close(); + } catch (IOException e) { + e.printStackTrace(); + } + ByteCodeUtils.updateHijackedJar(); + } - public static void checkActor(Class current) { - try { - Method method = current.getDeclaredMethod("setCombatInfo", new Class[] { int.class, int.class, int.class, int.class, int.class, int.class }); - if (method!=null) { - hooks.actorClass = current.getName(); - System.out.println("[RuneLit] Transforming Actor at class: "+current.getName()); - ActorTransform at = new ActorTransform(); - at.modify(current); - } - } catch (NoSuchMethodException e) { - //e.printStackTrace(); - } catch (NoClassDefFoundError e) { - //e.printStackTrace(); - } - } + public static void checkClasses(File jf, JarEntry entry) { + try { + URLClassLoader child = new URLClassLoader( + new URL[] {jf.toURI().toURL()}, + cl + ); + try { + Class classToLoad = Class.forName(entry.getName().replace(".class", ""), false, child); + checkActor(classToLoad); + checkProjectile(classToLoad); + checkPlayer(classToLoad); + } catch (Exception e) { + e.printStackTrace(); + } - public static void transformActor(Class actor) { - System.out.println("[RuneLit] Transforming Actor at class: "+actor.getName()); - ActorTransform at = new ActorTransform(); - at.modify(actor); - } + } catch (Exception e) { + e.printStackTrace(); + System.out.println("Class not found: "+entry.getName()); + } + } - public static void checkProjectile(Class current) { - try { - Method method = current.getDeclaredMethod("projectileMoved", new Class[] { int.class, int.class, int.class, int.class}); - if (method!=null) { - hooks.projectileClass = current.getName(); - System.out.println("[RuneLit] Transforming Projectile at class: "+current.getName()); - ProjectileTransform pt = new ProjectileTransform(); - pt.modify(current); - } - } catch (NoSuchMethodException e) { - //e.printStackTrace(); - } catch (NoClassDefFoundError e) { - //e.printStackTrace(); - } - } + public static void checkActor(Class current) { + try { + Method method = current.getDeclaredMethod("setCombatInfo", new Class[] { int.class, int.class, int.class, int.class, int.class, int.class }); + if (method!=null) { + hooks.actorClass = current.getName(); + System.out.println("[RuneLit] Transforming Actor at class: "+current.getName()); + ActorTransform at = new ActorTransform(); + at.modify(current); + } + } catch (NoSuchMethodException e) { + //e.printStackTrace(); + } catch (NoClassDefFoundError e) { + //e.printStackTrace(); + } + } - public static void transformProjectile(Class projectile) { - System.out.println("[RuneLit] Transforming Projectile at class: "+projectile.getName()); - ProjectileTransform pt = new ProjectileTransform(); - pt.modify(projectile); - } + public static void transformActor(Class actor) { + System.out.println("[RuneLit] Transforming Actor at class: "+actor.getName()); + ActorTransform at = new ActorTransform(); + at.modify(actor); + } - public static void checkPlayer(Class current) { - try { - Method method = current.getDeclaredMethod("getSkullIcon"); - if (method!=null) { - hooks.playerClass = current.getName(); - System.out.println("[RuneLit] Transforming Player at class: "+current.getName()); - PlayerTransform pt = new PlayerTransform(); - pt.modify(current); - } - } catch (NoSuchMethodException e) { - //e.printStackTrace(); - } catch (NoClassDefFoundError e) { - //e.printStackTrace(); - } - } + public static void checkProjectile(Class current) { + try { + Method method = current.getDeclaredMethod("projectileMoved", new Class[] { int.class, int.class, int.class, int.class}); + if (method!=null) { + hooks.projectileClass = current.getName(); + System.out.println("[RuneLit] Transforming Projectile at class: "+current.getName()); + ProjectileTransform pt = new ProjectileTransform(); + pt.modify(current); + } + } catch (NoSuchMethodException e) { + //e.printStackTrace(); + } catch (NoClassDefFoundError e) { + //e.printStackTrace(); + } + } + + public static void transformProjectile(Class projectile) { + System.out.println("[RuneLit] Transforming Projectile at class: "+projectile.getName()); + ProjectileTransform pt = new ProjectileTransform(); + pt.modify(projectile); + } + + public static void checkPlayer(Class current) { + try { + Method method = current.getDeclaredMethod("getSkullIcon"); + if (method!=null) { + hooks.playerClass = current.getName(); + System.out.println("[RuneLit] Transforming Player at class: "+current.getName()); + PlayerTransform pt = new PlayerTransform(); + pt.modify(current); + } + } catch (NoSuchMethodException e) { + //e.printStackTrace(); + } catch (NoClassDefFoundError e) { + //e.printStackTrace(); + } + } + + public static void transformPlayer(Class player) { + System.out.println("[RuneLit] Transforming Player at class: "+player.getName()); + PlayerTransform pt = new PlayerTransform(); + pt.modify(player); + } + + public static void transformBlackjack(Class clazz) { + System.out.println("[RuneLit] Transforming Blackjack at class: "+clazz.getName()); + ClientTransform bt = new ClientTransform(); + bt.modify(clazz); + } - public static void transformPlayer(Class player) { - System.out.println("[RuneLit] Transforming Player at class: "+player.getName()); - PlayerTransform pt = new PlayerTransform(); - pt.modify(player); - } } diff --git a/runelite-client/src/main/java/net/runelite/client/rs/bytecode/transformers/ClientTransform.java b/runelite-client/src/main/java/net/runelite/client/rs/bytecode/transformers/ClientTransform.java new file mode 100644 index 0000000000..3d0600ba3f --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/rs/bytecode/transformers/ClientTransform.java @@ -0,0 +1,194 @@ +package net.runelite.client.rs.bytecode.transformers; + +import javassist.CtBehavior; +import javassist.CtClass; +import javassist.CtMember; +import javassist.CtMethod; +import javassist.CtNewMethod; +import javassist.bytecode.StackMapTable; +import net.runelite.client.rs.bytecode.ByteCodePatcher; + +public class ClientTransform implements Transform { + + public CtClass ct = null; + + @Override + public void modify(Class clazz) { + try { + ct = ByteCodePatcher.classPool.get(clazz.getName()); + transformProtectedGetMenuOptions(); + transformProtectedGetMenuTargets(); + transformProtectedGetMenuIdentifiers(); + transformProtectedGetMenuTypes(); + transformProtectedGetMenuActionParams0(); + transformProtectedGetMenuActionParams1(); + transformGetMenuEntries(); + transformSetMenuEntries(); + transformOnMenuOptionsChanged(); + + ByteCodePatcher.modifiedClasses.add(ct); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void transformProtectedGetMenuOptions() { + CtMethod protectedGetMenuOptions; + try { + protectedGetMenuOptions = ct.getDeclaredMethod("1protect$getMenuOptions"); + ct.removeMethod(protectedGetMenuOptions); + protectedGetMenuOptions.setName("getMenuOptions"); + ct.addMethod(protectedGetMenuOptions); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void transformProtectedGetMenuTargets() { + CtMethod protectedGetMenuTargets; + try { + protectedGetMenuTargets = ct.getDeclaredMethod("1protect$getMenuTargets"); + ct.removeMethod(protectedGetMenuTargets); + protectedGetMenuTargets.setName("getMenuTargets"); + ct.addMethod(protectedGetMenuTargets); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void transformProtectedGetMenuIdentifiers() { + CtMethod protectedGetMenuIdentifiers; + try { + protectedGetMenuIdentifiers = ct.getDeclaredMethod("1protect$getMenuIdentifiers"); + ct.removeMethod(protectedGetMenuIdentifiers); + protectedGetMenuIdentifiers.setName("getMenuIdentifiers"); + ct.addMethod(protectedGetMenuIdentifiers); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void transformProtectedGetMenuTypes() { + CtMethod protectedGetMenuTypes; + try { + protectedGetMenuTypes = ct.getDeclaredMethod("1protect$getMenuTypes"); + // Don't remove as this is referenced elsewhere in client + //ct.removeMethod(protectedGetMenuTypes); + CtMethod newProtectedGetMenuTypes = CtNewMethod.copy(protectedGetMenuTypes, ct, null); + newProtectedGetMenuTypes.setName("getMenuTypes"); + ct.addMethod(newProtectedGetMenuTypes); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void transformProtectedGetMenuActionParams0() { + CtMethod protectedGetMenuActionParams0; + try { + protectedGetMenuActionParams0 = ct.getDeclaredMethod("1protect$getMenuActionParams0"); + ct.removeMethod(protectedGetMenuActionParams0); + protectedGetMenuActionParams0.setName("getMenuActionParams0"); + ct.addMethod(protectedGetMenuActionParams0); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void transformProtectedGetMenuActionParams1() { + CtMethod protectedGetMenuActionParams1; + try { + protectedGetMenuActionParams1 = ct.getDeclaredMethod("1protect$getMenuActionParams1"); + ct.removeMethod(protectedGetMenuActionParams1); + protectedGetMenuActionParams1.setName("getMenuActionParams1"); + ct.addMethod(protectedGetMenuActionParams1); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void transform() {} + + public void transformGetMenuEntries() { + CtMethod getMenuEntries; + try { + getMenuEntries = ct.getDeclaredMethod("getMenuEntries"); + ct.removeMethod(getMenuEntries); + getMenuEntries = CtMethod.make("public net.runelite.api.MenuEntry[] getMenuEntries() {" + + " int n2 = this.getMenuOptionCount();"+ + " String[] arrstring = this.getMenuOptions();"+ + " String[] arrstring2 = this.getMenuTargets();"+ + " int[] arrn = this.getMenuIdentifiers();"+ + " int[] arrn2 = this.getMenuTypes();"+ + " int[] arrn3 = this.getMenuActionParams0();"+ + " int[] arrn4 = this.getMenuActionParams1();"+ + " boolean[] arrbl = this.getMenuForceLeftClick();"+ + " net.runelite.api.MenuEntry[] arrmenuEntry = new net.runelite.api.MenuEntry[n2];"+ + " int n3 = 0;"+ + " while (n3 < n2) {"+ + " net.runelite.api.MenuEntry menuEntry = arrmenuEntry[n3] = new net.runelite.api.MenuEntry();"+ + " menuEntry.setOption(arrstring[n3]);"+ + " menuEntry.setTarget(arrstring2[n3]);"+ + " menuEntry.setIdentifier(arrn[n3]);"+ + " menuEntry.setType(arrn2[n3]);"+ + " menuEntry.setParam0(arrn3[n3]);"+ + " menuEntry.setParam1(arrn4[n3]);"+ + " menuEntry.setForceLeftClick(arrbl[n3]);"+ + " ++n3;"+ + " }"+ + " return arrmenuEntry;"+ + " }", ct); + ct.addMethod(getMenuEntries); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void transformSetMenuEntries() { + CtMethod setMenuEntries; + try { + setMenuEntries = ct.getDeclaredMethods("setMenuEntries"/*, works for now */)[0]; + ct.removeMethod(setMenuEntries); + String src; + setMenuEntries = CtNewMethod.make( + "public void setMenuEntries(net.runelite.api.MenuEntry[] paramArrayOfMenuEntry) {" + + "int i = 0;" + + "String[] arrayOfString1 = this.getMenuOptions();" + + "String[] arrayOfString2 = this.getMenuTargets();" + + "int[] arrayOfInt1 = this.getMenuIdentifiers();" + + "int[] arrayOfInt2 = this.getMenuTypes();" + + "int[] arrayOfInt3 = this.getMenuActionParams0();" + + "int[] arrayOfInt4 = this.getMenuActionParams1();" + + "boolean[] arrayOfBoolean = getMenuForceLeftClick();" + + "int testingInt[] = {1,2,3,4,5,6};" + + "for (int m = 0 ; m < paramArrayOfMenuEntry.length ; m++) {" + + "net.runelite.api.MenuEntry menuEntry = paramArrayOfMenuEntry[m];" + + "}" + + "}" + , ct); + ct.addMethod(setMenuEntries); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void transformOnMenuOptionsChanged() { + CtMethod onMenuOptionsChanged; + try { + onMenuOptionsChanged = ct.getDeclaredMethod("onMenuOptionsChanged", new CtClass[]{CtClass.intType}); + ct.removeMethod(onMenuOptionsChanged); + onMenuOptionsChanged = CtMethod.make(" public static void onMenuOptionsChanged(int n2) {"+ + " int n3;" + + " int n4 = oldMenuEntryCount;"+ + " oldMenuEntryCount = n3 = "+ByteCodePatcher.clientInstance+".getMenuOptionCount();"+ + " if (n3 != n4 + 1) return;"+ + " net.runelite.api.events.MenuEntryAdded menuEntryAdded = new net.runelite.api.events.MenuEntryAdded("+ByteCodePatcher.clientInstance+".getMenuOptions()[n3 - 1], "+ByteCodePatcher.clientInstance+".getMenuTargets()[n3 - 1], "+ByteCodePatcher.clientInstance+".getMenuTypes()[n3 - 1], "+ByteCodePatcher.clientInstance+".getMenuIdentifiers()[n3 - 1], "+ByteCodePatcher.clientInstance+".getMenuActionParams0()[n3 - 1], "+ByteCodePatcher.clientInstance+".getMenuActionParams1()[n3 - 1]);"+ + " "+ByteCodePatcher.clientInstance+".getCallbacks().post((Object)menuEntryAdded);" + + " }" + , ct); + ct.addMethod(onMenuOptionsChanged); + } catch (Exception e) { + e.printStackTrace(); + } + } +}