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() {} }