Fix drawMenu raw injector and add test

(change in compiled class is naming drawLoggedIn)
This commit is contained in:
Lucwousin
2019-11-06 23:53:03 +01:00
parent a7344a7773
commit 4f2c72fb75
5 changed files with 162 additions and 178 deletions

View File

@@ -14,7 +14,7 @@ plugins {
} }
group = "com.openosrs" group = "com.openosrs"
version = "1.0.1" version = "1.0.2"
repositories { repositories {
mavenCentral() mavenCentral()

View File

@@ -16,6 +16,7 @@ import com.openosrs.injector.injectors.MixinInjector;
import com.openosrs.injector.injectors.RSApiInjector; import com.openosrs.injector.injectors.RSApiInjector;
import com.openosrs.injector.injectors.raw.ClearColorBuffer; import com.openosrs.injector.injectors.raw.ClearColorBuffer;
import com.openosrs.injector.injectors.raw.DrawAfterWidgets; import com.openosrs.injector.injectors.raw.DrawAfterWidgets;
import com.openosrs.injector.injectors.raw.DrawMenu;
import com.openosrs.injector.injectors.raw.HidePlayerAttacks; import com.openosrs.injector.injectors.raw.HidePlayerAttacks;
import com.openosrs.injector.injectors.raw.Occluder; import com.openosrs.injector.injectors.raw.Occluder;
import com.openosrs.injector.injectors.raw.RasterizerAlpha; import com.openosrs.injector.injectors.raw.RasterizerAlpha;
@@ -72,7 +73,7 @@ public class Injection extends InjectData implements InjectTaskHandler
inject(new Occluder(this)); inject(new Occluder(this));
// inject(new DrawMenu(this)); inject(new DrawMenu(this));
inject(new HidePlayerAttacks(this)); inject(new HidePlayerAttacks(this));

View File

@@ -5,198 +5,127 @@
* This code is licensed under GPL3, see the complete license in * This code is licensed under GPL3, see the complete license in
* the LICENSE file in the root directory of this source tree. * the LICENSE file in the root directory of this source tree.
*/ */
//package com.openosrs.injector.injectors.raw; package com.openosrs.injector.injectors.raw;
//import com.openosrs.injector.InjectUtil; import com.openosrs.injector.InjectUtil;
//import com.openosrs.injector.Injexception; import com.openosrs.injector.Injexception;
//import com.openosrs.injector.injection.InjectData; import com.openosrs.injector.injection.InjectData;
//import static com.openosrs.injector.injection.InjectData.HOOKS; import static com.openosrs.injector.injection.InjectData.HOOKS;
//import com.openosrs.injector.injectors.AbstractInjector; import com.openosrs.injector.injectors.AbstractInjector;
//import java.util.List; import java.util.List;
//import java.util.ListIterator; import java.util.concurrent.atomic.AtomicReference;
//import net.runelite.asm.ClassFile; import net.runelite.asm.Method;
//import net.runelite.asm.ClassGroup; import net.runelite.asm.attributes.code.Instruction;
//import net.runelite.asm.Method; import net.runelite.asm.attributes.code.Instructions;
//import net.runelite.asm.Type; import net.runelite.asm.attributes.code.Label;
//import net.runelite.asm.attributes.code.Instruction; import net.runelite.asm.attributes.code.instructions.GetStatic;
//import net.runelite.asm.attributes.code.Instructions; import net.runelite.asm.attributes.code.instructions.IfEq;
//import net.runelite.asm.attributes.code.Label; import net.runelite.asm.attributes.code.instructions.IfNe;
//import net.runelite.asm.attributes.code.instruction.types.JumpingInstruction; import net.runelite.asm.attributes.code.instructions.InvokeStatic;
//import net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction; import net.runelite.asm.execution.Execution;
//import net.runelite.asm.attributes.code.instructions.GetStatic; import net.runelite.asm.execution.InstructionContext;
//import net.runelite.asm.attributes.code.instructions.IStore; import net.runelite.asm.execution.MethodContext;
//import net.runelite.asm.attributes.code.instructions.IfEq; import net.runelite.asm.pool.Class;
//import net.runelite.asm.attributes.code.instructions.IfNe; import net.runelite.asm.pool.Field;
//import net.runelite.asm.attributes.code.instructions.InvokeStatic; import net.runelite.asm.signature.Signature;
//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;
//public class DrawMenu extends AbstractInjector public class DrawMenu extends AbstractInjector
//{ {
//private static final net.runelite.asm.pool.Method HOOK = new net.runelite.asm.pool.Method( private static final net.runelite.asm.pool.Method DRAWMENU = new net.runelite.asm.pool.Method(
//new Class(HOOKS), new Class(HOOKS),
//"drawMenu", "drawMenu",
//new Signature("()Z") new Signature("()Z")
//); );
//private static final int MENU_COLOR = 0x5d5447;
//public DrawMenu(InjectData inject) public DrawMenu(InjectData inject)
//{ {
//super(inject); super(inject);
//} }
//public void inject() throws Injexception public void inject() throws Injexception
//{ {
///* /*
//* Label Getstatic client.isMenuOpen * The drawMenu method can be inlined, so we need this raw injector to find where to inject.
//* Ifne -> Label Drawmenu *
//* Jump -> Label Drawtext * Originally I wanted to make sure we don't skip the method where client gets told not to draw
//* * the widgets behind the menu. This would be useless though, as the client redraws the widgets
//* Label drawtext * no matter what. It would also be such a insignificant performance boost it doesn't seem worth
//* Ldc xxx * the extra headache to me.
//* Getstatic client. something with viewport size? *
//* Imul * --- what the code looks like completely uninlined ---
//* Iconst_m1 * if (!isMenuOpen) {
//* Ifne -> Label after draw menu <- info we need * if (viewportX != -1) {
//* Getstatic / LDC (same getstatic and LDC before) * drawTopLeftText(viewportX, viewportY);
//* Getstatic / LDC * }
//*/ * } else {
//final ClassFile deobClient = inject.getDeobfuscated().findClass("Client"); * drawMenu();
//final ClassGroup vanilla = inject.getVanilla(); * }
*
* if (gameDrawingMode == 3) {
* ...
* --------
*/
//final Field isMenuOpen = inject.toVanilla(deobClient.findField("isMenuOpen")).getPoolField(); final Method drawLoggedIn = InjectUtil.findMethod(inject, "drawLoggedIn", "Client", null, true, false);
//final Method drawLoggedIn = inject.toVanilla(deobClient.findMethod("drawLoggedIn")); final Field gameDrawMode = InjectUtil.findField(inject, "gameDrawingMode", "Client").getPoolField();
final Field isMenuOpen = InjectUtil.findField(inject, "isMenuOpen", "Client").getPoolField();
//final Instructions inst = drawLoggedIn.getCode().getInstructions(); final Execution execution = new Execution(inject.getVanilla());
execution.noInvoke = true;
execution.addMethod(drawLoggedIn);
//boolean foundCol = false, foundEnd = false; AtomicReference<MethodContext> mcRef = new AtomicReference<>(null);
//int injIdx = -1;
//final ListIterator<Instruction> it = inst.listIterator();
//while (it.hasNext())
//{
//Instruction i = it.next();
//if (!foundCol &&
//(i instanceof PushConstantInstruction) &&
//((PushConstantInstruction) i).getConstant().equals(MENU_COLOR))
//{
//foundCol = true;
//injIdx = it.nextIndex();
//}
//else if (!foundEnd &&
//(i instanceof PushConstantInstruction) &&
//((PushConstantInstruction) i).getConstant().equals(0))
//{
//i = it.next();
//if (!(i instanceof IStore))
//{
//continue;
//}
//int varIdx = ((IStore) i).getVariableIndex(); execution.addMethodContextVisitor(mcRef::set);
//i = it.next(); execution.run();
//if (!(i instanceof JumpingInstruction)) Instruction injectInvokeAfter = null;
//{ Label labelToJumpTo = null;
//continue;
//}
//List<Label> jumps = ((JumpingInstruction) i).getJumps(); MethodContext mc = mcRef.get();
//if (jumps.size() > 1) for (InstructionContext ic : mc.getInstructionContexts())
//{ {
//continue; Instruction instruction = ic.getInstruction();
//} if (!(instruction instanceof GetStatic))
// continue;
//Instruction afterLabel = inst.
//}
//}
if (((GetStatic) instruction).getField().equals(isMenuOpen))
{
InstructionContext isMenuOpenPopper = ic.getPushes().get(0).getPopped().get(0);
Instruction isMenuOpenPopI = isMenuOpenPopper.getInstruction();
//final Execution ex = new Execution(vanilla); // Unless there's a isMenuOpen in drawLoggedIn I missed (or something new got inlined (and I missed that)) this should never happen
//// Static step makes static methods not count as methods assert isMenuOpenPopI instanceof IfEq || isMenuOpenPopI instanceof IfNe : "isMenuOpen was popped by a " + isMenuOpenPopI + "?";
//ex.staticStep = true;
//ex.noExceptions = true;
//ex.addMethod(drawLoggedIn);
//final Instruction // If the popper is a IfNe the label it's pointing to is the drawMenu one and topLeft is directly after it
//ex.addExecutionVisitor((InstructionContext ic) -> // else it's the other way around, obviously
//{ if (isMenuOpenPopI instanceof IfNe)
//Instruction i = ic.getInstruction(); injectInvokeAfter = ((IfNe) isMenuOpenPopI).getTo();
//if (i instanceof PushConstantInstruction) else
//{ injectInvokeAfter = isMenuOpenPopI;
//if (((PushConstantInstruction) i).getConstant().equals(MENU_COLOR)) }
//{ else if (((GetStatic) instruction).getField().equals(gameDrawMode))
//injIdx {
//} List<Instruction> instrL = instruction.getInstructions().getInstructions();
//} for (int i = instrL.indexOf(instruction); !(instruction instanceof Label); i--)
//}); instruction = instrL.get(i);
//ex.run();
//final Instructions ins = drawLoggedIn.getCode().getInstructions(); labelToJumpTo = (Label) instruction;
//ListIterator<Instruction> it = ins.getInstructions().listIterator(); }
//int injectIndex = -1;
//Label after = null;
//boolean foundBefore = false;
//boolean foundAfter = false;
//while (it.hasNext()) if (injectInvokeAfter != null && labelToJumpTo != null)
//{ break;
//Instruction i = it.next(); }
//if (!(i instanceof GetStatic) && !(i instanceof InvokeStatic)) if (injectInvokeAfter == null || labelToJumpTo == null)
//{ throw new Injexception("Couldn't find the right location for DrawMenu to inject");
//continue;
//}
//if (!foundBefore && i instanceof GetStatic) final Instructions instrs = mc.getMethod().getCode().getInstructions();
//{ int idx = instrs.getInstructions().indexOf(injectInvokeAfter);
//if (!((GetStatic) i).getField().equals(isMenuOpen))
//{
//continue;
//}
//i = it.next(); instrs.addInstruction(++idx, new InvokeStatic(instrs, DRAWMENU));
//if (!(i instanceof IfEq) && !(i instanceof IfNe)) instrs.addInstruction(++idx, new IfNe(instrs, labelToJumpTo));
//{
//continue;
//}
//if (i instanceof IfEq) log.info("DrawMenu injected a method call at index {} in method {}. With a comparison jumping to {}", idx, drawLoggedIn, labelToJumpTo);
//{ }
//injectIndex = it.nextIndex(); }
//}
//else
//{
//injectIndex = ins.getInstructions().indexOf(((IfNe) i).getJumps().get(0)) + 1;
//}
//foundBefore = true;
//}
//else if (!foundAfter && i instanceof InvokeStatic
//&& ((InvokeStatic) i).getMethod().equals("topLeftText"))
//{
//i = it.next();
//assert i instanceof JumpingInstruction;
//after = ((JumpingInstruction) i).getJumps().get(0);
//foundAfter = true;
//}
//if (foundBefore && foundAfter)
//{
//break;
//}
//}
//if (!foundBefore || !foundAfter || injectIndex == -1)
//{
//}
//ins.addInstruction(injectIndex, new IfNe(ins, after));
//ins.addInstruction(injectIndex, new InvokeStatic(ins, HOOK));
//log.info("Injected drawmenu hook in {} at index {}", "", injectIndex);
//}
//}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 2019, Lucas <https://github.com/Lucwousin>
* All rights reserved.
*
* This code is licensed under GPL3, see the complete license in
* the LICENSE file in the root directory of this source tree.
*/
package com.openosrs.injector.injectors.raw;
import com.google.common.io.ByteStreams;
import com.openosrs.injector.TestInjection;
import com.openosrs.injector.injection.InjectData;
import com.openosrs.injector.rsapi.RSApi;
import net.runelite.asm.ClassFile;
import net.runelite.asm.ClassGroup;
import net.runelite.deob.util.JarUtil;
import org.junit.Test;
public class DrawMenuTest
{
@Test
public void test160() throws Exception
{
// 160 has both drawMenu and drawTopLeftText inlined
ClassFile deobClient = JarUtil.loadClass(ByteStreams.toByteArray(getClass().getResourceAsStream("/drawafterwidgets/Client_deob160.class")));
ClassFile obClient = JarUtil.loadClass(ByteStreams.toByteArray(getClass().getResourceAsStream("/drawafterwidgets/Client_ob160.class")));
ClassGroup van = new ClassGroup();
van.addClass(obClient);
ClassGroup deob = new ClassGroup();
deob.addClass(deobClient);
InjectData inject = new TestInjection(van, deob, new ClassGroup(), new RSApi());
new DrawMenu(inject).inject();
}
@Test
public void test180() throws Exception
{
// 180 has only drawMenu inlined
ClassFile deobClient = JarUtil.loadClass(ByteStreams.toByteArray(getClass().getResourceAsStream("/drawafterwidgets/Client_deob180.class")));
ClassFile obClient = JarUtil.loadClass(ByteStreams.toByteArray(getClass().getResourceAsStream("/drawafterwidgets/Client_ob180.class")));
ClassGroup van = new ClassGroup();
van.addClass(obClient);
ClassGroup deob = new ClassGroup();
deob.addClass(deobClient);
InjectData inject = new TestInjection(van, deob, new ClassGroup(), new RSApi());
new DrawMenu(inject).inject();
}
}