|
23 | 23 |
|
24 | 24 | import com.falsepattern.lib.asm.IClassNodeTransformer;
|
25 | 25 | import com.falsepattern.lib.internal.Tags;
|
26 |
| -import com.falsepattern.lib.mixin.MixinInfo; |
27 | 26 | import lombok.val;
|
28 | 27 | import org.objectweb.asm.tree.ClassNode;
|
29 |
| -import org.objectweb.asm.tree.MethodNode; |
| 28 | +import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; |
30 | 29 |
|
31 |
| -import java.util.List; |
| 30 | +import java.util.HashMap; |
| 31 | +import java.util.Map; |
32 | 32 |
|
33 | 33 | public class IMixinPluginTransformer implements IClassNodeTransformer {
|
34 |
| - private static final String CLASSNODE_MIXINBOOTER = "org/spongepowered/libraries/org/objectweb/asm/tree/ClassNode"; |
35 |
| - private static final String CLASSNODE_REGULAR = "org/spongepowered/asm/lib/tree/ClassNode"; |
36 | 34 | private static final String IMIXINPLUGIN = Tags.GROUPNAME + ".mixin.IMixinPlugin";
|
37 | 35 | private static final String IMIXINPLUGIN_INTERNAL = IMIXINPLUGIN.replace('.', '/');
|
38 |
| - private static final String IMIXINCONFIGPLUGIN_INTERNAL = "org/spongepowered/asm/mixin/extensibility/IMixinConfigPlugin"; |
| 36 | + private static final String IMIXINCONFIGPLUGIN = "org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin"; |
| 37 | + private static final String IMIXINCONFIGPLUGIN_INTERNAL = IMIXINCONFIGPLUGIN.replace('.', '/'); |
| 38 | + private static final Map<Class<?>, String> primitiveDescriptors = new HashMap<>(); |
| 39 | + |
| 40 | + private static String PREAPPLY_DESC = null; |
| 41 | + private static String POSTAPPLY_DESC = null; |
| 42 | + private static String CLASSNODE_REAL = null; |
| 43 | + |
| 44 | + static { |
| 45 | + primitiveDescriptors.put(Void.TYPE, "V"); |
| 46 | + primitiveDescriptors.put(Boolean.TYPE, "Z"); |
| 47 | + primitiveDescriptors.put(Byte.TYPE, "B"); |
| 48 | + primitiveDescriptors.put(Short.TYPE, "S"); |
| 49 | + primitiveDescriptors.put(Integer.TYPE, "I"); |
| 50 | + primitiveDescriptors.put(Long.TYPE, "J"); |
| 51 | + primitiveDescriptors.put(Float.TYPE, "F"); |
| 52 | + primitiveDescriptors.put(Double.TYPE, "D"); |
| 53 | + primitiveDescriptors.put(Character.TYPE, "C"); |
| 54 | + } |
| 55 | + |
39 | 56 | @Override
|
40 | 57 | public String getName() {
|
41 | 58 | return "IMixinPluginTransformer";
|
42 | 59 | }
|
43 | 60 |
|
44 | 61 | @Override
|
45 | 62 | public boolean shouldTransform(ClassNode cn, String transformedName, boolean obfuscated) {
|
46 |
| - return transformedName.equals(IMIXINPLUGIN) || |
47 |
| - cn.interfaces.stream().anyMatch((i) -> i.equals(IMIXINPLUGIN_INTERNAL) || i.equals(IMIXINCONFIGPLUGIN_INTERNAL)); |
| 63 | + return IMIXINPLUGIN.equals(transformedName) || |
| 64 | + IMIXINCONFIGPLUGIN.equals(transformedName) || |
| 65 | + cn.interfaces.stream().anyMatch((i) -> IMIXINPLUGIN_INTERNAL.equals(i) || |
| 66 | + IMIXINCONFIGPLUGIN_INTERNAL.equals(i)); |
48 | 67 | }
|
49 | 68 |
|
50 | 69 | @Override
|
51 | 70 | public void transform(ClassNode cn, String transformedName, boolean obfuscated) {
|
52 |
| - if (transformedName.equals(IMIXINPLUGIN)) { |
53 |
| - transformIMixinPlugin(cn); |
| 71 | + if (IMIXINCONFIGPLUGIN.equals(transformedName)) { |
| 72 | + extractMixinConfigPluginData(cn); |
54 | 73 | } else {
|
55 | 74 | transformPlugin(cn, transformedName);
|
56 | 75 | }
|
57 | 76 | }
|
58 | 77 |
|
59 |
| - private static void transformIMixinPlugin(ClassNode cn) { |
60 |
| - if (MixinInfo.isMixinBooterLegacy()) { |
61 |
| - FPTransformer.LOG.info("Detected MixinBooterLegacy. Converting IMixinPlugin to compat mode."); |
62 |
| - doRename(cn.methods, CLASSNODE_REGULAR, CLASSNODE_MIXINBOOTER); |
| 78 | + private static void extractMixinConfigPluginData(ClassNode cn) { |
| 79 | + for (val method : cn.methods) { |
| 80 | + switch (method.name) { |
| 81 | + case "preApply": |
| 82 | + PREAPPLY_DESC = method.desc; |
| 83 | + break; |
| 84 | + case "postApply": |
| 85 | + POSTAPPLY_DESC = method.desc; |
| 86 | + break; |
| 87 | + default: |
| 88 | + continue; |
| 89 | + } |
| 90 | + if (CLASSNODE_REAL != null) { |
| 91 | + for (val local: method.localVariables) { |
| 92 | + if (local.desc.contains("ClassNode;")) { |
| 93 | + local.desc = local.desc.replaceAll("L[a-zA-Z/$]+[a-zA-Z$]+/ClassNode;", CLASSNODE_REAL); |
| 94 | + } |
| 95 | + } |
| 96 | + } |
63 | 97 | }
|
64 | 98 | }
|
65 | 99 |
|
66 | 100 | private static void transformPlugin(ClassNode cn, String transformedName) {
|
67 | 101 | FPTransformer.LOG.info("Transforming " + transformedName + " to fit current mixin environment.");
|
68 |
| - if (!MixinInfo.isMixinBooterLegacy()) { |
69 |
| - doRename(cn.methods, CLASSNODE_MIXINBOOTER, CLASSNODE_REGULAR); |
70 |
| - } else { |
71 |
| - doRename(cn.methods, CLASSNODE_REGULAR, CLASSNODE_MIXINBOOTER); |
| 102 | + if (PREAPPLY_DESC == null) { |
| 103 | + PREAPPLY_DESC = extractMethodWithReflection("preApply"); |
| 104 | + } |
| 105 | + if (POSTAPPLY_DESC == null) { |
| 106 | + POSTAPPLY_DESC = extractMethodWithReflection("postApply"); |
| 107 | + } |
| 108 | + for (val method : cn.methods) { |
| 109 | + switch (method.name) { |
| 110 | + case "preApply": |
| 111 | + method.desc = PREAPPLY_DESC; |
| 112 | + break; |
| 113 | + case "postApply": |
| 114 | + method.desc = POSTAPPLY_DESC; |
| 115 | + break; |
| 116 | + } |
72 | 117 | }
|
73 | 118 | }
|
74 | 119 |
|
75 |
| - private static void doRename(List<MethodNode> methods, String from, String to) { |
76 |
| - for (val method : methods) { |
77 |
| - if (method.name.equals("preApply") || method.name.equals("postApply")) { |
78 |
| - val newDesc = method.desc.replace(from, to); |
79 |
| - if (!method.desc.equals(newDesc)) { |
80 |
| - FPTransformer.LOG.debug(method.name + method.desc + " -> " + method.name + newDesc); |
81 |
| - } |
82 |
| - method.desc = newDesc; |
83 |
| - for (val local: method.localVariables) { |
84 |
| - local.desc = local.desc.replace(from, to); |
| 120 | + private static String extractMethodWithReflection(String m) { |
| 121 | + for (val method: IMixinConfigPlugin.class.getDeclaredMethods()) { |
| 122 | + if (method.getName().equals(m)) { |
| 123 | + StringBuilder b = new StringBuilder("("); |
| 124 | + for (val param: method.getParameterTypes()) { |
| 125 | + if (param.getName().contains("ClassNode")) { |
| 126 | + CLASSNODE_REAL = "L" + param.getName().replace('.', '/') + ";"; |
| 127 | + } |
| 128 | + b.append(classToRaw(param)); |
85 | 129 | }
|
| 130 | + b.append(")").append(classToRaw(method.getReturnType())); |
| 131 | + return b.toString(); |
86 | 132 | }
|
87 | 133 | }
|
| 134 | + throw new RuntimeException("Could not extract " + m + " from IMixinConfigPlugin!"); |
| 135 | + } |
| 136 | + |
| 137 | + private static String classToRaw(Class<?> clazz) { |
| 138 | + if (primitiveDescriptors.containsKey(clazz)) { |
| 139 | + return primitiveDescriptors.get(clazz); |
| 140 | + } else { |
| 141 | + return "L" + clazz.getName().replace('.', '/') + ";"; |
| 142 | + } |
88 | 143 | }
|
89 | 144 | }
|
0 commit comments