RSCanvas stuff, mostly from runeloader. I assume this breaks resizable. I can't tell whether or not this defers all rendering by 1 frame. Fix various injectreplace bugs. I need to make the unused parameter annotate methods with ObfuscatedSignature or I can't export methods that had an unused parameter. This is going to all break if I ever need to export something with an unused parameter that isn't at the end. Should consider only removing unused parameters that I can detect as being garbage.
This commit is contained in:
5
pom.xml
5
pom.xml
@@ -39,6 +39,11 @@
|
|||||||
<artifactId>api</artifactId>
|
<artifactId>api</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.runelite</groupId>
|
||||||
|
<artifactId>client</artifactId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import java.io.DataOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import net.runelite.asm.signature.Signature;
|
||||||
|
|
||||||
public class ClassFile
|
public class ClassFile
|
||||||
{
|
{
|
||||||
@@ -246,6 +247,11 @@ public class ClassFile
|
|||||||
{
|
{
|
||||||
return methods.findMethod(name);
|
return methods.findMethod(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Method findMethod(String name, Signature signature)
|
||||||
|
{
|
||||||
|
return methods.findMethod(new NameAndType(name, signature));
|
||||||
|
}
|
||||||
|
|
||||||
public Method findMethodDeep(String name)
|
public Method findMethodDeep(String name)
|
||||||
{
|
{
|
||||||
@@ -300,4 +306,9 @@ public class ClassFile
|
|||||||
{
|
{
|
||||||
this.access_flags &= ~ACC_FINAL;
|
this.access_flags &= ~ACC_FINAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void clearAbstract()
|
||||||
|
{
|
||||||
|
this.access_flags &= ~ACC_ABSTRACT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,6 +143,14 @@ public class Method
|
|||||||
return (accessFlags & ACC_FINAL) != 0;
|
return (accessFlags & ACC_FINAL) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setFinal(boolean f)
|
||||||
|
{
|
||||||
|
if (f)
|
||||||
|
accessFlags |= ACC_FINAL;
|
||||||
|
else
|
||||||
|
accessFlags &= ~ACC_FINAL;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isPrivate()
|
public boolean isPrivate()
|
||||||
{
|
{
|
||||||
return (accessFlags & ACC_PRIVATE) != 0;
|
return (accessFlags & ACC_PRIVATE) != 0;
|
||||||
@@ -152,6 +160,11 @@ public class Method
|
|||||||
{
|
{
|
||||||
accessFlags = (short) ((accessFlags & ~ACCESS_MODIFIERS) | ACC_PRIVATE);
|
accessFlags = (short) ((accessFlags & ~ACCESS_MODIFIERS) | ACC_PRIVATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setPublic()
|
||||||
|
{
|
||||||
|
accessFlags = (short) ((accessFlags & ~ACCESS_MODIFIERS) | ACC_PUBLIC);
|
||||||
|
}
|
||||||
|
|
||||||
public Exceptions getExceptions()
|
public Exceptions getExceptions()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,6 +16,11 @@ public class AConstNull extends Instruction
|
|||||||
super(instructions, type, pc);
|
super(instructions, type, pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AConstNull(Instructions instructions)
|
||||||
|
{
|
||||||
|
super(instructions, InstructionType.ACONST_NULL, -1);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InstructionContext execute(Frame frame)
|
public InstructionContext execute(Frame frame)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -68,16 +68,6 @@ public class InvokeInterface extends Instruction implements InvokeInstruction
|
|||||||
{
|
{
|
||||||
return myMethods != null ? myMethods : Arrays.asList();
|
return myMethods != null ? myMethods : Arrays.asList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void findMethodFromClass(List<net.runelite.asm.Method> list, ClassFile clazz)
|
|
||||||
{
|
|
||||||
net.runelite.asm.Method m = clazz.findMethodDeep(method.getNameAndType());
|
|
||||||
if (m != null && !list.contains(m))
|
|
||||||
list.add(m);
|
|
||||||
|
|
||||||
for (ClassFile cf : clazz.getChildren())
|
|
||||||
findMethodFromClass(list, cf);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InstructionContext execute(Frame frame)
|
public InstructionContext execute(Frame frame)
|
||||||
|
|||||||
@@ -141,11 +141,13 @@ public class InvokeSpecial extends Instruction implements InvokeInstruction
|
|||||||
public void setMethod(Method method)
|
public void setMethod(Method method)
|
||||||
{
|
{
|
||||||
this.method = method;
|
this.method = method;
|
||||||
|
lookup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void lookup()
|
public void lookup()
|
||||||
{
|
{
|
||||||
|
myMethods = null;
|
||||||
ClassGroup group = this.getInstructions().getCode().getAttributes().getClassFile().getGroup();
|
ClassGroup group = this.getInstructions().getCode().getAttributes().getClassFile().getGroup();
|
||||||
|
|
||||||
ClassFile otherClass = group.findClass(method.getClassEntry().getName());
|
ClassFile otherClass = group.findClass(method.getClassEntry().getName());
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ public class New extends Instruction
|
|||||||
public void setNewClass(Class clazz)
|
public void setNewClass(Class clazz)
|
||||||
{
|
{
|
||||||
this.clazz = clazz;
|
this.clazz = clazz;
|
||||||
|
lookup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import net.runelite.asm.attributes.Annotations;
|
|||||||
import net.runelite.asm.attributes.Attributes;
|
import net.runelite.asm.attributes.Attributes;
|
||||||
import net.runelite.asm.attributes.Code;
|
import net.runelite.asm.attributes.Code;
|
||||||
import net.runelite.asm.attributes.annotation.Annotation;
|
import net.runelite.asm.attributes.annotation.Annotation;
|
||||||
|
import net.runelite.asm.attributes.annotation.Element;
|
||||||
import net.runelite.asm.attributes.code.Instruction;
|
import net.runelite.asm.attributes.code.Instruction;
|
||||||
import net.runelite.asm.attributes.code.InstructionType;
|
import net.runelite.asm.attributes.code.InstructionType;
|
||||||
import net.runelite.asm.attributes.code.Instructions;
|
import net.runelite.asm.attributes.code.Instructions;
|
||||||
@@ -172,7 +173,12 @@ public class Inject
|
|||||||
assert !m.isStatic();
|
assert !m.isStatic();
|
||||||
|
|
||||||
String exportedName = an.find(EXPORT).getElement().getString();
|
String exportedName = an.find(EXPORT).getElement().getString();
|
||||||
obfuscatedName = an.find(OBFUSCATED_NAME).getElement().getString();
|
|
||||||
|
Annotation obAn = an.find(OBFUSCATED_NAME);
|
||||||
|
if (obAn != null)
|
||||||
|
obfuscatedName = obAn.getElement().getString();
|
||||||
|
else
|
||||||
|
obfuscatedName = m.getName();
|
||||||
|
|
||||||
Method otherm;
|
Method otherm;
|
||||||
|
|
||||||
@@ -181,8 +187,11 @@ public class Inject
|
|||||||
String garbage = null;
|
String garbage = null;
|
||||||
if (obfuscatedSignature != null)
|
if (obfuscatedSignature != null)
|
||||||
{
|
{
|
||||||
String signatureString = obfuscatedSignature.getElements().get(0).getString();
|
List<Element> elements = obfuscatedSignature.getElements();
|
||||||
garbage = obfuscatedSignature.getElements().get(1).getString();
|
|
||||||
|
String signatureString = elements.get(0).getString();
|
||||||
|
if (elements.size() == 2)
|
||||||
|
garbage = obfuscatedSignature.getElements().get(1).getString();
|
||||||
|
|
||||||
Signature signature = new Signature(signatureString); // parse signature
|
Signature signature = new Signature(signatureString); // parse signature
|
||||||
|
|
||||||
@@ -349,7 +358,11 @@ public class Inject
|
|||||||
// deobfuscatedMethod = deobfuscated method, used to get the deobfuscated signature
|
// deobfuscatedMethod = deobfuscated method, used to get the deobfuscated signature
|
||||||
// invokeMethod = method to invoke, obfuscated
|
// invokeMethod = method to invoke, obfuscated
|
||||||
|
|
||||||
assert clazz.findMethod(method.getName()) == null;
|
if (clazz.findMethod(method.getName()) != null)
|
||||||
|
{
|
||||||
|
return; // hmm. this might be due to an export/import of a non obfuscated method
|
||||||
|
}
|
||||||
|
|
||||||
assert !invokeMethod.isStatic();
|
assert !invokeMethod.isStatic();
|
||||||
assert invokeMethod.getMethods().getClassFile() == clazz;
|
assert invokeMethod.getMethods().getClassFile() == clazz;
|
||||||
|
|
||||||
@@ -423,6 +436,10 @@ public class Inject
|
|||||||
{
|
{
|
||||||
// function requires garbage value
|
// function requires garbage value
|
||||||
|
|
||||||
|
// if garbage is null here it might just be an unused parameter, not part of the obfuscation
|
||||||
|
if (garbage == null)
|
||||||
|
garbage = "0";
|
||||||
|
|
||||||
switch (lastGarbageArgumentType.getType())
|
switch (lastGarbageArgumentType.getType())
|
||||||
{
|
{
|
||||||
case "Z":
|
case "Z":
|
||||||
|
|||||||
@@ -14,24 +14,31 @@ import net.runelite.asm.attributes.annotation.Annotation;
|
|||||||
import net.runelite.asm.attributes.code.Instruction;
|
import net.runelite.asm.attributes.code.Instruction;
|
||||||
import net.runelite.asm.attributes.code.InstructionType;
|
import net.runelite.asm.attributes.code.InstructionType;
|
||||||
import net.runelite.asm.attributes.code.Instructions;
|
import net.runelite.asm.attributes.code.Instructions;
|
||||||
|
import net.runelite.asm.attributes.code.instructions.AConstNull;
|
||||||
import net.runelite.asm.attributes.code.instructions.ALoad;
|
import net.runelite.asm.attributes.code.instructions.ALoad;
|
||||||
|
import net.runelite.asm.attributes.code.instructions.BiPush;
|
||||||
import net.runelite.asm.attributes.code.instructions.DLoad;
|
import net.runelite.asm.attributes.code.instructions.DLoad;
|
||||||
import net.runelite.asm.attributes.code.instructions.FLoad;
|
import net.runelite.asm.attributes.code.instructions.FLoad;
|
||||||
import net.runelite.asm.attributes.code.instructions.ILoad;
|
import net.runelite.asm.attributes.code.instructions.ILoad;
|
||||||
import net.runelite.asm.attributes.code.instructions.InvokeSpecial;
|
import net.runelite.asm.attributes.code.instructions.InvokeSpecial;
|
||||||
import net.runelite.asm.attributes.code.instructions.InvokeVirtual;
|
import net.runelite.asm.attributes.code.instructions.InvokeVirtual;
|
||||||
|
import net.runelite.asm.attributes.code.instructions.LDC2_W;
|
||||||
|
import net.runelite.asm.attributes.code.instructions.LDC_W;
|
||||||
import net.runelite.asm.attributes.code.instructions.LLoad;
|
import net.runelite.asm.attributes.code.instructions.LLoad;
|
||||||
import net.runelite.asm.attributes.code.instructions.New;
|
import net.runelite.asm.attributes.code.instructions.New;
|
||||||
import net.runelite.asm.attributes.code.instructions.Pop;
|
import net.runelite.asm.attributes.code.instructions.Pop;
|
||||||
import net.runelite.asm.attributes.code.instructions.Return;
|
import net.runelite.asm.attributes.code.instructions.Return;
|
||||||
|
import net.runelite.asm.attributes.code.instructions.SiPush;
|
||||||
import net.runelite.asm.pool.NameAndType;
|
import net.runelite.asm.pool.NameAndType;
|
||||||
|
import net.runelite.asm.signature.Signature;
|
||||||
import net.runelite.asm.signature.Type;
|
import net.runelite.asm.signature.Type;
|
||||||
|
|
||||||
public class InjectReplace
|
public class InjectReplace
|
||||||
{
|
{
|
||||||
private static final Type REPLACE = new Type("Lnet/runelite/mapping/Replace;");
|
private static final Type REPLACE = new Type("Lnet/runelite/mapping/Replace;");
|
||||||
private static final Type OBFUSCATED_OVERRIDE = new Type("Lnet/runelite/mapping/ObfuscatedOverride;");
|
private static final Type OBFUSCATED_OVERRIDE = new Type("Lnet/runelite/mapping/ObfuscatedOverride;");
|
||||||
//private static final Type OBFUSCATED_NAME = new Type("Lnet/runelite/mapping/ObfuscatedName;");
|
private static final Type OBFUSCATED_NAME = new Type("Lnet/runelite/mapping/ObfuscatedName;");
|
||||||
|
private static final Type OBFUSCATED_SIGNATURE = new Type("Lnet/runelite/mapping/ObfuscatedSignature;");
|
||||||
private static final Type EXPORT = new Type("Lnet/runelite/mapping/Export;");
|
private static final Type EXPORT = new Type("Lnet/runelite/mapping/Export;");
|
||||||
|
|
||||||
private ClassFile cf, vanilla;
|
private ClassFile cf, vanilla;
|
||||||
@@ -79,6 +86,7 @@ public class InjectReplace
|
|||||||
// set parent
|
// set parent
|
||||||
classToInject.setParentClass(vanilla.getPoolClass());
|
classToInject.setParentClass(vanilla.getPoolClass());
|
||||||
vanilla.clearFinal(); // can't be final anymore now that we inherit from it
|
vanilla.clearFinal(); // can't be final anymore now that we inherit from it
|
||||||
|
classToInject.clearAbstract(); // this is being instantiated now, so is no longer abstract
|
||||||
|
|
||||||
injectConstructors(classToInject);
|
injectConstructors(classToInject);
|
||||||
|
|
||||||
@@ -94,7 +102,7 @@ public class InjectReplace
|
|||||||
|
|
||||||
private void injectConstructors(ClassFile classToInject)
|
private void injectConstructors(ClassFile classToInject)
|
||||||
{
|
{
|
||||||
// Delete compiler generate constructors
|
// Delete compiler generated constructors
|
||||||
Methods methods = classToInject.getMethods();
|
Methods methods = classToInject.getMethods();
|
||||||
Methods vanillaMethods = vanilla.getMethods();
|
Methods vanillaMethods = vanilla.getMethods();
|
||||||
|
|
||||||
@@ -139,6 +147,9 @@ public class InjectReplace
|
|||||||
Method constructor = new Method(methods, "<init>", m.getDescriptor());
|
Method constructor = new Method(methods, "<init>", m.getDescriptor());
|
||||||
constructor.setAccessFlags(Method.ACC_PUBLIC);
|
constructor.setAccessFlags(Method.ACC_PUBLIC);
|
||||||
|
|
||||||
|
// ensure vanilla ctor is public too
|
||||||
|
m.setAccessFlags(Method.ACC_PUBLIC);
|
||||||
|
|
||||||
Attributes methodAttributes = constructor.getAttributes();
|
Attributes methodAttributes = constructor.getAttributes();
|
||||||
|
|
||||||
// create code attribute
|
// create code attribute
|
||||||
@@ -222,41 +233,102 @@ public class InjectReplace
|
|||||||
String overridenMethod = annotation.getElement().getString(); // name of @Exported method to override
|
String overridenMethod = annotation.getElement().getString(); // name of @Exported method to override
|
||||||
|
|
||||||
// Find method with exported name on 'cf'
|
// Find method with exported name on 'cf'
|
||||||
Method obfuscatedMethodToOverride = findMethodByExportedName(overridenMethod);
|
Method obfuscatedMethodToOverride = findMethodByExportedName(overridenMethod); // this is from the deobfuscated jar
|
||||||
|
Method vanillaMethodToOverride = findVanillaMethodFromDeobfuscatedMethod(obfuscatedMethodToOverride);
|
||||||
NameAndType deobfuscatedNat = m.getNameAndType();
|
NameAndType deobfuscatedNat = m.getNameAndType();
|
||||||
|
|
||||||
assert obfuscatedMethodToOverride != null;
|
assert obfuscatedMethodToOverride != null;
|
||||||
assert !obfuscatedMethodToOverride.isFinal();
|
assert vanillaMethodToOverride != null;
|
||||||
assert !obfuscatedMethodToOverride.isPrivate();
|
|
||||||
|
vanillaMethodToOverride.setFinal(false);
|
||||||
|
vanillaMethodToOverride.setPublic();
|
||||||
|
|
||||||
|
assert !vanillaMethodToOverride.isFinal();
|
||||||
|
assert !vanillaMethodToOverride.isPrivate();
|
||||||
|
|
||||||
// Rename method to override
|
// Rename method to override
|
||||||
m.setName(obfuscatedMethodToOverride.getName());
|
m.setName(vanillaMethodToOverride.getName());
|
||||||
|
|
||||||
assert false;
|
String garbageValue = null;
|
||||||
if (!m.getDescriptor().equals(obfuscatedMethodToOverride.getDescriptor()))
|
Signature originalSignature = null;
|
||||||
|
if (!m.getDescriptor().equals(vanillaMethodToOverride.getDescriptor()))
|
||||||
{
|
{
|
||||||
// Obfuscation can add garbage parameter.
|
// Obfuscation can add garbage parameter.
|
||||||
assert m.getDescriptor().size() + 1 == obfuscatedMethodToOverride.getDescriptor().size();
|
assert m.getDescriptor().size() + 1 == vanillaMethodToOverride.getDescriptor().size();
|
||||||
|
|
||||||
// Either we have to modify the bytecode when it is copied over to include this,
|
originalSignature = m.getDescriptor();
|
||||||
// or maybe can inject overloaded function into superclass if it doesn't cause a signature collision
|
|
||||||
assert false;
|
m.arguments = vanillaMethodToOverride.getDescriptor(); // is this right?
|
||||||
|
|
||||||
|
garbageValue = this.getGarbage(obfuscatedMethodToOverride);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This means method is overriden. It is possible that the return value is a child class
|
// This means method is overriden. It is possible that the return value is a child class
|
||||||
// of the parents overriden method, and it will still override the method however the signatures won't match,
|
// of the parents overriden method, and it will still override the method however the signatures won't match,
|
||||||
// but we don't do that.
|
// but we don't do that.
|
||||||
assert m.getDescriptor().equals(obfuscatedMethodToOverride.getDescriptor());
|
assert m.getDescriptor().equals(vanillaMethodToOverride.getDescriptor());
|
||||||
|
|
||||||
// Now that the function is overriden, when the invoke injector is called, it turns around and invokevirtuals
|
// Now that the function is overriden, when the invoke injector is called, it turns around and invokevirtuals
|
||||||
// the parent method, which hits ours.
|
// the parent method, which hits ours.
|
||||||
|
|
||||||
// locate super.method() calls and modify...
|
// locate super.method() calls and modify...
|
||||||
for (Instruction i : m.getCode().getInstructions().getInstructions())
|
for (Instruction i : new ArrayList<>(m.getCode().getInstructions().getInstructions()))
|
||||||
{
|
{
|
||||||
if (!(i instanceof InvokeSpecial))
|
if (!(i instanceof InvokeSpecial))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (originalSignature != null)
|
||||||
|
{
|
||||||
|
assert originalSignature.size() + 1 == m.getDescriptor().size();
|
||||||
|
|
||||||
|
Instructions instructions = m.getCode().getInstructions();
|
||||||
|
List<Instruction> ins = instructions.getInstructions();
|
||||||
|
Type type = m.getDescriptor().getTypeOfArg(m.getDescriptor().size() - 1);
|
||||||
|
int offset = ins.indexOf(i);
|
||||||
|
|
||||||
|
assert offset != -1;
|
||||||
|
|
||||||
|
// XXX we could maybe just pull the variable off of the lvt here, instead
|
||||||
|
// if we know we haven't overwritten it?
|
||||||
|
if (type.getArrayDims() > 0 || !type.isPrimitive())
|
||||||
|
{
|
||||||
|
ins.add(offset, new AConstNull(instructions));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (garbageValue == null)
|
||||||
|
{
|
||||||
|
garbageValue = "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type.getType())
|
||||||
|
{
|
||||||
|
case "Z":
|
||||||
|
case "B":
|
||||||
|
case "C":
|
||||||
|
ins.add(offset, new BiPush(instructions, Byte.parseByte(garbageValue)));
|
||||||
|
break;
|
||||||
|
case "S":
|
||||||
|
ins.add(offset, new SiPush(instructions, Short.parseShort(garbageValue)));
|
||||||
|
break;
|
||||||
|
case "I":
|
||||||
|
ins.add(offset, new LDC_W(instructions, Integer.parseInt(garbageValue)));
|
||||||
|
break;
|
||||||
|
case "D":
|
||||||
|
ins.add(offset, new LDC2_W(instructions, Double.parseDouble(garbageValue)));
|
||||||
|
break;
|
||||||
|
case "F":
|
||||||
|
ins.add(offset, new LDC_W(instructions, Float.parseFloat(garbageValue)));
|
||||||
|
break;
|
||||||
|
case "J":
|
||||||
|
ins.add(offset, new LDC2_W(instructions, Long.parseLong(garbageValue)));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Unknown type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
InvokeSpecial is = (InvokeSpecial) i;
|
InvokeSpecial is = (InvokeSpecial) i;
|
||||||
|
|
||||||
net.runelite.asm.pool.Method invokedMethod = (net.runelite.asm.pool.Method) is.getMethod();
|
net.runelite.asm.pool.Method invokedMethod = (net.runelite.asm.pool.Method) is.getMethod();
|
||||||
@@ -293,6 +365,60 @@ public class InjectReplace
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Method findVanillaMethodFromDeobfuscatedMethod(Method method)
|
||||||
|
{
|
||||||
|
String name = getObfuscatedName(method);
|
||||||
|
Signature sig = getObfuscatedSignature(method);
|
||||||
|
return vanilla.findMethod(name, sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getObfuscatedName(Method method)
|
||||||
|
{
|
||||||
|
Annotations an = method.getAttributes().getAnnotations();
|
||||||
|
if (an == null)
|
||||||
|
return method.getName();
|
||||||
|
|
||||||
|
Annotation a = an.find(OBFUSCATED_NAME);
|
||||||
|
if (a == null)
|
||||||
|
return method.getName();
|
||||||
|
|
||||||
|
return a.getElement().getString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Signature getObfuscatedSignature(Method method)
|
||||||
|
{
|
||||||
|
Annotations an = method.getAttributes().getAnnotations();
|
||||||
|
if (an == null)
|
||||||
|
{
|
||||||
|
return method.getDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
|
Annotation obSig = an.find(OBFUSCATED_SIGNATURE);
|
||||||
|
if (obSig == null)
|
||||||
|
{
|
||||||
|
return method.getDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Signature(obSig.getElement().getString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getGarbage(Method method)
|
||||||
|
{
|
||||||
|
Annotations an = method.getAttributes().getAnnotations();
|
||||||
|
if (an == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Annotation obSig = an.find(OBFUSCATED_SIGNATURE);
|
||||||
|
if (obSig == null || obSig.getElements().size() < 2)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return obSig.getElements().get(1).getString();
|
||||||
|
}
|
||||||
|
|
||||||
private void replaceSuperclass(ClassFile classToInject)
|
private void replaceSuperclass(ClassFile classToInject)
|
||||||
{
|
{
|
||||||
for (ClassFile cf : vanilla.getGroup().getClasses())
|
for (ClassFile cf : vanilla.getGroup().getClasses())
|
||||||
@@ -382,6 +508,9 @@ public class InjectReplace
|
|||||||
InvokeSpecial is = (InvokeSpecial) i;
|
InvokeSpecial is = (InvokeSpecial) i;
|
||||||
net.runelite.asm.pool.Method method = (net.runelite.asm.pool.Method) is.getMethod();
|
net.runelite.asm.pool.Method method = (net.runelite.asm.pool.Method) is.getMethod();
|
||||||
|
|
||||||
|
if (!method.getNameAndType().getName().equals("<init>") || !method.getClassEntry().equals(vanilla.getPoolClass()))
|
||||||
|
continue;
|
||||||
|
|
||||||
is.setMethod(new net.runelite.asm.pool.Method(
|
is.setMethod(new net.runelite.asm.pool.Method(
|
||||||
classToInject.getPoolClass(),
|
classToInject.getPoolClass(),
|
||||||
method.getNameAndType()
|
method.getNameAndType()
|
||||||
|
|||||||
27
src/main/java/net/runelite/inject/RSCanvas.java
Normal file
27
src/main/java/net/runelite/inject/RSCanvas.java
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package net.runelite.inject;
|
||||||
|
|
||||||
|
import java.awt.Canvas;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
|
public abstract class RSCanvas extends Canvas
|
||||||
|
{
|
||||||
|
private final BufferedImage clientBuffer = new BufferedImage(756, 503, BufferedImage.TYPE_INT_RGB);
|
||||||
|
private final BufferedImage gameBuffer = new BufferedImage(756, 503, BufferedImage.TYPE_INT_RGB);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Graphics getGraphics()
|
||||||
|
{
|
||||||
|
Graphics clientGraphics = clientBuffer.getGraphics();
|
||||||
|
clientGraphics.drawImage(gameBuffer, 0, 0, null);
|
||||||
|
//clientGraphics.dispose();
|
||||||
|
|
||||||
|
//clientGraphics = clientBuffer.getGraphics();
|
||||||
|
clientGraphics.drawString("something, something", 42, 42);
|
||||||
|
|
||||||
|
Graphics superGraphics = super.getGraphics();
|
||||||
|
superGraphics.drawImage(clientBuffer, 0, 0, null);
|
||||||
|
|
||||||
|
return gameBuffer.getGraphics();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user