Update injector for new Annotations

cleanup mixininjector kinda
change replaced methods to just ldc the garbage
make rsapi objects extend their respective visitors
This commit is contained in:
Lucwousin
2020-07-19 03:14:27 +02:00
parent e7d62c3c33
commit 3a66a43986
22 changed files with 165 additions and 233 deletions

View File

@@ -15,10 +15,10 @@ plugins {
id("se.patrikerdes.use-latest-versions") version "0.2.14" id("se.patrikerdes.use-latest-versions") version "0.2.14"
} }
val oprsver = "3.3.1" val oprsver = "3.4.0"
group = "com.openosrs" group = "com.openosrs"
version = "1.1.4" version = "1.1.5"
repositories { repositories {
mavenCentral() mavenCentral()

View File

@@ -14,14 +14,14 @@ import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import net.runelite.asm.Annotated; import net.runelite.asm.Annotation;
import net.runelite.asm.ClassFile; import net.runelite.asm.ClassFile;
import net.runelite.asm.ClassGroup; import net.runelite.asm.ClassGroup;
import net.runelite.asm.Field; import net.runelite.asm.Field;
import net.runelite.asm.Method; import net.runelite.asm.Method;
import net.runelite.asm.Named; import net.runelite.asm.Named;
import net.runelite.asm.Type; import net.runelite.asm.Type;
import net.runelite.asm.attributes.annotation.Annotation; import net.runelite.asm.attributes.Annotated;
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;
@@ -368,8 +368,8 @@ public interface InjectUtil
*/ */
static <T extends Annotated & Named> String getObfuscatedName(T from) static <T extends Annotated & Named> String getObfuscatedName(T from)
{ {
Annotation name = from.getAnnotations().find(DeobAnnotations.OBFUSCATED_NAME); Annotation name = from.findAnnotation(DeobAnnotations.OBFUSCATED_NAME);
return name == null ? from.getName() : name.getElement().getString(); return name == null ? from.getName() : name.getValueString();
} }
/** /**
@@ -377,8 +377,8 @@ public interface InjectUtil
*/ */
static String getExportedName(Annotated from) static String getExportedName(Annotated from)
{ {
Annotation export = from.getAnnotations().find(DeobAnnotations.EXPORT); Annotation export = from.findAnnotation(DeobAnnotations.EXPORT);
return export == null ? null : export.getElement().getString(); return export == null ? null : export.getValueString();
} }
/** /**
@@ -450,7 +450,7 @@ public interface InjectUtil
*/ */
static ClassFile getVanillaClassFromAnnotationString(InjectData data, Annotation annotation) static ClassFile getVanillaClassFromAnnotationString(InjectData data, Annotation annotation)
{ {
Object v = annotation.getElement().getValue(); Object v = annotation.getValue();
String str = ((org.objectweb.asm.Type) v).getInternalName(); String str = ((org.objectweb.asm.Type) v).getInternalName();
return data.toVanilla(data.toDeob(str)); return data.toVanilla(data.toDeob(str));
} }

View File

@@ -36,10 +36,10 @@ import com.openosrs.injector.injection.InjectData;
import com.openosrs.injector.rsapi.RSApiMethod; import com.openosrs.injector.rsapi.RSApiMethod;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import net.runelite.asm.Annotation;
import net.runelite.asm.ClassFile; import net.runelite.asm.ClassFile;
import net.runelite.asm.Type; import net.runelite.asm.Type;
import net.runelite.asm.attributes.Code; import net.runelite.asm.attributes.Code;
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.Instructions; import net.runelite.asm.attributes.code.Instructions;
import net.runelite.asm.attributes.code.instructions.CheckCast; import net.runelite.asm.attributes.code.instructions.CheckCast;
@@ -67,7 +67,7 @@ public class InjectConstruct extends AbstractInjector
{ {
for (RSApiMethod apiMethod : inject.getRsApi().getConstructs()) for (RSApiMethod apiMethod : inject.getRsApi().getConstructs())
{ {
Annotation construct = apiMethod.getAnnotations().find(CONSTRUCT); Annotation construct = apiMethod.findAnnotation(CONSTRUCT);
if (construct == null) if (construct == null)
continue; continue;

View File

@@ -40,12 +40,12 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.inject.Provider; import javax.inject.Provider;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import net.runelite.asm.Annotation;
import net.runelite.asm.ClassFile; import net.runelite.asm.ClassFile;
import net.runelite.asm.Field; import net.runelite.asm.Field;
import net.runelite.asm.Method; import net.runelite.asm.Method;
import net.runelite.asm.Type; import net.runelite.asm.Type;
import net.runelite.asm.attributes.Code; import net.runelite.asm.attributes.Code;
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;
@@ -101,14 +101,12 @@ public class InjectHook extends AbstractInjector
{ {
for (Method mixinMethod : mixinClass.getMethods()) for (Method mixinMethod : mixinClass.getMethods())
{ {
final Annotation fieldHook = mixinMethod.getAnnotations().find(FIELDHOOK); final Annotation fieldHook = mixinMethod.findAnnotation(FIELDHOOK);
if (fieldHook == null) if (fieldHook == null)
{
continue; continue;
}
final String hookName = fieldHook.getElement().getString(); final String hookName = fieldHook.getValueString();
final boolean before = fieldHook.getElements().size() == 2 && fieldHook.getElements().get(1).getValue().equals(true); final boolean before = isBefore(fieldHook);
final ClassFile deobTarget = inject.toDeob(targetClass.getName()); final ClassFile deobTarget = inject.toDeob(targetClass.getName());
final Field deobField; final Field deobField;
@@ -361,4 +359,10 @@ public class InjectHook extends AbstractInjector
); );
} }
} }
private static boolean isBefore(Annotation a)
{
Object val = a.get("before");
return val instanceof Boolean && (Boolean) val;
}
} }

View File

@@ -37,10 +37,10 @@ import java.util.List;
import java.util.ListIterator; import java.util.ListIterator;
import java.util.Map; import java.util.Map;
import javax.inject.Provider; import javax.inject.Provider;
import net.runelite.asm.Annotation;
import net.runelite.asm.ClassFile; import net.runelite.asm.ClassFile;
import net.runelite.asm.Method; import net.runelite.asm.Method;
import net.runelite.asm.Type; import net.runelite.asm.Type;
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.Instructions; import net.runelite.asm.attributes.code.Instructions;
import net.runelite.asm.attributes.code.instruction.types.ReturnInstruction; import net.runelite.asm.attributes.code.instruction.types.ReturnInstruction;
@@ -78,15 +78,15 @@ public class InjectHookMethod extends AbstractInjector
{ {
for (Method mixinMethod : mixinClass.getMethods()) for (Method mixinMethod : mixinClass.getMethods())
{ {
final Annotation methodHook = mixinMethod.getAnnotations().find(METHODHOOK); final Annotation methodHook = mixinMethod.findAnnotation(METHODHOOK);
if (methodHook == null) if (methodHook == null)
continue; continue;
if (!mixinMethod.getDescriptor().isVoid()) if (!mixinMethod.getDescriptor().isVoid())
throw new InjectException("Method hook " + mixinMethod.getPoolMethod() + " doesn't have void return type"); throw new InjectException("Method hook " + mixinMethod.getPoolMethod() + " doesn't have void return type");
final String hookName = methodHook.getElement().getString(); final String hookName = methodHook.getValueString();
final boolean end = methodHook.getElements().size() == 2 && methodHook.getElements().get(1).getValue().equals(true); final boolean end = isEnd(methodHook);
final ClassFile deobTarget = inject.toDeob(targetClass.getName()); final ClassFile deobTarget = inject.toDeob(targetClass.getName());
final Signature deobSig = InjectUtil.apiToDeob(inject, mixinMethod.getDescriptor()); final Signature deobSig = InjectUtil.apiToDeob(inject, mixinMethod.getDescriptor());
@@ -164,4 +164,10 @@ public class InjectHookMethod extends AbstractInjector
) )
); );
} }
private static boolean isEnd(Annotation annotation)
{
Object val = annotation.get("end");
return val instanceof Boolean && (Boolean) val;
}
} }

