package io.gitlab.jfronny.libjf.unsafe.asm; import io.gitlab.jfronny.libjf.LibJf; import io.gitlab.jfronny.libjf.unsafe.asm.patch.Patch; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.MappingResolver; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.tree.ClassNode; import org.spongepowered.asm.mixin.transformer.FabricMixinTransformerProxy; import org.spongepowered.asm.transformers.MixinClassWriter; import java.util.Set; public class AsmTransformer extends FabricMixinTransformerProxy { public static AsmTransformer INSTANCE; public static final MappingResolver MAPPING_RESOLVER = FabricLoader.getInstance().getMappingResolver(); public static final String INTERMEDIARY = "intermediary"; public FabricMixinTransformerProxy delegate; public Set asmConfigs; private AsmConfig currentConfig = null; @Override public byte[] transformClassBytes(String name, String transformedName, byte[] classBytes) { classBytes = delegate.transformClassBytes(name, transformedName, classBytes); if (classBytes == null || name == null) return classBytes; if (isClassUnmoddable(name, null)) return classBytes; ClassNode klazz = new ClassNode(); ClassReader reader = new ClassReader(classBytes); reader.accept(klazz, ClassReader.EXPAND_FRAMES); //ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG //if ((klazz.access & Opcodes.ACC_INTERFACE) != 0) { // return classBytes; //} for (AsmConfig config : asmConfigs) { currentConfig = config; if (!isClassUnmoddable(name, config)) { for (Patch patch : config.getPatches()) { patch.apply(klazz); } } } currentConfig = null; ClassWriter writer = new MixinClassWriter(reader, ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); try { klazz.accept(writer); } catch (NullPointerException t) { LibJf.LOGGER.error("Could not transform " + transformedName, t); return null; } classBytes = writer.toByteArray(); return classBytes; } public boolean isClassUnmoddable(String className, AsmConfig config) { if (className.replace('/', '.').startsWith("org.objectweb.asm") //|| className.startsWith("net.fabricmc.loader") //|| className.startsWith("io.gitlab.jfronny.libjf.unsafe.asm") ) return true; if (config == null) return false; Set classes = config.skipClasses(); if (classes == null) return false; return classes.contains(MAPPING_RESOLVER.unmapClassName(INTERMEDIARY, className)); } public AsmConfig getCurrentConfig() { return currentConfig; } }