recipe-nope/src/main/java/dev/pfaff/recipe_nope/injector/util/ReflectUtil.java

105 lines
3.6 KiB
Java

package dev.pfaff.recipe_nope.injector.util;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.MappingResolver;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
public final class ReflectUtil {
public static final MappingResolver RESOLVER = FabricLoader.getInstance().getMappingResolver();
public static String typeDescriptor(String qualifiedName, boolean unmap) {
if (unmap) qualifiedName = unresolveClass(qualifiedName);
return 'L' + qualifiedName.replace('.', '/') + ';';
}
public static String typeDescriptor(Class<?> clazz, boolean unmap) {
if (clazz.isPrimitive()) {
if (clazz == void.class) return "V";
if (clazz == boolean.class) return "Z";
if (clazz == byte.class) return "B";
if (clazz == short.class) return "S";
if (clazz == int.class) return "I";
if (clazz == long.class) return "J";
if (clazz == float.class) return "F";
if (clazz == double.class) return "D";
if (clazz == char.class) return "C";
throw new AssertionError();
}
if (clazz.isArray()) {
return '[' + typeDescriptor(clazz.componentType(), unmap);
}
return typeDescriptor(clazz.getName(), unmap);
}
public static int varInsn(Type type, int base) {
if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
return base + 4;
}
if (type == Type.VOID_TYPE) return -1;
if (type == Type.BOOLEAN_TYPE || type == Type.BYTE_TYPE || type == Type.SHORT_TYPE || type == Type.CHAR_TYPE || type == Type.INT_TYPE) return base + 0;
if (type == Type.LONG_TYPE) return base + 1;
if (type == Type.FLOAT_TYPE) return base + 2;
if (type == Type.DOUBLE_TYPE) return base + 3;
throw new AssertionError();
}
public static int varLoadInsn(Type type) {
return varInsn(type, Opcodes.ILOAD);
}
public static int varStoreInsn(Type type) {
return varInsn(type, Opcodes.ISTORE);
}
public static String methodDescriptor(MethodType mt, boolean unmap) {
StringBuilder sb = new StringBuilder();
sb.append('(');
for (int i = 0; i < mt.parameterCount(); i++) {
sb.append(typeDescriptor(mt.parameterType(i), unmap));
}
sb.append(')');
sb.append(typeDescriptor(mt.returnType(), unmap));
return sb.toString();
}
public static String resolveClassName(String intermediaryName) {
return RESOLVER.mapClassName("intermediary", intermediaryName);
}
public static String unresolveClass(String qualifiedName) {
return RESOLVER.unmapClassName("intermediary", qualifiedName);
}
public static String unresolveClass(Class<?> clazz) {
return unresolveClass(clazz.getName());
}
public static String resolveMethodName(Class<?> owner, String intermediaryName, MethodType mt) {
return RESOLVER.mapMethodName("intermediary", unresolveClass(owner), intermediaryName, methodDescriptor(mt, true));
}
public static String resolveFieldName(Class<?> owner, String intermediaryName, MethodType mt) {
return RESOLVER.mapFieldName("intermediary", unresolveClass(owner), intermediaryName, methodDescriptor(mt, true));
}
public static MethodHandle findVirtual(MethodHandles.Lookup lookup, Class<?> clazz, String intermediaryName, MethodType mt)
throws ReflectiveOperationException {
return lookup.findVirtual(clazz, resolveMethodName(clazz, intermediaryName, mt), mt);
}
public static MethodHandle findStatic(MethodHandles.Lookup lookup, Class<?> clazz, String intermediaryName, MethodType mt)
throws ReflectiveOperationException {
return lookup.findStatic(clazz, resolveMethodName(clazz, intermediaryName, mt), mt);
}
private ReflectUtil() {}
}