View File

@@ -31,7 +31,6 @@
package com.openosrs.injector.injectors; package com.openosrs.injector.injectors;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.openosrs.injector.InjectException; import com.openosrs.injector.InjectException;
import com.openosrs.injector.InjectUtil; import com.openosrs.injector.InjectUtil;
@@ -41,15 +40,17 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.ListIterator; import java.util.ListIterator;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.inject.Provider; import javax.inject.Provider;
import lombok.AllArgsConstructor; import lombok.Value;
import net.runelite.asm.Annotation;
import net.runelite.asm.ClassFile; import net.runelite.asm.ClassFile;
import net.runelite.asm.Field; import net.runelite.asm.Field;
import net.runelite.asm.Method; import net.runelite.asm.Method;
import net.runelite.asm.Type; import net.runelite.asm.Type;
import net.runelite.asm.attributes.Annotated;
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.ArrayElement;
import net.runelite.asm.attributes.code.Instruction; import net.runelite.asm.attributes.code.Instruction;
import net.runelite.asm.attributes.code.Instructions; import net.runelite.asm.attributes.code.Instructions;
import net.runelite.asm.attributes.code.instruction.types.FieldInstruction; import net.runelite.asm.attributes.code.instruction.types.FieldInstruction;
@@ -63,10 +64,10 @@ import net.runelite.asm.attributes.code.instructions.ALoad;
import net.runelite.asm.attributes.code.instructions.ANewArray; import net.runelite.asm.attributes.code.instructions.ANewArray;
import net.runelite.asm.attributes.code.instructions.CheckCast; import net.runelite.asm.attributes.code.instructions.CheckCast;
import net.runelite.asm.attributes.code.instructions.GetField; import net.runelite.asm.attributes.code.instructions.GetField;
import net.runelite.asm.attributes.code.instructions.ILoad;
import net.runelite.asm.attributes.code.instructions.InvokeDynamic; import net.runelite.asm.attributes.code.instructions.InvokeDynamic;
import net.runelite.asm.attributes.code.instructions.InvokeSpecial; import net.runelite.asm.attributes.code.instructions.InvokeSpecial;
import net.runelite.asm.attributes.code.instructions.InvokeStatic; import net.runelite.asm.attributes.code.instructions.InvokeStatic;
import net.runelite.asm.attributes.code.instructions.LDC;
import net.runelite.asm.attributes.code.instructions.Pop; import net.runelite.asm.attributes.code.instructions.Pop;
import net.runelite.asm.attributes.code.instructions.PutField; import net.runelite.asm.attributes.code.instructions.PutField;
import net.runelite.asm.signature.Signature; import net.runelite.asm.signature.Signature;
@@ -137,48 +138,11 @@ public class MixinInjector extends AbstractInjector
for (ClassFile mixinClass : inject.getMixins()) for (ClassFile mixinClass : inject.getMixins())
{ {
for (Annotation annotation : mixinClass.getAnnotations()) final List<ClassFile> ret = getMixins(mixinClass);
{ builder.put(
// If there's multiple mixins we gotta create new copies of the classfiles (ret.size() > 1 ? mixinProvider(mixinClass) : () -> mixinClass),
// to make sure we aren't changing code in all classes at once ret
if (MIXIN.equals(annotation.getType())) );
{
builder.put(
() -> mixinClass,
ImmutableList.of(InjectUtil.getVanillaClassFromAnnotationString(inject, annotation))
);
}
else if (MIXINS.equals(annotation.getType()))
{
final Provider<ClassFile>mixinProvider = new Provider<ClassFile>()
{
byte[] bytes = null;
@Override
public ClassFile get()
{
if (bytes != null)
return JarUtil.loadClass(bytes);
bytes = JarUtil.writeClass(mixinClass.getGroup(), mixinClass);
return mixinClass;
}
};
assert annotation.getElement() instanceof ArrayElement;
ArrayElement arr = (ArrayElement) annotation.getElement();
ImmutableList.Builder<ClassFile> b = ImmutableList.builder();
for (Object ob : arr)
{
assert ob instanceof Annotation;
b.add(InjectUtil.getVanillaClassFromAnnotationString(inject, (Annotation) ob));
}
builder.put(mixinProvider, b.build());
}
}
} }
return builder.build(); return builder.build();
@@ -192,9 +156,8 @@ public class MixinInjector extends AbstractInjector
{ {
for (Field field : mixinClass.getFields()) for (Field field : mixinClass.getFields())
{ {
if (field.getAnnotations().find(INJECT) == null && if (field.findAnnotation(INJECT) == null &&
(!ASSERTION_FIELD.equals(field.getName()) || (!ASSERTION_FIELD.equals(field.getName()) || targetClass.findField(ASSERTION_FIELD, Type.BOOLEAN) != null))
targetClass.findField(ASSERTION_FIELD, Type.BOOLEAN) != null))
{ {
continue; continue;
} }
@@ -204,9 +167,9 @@ public class MixinInjector extends AbstractInjector
copy.setPublic(); copy.setPublic();
copy.setValue(field.getValue()); copy.setValue(field.getValue());
for (Annotation annotation : field.getAnnotations()) for (Map.Entry<Type, Annotation> e : field.getAnnotations().entrySet())
if (!annotation.getType().toString().startsWith("Lnet/runelite/api/mixins")) if (!e.getKey().toString().startsWith("Lnet/runelite/api/mixins"))
copy.getAnnotations().addAnnotation(annotation); copy.addAnnotation(e.getValue());
targetClass.addField(copy); targetClass.addField(copy);
@@ -224,7 +187,7 @@ public class MixinInjector extends AbstractInjector
for (final Field field : mixinClass.getFields()) for (final Field field : mixinClass.getFields())
{ {
Annotation shadow = field.getAnnotations().find(SHADOW); Annotation shadow = field.findAnnotation(SHADOW);
if (shadow == null) if (shadow == null)
continue; continue;
@@ -232,7 +195,7 @@ public class MixinInjector extends AbstractInjector
if (!field.isStatic()) if (!field.isStatic())
throw new InjectException("Shadowed fields must be static"); throw new InjectException("Shadowed fields must be static");
String shadowed = shadow.getElement().getString(); String shadowed = shadow.getValueString();
Field targetField = injectedFields.get(shadowed); Field targetField = injectedFields.get(shadowed);
Number getter = null; Number getter = null;
@@ -267,11 +230,11 @@ public class MixinInjector extends AbstractInjector
// Handle the copy mixins first, so all other mixins know of the copies // Handle the copy mixins first, so all other mixins know of the copies
for (Method mixinMethod : mixinClass.getMethods()) for (Method mixinMethod : mixinClass.getMethods())
{ {
Annotation copyA = mixinMethod.getAnnotations().find(COPY); Annotation copyA = mixinMethod.findAnnotation(COPY);
if (copyA == null) if (copyA == null)
continue; continue;
String copiedName = copyA.getValueString();
String copiedName = copyA.getElement().getString();
Signature deobSig = InjectUtil.apiToDeob(inject, mixinMethod.getDescriptor()); Signature deobSig = InjectUtil.apiToDeob(inject, mixinMethod.getDescriptor());
boolean notStat = !mixinMethod.isStatic(); boolean notStat = !mixinMethod.isStatic();
@@ -291,7 +254,8 @@ public class MixinInjector extends AbstractInjector
copy.setAccessFlags(sourceMethod.getAccessFlags()); copy.setAccessFlags(sourceMethod.getAccessFlags());
copy.setPublic(); copy.setPublic();
copy.getExceptions().getExceptions().addAll(sourceMethod.getExceptions().getExceptions()); copy.getExceptions().getExceptions().addAll(sourceMethod.getExceptions().getExceptions());
copy.getAnnotations().getAnnotations().addAll(sourceMethod.getAnnotations().getAnnotations()); for (var a : sourceMethod.getAnnotations().values())
copy.addAnnotation(a);
targetClass.addMethod(copy); targetClass.addMethod(copy);
++copied; ++copied;
@@ -303,7 +267,7 @@ public class MixinInjector extends AbstractInjector
boolean hasGarbageValue = mixinMethod.getDescriptor().size() != sourceMethod.getDescriptor().size() boolean hasGarbageValue = mixinMethod.getDescriptor().size() != sourceMethod.getDescriptor().size()
&& deobSourceMethod.getDescriptor().size() < copy.getDescriptor().size(); && deobSourceMethod.getDescriptor().size() < copy.getDescriptor().size();
copiedMethods.put(mixinMethod.getPoolMethod(), new CopiedMethod(copy, hasGarbageValue)); copiedMethods.put(mixinMethod.getPoolMethod(), new CopiedMethod(copy, !hasGarbageValue ? null : Integer.valueOf(DeobAnnotations.getDecoder(deobSourceMethod))));
} }
// Handle the rest of the mixin types // Handle the rest of the mixin types
@@ -311,7 +275,7 @@ public class MixinInjector extends AbstractInjector
{ {
boolean isClinit = "<clinit>".equals(mixinMethod.getName()); boolean isClinit = "<clinit>".equals(mixinMethod.getName());
boolean isInit = "<init>".equals(mixinMethod.getName()); boolean isInit = "<init>".equals(mixinMethod.getName());
boolean hasInject = mixinMethod.getAnnotations().find(INJECT) != null; boolean hasInject = mixinMethod.findAnnotation(INJECT) != null;
// You can't annotate clinit, so its always injected // You can't annotate clinit, so its always injected
if ((hasInject && isInit) || isClinit) if ((hasInject && isInit) || isClinit)
@@ -345,7 +309,7 @@ public class MixinInjector extends AbstractInjector
{ {
Instructions instructions = copy.getCode().getInstructions(); Instructions instructions = copy.getCode().getInstructions();
ListIterator<Instruction> listIter = instructions.listIterator(); ListIterator<Instruction> listIter = instructions.listIterator();
for (; listIter.hasNext(); ) while (listIter.hasNext())
{ {
Instruction instr = listIter.next(); Instruction instr = listIter.next();
if (instr instanceof InvokeSpecial) if (instr instanceof InvokeSpecial)
@@ -424,10 +388,10 @@ public class MixinInjector extends AbstractInjector
log.debug("[DEBUG] Injected mixin method {} to {}", copy, targetClass); log.debug("[DEBUG] Injected mixin method {} to {}", copy, targetClass);
++injected; ++injected;
} }
else if (mixinMethod.getAnnotations().find(REPLACE) != null) else if (mixinMethod.findAnnotation(REPLACE) != null)
{ {
Annotation replaceAnnotation = mixinMethod.getAnnotations().find(REPLACE); Annotation replaceAnnotation = mixinMethod.findAnnotation(REPLACE);
String replacedName = (String) replaceAnnotation.getElement().getValue(); String replacedName = replaceAnnotation.getValueString();
ClassFile deobClass = inject.toDeob(targetClass.getName()); ClassFile deobClass = inject.toDeob(targetClass.getName());
Method deobMethod = findDeobMatching(deobClass, mixinMethod, replacedName); Method deobMethod = findDeobMatching(deobClass, mixinMethod, replacedName);
@@ -559,17 +523,13 @@ public class MixinInjector extends AbstractInjector
CopiedMethod copiedMethod = copiedMethods.get(ii.getMethod()); CopiedMethod copiedMethod = copiedMethods.get(ii.getMethod());
if (copiedMethod != null) if (copiedMethod != null)
{ {
ii.setMethod(copiedMethod.obMethod.getPoolMethod()); ii.setMethod(copiedMethod.copy.getPoolMethod());
// Pass through garbage value if the method has one // Pass through garbage value if the method has one
if (copiedMethod.hasGarbageValue) if (copiedMethod.garbage != null)
{ {
int garbageIndex = copiedMethod.obMethod.isStatic()
? copiedMethod.obMethod.getDescriptor().size() - 1
: copiedMethod.obMethod.getDescriptor().size();
iterator.previous(); iterator.previous();
iterator.add(new ILoad(method.getCode().getInstructions(), garbageIndex)); iterator.add(new LDC(method.getCode().getInstructions(), copiedMethod.garbage));
iterator.next(); iterator.next();
} }
} }
@@ -697,19 +657,53 @@ public class MixinInjector extends AbstractInjector
} }
} }
@AllArgsConstructor @SuppressWarnings("unchecked")
private List<ClassFile> getMixins(Annotated from)
{
final Annotation mixin = from.findAnnotation(MIXIN);
if (mixin != null)
{
return List.of(InjectUtil.getVanillaClassFromAnnotationString(inject, mixin));
}
final Annotation mixins = from.findAnnotation(MIXINS);
if (mixins != null)
{
return ((List<Annotation>) mixins.getValue()).stream()
.map(mix -> InjectUtil.getVanillaClassFromAnnotationString(inject, mix))
.collect(Collectors.toUnmodifiableList());
}
throw new IllegalArgumentException("No MIXIN or MIXINS found on " + from.toString());
}
@Value
private static class CopiedMethod private static class CopiedMethod
{ {
private Method obMethod; @Nonnull Method copy;
private boolean hasGarbageValue; @Nullable Integer garbage;
} }
@AllArgsConstructor @Value
private static class ShadowField private static class ShadowField
{ {
private Field targetField; @Nonnull Field targetField;
@Nullable Number obfuscatedGetter;
}
@Nullable private static Provider<ClassFile> mixinProvider(ClassFile mixin)
private Number obfuscatedGetter; {
return new Provider<>()
{
byte[] bytes = null;
@Override
public ClassFile get()
{
if (bytes != null)
return JarUtil.loadClass(bytes);
bytes = JarUtil.writeClass(mixin.getGroup(), mixin);
return mixin;
}
};
} }
} }

View File

@@ -43,11 +43,11 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.ListIterator; import java.util.ListIterator;
import java.util.Map; import java.util.Map;
import net.runelite.asm.Annotated;
import net.runelite.asm.ClassFile; import net.runelite.asm.ClassFile;
import net.runelite.asm.Field; import net.runelite.asm.Field;
import net.runelite.asm.Method; import net.runelite.asm.Method;
import net.runelite.asm.Type; import net.runelite.asm.Type;
import net.runelite.asm.attributes.Annotated;
import net.runelite.asm.signature.Signature; import net.runelite.asm.signature.Signature;
import net.runelite.deob.DeobAnnotations; import net.runelite.deob.DeobAnnotations;
import static com.openosrs.injector.rsapi.RSApi.API_BASE; import static com.openosrs.injector.rsapi.RSApi.API_BASE;

View File

@@ -53,10 +53,7 @@ public class RSApi implements Iterable<RSApiClass>
final RSApiClass apiClass = new RSApiClass(); final RSApiClass apiClass = new RSApiClass();
reader.accept( reader.accept(apiClass, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
new RSApiClassVisitor(apiClass),
ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES
);
this.classes.add(apiClass); this.classes.add(apiClass);
} }

View File

@@ -12,18 +12,22 @@ import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import lombok.Data; import lombok.Getter;
import net.runelite.asm.attributes.Annotations; import lombok.Setter;
import net.runelite.asm.attributes.annotation.Annotation; import net.runelite.asm.Annotation;
import net.runelite.asm.pool.Class; import net.runelite.asm.pool.Class;
import net.runelite.asm.pool.Method; import net.runelite.asm.pool.Method;
import net.runelite.asm.signature.Signature; import net.runelite.asm.signature.Signature;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import static com.openosrs.injector.rsapi.RSApi.CONSTRUCT; import static com.openosrs.injector.rsapi.RSApi.CONSTRUCT;
import static com.openosrs.injector.rsapi.RSApi.IMPORT; import static com.openosrs.injector.rsapi.RSApi.IMPORT;
@Data @Getter
public class RSApiClass implements Iterable<RSApiMethod> @Setter
public class RSApiClass extends ClassVisitor implements Iterable<RSApiMethod>
{ {
private Class clazz; private Class clazz;
private final List<Class> interfaces = new ArrayList<>(); private final List<Class> interfaces = new ArrayList<>();
@@ -32,6 +36,11 @@ public class RSApiClass implements Iterable<RSApiMethod>
private final Map<String, List<RSApiMethod>> imports = new HashMap<>(); private final Map<String, List<RSApiMethod>> imports = new HashMap<>();
RSApiClass()
{
super(Opcodes.ASM5);
}
void init(List<RSApiMethod> constructList) void init(List<RSApiMethod> constructList)
{ {
for (RSApiMethod method : this) for (RSApiMethod method : this)
@@ -39,23 +48,18 @@ public class RSApiClass implements Iterable<RSApiMethod>
if (method.isSynthetic()) if (method.isSynthetic())
continue; continue;
final Annotations annotations = method.getAnnotations(); if (method.findAnnotation(CONSTRUCT) != null)
if (annotations.find(CONSTRUCT) != null)
{ {
constructList.add(method); constructList.add(method);
continue; continue;
} }
final Annotation imported = annotations.find(IMPORT); final Annotation imported = method.findAnnotation(IMPORT);
if (imported != null) if (imported != null)
{
final String importStr = imported.getElement().getString();
imports.computeIfAbsent( imports.computeIfAbsent(
importStr, imported.getValueString(),
(str) -> new ArrayList<>() (str) -> new ArrayList<>()
).add(method); ).add(method);
}
} }
} }
@@ -85,4 +89,17 @@ public class RSApiClass implements Iterable<RSApiMethod>
{ {
return this.methods.iterator(); return this.methods.iterator();
} }
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces)
{
clazz = new Class(name);
for (String s : interfaces)
this.interfaces.add(new Class(s));
}
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions)
{
return addMethod(name, new Signature(desc), access);
}
} }

View File

@@ -1,39 +0,0 @@
/*
* 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.rsapi;
import net.runelite.asm.pool.Class;
import net.runelite.asm.signature.Signature;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
public class RSApiClassVisitor extends ClassVisitor
{
private final RSApiClass apiClass;
RSApiClassVisitor(RSApiClass apiClass)
{
super(Opcodes.ASM5);
this.apiClass = apiClass;
}
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces)
{
apiClass.setClazz(new Class(name));
for (String s : interfaces)
apiClass.getInterfaces().add(new Class(s));
}
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions)
{
final RSApiMethod method = apiClass.addMethod(name, new Signature(desc), access);
return new RSApiMethodVisitor(method);
}
}

View File

@@ -7,25 +7,39 @@
*/ */
package com.openosrs.injector.rsapi; package com.openosrs.injector.rsapi;
import java.util.HashMap;
import java.util.Map;
import lombok.Data; import lombok.Data;
import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import net.runelite.asm.Annotated; import lombok.Setter;
import net.runelite.asm.Annotation;
import net.runelite.asm.Named; import net.runelite.asm.Named;
import net.runelite.asm.attributes.Annotations; import net.runelite.asm.Type;
import net.runelite.asm.attributes.Annotated;
import net.runelite.asm.pool.Class; import net.runelite.asm.pool.Class;
import net.runelite.asm.pool.Method; import net.runelite.asm.pool.Method;
import net.runelite.asm.signature.Signature; import net.runelite.asm.signature.Signature;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
@Data @Getter
@RequiredArgsConstructor @Setter
public class RSApiMethod implements Annotated, Named public class RSApiMethod extends MethodVisitor implements Annotated, Named
{ {
private final Method method; private final Method method;
private final int accessFlags; private final int accessFlags;
private final Annotations annotations = new Annotations(); private final Map<Type, Annotation> annotations = new HashMap<>();
private boolean injected; private boolean injected;
RSApiMethod(Method method, int accesFlags)
{
super(Opcodes.ASM5);
this.method = method;
this.accessFlags = accesFlags;
}
public Class getClazz() public Class getClazz()
{ {
return method.getClazz(); return method.getClazz();
@@ -50,4 +64,11 @@ public class RSApiMethod implements Annotated, Named
{ {
return (accessFlags & (Opcodes.ACC_ABSTRACT | Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC)) == 1; return (accessFlags & (Opcodes.ACC_ABSTRACT | Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC)) == 1;
} }
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible)
{
final var annotation = new Annotation(new Type(descriptor), visible);
this.addAnnotation(annotation);
return annotation;
}
} }

View File

@@ -1,34 +0,0 @@
/*
* 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.rsapi;
import net.runelite.asm.attributes.annotation.Annotation;
import net.runelite.asm.attributes.annotation.Element;
import net.runelite.asm.attributes.annotation.SimpleElement;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Opcodes;
public class RSApiMethodAnnotationVisitor extends AnnotationVisitor
{
private final Annotation annotation;
RSApiMethodAnnotationVisitor(Annotation annotation)
{
super(Opcodes.ASM5);
this.annotation = annotation;
}
@Override
public void visit(String name, Object value)
{
Element element = new SimpleElement(name, value);
annotation.addElement(element);
}
}

View File

@@ -1,32 +0,0 @@
/*
* 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.rsapi;
import net.runelite.asm.Type;
import net.runelite.asm.attributes.annotation.Annotation;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
public class RSApiMethodVisitor extends MethodVisitor
{
private final RSApiMethod method;
RSApiMethodVisitor(RSApiMethod method)
{
super(Opcodes.ASM5);
this.method = method;
}
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible)
{
Annotation annotation = new Annotation(new Type(descriptor));
this.method.getAnnotations().addAnnotation(annotation);
return new RSApiMethodAnnotationVisitor(annotation);
}
}

View File

@@ -70,7 +70,7 @@ class DeobTarget
@ObfuscatedName("ob_foo3") @ObfuscatedName("ob_foo3")
@ObfuscatedSignature( @ObfuscatedSignature(
signature = "(I)V", descriptor = "(I)V",
garbageValue = "123" garbageValue = "123"
) )
private void foo3() private void foo3()
@@ -108,14 +108,12 @@ abstract class Source
} }
@Copy("foo3") @Copy("foo3")
abstract void foo3();
@Replace("foo3") @Replace("foo3")
private void rl$foo3() private void copy$foo3()
{ {
System.out.println("replaced"); System.out.println("replaced");
System.out.println(foo4); System.out.println(foo4);
foo3(); copy$foo3();
} }
} }