Merge pull request #9 from Lucwousin/annotations
Update injector for new Annotations
This commit is contained in:
@@ -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()
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user