new rasterizer injector, also less brackets in injectutil
This commit is contained in:
@@ -30,6 +30,7 @@ import net.runelite.asm.attributes.code.instructions.VReturn;
|
|||||||
import net.runelite.asm.pool.Class;
|
import net.runelite.asm.pool.Class;
|
||||||
import net.runelite.asm.signature.Signature;
|
import net.runelite.asm.signature.Signature;
|
||||||
import net.runelite.deob.DeobAnnotations;
|
import net.runelite.deob.DeobAnnotations;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public interface InjectUtil
|
public interface InjectUtil
|
||||||
{
|
{
|
||||||
@@ -40,9 +41,9 @@ public interface InjectUtil
|
|||||||
* @param name The name of the method you want to find
|
* @param name The name of the method you want to find
|
||||||
* @return The obfuscated version of the found method
|
* @return The obfuscated version of the found method
|
||||||
*/
|
*/
|
||||||
static Method findStaticMethod(InjectData data, String name) throws Injexception
|
static Method findMethod(InjectData data, String name) throws Injexception
|
||||||
{
|
{
|
||||||
return findStaticMethod(data, name, null, null);
|
return findMethod(data, name, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,44 +56,84 @@ public interface InjectUtil
|
|||||||
*
|
*
|
||||||
* @return The obfuscated version of the found method
|
* @return The obfuscated version of the found method
|
||||||
*/
|
*/
|
||||||
static Method findStaticMethod(InjectData data, String name, String classHint, Signature sig) throws Injexception
|
static Method findMethod(
|
||||||
|
InjectData data,
|
||||||
|
String name,
|
||||||
|
String classHint,
|
||||||
|
Signature sig)
|
||||||
|
throws Injexception
|
||||||
|
{
|
||||||
|
return findMethod(data, name, classHint, sig, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a method in injectData's deobfuscated classes.
|
||||||
|
*
|
||||||
|
* @param data InjectData instance
|
||||||
|
* @param name (Exported) method name
|
||||||
|
* @param classHint The (exported) name of a class you expect (or know) the method to be in, or null, if you're not sure
|
||||||
|
* @throws Injexception If the hint class couldn't be found, or no method matching the settings was found
|
||||||
|
*/
|
||||||
|
static Method findMethod(
|
||||||
|
InjectData data,
|
||||||
|
String name,
|
||||||
|
@Nullable String classHint)
|
||||||
|
throws Injexception
|
||||||
|
{
|
||||||
|
return findMethod(data, name, classHint, null, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a method in injectData's deobfuscated classes.
|
||||||
|
*
|
||||||
|
* @param data InjectData instance
|
||||||
|
* @param name (Exported) method name
|
||||||
|
* @param classHint The (exported) name of a class you expect (or know) the method to be in, or null, if you're not sure
|
||||||
|
* @param sig The deobfuscated methods' signature, or null, if you're unsure
|
||||||
|
* @param notStatic If this is true, only check non-static methods. If classHint isn't null, check only subclasses
|
||||||
|
* @param returnDeob If this is true, this method will return the deobfuscated method, instead of turning it into vanilla first
|
||||||
|
*
|
||||||
|
* @throws Injexception If the hint class couldn't be found, or no method matching the settings was found
|
||||||
|
*/
|
||||||
|
static Method findMethod(
|
||||||
|
InjectData data,
|
||||||
|
String name,
|
||||||
|
@Nullable String classHint,
|
||||||
|
@Nullable Signature sig,
|
||||||
|
boolean notStatic,
|
||||||
|
boolean returnDeob)
|
||||||
|
throws Injexception
|
||||||
{
|
{
|
||||||
final ClassGroup deob = data.getDeobfuscated();
|
final ClassGroup deob = data.getDeobfuscated();
|
||||||
Method method;
|
|
||||||
|
|
||||||
if (classHint != null)
|
if (classHint != null)
|
||||||
{
|
{
|
||||||
ClassFile clazz = findClassOrThrow(deob, classHint);
|
ClassFile cf;
|
||||||
|
Method m;
|
||||||
if (sig == null)
|
cf = findClassOrThrow(deob, classHint);
|
||||||
|
if (notStatic)
|
||||||
{
|
{
|
||||||
method = clazz.findStaticMethod(name);
|
if (sig == null)
|
||||||
|
m = cf.findMethodDeep(name);
|
||||||
|
else
|
||||||
|
m = cf.findMethodDeep(name, sig);
|
||||||
|
if (m == null)
|
||||||
|
throw new Injexception(String.format("Couldn't find %s in subclasses of %s", name, classHint));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
m = cf.findMethod(name);
|
||||||
method = clazz.findStaticMethod(name, sig);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (method != null)
|
if (m != null)
|
||||||
return data.toVanilla(method);
|
return returnDeob ? m : data.toVanilla(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ClassFile clazz : deob)
|
for (ClassFile cf : deob)
|
||||||
{
|
for (Method m : cf.getMethods())
|
||||||
if (sig == null)
|
if (m.getName().equals(name))
|
||||||
{
|
if (!notStatic || !m.isStatic())
|
||||||
method = clazz.findStaticMethod(name);
|
if (sig == null || sig.equals(m.getDescriptor()))
|
||||||
}
|
return returnDeob ? m : data.toVanilla(m);
|
||||||
else
|
|
||||||
{
|
|
||||||
method = clazz.findStaticMethod(name, sig);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (method != null)
|
throw new Injexception(String.format("Couldn't find %s", name));
|
||||||
return data.toVanilla(method);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Injexception("Static method " + name + " doesn't exist");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ClassFile findClassOrThrow(ClassGroup group, String name) throws Injexception
|
static ClassFile findClassOrThrow(ClassGroup group, String name) throws Injexception
|
||||||
@@ -104,19 +145,6 @@ public interface InjectUtil
|
|||||||
return clazz;
|
return clazz;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds a static method in deob and converts it to ob
|
|
||||||
*
|
|
||||||
* @param data InjectData instance
|
|
||||||
* @param pool Pool method of the method you want
|
|
||||||
*
|
|
||||||
* @return The obfuscated version of the found method
|
|
||||||
*/
|
|
||||||
static Method findStaticMethod(InjectData data, net.runelite.asm.pool.Method pool) throws Injexception
|
|
||||||
{
|
|
||||||
return findStaticMethod(data, pool.getName(), pool.getClazz().getName(), pool.getType());
|
|
||||||
}
|
|
||||||
|
|
||||||
static Method findMethodWithArgs(InjectData data, String name, String hintClass, Signature sig) throws Injexception
|
static Method findMethodWithArgs(InjectData data, String name, String hintClass, Signature sig) throws Injexception
|
||||||
{
|
{
|
||||||
final ClassGroup deob = data.getDeobfuscated();
|
final ClassGroup deob = data.getDeobfuscated();
|
||||||
@@ -151,13 +179,12 @@ public interface InjectUtil
|
|||||||
/**
|
/**
|
||||||
* Fail-fast implementation of ClassGroup.findStaticMethod
|
* Fail-fast implementation of ClassGroup.findStaticMethod
|
||||||
*/
|
*/
|
||||||
static Method findStaticMethod(ClassGroup group, String name, Signature type) throws Injexception
|
static Method findMethod(ClassGroup group, String name, Signature type) throws Injexception
|
||||||
{
|
{
|
||||||
Method m = group.findStaticMethod(name, type);
|
Method m = group.findStaticMethod(name, type);
|
||||||
if (m == null)
|
if (m == null)
|
||||||
{
|
|
||||||
throw new Injexception(String.format("Method %s couldn't be found", name + type.toString()));
|
throw new Injexception(String.format("Method %s couldn't be found", name + type.toString()));
|
||||||
}
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,9 +195,8 @@ public interface InjectUtil
|
|||||||
{
|
{
|
||||||
Method m = clazz.findMethodDeep(name, type);
|
Method m = clazz.findMethodDeep(name, type);
|
||||||
if (m == null)
|
if (m == null)
|
||||||
{
|
|
||||||
throw new Injexception(String.format("Method %s couldn't be found", name + type.toString()));
|
throw new Injexception(String.format("Method %s couldn't be found", name + type.toString()));
|
||||||
}
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,10 +211,9 @@ public interface InjectUtil
|
|||||||
{
|
{
|
||||||
Field f = clazz.findField(name);
|
Field f = clazz.findField(name);
|
||||||
if (f != null && f.isStatic())
|
if (f != null && f.isStatic())
|
||||||
{
|
|
||||||
return f;
|
return f;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Injexception("Couldn't find static field " + name);
|
throw new Injexception("Couldn't find static field " + name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,67 +237,40 @@ public interface InjectUtil
|
|||||||
ClassFile clazz = findClassOrThrow(deob, classHint);
|
ClassFile clazz = findClassOrThrow(deob, classHint);
|
||||||
|
|
||||||
if (type == null)
|
if (type == null)
|
||||||
{
|
|
||||||
field = clazz.findField(name);
|
field = clazz.findField(name);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
field = clazz.findField(name, type);
|
field = clazz.findField(name, type);
|
||||||
}
|
|
||||||
|
|
||||||
if (field != null)
|
if (field != null)
|
||||||
{
|
|
||||||
return data.toVanilla(field);
|
return data.toVanilla(field);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ClassFile clazz : deob)
|
for (ClassFile clazz : deob)
|
||||||
{
|
{
|
||||||
if (type == null)
|
if (type == null)
|
||||||
{
|
|
||||||
field = clazz.findField(name);
|
field = clazz.findField(name);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
field = clazz.findField(name, type);
|
field = clazz.findField(name, type);
|
||||||
}
|
|
||||||
|
|
||||||
if (field != null)
|
if (field != null)
|
||||||
{
|
|
||||||
return data.toVanilla(field);
|
return data.toVanilla(field);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Injexception(String.format("Static field %s doesn't exist", (type != null ? type + " " : "") + name));
|
throw new Injexception(String.format("Static field %s doesn't exist", (type != null ? type + " " : "") + name));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds a static field in deob and converts it to ob
|
|
||||||
*
|
|
||||||
* @param data InjectData instance
|
|
||||||
* @param pool Pool field of the field you want
|
|
||||||
*
|
|
||||||
* @return The obfuscated version of the found field
|
|
||||||
*/
|
|
||||||
static Field findStaticField(InjectData data, net.runelite.asm.pool.Field pool) throws Injexception
|
|
||||||
{
|
|
||||||
return findStaticField(data, pool.getName(), pool.getClazz().getName(), pool.getType());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fail-fast implementation of ClassGroup.findFieldDeep
|
* Fail-fast implementation of ClassGroup.findFieldDeep
|
||||||
*/
|
*/
|
||||||
static Field findFieldDeep(ClassFile clazz, String name) throws Injexception
|
static Field findFieldDeep(ClassFile clazz, String name) throws Injexception
|
||||||
{
|
{
|
||||||
|
Field f;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
if ((f = clazz.findField(name)) != null)
|
||||||
Field f = clazz.findField(name);
|
|
||||||
if (f != null)
|
|
||||||
{
|
|
||||||
return f;
|
return f;
|
||||||
}
|
|
||||||
}
|
|
||||||
while ((clazz = clazz.getParent()) != null);
|
while ((clazz = clazz.getParent()) != null);
|
||||||
|
|
||||||
throw new Injexception("Couldn't find field " + name);
|
throw new Injexception("Couldn't find field " + name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,19 +289,12 @@ public interface InjectUtil
|
|||||||
|
|
||||||
field = clazz.findField(name);
|
field = clazz.findField(name);
|
||||||
if (field != null)
|
if (field != null)
|
||||||
{
|
|
||||||
return field;
|
return field;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ClassFile clazz : group)
|
for (ClassFile clazz : group)
|
||||||
{
|
if ((field = clazz.findField(name)) != null)
|
||||||
field = clazz.findField(name);
|
|
||||||
if (field != null)
|
|
||||||
{
|
|
||||||
return field;
|
return field;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Injexception("Field " + name + " doesn't exist");
|
throw new Injexception("Field " + name + " doesn't exist");
|
||||||
}
|
}
|
||||||
@@ -327,15 +318,11 @@ public interface InjectUtil
|
|||||||
static Type apiToDeob(InjectData data, Type api)
|
static Type apiToDeob(InjectData data, Type api)
|
||||||
{
|
{
|
||||||
if (api.isPrimitive())
|
if (api.isPrimitive())
|
||||||
{
|
|
||||||
return api;
|
return api;
|
||||||
}
|
|
||||||
|
|
||||||
final String internalName = api.getInternalName();
|
final String internalName = api.getInternalName();
|
||||||
if (internalName.startsWith(API_BASE))
|
if (internalName.startsWith(API_BASE))
|
||||||
{
|
|
||||||
return Type.getType("L" + api.getInternalName().substring(API_BASE.length()) + ";", api.getDimensions());
|
return Type.getType("L" + api.getInternalName().substring(API_BASE.length()) + ";", api.getDimensions());
|
||||||
}
|
|
||||||
else if (internalName.startsWith(RL_API_BASE))
|
else if (internalName.startsWith(RL_API_BASE))
|
||||||
{
|
{
|
||||||
Class rlApiC = new Class(internalName);
|
Class rlApiC = new Class(internalName);
|
||||||
@@ -370,15 +357,11 @@ public interface InjectUtil
|
|||||||
static Type deobToVanilla(InjectData data, Type deobT)
|
static Type deobToVanilla(InjectData data, Type deobT)
|
||||||
{
|
{
|
||||||
if (deobT.isPrimitive())
|
if (deobT.isPrimitive())
|
||||||
{
|
|
||||||
return deobT;
|
return deobT;
|
||||||
}
|
|
||||||
|
|
||||||
final ClassFile deobClass = data.getDeobfuscated().findClass(deobT.getInternalName());
|
final ClassFile deobClass = data.getDeobfuscated().findClass(deobT.getInternalName());
|
||||||
if (deobClass == null)
|
if (deobClass == null)
|
||||||
{
|
|
||||||
return deobT;
|
return deobT;
|
||||||
}
|
|
||||||
|
|
||||||
return Type.getType("L" + data.toVanilla(deobClass).getName() + ";", deobT.getDimensions());
|
return Type.getType("L" + data.toVanilla(deobClass).getName() + ";", deobT.getDimensions());
|
||||||
}
|
}
|
||||||
@@ -394,17 +377,11 @@ public interface InjectUtil
|
|||||||
List<Type> bb = b.getArguments();
|
List<Type> bb = b.getArguments();
|
||||||
|
|
||||||
if (aa.size() != bb.size())
|
if (aa.size() != bb.size())
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < aa.size(); i++)
|
for (int i = 0; i < aa.size(); i++)
|
||||||
{
|
|
||||||
if (!aa.get(i).equals(bb.get(i)))
|
if (!aa.get(i).equals(bb.get(i)))
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -435,9 +412,7 @@ public interface InjectUtil
|
|||||||
static Instruction createLoadForTypeIndex(Instructions instructions, Type type, int index)
|
static Instruction createLoadForTypeIndex(Instructions instructions, Type type, int index)
|
||||||
{
|
{
|
||||||
if (type.getDimensions() > 0 || !type.isPrimitive())
|
if (type.getDimensions() > 0 || !type.isPrimitive())
|
||||||
{
|
|
||||||
return new ALoad(instructions, index);
|
return new ALoad(instructions, index);
|
||||||
}
|
|
||||||
|
|
||||||
switch (type.toString())
|
switch (type.toString())
|
||||||
{
|
{
|
||||||
@@ -464,9 +439,7 @@ public interface InjectUtil
|
|||||||
static Instruction createReturnForType(Instructions instructions, Type type)
|
static Instruction createReturnForType(Instructions instructions, Type type)
|
||||||
{
|
{
|
||||||
if (!type.isPrimitive())
|
if (!type.isPrimitive())
|
||||||
{
|
|
||||||
return new Return(instructions, InstructionType.ARETURN);
|
return new Return(instructions, InstructionType.ARETURN);
|
||||||
}
|
|
||||||
|
|
||||||
switch (type.toString())
|
switch (type.toString())
|
||||||
{
|
{
|
||||||
@@ -492,13 +465,9 @@ public interface InjectUtil
|
|||||||
static Instruction createInvokeFor(Instructions instructions, net.runelite.asm.pool.Method method, boolean isStatic)
|
static Instruction createInvokeFor(Instructions instructions, net.runelite.asm.pool.Method method, boolean isStatic)
|
||||||
{
|
{
|
||||||
if (isStatic)
|
if (isStatic)
|
||||||
{
|
|
||||||
return new InvokeStatic(instructions, method);
|
return new InvokeStatic(instructions, method);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
return new InvokeVirtual(instructions, method);
|
return new InvokeVirtual(instructions, method);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ 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.Occluder;
|
import com.openosrs.injector.injectors.raw.Occluder;
|
||||||
import com.openosrs.injector.injectors.raw.RasterizerHook;
|
import com.openosrs.injector.injectors.raw.RasterizerAlpha;
|
||||||
import com.openosrs.injector.injectors.raw.RenderDraw;
|
import com.openosrs.injector.injectors.raw.RenderDraw;
|
||||||
import com.openosrs.injector.injectors.raw.ScriptVM;
|
import com.openosrs.injector.injectors.raw.ScriptVM;
|
||||||
import com.openosrs.injector.rsapi.RSApi;
|
import com.openosrs.injector.rsapi.RSApi;
|
||||||
@@ -41,7 +41,7 @@ public class Injection extends InjectData implements InjectTaskHandler
|
|||||||
|
|
||||||
inject(new InterfaceInjector(this));
|
inject(new InterfaceInjector(this));
|
||||||
|
|
||||||
inject(new RasterizerHook(this));
|
inject(new RasterizerAlpha(this));
|
||||||
|
|
||||||
inject(new MixinInjector(this));
|
inject(new MixinInjector(this));
|
||||||
|
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ public class MixinInjector extends AbstractInjector
|
|||||||
|
|
||||||
if (mixinMethod.isStatic())
|
if (mixinMethod.isStatic())
|
||||||
{
|
{
|
||||||
deobSourceMethod = InjectUtil.findStaticMethod(inject.getDeobfuscated(), copiedName, mixinMethod.getDescriptor().rsApiToRsClient());
|
deobSourceMethod = InjectUtil.findMethod(inject.getDeobfuscated(), copiedName, mixinMethod.getDescriptor().rsApiToRsClient());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ public class ClearColorBuffer extends AbstractInjector
|
|||||||
*/
|
*/
|
||||||
final Execution exec = new Execution(inject.getVanilla());
|
final Execution exec = new Execution(inject.getVanilla());
|
||||||
|
|
||||||
final net.runelite.asm.pool.Method fillRectPool = InjectUtil.findStaticMethod(inject, "Rasterizer2D_fillRectangle", "Rasterizer2D", null).getPoolMethod();
|
final net.runelite.asm.pool.Method fillRectPool = InjectUtil.findMethod(inject, "Rasterizer2D_fillRectangle", "Rasterizer2D", null).getPoolMethod();
|
||||||
final Method drawEntities = InjectUtil.findStaticMethod(inject, "drawEntities"); // XXX: should prob be called drawViewport?
|
final Method drawEntities = InjectUtil.findMethod(inject, "drawEntities"); // XXX: should prob be called drawViewport?
|
||||||
|
|
||||||
exec.addMethod(drawEntities);
|
exec.addMethod(drawEntities);
|
||||||
exec.noInvoke = true;
|
exec.noInvoke = true;
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ public class DrawAfterWidgets extends AbstractInjector
|
|||||||
|
|
||||||
boolean injected = false;
|
boolean injected = false;
|
||||||
|
|
||||||
Method noClip = InjectUtil.findStaticMethod(inject, "Rasterizer2D_resetClip", "Rasterizer2D", null); // !!!!!
|
Method noClip = InjectUtil.findMethod(inject, "Rasterizer2D_resetClip", "Rasterizer2D", null); // !!!!!
|
||||||
|
|
||||||
if (noClip == null)
|
if (noClip == null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
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.Injection;
|
|
||||||
import com.openosrs.injector.Injexception;
|
import com.openosrs.injector.Injexception;
|
||||||
import com.openosrs.injector.injection.InjectData;
|
import com.openosrs.injector.injection.InjectData;
|
||||||
import com.openosrs.injector.injectors.AbstractInjector;
|
import com.openosrs.injector.injectors.AbstractInjector;
|
||||||
import com.openosrs.injector.injectors.Injector;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
import net.runelite.asm.Method;
|
import net.runelite.asm.Method;
|
||||||
@@ -34,7 +32,7 @@ public class HidePlayerAttacks extends AbstractInjector
|
|||||||
|
|
||||||
public void inject() throws Injexception
|
public void inject() throws Injexception
|
||||||
{
|
{
|
||||||
final Method addPlayerOptions = InjectUtil.findStaticMethod(inject, "addPlayerToMenu");
|
final Method addPlayerOptions = InjectUtil.findMethod(inject, "addPlayerToMenu");
|
||||||
final net.runelite.asm.pool.Method shouldHideAttackOptionFor = inject.getVanilla().findClass("client").findMethod("shouldHideAttackOptionFor").getPoolMethod();
|
final net.runelite.asm.pool.Method shouldHideAttackOptionFor = inject.getVanilla().findClass("client").findMethod("shouldHideAttackOptionFor").getPoolMethod();
|
||||||
|
|
||||||
injectHideAttack(addPlayerOptions, shouldHideAttackOptionFor);
|
injectHideAttack(addPlayerOptions, shouldHideAttackOptionFor);
|
||||||
|
|||||||
@@ -0,0 +1,256 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Lucas <https://github.com/Lucwousin>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package com.openosrs.injector.injectors.raw;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.openosrs.injector.InjectUtil;
|
||||||
|
import com.openosrs.injector.Injexception;
|
||||||
|
import com.openosrs.injector.injection.InjectData;
|
||||||
|
import com.openosrs.injector.injectors.AbstractInjector;
|
||||||
|
import net.runelite.asm.ClassFile;
|
||||||
|
import net.runelite.asm.Field;
|
||||||
|
import net.runelite.asm.Method;
|
||||||
|
import net.runelite.asm.attributes.Code;
|
||||||
|
import net.runelite.asm.attributes.code.Instruction;
|
||||||
|
import net.runelite.asm.attributes.code.InstructionType;
|
||||||
|
import net.runelite.asm.attributes.code.Instructions;
|
||||||
|
import net.runelite.asm.attributes.code.instruction.types.FieldInstruction;
|
||||||
|
import net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction;
|
||||||
|
import net.runelite.asm.attributes.code.instruction.types.LVTInstruction;
|
||||||
|
import net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction;
|
||||||
|
import net.runelite.asm.attributes.code.instructions.GetStatic;
|
||||||
|
import net.runelite.asm.attributes.code.instructions.IALoad;
|
||||||
|
import net.runelite.asm.attributes.code.instructions.IAStore;
|
||||||
|
import net.runelite.asm.attributes.code.instructions.IAdd;
|
||||||
|
import net.runelite.asm.attributes.code.instructions.ILoad;
|
||||||
|
import net.runelite.asm.attributes.code.instructions.IOr;
|
||||||
|
import net.runelite.asm.attributes.code.instructions.IShR;
|
||||||
|
import net.runelite.asm.attributes.code.instructions.ISub;
|
||||||
|
import net.runelite.asm.attributes.code.instructions.IUShR;
|
||||||
|
import net.runelite.asm.attributes.code.instructions.InvokeStatic;
|
||||||
|
import net.runelite.asm.attributes.code.instructions.LDC;
|
||||||
|
import net.runelite.asm.attributes.code.instructions.SiPush;
|
||||||
|
import net.runelite.asm.execution.Execution;
|
||||||
|
import net.runelite.asm.execution.InstructionContext;
|
||||||
|
import net.runelite.asm.execution.MethodContext;
|
||||||
|
import net.runelite.asm.execution.StackContext;
|
||||||
|
import net.runelite.asm.execution.VariableContext;
|
||||||
|
import net.runelite.asm.pool.Class;
|
||||||
|
import net.runelite.asm.signature.Signature;
|
||||||
|
|
||||||
|
public class RasterizerAlpha extends AbstractInjector
|
||||||
|
{
|
||||||
|
private static final net.runelite.asm.pool.Method DRAWALPHA = new net.runelite.asm.pool.Method(
|
||||||
|
new Class("client"),
|
||||||
|
"drawAlpha",
|
||||||
|
new Signature("([IIII)V")
|
||||||
|
);
|
||||||
|
private static final int ALPHA = 0xff000000;
|
||||||
|
|
||||||
|
public RasterizerAlpha(InjectData inject)
|
||||||
|
{
|
||||||
|
super(inject);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This class exists to allow transparency in overlays
|
||||||
|
*/
|
||||||
|
public void inject() throws Injexception
|
||||||
|
{
|
||||||
|
final Field r2dPx = InjectUtil.findField(inject, "Rasterizer2D_pixels", "Rasterizer2D");
|
||||||
|
final Method draw = InjectUtil.findMethod(inject, "draw", "Client");
|
||||||
|
final ClassFile rasterizer2D = r2dPx.getClassFile();
|
||||||
|
final Execution ex = new Execution(rasterizer2D.getGroup());
|
||||||
|
ex.staticStep = false;
|
||||||
|
ex.step = false;
|
||||||
|
ex.addMethod(draw);
|
||||||
|
|
||||||
|
int[] counts = new int[2];
|
||||||
|
|
||||||
|
ex.addMethodContextVisitor((MethodContext mc) ->
|
||||||
|
{
|
||||||
|
Instructions instrs = getInstrs(mc);
|
||||||
|
if (instrs == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
int orCount = 0;
|
||||||
|
|
||||||
|
for (InstructionContext ic : mc.getInstructionContexts())
|
||||||
|
{
|
||||||
|
Instruction instruction = ic.getInstruction();
|
||||||
|
if (!(instruction instanceof IAStore))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Field field = astore.getMyField(ic);
|
||||||
|
// doesn't track into methods so doing it here
|
||||||
|
StackContext array = ic.getPops().get(2);
|
||||||
|
|
||||||
|
if (!isSameField(r2dPx, array))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// This is the colour that's being set
|
||||||
|
StackContext colour = ic.getPops().get(0);
|
||||||
|
|
||||||
|
// resolve gets the original value pusher
|
||||||
|
InstructionContext colPusher = colour.getPushed().resolve(colour);
|
||||||
|
Instruction colPushI = colPusher.getInstruction();
|
||||||
|
|
||||||
|
// If it's not a >> or a | we're not interested
|
||||||
|
if (colPushI instanceof LVTInstruction // when called from a method we didn't execute
|
||||||
|
|| colPushI instanceof PushConstantInstruction &&
|
||||||
|
!((PushConstantInstruction) colPushI).getConstant().equals(0)
|
||||||
|
|| colPushI instanceof IALoad)
|
||||||
|
{
|
||||||
|
// OR with 0xFF000000, unless 0
|
||||||
|
int storeIdx = instrs.getInstructions().indexOf(instruction);
|
||||||
|
|
||||||
|
instrs.addInstruction(storeIdx++, new LDC(instrs, ALPHA));
|
||||||
|
instrs.addInstruction(storeIdx, new IOr(instrs, InstructionType.IOR));
|
||||||
|
++orCount;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (!(
|
||||||
|
colPushI instanceof IShR ||
|
||||||
|
colPushI instanceof IUShR ||
|
||||||
|
colPushI instanceof IAdd))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// So we know we're dealing with alpha here, now we need the alpha value
|
||||||
|
// earlier on in the method there's been a 256 - XXX, where xxx is alpha
|
||||||
|
|
||||||
|
for (InstructionContext ins : mc.getInstructionContexts())
|
||||||
|
{
|
||||||
|
if (!(ins.getInstruction() instanceof SiPush))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SiPush pci = (SiPush) ins.getInstruction();
|
||||||
|
if ((short) pci.getConstant() != (short) 256)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
InstructionContext isub = ins.getPushes().get(0).getPopped().get(0);
|
||||||
|
if (!(isub.getInstruction() instanceof ISub))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
StackContext alphaPop = isub.getPops().get(0);
|
||||||
|
InstructionContext alphaPusher = alphaPop.getPushed().resolve(alphaPop);
|
||||||
|
InstructionContext isubResult = isub.getPushes().get(0).getPopped().get(0);
|
||||||
|
|
||||||
|
if (pushesToSameField(isubResult, alphaPusher))
|
||||||
|
{
|
||||||
|
alphaPusher = resolveFieldThroughInvokes(alphaPop);
|
||||||
|
|
||||||
|
if (alphaPusher == null)
|
||||||
|
throw new RuntimeException("Alpha var is overwritten and we don't know what pushed it"); // cheeky unchecked
|
||||||
|
}
|
||||||
|
|
||||||
|
int storeIdx = instrs.getInstructions().indexOf(instruction);
|
||||||
|
|
||||||
|
Instruction alphaPushI = alphaPusher.getInstruction();
|
||||||
|
if (alphaPushI instanceof GetStatic)
|
||||||
|
{
|
||||||
|
instrs.addInstruction(storeIdx++, new LDC(instrs, 255));
|
||||||
|
instrs.addInstruction(storeIdx++, new GetStatic(instrs, ((GetStatic) alphaPushI).getField()));
|
||||||
|
instrs.addInstruction(storeIdx++, new ISub(instrs, InstructionType.ISUB));
|
||||||
|
}
|
||||||
|
else if (alphaPushI instanceof LVTInstruction)
|
||||||
|
{
|
||||||
|
instrs.addInstruction(storeIdx++, new ILoad(instrs, ((LVTInstruction) alphaPushI).getVariableIndex()));
|
||||||
|
}
|
||||||
|
|
||||||
|
instrs.getInstructions().set(storeIdx, new InvokeStatic(instrs, DRAWALPHA));
|
||||||
|
++count;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (orCount != 0)
|
||||||
|
{
|
||||||
|
counts[0] += orCount;
|
||||||
|
log.info("Added {} OR's into {}", orCount, mc.getMethod());
|
||||||
|
}
|
||||||
|
if (count != 0)
|
||||||
|
{
|
||||||
|
counts[1] += count;
|
||||||
|
log.info("Injected {} DrawAlpha invokes into {}", count, mc.getMethod());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ex.run();
|
||||||
|
log.info("Injected {} DrawAlpha invokes and {} ors", counts[1], counts[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean pushesToSameField(InstructionContext cA, InstructionContext cB)
|
||||||
|
{
|
||||||
|
if (cA.getInstruction() instanceof FieldInstruction && cB instanceof FieldInstruction)
|
||||||
|
{
|
||||||
|
Field a = ((FieldInstruction) cA.getInstruction()).getMyField();
|
||||||
|
Field b = ((FieldInstruction) cB.getInstruction()).getMyField();
|
||||||
|
|
||||||
|
return a == b;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Instructions getInstrs(MethodContext mc)
|
||||||
|
{
|
||||||
|
Code c = mc.getMethod().getCode();
|
||||||
|
if (c == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return c.getInstructions();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InstructionContext resolveFieldThroughInvokes(StackContext stackContext)
|
||||||
|
{
|
||||||
|
InstructionContext pusher = stackContext.getPushed().resolve(stackContext);
|
||||||
|
if (pusher.getInstruction() instanceof GetFieldInstruction)
|
||||||
|
return pusher;
|
||||||
|
|
||||||
|
// No field I wanna trace, rn at least
|
||||||
|
if (!(pusher.getInstruction() instanceof LVTInstruction))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
int vidx = ((LVTInstruction) pusher.getInstruction()).getVariableIndex();
|
||||||
|
|
||||||
|
VariableContext vc = pusher.getVariables().get(vidx);
|
||||||
|
stackContext = Lists.reverse(vc.getInstructionWhichStored().getPops()).get(vidx);
|
||||||
|
|
||||||
|
return resolveFieldThroughInvokes(stackContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isSameField(Field f, StackContext array)
|
||||||
|
{
|
||||||
|
InstructionContext ic = resolveFieldThroughInvokes(array);
|
||||||
|
|
||||||
|
if (ic == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return ((GetFieldInstruction) ic.getInstruction()).getMyField() == f;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,383 +0,0 @@
|
|||||||
package com.openosrs.injector.injectors.raw;
|
|
||||||
|
|
||||||
import com.openosrs.injector.InjectUtil;
|
|
||||||
import com.openosrs.injector.Injexception;
|
|
||||||
import com.openosrs.injector.injection.InjectData;
|
|
||||||
import com.openosrs.injector.injectors.AbstractInjector;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import net.runelite.asm.Field;
|
|
||||||
import net.runelite.asm.Type;
|
|
||||||
import net.runelite.asm.attributes.Code;
|
|
||||||
import net.runelite.asm.attributes.code.Instruction;
|
|
||||||
import net.runelite.asm.attributes.code.InstructionType;
|
|
||||||
import net.runelite.asm.attributes.code.Instructions;
|
|
||||||
import net.runelite.asm.attributes.code.instruction.types.LVTInstruction;
|
|
||||||
import net.runelite.asm.attributes.code.instructions.ALoad;
|
|
||||||
import net.runelite.asm.attributes.code.instructions.ArrayStore;
|
|
||||||
import net.runelite.asm.attributes.code.instructions.GetField;
|
|
||||||
import net.runelite.asm.attributes.code.instructions.GetStatic;
|
|
||||||
import net.runelite.asm.attributes.code.instructions.IALoad;
|
|
||||||
import net.runelite.asm.attributes.code.instructions.IAStore;
|
|
||||||
import net.runelite.asm.attributes.code.instructions.ILoad;
|
|
||||||
import net.runelite.asm.attributes.code.instructions.IOr;
|
|
||||||
import net.runelite.asm.attributes.code.instructions.ISub;
|
|
||||||
import net.runelite.asm.attributes.code.instructions.InvokeStatic;
|
|
||||||
import net.runelite.asm.attributes.code.instructions.LDC;
|
|
||||||
import net.runelite.asm.execution.Execution;
|
|
||||||
import net.runelite.asm.execution.InstructionContext;
|
|
||||||
import net.runelite.asm.pool.Class;
|
|
||||||
import net.runelite.asm.pool.Method;
|
|
||||||
import net.runelite.asm.signature.Signature;
|
|
||||||
|
|
||||||
public class RasterizerHook extends AbstractInjector
|
|
||||||
{
|
|
||||||
// TODO: Should probably make this better
|
|
||||||
|
|
||||||
private static final int val = 0xff000000;
|
|
||||||
private static final Class R3D = new Class("Rasterizer3D");
|
|
||||||
private static final Class FONT = new Class("AbstractFont");
|
|
||||||
private static final Class R2D = new Class("Rasterizer2D");
|
|
||||||
private static final Class SPRITE = new Class("Sprite");
|
|
||||||
private net.runelite.asm.pool.Field R2D_PIXELS;
|
|
||||||
|
|
||||||
private static final Method r3d_vert = new Method(R3D, "Rasterizer3D_vertAlpha", new Signature("([IIIIIIII)V"));
|
|
||||||
private static final Method r3d_horiz = new Method(R3D, "Rasterizer3D_horizAlpha", new Signature("([IIIIII)V"));
|
|
||||||
private static final net.runelite.asm.pool.Field r3d_field = new net.runelite.asm.pool.Field(R3D, "Rasterizer3D_alpha", Type.INT);
|
|
||||||
|
|
||||||
private static final Method font_alpha = new Method(FONT, "AbstractFont_placeGlyphAlpha", new Signature("([I[BIIIIIIII)V"));
|
|
||||||
|
|
||||||
private static final Method circle_alpha = new Method(R2D, "Rasterizer2D_drawCircleAlpha", new Signature("(IIIII)V"));
|
|
||||||
private static final Method line_alpha = new Method(R2D, "Rasterizer2D_drawHorizontalLineAlpha", new Signature("(IIIII)V"));
|
|
||||||
private static final Method line_alpha2 = new Method(R2D, "Rasterizer2D_drawVerticalLineAlpha", new Signature("(IIIII)V"));
|
|
||||||
private static final Method fill_rect_alpha = new Method(R2D, "Rasterizer2D_fillRectangleAlpha", new Signature("(IIIIII)V"));
|
|
||||||
|
|
||||||
private static final Method sprite_alpha1 = new Method(SPRITE, "Sprite_drawTransparent", new Signature("([I[IIIIIIIII)V"));
|
|
||||||
private static final Method sprite_alpha2 = new Method(SPRITE, "Sprite_drawTransScaled", new Signature("([I[IIIIIIIIIIII)V"));
|
|
||||||
|
|
||||||
private static final String font = "AbstractFont_placeGlyph";
|
|
||||||
private static final String rast3D = "Rasterizer3D_iDontKnow";
|
|
||||||
private static final String rast3D2 = "Rasterizer3D_textureAlpha";
|
|
||||||
private static final String sprite = "Sprite_draw";
|
|
||||||
private static final String sprite2 = "Sprite_drawScaled";
|
|
||||||
private static final String sprite3 = "Sprite_drawTransOverlay";
|
|
||||||
private static final String sprite4 = "Sprite_drawTransBg";
|
|
||||||
private static final String indexedSprite = "IndexedSprite_something";
|
|
||||||
private static final String indexedSprite2 = "IndexedSprite_two";
|
|
||||||
|
|
||||||
private static final net.runelite.asm.pool.Method drawAlpha = new net.runelite.asm.pool.Method(
|
|
||||||
new Class("client"),
|
|
||||||
"drawAlpha",
|
|
||||||
new Signature("([IIII)V")
|
|
||||||
);
|
|
||||||
|
|
||||||
private int drawAlphaCount = 0;
|
|
||||||
private int orCount = 0;
|
|
||||||
|
|
||||||
public RasterizerHook(InjectData inject) throws Injexception
|
|
||||||
{
|
|
||||||
super(inject);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void inject() throws Injexception
|
|
||||||
{
|
|
||||||
R2D_PIXELS = InjectUtil.findStaticField(inject, "Rasterizer2D_pixels", R2D.getName(), new Type("[I")).getPoolField();
|
|
||||||
|
|
||||||
injectDrawAlpha();
|
|
||||||
|
|
||||||
runVars();
|
|
||||||
|
|
||||||
run();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void injectDrawAlpha() throws Injexception
|
|
||||||
{
|
|
||||||
final Field field = InjectUtil.findStaticField(inject, r3d_field);
|
|
||||||
runR3DAlpha(r3d_horiz, field, 15);
|
|
||||||
runR3DAlpha(r3d_vert, field, 12);
|
|
||||||
runFontAlpha(font_alpha, 1, 9);
|
|
||||||
|
|
||||||
runAlpha(circle_alpha, 2, 4);
|
|
||||||
runAlpha(line_alpha, 1, 4);
|
|
||||||
runAlpha(line_alpha2, 1, 4);
|
|
||||||
runAlpha(fill_rect_alpha, 1, 5);
|
|
||||||
runAlpha(sprite_alpha1, 1, 9, 0);
|
|
||||||
runAlpha(sprite_alpha2, 1, 12, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void runR3DAlpha(Method pool, net.runelite.asm.Field field, int req) throws Injexception
|
|
||||||
{
|
|
||||||
net.runelite.asm.Method method = InjectUtil.findStaticMethod(inject, pool);
|
|
||||||
Instructions ins = method.getCode().getInstructions();
|
|
||||||
int varIdx = 0; // This is obviously dumb but I cba making this better
|
|
||||||
int added = 0;
|
|
||||||
|
|
||||||
List<Integer> indices = new ArrayList<>();
|
|
||||||
for (Instruction i : method.findLVTInstructionsForVariable(varIdx))
|
|
||||||
{
|
|
||||||
indices.add(ins.getInstructions().indexOf(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (indices.isEmpty())
|
|
||||||
{
|
|
||||||
throw new Injexception("Couldn't find hook location in " + pool.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i : indices)
|
|
||||||
{
|
|
||||||
for (int codeIndex = i + added; codeIndex < ins.getInstructions().size(); codeIndex++)
|
|
||||||
{
|
|
||||||
if (ins.getInstructions().get(codeIndex) instanceof IAStore)
|
|
||||||
{
|
|
||||||
ins.getInstructions().set(codeIndex, new InvokeStatic(ins, drawAlpha));
|
|
||||||
|
|
||||||
ins.getInstructions().add(codeIndex, new ISub(ins, InstructionType.ISUB));
|
|
||||||
ins.getInstructions().add(codeIndex, new GetStatic(ins, field.getPoolField()));
|
|
||||||
ins.getInstructions().add(codeIndex, new LDC(ins, 255));
|
|
||||||
added++;
|
|
||||||
drawAlphaCount++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (added != req)
|
|
||||||
{
|
|
||||||
throw new Injexception("Not enough drawAlphas injected into " + pool.toString() + " (" + added + "/" + req + ")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void runFontAlpha(Method pool, int req, int extraArg) throws Injexception
|
|
||||||
{
|
|
||||||
net.runelite.asm.Method meth = InjectUtil.findStaticMethod(inject, pool);
|
|
||||||
Instructions ins = meth.getCode().getInstructions();
|
|
||||||
int varIdx = 0; // This is obviously dumb but I cba making this better
|
|
||||||
int added = 0;
|
|
||||||
|
|
||||||
List<Integer> indices = new ArrayList<>();
|
|
||||||
for (Instruction i : meth.findLVTInstructionsForVariable(varIdx))
|
|
||||||
{
|
|
||||||
indices.add(ins.getInstructions().indexOf(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (indices.isEmpty())
|
|
||||||
{
|
|
||||||
throw new Injexception("Couldn't find hook location in " + pool.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i : indices)
|
|
||||||
{
|
|
||||||
for (int codeIndex = i + added; codeIndex < ins.getInstructions().size(); codeIndex++)
|
|
||||||
{
|
|
||||||
if (ins.getInstructions().get(codeIndex) instanceof IAStore)
|
|
||||||
{
|
|
||||||
ins.getInstructions().set(codeIndex, new InvokeStatic(ins, drawAlpha));
|
|
||||||
|
|
||||||
ins.getInstructions().add(codeIndex, new ISub(ins, InstructionType.ISUB));
|
|
||||||
ins.getInstructions().add(codeIndex, new ILoad(ins, extraArg));
|
|
||||||
ins.getInstructions().add(codeIndex, new LDC(ins, 255));
|
|
||||||
added++;
|
|
||||||
drawAlphaCount++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (added != req)
|
|
||||||
{
|
|
||||||
throw new Injexception("Not enough drawAlphas injected into " + pool.toString() + " (" + added + "/" + req + ")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void runAlpha(Method pool, int req, int extraArg) throws Injexception
|
|
||||||
{
|
|
||||||
runAlpha(pool, req, extraArg, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void runAlpha(Method pool, int req, int extraArg, int varIndex) throws Injexception
|
|
||||||
{
|
|
||||||
net.runelite.asm.Method meth = InjectUtil.findStaticMethod(inject, pool);
|
|
||||||
|
|
||||||
Code code = meth.getCode();
|
|
||||||
Instructions ins = code.getInstructions();
|
|
||||||
int added = 0;
|
|
||||||
|
|
||||||
List<Integer> indices = new ArrayList<>();
|
|
||||||
for (Instruction i : ins.getInstructions())
|
|
||||||
{
|
|
||||||
if (!(i instanceof IALoad) && !(i instanceof GetField) && !(i instanceof ALoad))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i instanceof GetField)
|
|
||||||
{
|
|
||||||
if (((GetField) i).getField().equals(R2D_PIXELS))
|
|
||||||
{
|
|
||||||
indices.add(ins.getInstructions().indexOf(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ((i instanceof ALoad) && varIndex >= 0 && ((LVTInstruction) i).getVariableIndex() == varIndex)
|
|
||||||
{
|
|
||||||
indices.add(ins.getInstructions().indexOf(i));
|
|
||||||
}
|
|
||||||
else if (varIndex == -1)
|
|
||||||
{
|
|
||||||
indices.add(ins.getInstructions().indexOf(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (indices.isEmpty())
|
|
||||||
{
|
|
||||||
throw new Injexception("Couldn't find hook location in " + pool.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
final int oldCount = drawAlphaCount;
|
|
||||||
|
|
||||||
for (int i : indices)
|
|
||||||
{
|
|
||||||
for (int codeIndex = i + added; codeIndex < ins.getInstructions().size(); codeIndex++)
|
|
||||||
{
|
|
||||||
if (ins.getInstructions().get(codeIndex) instanceof IAStore)
|
|
||||||
{
|
|
||||||
ins.getInstructions().set(codeIndex, new InvokeStatic(ins, drawAlpha));
|
|
||||||
if (extraArg != -1)
|
|
||||||
{
|
|
||||||
ins.getInstructions().add(codeIndex, new ILoad(ins, extraArg));
|
|
||||||
added++;
|
|
||||||
}
|
|
||||||
drawAlphaCount++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (drawAlphaCount - oldCount > req)
|
|
||||||
{
|
|
||||||
throw new Injexception("Too many drawAlpha's were injected into " + pool.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void runVars() throws Injexception
|
|
||||||
{
|
|
||||||
runOnMethodWithVar(rast3D, 0, 36);
|
|
||||||
runOnMethodWithVar(rast3D2, 0, 36);
|
|
||||||
// 36 expected
|
|
||||||
runOnMethodWithVar(font, 0, 5);
|
|
||||||
// 5 expected
|
|
||||||
runOnMethodWithVar(sprite, 1, 5);
|
|
||||||
runOnMethodWithVar(sprite2, 0, 1);
|
|
||||||
runOnMethodWithVar(sprite3, 0, 1);
|
|
||||||
runOnMethodWithVar(sprite4, 0, 5);
|
|
||||||
// 12 expected
|
|
||||||
runOnMethodWithVar(indexedSprite, 0, 1);
|
|
||||||
runOnMethodWithVar(indexedSprite2, 0, 5);
|
|
||||||
// 6 expected
|
|
||||||
}
|
|
||||||
|
|
||||||
private void run() throws Injexception
|
|
||||||
{
|
|
||||||
final int startCount = orCount; // Cause you can't just count shit ty
|
|
||||||
|
|
||||||
Execution ex = new Execution(inject.getVanilla());
|
|
||||||
ex.populateInitialMethods();
|
|
||||||
|
|
||||||
Set<Instruction> done = new HashSet<>();
|
|
||||||
ex.addExecutionVisitor((InstructionContext ic) ->
|
|
||||||
{
|
|
||||||
Instruction i = ic.getInstruction();
|
|
||||||
Instructions ins = i.getInstructions();
|
|
||||||
Code code = ins.getCode();
|
|
||||||
net.runelite.asm.Method method = code.getMethod();
|
|
||||||
|
|
||||||
if (!(i instanceof IAStore))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!done.add(i))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayStore as = (ArrayStore) i;
|
|
||||||
Field fieldBeingSet = as.getMyField(ic);
|
|
||||||
|
|
||||||
if (fieldBeingSet == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fieldBeingSet.getPoolField().equals(R2D_PIXELS))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int index = ins.getInstructions().indexOf(i);
|
|
||||||
|
|
||||||
if (!(ins.getInstructions().get(index - 1) instanceof ILoad) && !ic.getPops().get(0).getValue().isUnknownOrNull())
|
|
||||||
{
|
|
||||||
if ((int) ic.getPops().get(0).getValue().getValue() == 0)
|
|
||||||
{
|
|
||||||
log.debug("Didn't add hook in method {}.{}. {} added, {} total, value 0", method.getClassFile().getClassName(), method.getName(), orCount - startCount, orCount);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ins.getInstructions().add(index, new IOr(ins, InstructionType.IOR)); // Add instructions backwards
|
|
||||||
ins.getInstructions().add(index, new LDC(ins, val));
|
|
||||||
orCount++;
|
|
||||||
log.debug("Added hook in method {}.{}. {} added, {} total", method.getClassFile().getClassName(), method.getName(), orCount - startCount, orCount);
|
|
||||||
});
|
|
||||||
|
|
||||||
ex.run();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void runOnMethodWithVar(String meth, int varIndex, int req) throws Injexception
|
|
||||||
{
|
|
||||||
net.runelite.asm.Method method = InjectUtil.findStaticMethod(inject, meth);
|
|
||||||
|
|
||||||
Instructions ins = method.getCode().getInstructions();
|
|
||||||
List<Integer> indices = new ArrayList<>();
|
|
||||||
|
|
||||||
for (Instruction i : method.findLVTInstructionsForVariable(varIndex))
|
|
||||||
{
|
|
||||||
int index = ins.getInstructions().indexOf(i);
|
|
||||||
|
|
||||||
assert index != -1;
|
|
||||||
assert ins.getInstructions().get(index + 1) instanceof ILoad; // Index in the array
|
|
||||||
|
|
||||||
indices.add(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
int added = 0;
|
|
||||||
for (int i : indices)
|
|
||||||
{
|
|
||||||
for (int codeIndex = i + added; codeIndex < ins.getInstructions().size(); codeIndex++)
|
|
||||||
{
|
|
||||||
if (ins.getInstructions().get(codeIndex) instanceof IAStore)
|
|
||||||
{
|
|
||||||
added += 2;
|
|
||||||
orCount++;
|
|
||||||
ins.addInstruction(codeIndex, new IOr(ins, InstructionType.IOR)); // Add instructions backwards
|
|
||||||
ins.addInstruction(codeIndex, new LDC(ins, val));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (added / 2 != req)
|
|
||||||
{
|
|
||||||
throw new Injexception("Didn't inject the right amount of ors into " + meth);
|
|
||||||
}
|
|
||||||
|
|
||||||
log.info("Added {} instructions in {}. {} total", added / 2, meth, orCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean validate()
|
|
||||||
{
|
|
||||||
return drawAlphaCount + 1 == 35 && orCount + 1 == 125;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user