project: Injector and mixins

This commit is contained in:
Owain van Brakel
2021-12-15 05:39:57 +01:00
parent 62a5942180
commit 6b133497df
30 changed files with 530 additions and 168 deletions

View File

@@ -13,6 +13,7 @@ import static com.openosrs.injector.rsapi.RSApi.RL_API_BASE;
import com.openosrs.injector.rsapi.RSApiClass;
import com.openosrs.injector.rsapi.RSApiMethod;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -340,6 +341,11 @@ public interface InjectUtil
}
static Type apiToDeob(InjectData data, Type api)
{
return apiToDeob(data, api, null);
}
static Type apiToDeob(InjectData data, Type api, Type deobType)
{
if (api.isPrimitive())
{
@@ -354,29 +360,43 @@ public interface InjectUtil
else if (internalName.startsWith(RL_API_BASE))
{
Class rlApiC = new Class(internalName);
RSApiClass highestKnown = data.getRsApi().withInterface(rlApiC);
Set<RSApiClass> allClasses = data.getRsApi().withInterface(rlApiC);
// Cheeky unchecked exception
assert highestKnown != null : "No rs api class implements rl api class " + rlApiC.toString();
assert allClasses.size() > 0 : "No rs api class implements rl api class " + rlApiC.toString();
boolean changed;
do
if (allClasses.size() == 1)
{
changed = false;
for (RSApiClass interf : highestKnown.getApiInterfaces())
RSApiClass highestKnown = allClasses.stream().findFirst().get();
boolean changed;
do
{
if (interf.getInterfaces().contains(rlApiC))
changed = false;
for (RSApiClass interf : highestKnown.getApiInterfaces())
{
highestKnown = interf;
changed = true;
break;
if (interf.getInterfaces().contains(rlApiC))
{
highestKnown = interf;
changed = true;
break;
}
}
}
while (changed);
return apiToDeob(data, Type.getType(highestKnown.getName(), api.getDimensions()));
}
else
{
for (RSApiClass rsApiClass : allClasses)
{
if (rsApiClass.getName().contains(deobType.getInternalName()))
{
return apiToDeob(data, Type.getType(rsApiClass.getName(), api.getDimensions()));
}
}
}
while (changed);
return apiToDeob(data, Type.getType(highestKnown.getName(), api.getDimensions()));
}
return api;

View File

@@ -23,7 +23,7 @@ import com.openosrs.injector.injectors.raw.Occluder;
import com.openosrs.injector.injectors.raw.RasterizerAlpha;
import com.openosrs.injector.injectors.raw.RenderDraw;
import com.openosrs.injector.injectors.raw.CopyRuneLiteClasses;
import com.openosrs.injector.injectors.raw.RuneLiteIterableHashTable;
import com.openosrs.injector.injectors.raw.RuneLiteIterables;
import com.openosrs.injector.injectors.raw.RuneliteObject;
import com.openosrs.injector.injectors.raw.ScriptVM;
import com.openosrs.injector.rsapi.RSApi;
@@ -117,7 +117,7 @@ public class Injector extends InjectData implements InjectTaskHandler
inject(new CopyRuneLiteClasses(this));
inject(new RuneLiteIterableHashTable(this));
inject(new RuneLiteIterables(this));
inject(new RuneliteObject(this));

View File

@@ -131,7 +131,7 @@ public class RSApiInjector extends AbstractInjector
}
else if (sig.size() == 0)
{
Type type = InjectUtil.apiToDeob(inject, sig.getReturnValue());
Type type = InjectUtil.apiToDeob(inject, sig.getReturnValue(), deobType);
if (deobType.equals(type))
{
continue;

View File

@@ -19,6 +19,7 @@ import net.runelite.asm.Type;
import net.runelite.asm.attributes.Code;
import net.runelite.asm.attributes.code.Instruction;
import net.runelite.asm.attributes.code.Instructions;
import net.runelite.asm.attributes.code.instructions.CheckCast;
import net.runelite.asm.attributes.code.instructions.GetField;
import net.runelite.asm.attributes.code.instructions.GetStatic;
import net.runelite.asm.attributes.code.instructions.InvokeSpecial;
@@ -35,7 +36,9 @@ public class CopyRuneLiteClasses extends AbstractInjector
{
private static final List<String> RUNELITE_OBJECTS = List.of(
"RuneLiteObject",
"RuneLiteIterableHashTable"
"RuneLiteIterableLinkDeque",
"RuneLiteIterableNodeDeque",
"RuneLiteIterableNodeHashTable"
);
public CopyRuneLiteClasses(InjectData inject)

View File

@@ -1,61 +0,0 @@
/*
* Copyright (c) 2021, Owain van Brakel <https://github.com/Owain94>
* All rights reserved.
*
* This code is licensed under GPL3, see the complete license in
* the LICENSE file in the root directory of this submodule.
*/
package com.openosrs.injector.injectors.raw;
import com.openosrs.injector.injection.InjectData;
import com.openosrs.injector.injectors.AbstractInjector;
import java.util.List;
import net.runelite.asm.ClassFile;
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.instructions.ALoad;
import net.runelite.asm.attributes.code.instructions.Dup;
import net.runelite.asm.attributes.code.instructions.InvokeSpecial;
import net.runelite.asm.attributes.code.instructions.New;
import net.runelite.asm.attributes.code.instructions.Return;
import net.runelite.asm.signature.Signature;
public class RuneLiteIterableHashTable extends AbstractInjector
{
private static final String RUNELITE_ITERABLE_HASHTABLE = "RuneLiteIterableHashTable";
public RuneLiteIterableHashTable(InjectData inject)
{
super(inject);
}
public void inject()
{
ClassFile runeliteIterableHashTableVanilla = inject.vanilla.findClass(RUNELITE_ITERABLE_HASHTABLE);
final ClassFile nodeHashTableVanilla = inject.toVanilla(
inject.getDeobfuscated()
.findClass("NodeHashTable")
);
Method copy = new Method(nodeHashTableVanilla, "iterator", new Signature("()Ljava/util/Iterator;"));
copy.setPublic();
final Code code = new Code(copy);
code.setMaxStack(3);
copy.setCode(code);
nodeHashTableVanilla.addMethod(copy);
final Instructions instructions = code.getInstructions();
final List<Instruction> ins = instructions.getInstructions();
ins.add(new New(instructions, runeliteIterableHashTableVanilla.getPoolClass()));
ins.add(new Dup(instructions));
ins.add(new ALoad(instructions, 0));
ins.add(new InvokeSpecial(instructions, new net.runelite.asm.pool.Method(runeliteIterableHashTableVanilla.getPoolClass(), "<init>", new Signature("(L" + nodeHashTableVanilla.getName() + ";)V"))));
ins.add(new Return(instructions, InstructionType.ARETURN));
}
}

View File

@@ -0,0 +1,124 @@
/*
* Copyright (c) 2021, Owain van Brakel <https://github.com/Owain94>
* All rights reserved.
*
* This code is licensed under GPL3, see the complete license in
* the LICENSE file in the root directory of this submodule.
*/
package com.openosrs.injector.injectors.raw;
import com.openosrs.injector.injection.InjectData;
import com.openosrs.injector.injectors.AbstractInjector;
import java.util.List;
import net.runelite.asm.ClassFile;
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.instructions.ALoad;
import net.runelite.asm.attributes.code.instructions.Dup;
import net.runelite.asm.attributes.code.instructions.InvokeSpecial;
import net.runelite.asm.attributes.code.instructions.New;
import net.runelite.asm.attributes.code.instructions.Return;
import net.runelite.asm.signature.Signature;
public class RuneLiteIterables extends AbstractInjector
{
private static final String RUNELITE_ITERABLE_HASHTABLE = "RuneLiteIterableNodeHashTable";
private static final String RUNELITE_ITERABLE_NODE_DEQUE = "RuneLiteIterableNodeDeque";
private static final String RUNELITE_ITERABLE_LINK_DEQUE = "RuneLiteIterableLinkDeque";
public RuneLiteIterables(InjectData inject)
{
super(inject);
}
public void inject()
{
injectHashTable();
injectNodeDeque();
injectLinkDeque();
}
public void injectHashTable()
{
ClassFile runeliteIterableHashTableVanilla = inject.vanilla.findClass(RUNELITE_ITERABLE_HASHTABLE);
final ClassFile nodeHashTableVanilla = inject.toVanilla(
inject.getDeobfuscated()
.findClass(RUNELITE_ITERABLE_HASHTABLE.replace("RuneLiteIterable", ""))
);
Method copy = new Method(nodeHashTableVanilla, "iterator", new Signature("()Ljava/util/Iterator;"));
copy.setPublic();
final Code code = new Code(copy);
code.setMaxStack(3);
copy.setCode(code);
nodeHashTableVanilla.addMethod(copy);
final Instructions instructions = code.getInstructions();
final List<Instruction> ins = instructions.getInstructions();
ins.add(new New(instructions, runeliteIterableHashTableVanilla.getPoolClass()));
ins.add(new Dup(instructions));
ins.add(new ALoad(instructions, 0));
ins.add(new InvokeSpecial(instructions, new net.runelite.asm.pool.Method(runeliteIterableHashTableVanilla.getPoolClass(), "<init>", new Signature("(L" + nodeHashTableVanilla.getName() + ";)V"))));
ins.add(new Return(instructions, InstructionType.ARETURN));
}
public void injectNodeDeque()
{
ClassFile runeliteIterableNodeDequeVanilla = inject.vanilla.findClass(RUNELITE_ITERABLE_NODE_DEQUE);
final ClassFile nodeDequeVanilla = inject.toVanilla(
inject.getDeobfuscated()
.findClass(RUNELITE_ITERABLE_NODE_DEQUE.replace("RuneLiteIterable", ""))
);
Method copy = new Method(nodeDequeVanilla, "iterator", new Signature("()Ljava/util/Iterator;"));
copy.setPublic();
final Code code = new Code(copy);
code.setMaxStack(3);
copy.setCode(code);
nodeDequeVanilla.addMethod(copy);
final Instructions instructions = code.getInstructions();
final List<Instruction> ins = instructions.getInstructions();
ins.add(new New(instructions, runeliteIterableNodeDequeVanilla.getPoolClass()));
ins.add(new Dup(instructions));
ins.add(new ALoad(instructions, 0));
ins.add(new InvokeSpecial(instructions, new net.runelite.asm.pool.Method(runeliteIterableNodeDequeVanilla.getPoolClass(), "<init>", new Signature("(L" + nodeDequeVanilla.getName() + ";)V"))));
ins.add(new Return(instructions, InstructionType.ARETURN));
}
public void injectLinkDeque()
{
ClassFile runeliteIterableLinkDequeVanilla = inject.vanilla.findClass(RUNELITE_ITERABLE_LINK_DEQUE);
final ClassFile linkDequeVanilla = inject.toVanilla(
inject.getDeobfuscated()
.findClass(RUNELITE_ITERABLE_LINK_DEQUE.replace("RuneLiteIterable", ""))
);
Method copy = new Method(linkDequeVanilla, "iterator", new Signature("()Ljava/util/Iterator;"));
copy.setPublic();
final Code code = new Code(copy);
code.setMaxStack(3);
copy.setCode(code);
linkDequeVanilla.addMethod(copy);
final Instructions instructions = code.getInstructions();
final List<Instruction> ins = instructions.getInstructions();
ins.add(new New(instructions, runeliteIterableLinkDequeVanilla.getPoolClass()));
ins.add(new Dup(instructions));
ins.add(new ALoad(instructions, 0));
ins.add(new InvokeSpecial(instructions, new net.runelite.asm.pool.Method(runeliteIterableLinkDequeVanilla.getPoolClass(), "<init>", new Signature("(L" + linkDequeVanilla.getName() + ";)V"))));
ins.add(new Return(instructions, InstructionType.ARETURN));
}
}

View File

@@ -15,8 +15,10 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import lombok.Getter;
import lombok.NoArgsConstructor;
import net.runelite.asm.Type;
@@ -111,23 +113,19 @@ public class RSApi implements Iterable<RSApiClass>
return findClass(name) != null;
}
public RSApiClass withInterface(Class interf)
public Set<RSApiClass> withInterface(Class interf)
{
RSApiClass clazz = findClass(interf.getName());
if (clazz != null)
{
return clazz;
}
Set<RSApiClass> classes = new HashSet<>();
for (RSApiClass apiC : this)
{
if (apiC.getInterfaces().contains(interf))
{
return apiC;
classes.add(apiC);
}
}
return null;
return classes;
}
@NotNull