Skip to content

Commit

Permalink
Improve coremods compatibility by a lot + Clean up CCC and NEI compat
Browse files Browse the repository at this point in the history
  • Loading branch information
thecatcore committed Apr 22, 2024
1 parent e9b9e96 commit c1f20f7
Show file tree
Hide file tree
Showing 13 changed files with 179 additions and 119 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package fr.catcore.fabricatedforge.compat;

import fr.catcore.fabricatedforge.compat.asm.BetterClassWriter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package fr.catcore.fabricatedforge.compat;

import fr.catcore.fabricatedforge.compat.asm.ASMRemapperTransformer;
import fr.catcore.fabricatedforge.util.Utils;
import fr.catcore.modremapperapi.ClassTransformer;
import fr.catcore.modremapperapi.api.ModRemapper;
import fr.catcore.modremapperapi.remapping.RemapUtil;
import fr.catcore.modremapperapi.remapping.VisitorInfos;
Expand Down Expand Up @@ -35,6 +37,7 @@ public void registerVisitors(VisitorInfos visitorInfos) {
@Override
public void afterRemap() {
Mixins.addConfiguration("fabricated-forge.mods.mixins.json");
Utils.TRANSFORMER_EXCLUSIONS.add("fr.catcore.fabricatedforge.compat.BetterClassWriter");
Utils.TRANSFORMER_EXCLUSIONS.add("fr.catcore.fabricatedforge.compat.asm.BetterClassWriter");
ClassTransformer.registerPostTransformer(new ASMRemapperTransformer());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package fr.catcore.fabricatedforge.compat.asm;

import fr.catcore.modremapperapi.api.IClassTransformer;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.*;

import java.util.HashMap;
import java.util.Map;

public class ASMRemapperTransformer implements IClassTransformer, Opcodes {
private final static String[] EXCLUDED = new String[]{
"fr.catcore.",
"cpw.mods.fml.",
"net.minecraftforge.",
"org.objectweb.asm.",
"net.fabricmc.",
"com.llamalad7.",
"org.spongepowered.",
"org.lwjgl."
};

private final static Map<String, String> INSTANCE_REPLACER = arrayToMap(new String[][]{
{"org/objectweb/asm/tree/FieldInsnNode", "fr/catcore/fabricatedforge/compat/asm/BetterFieldInsnNode"},
{"org/objectweb/asm/tree/MethodInsnNode", "fr/catcore/fabricatedforge/compat/asm/BetterMethodInsnNode"},
{"org/objectweb/asm/ClassWriter", "fr/catcore/fabricatedforge/compat/asm/BetterClassWriter"}
});

@Override
public boolean handlesClass(String s, String s1) {
for (String exclude : EXCLUDED) {
if (s.startsWith(exclude)) return false;
}

return true;
}

@Override
public byte[] transformClass(String s, String s1, byte[] bytes) {
ClassNode classNode = new ClassNode();
ClassReader classReader = new ClassReader(bytes);
classReader.accept(classNode, 0);

boolean touched = false;

for (MethodNode methodNode : classNode.methods) {
AbstractInsnNode insnNode = methodNode.instructions.getFirst();

if (insnNode != null) {
while (insnNode != null) {
if (insnNode.getOpcode() == NEW && insnNode instanceof TypeInsnNode) {
TypeInsnNode typeInsnNode = (TypeInsnNode) insnNode;

if (INSTANCE_REPLACER.containsKey(typeInsnNode.desc)) {
typeInsnNode.desc = INSTANCE_REPLACER.get(typeInsnNode.desc);
touched = true;
}
} else if (insnNode.getOpcode() == INVOKESPECIAL && insnNode instanceof MethodInsnNode) {
MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode;

if (methodInsnNode.name.equals("<init>") && INSTANCE_REPLACER.containsKey(methodInsnNode.owner)) {
methodInsnNode.owner = INSTANCE_REPLACER.get(methodInsnNode.owner);
touched = true;
}
}

insnNode = insnNode.getNext();
}
}
}

if (touched) {
ClassWriter classWriter = new ClassWriter(3);
classNode.accept(classWriter);

bytes = classWriter.toByteArray();
System.out.println("ASMRemapper transformed: " + s);
}

return bytes;
}

private static Map<String, String> arrayToMap(String[][] arrays) {
Map<String, String> map = new HashMap<>();

for (String[] array : arrays) {
map.put(array[0], array[1]);
}

return map;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package fr.catcore.fabricatedforge.compat;
package fr.catcore.fabricatedforge.compat.asm;

import net.fabricmc.loader.api.FabricLoader;
import org.objectweb.asm.ClassReader;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package fr.catcore.fabricatedforge.compat.asm;

import fr.catcore.fabricatedforge.Constants;
import io.github.fabriccompatibiltylayers.modremappingapi.api.MappingUtils;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.LabelNode;

import java.util.Map;

public class BetterFieldInsnNode extends FieldInsnNode {
/**
* Constructs a new {@link FieldInsnNode}.
*
* @param opcode the opcode of the type instruction to be constructed. This opcode must be
* GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
* @param owner the internal name of the field's owner class (see {@link
* Type#getInternalName()}).
* @param name the field's name.
* @param descriptor the field's descriptor (see {@link Type}).
*/
public BetterFieldInsnNode(int opcode, String owner, String name, String descriptor) {
this(opcode, Constants.mapClass(owner), Constants.mapFieldFromRemappedClass(Constants.mapClass(owner), name, descriptor));
}

private BetterFieldInsnNode(int code, String owner, MappingUtils.ClassMember classMember) {
super(code, owner, classMember.name, Constants.mapTypeDescriptor(classMember.desc));
}

@Override
public AbstractInsnNode clone(Map<LabelNode, LabelNode> clonedLabels) {
return new BetterFieldInsnNode(opcode, owner, name, desc).cloneAnnotations(this);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package fr.catcore.fabricatedforge.compat.asm;

import fr.catcore.fabricatedforge.Constants;
import io.github.fabriccompatibiltylayers.modremappingapi.api.MappingUtils;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.MethodInsnNode;

import java.util.Map;

public class BetterMethodInsnNode extends MethodInsnNode implements Opcodes {
public BetterMethodInsnNode(int opcode, String owner, String name, String descriptor) {
this(opcode, owner, name, descriptor, opcode == Opcodes.INVOKEINTERFACE);
}

public BetterMethodInsnNode(int opcode, String owner, String name, String descriptor, boolean isInterface) {
this(opcode, Constants.mapClass(owner), Constants.mapMethodFromRemappedClass(Constants.mapClass(owner), name, descriptor), isInterface);
}

private BetterMethodInsnNode(int opcode, String owner, MappingUtils.ClassMember member, boolean isInterface) {
super(opcode, owner, member.name, Constants.mapMethodDescriptor(member.desc), isInterface);
}

@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> clonedLabels) {
return new BetterMethodInsnNode(opcode, owner, name, desc, itf).cloneAnnotations(this);
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
package fr.catcore.fabricatedforge.compat.mixin.codechickencore;

import codechicken.core.asm.ASMHelper;
import fr.catcore.fabricatedforge.compat.BetterClassWriter;
import fr.catcore.fabricatedforge.compat.CompatUtils;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
Expand All @@ -20,13 +16,4 @@ public class ASMHelperMixin {
public static ClassNode createClassNode(byte[] bytes) {
return CompatUtils.createNode(bytes, 0);
}

/**
* @author E
* @reason E
*/
@Overwrite(remap = false)
public static byte[] createBytes(ClassNode cnode, int i) {
return CompatUtils.writeClass(cnode, i);
}
}

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@
"codechickencore.ClassOverriderMixin",
"codechickencore.DelegatedTransformerMixin",
"codechickencore.DescriptorMappingMixin",
"codechickencore.FeatureHackTransformerMixin",
"codechickencore.TweakTransformerMixin",
"nei.FurnaceRecipeHandlerMixin",
"nei.NEITransformerMixin",
"nei.TMIUninstallerMixin",
"treecapitator.ItemInWorldManagerTransformerMixin"
],
Expand Down
21 changes: 15 additions & 6 deletions src/main/java/cpw/mods/fml/relauncher/IClassTransformer.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package cpw.mods.fml.relauncher;

import fr.catcore.fabricatedforge.util.Utils;
import net.legacyfabric.fabric.api.logger.v1.Logger;

import java.util.ArrayList;
import java.util.HashMap;
Expand All @@ -22,6 +23,7 @@

public interface IClassTransformer extends fr.catcore.modremapperapi.api.IClassTransformer {
static final List<String> CLASS_NAMES = new ArrayList<>();
static final Logger LOGGER = Logger.get("Fabricated-Legacy-Forge", "ClassTransformers");

Map<IClassTransformer, List<String>> transformed = new HashMap<>();

Expand All @@ -30,26 +32,33 @@ public interface IClassTransformer extends fr.catcore.modremapperapi.api.IClassT
@Override
default byte[] transformClass(String name, String transformedName, byte[] original) {
if (original == null) return null;
return this.transform(name, original);
byte[] transformed = this.transform(name, original);

if (original != transformed && !this.toString().startsWith("cpw.mods.fml.common.asm.transformers.SideTransformer")) {
LOGGER.debug(name + " transformed by " + this);
}

return transformed;
}

@Override
default boolean handlesClass(String s, String s1) {
String className = this.getClass().getName();
String className = this.toString();

if (!CLASS_NAMES.contains(className)) {
CLASS_NAMES.add(className);
transformed.put(this, new ArrayList<>());
}

if (CLASS_NAMES.contains(s)) return false;

for (String toExclude : Utils.TRANSFORMER_EXCLUSIONS) {
if (s.startsWith(toExclude)) return false;
if (s.startsWith(toExclude)) {
return false;
}
}

if (transformed.get(this).contains(s)) {
throw new RuntimeException("Detected transformation loop for class " + s + " in ClassTransformer " + className);
LOGGER.warn("Detected transformation loop for class " + s + " in ClassTransformer " + className);
return false;
}

transformed.get(this).add(s);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ public Optional<String> getDefaultPackage() {

@Override
public void afterRemap() {

System.out.println(System.getProperty("java.security.properties"));
}

static {
Expand Down

0 comments on commit c1f20f7

Please sign in to comment.