GS 0.2+ crash fix

This commit is contained in:
FalsePattern committed 2022-09-04 10:24:57 +02:00
1 parent bdf73dd29a
commit ea95bac048
3 files changed
+93 -32

No files matched your search

@@ -23,19 +23,36 @@ package com.falsepattern.lib.internal.asm;
import com.falsepattern.lib.asm.IClassNodeTransformer;
import com.falsepattern.lib.internal.Tags;
import com.falsepattern.lib.mixin.MixinInfo;
import lombok.val;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
public class IMixinPluginTransformer implements IClassNodeTransformer {
private static final String CLASSNODE_MIXINBOOTER = "org/spongepowered/libraries/org/objectweb/asm/tree/ClassNode";
private static final String CLASSNODE_REGULAR = "org/spongepowered/asm/lib/tree/ClassNode";
private static final String IMIXINPLUGIN = Tags.GROUPNAME + ".mixin.IMixinPlugin";
private static final String IMIXINPLUGIN_INTERNAL = IMIXINPLUGIN.replace('.', '/');
private static final String IMIXINCONFIGPLUGIN_INTERNAL = "org/spongepowered/asm/mixin/extensibility/IMixinConfigPlugin";
private static final String IMIXINCONFIGPLUGIN = "org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin";
private static final String IMIXINCONFIGPLUGIN_INTERNAL = IMIXINCONFIGPLUGIN.replace('.', '/');
private static final Map<Class<?>, String> primitiveDescriptors = new HashMap<>();
private static String PREAPPLY_DESC = null;
private static String POSTAPPLY_DESC = null;
private static String CLASSNODE_REAL = null;
static {
primitiveDescriptors.put(Void.TYPE, "V");
primitiveDescriptors.put(Boolean.TYPE, "Z");
primitiveDescriptors.put(Byte.TYPE, "B");
primitiveDescriptors.put(Short.TYPE, "S");
primitiveDescriptors.put(Integer.TYPE, "I");
primitiveDescriptors.put(Long.TYPE, "J");
primitiveDescriptors.put(Float.TYPE, "F");
primitiveDescriptors.put(Double.TYPE, "D");
primitiveDescriptors.put(Character.TYPE, "C");
}
@Override
public String getName() {
return "IMixinPluginTransformer";
@@ -43,47 +60,85 @@ public class IMixinPluginTransformer implements IClassNodeTransformer {
@Override
public boolean shouldTransform(ClassNode cn, String transformedName, boolean obfuscated) {
return transformedName.equals(IMIXINPLUGIN) ||
cn.interfaces.stream().anyMatch((i) -> i.equals(IMIXINPLUGIN_INTERNAL) || i.equals(IMIXINCONFIGPLUGIN_INTERNAL));
return IMIXINPLUGIN.equals(transformedName) ||
IMIXINCONFIGPLUGIN.equals(transformedName) ||
cn.interfaces.stream().anyMatch((i) -> IMIXINPLUGIN_INTERNAL.equals(i) ||
IMIXINCONFIGPLUGIN_INTERNAL.equals(i));
}
@Override
public void transform(ClassNode cn, String transformedName, boolean obfuscated) {
if (transformedName.equals(IMIXINPLUGIN)) {
transformIMixinPlugin(cn);
if (IMIXINCONFIGPLUGIN.equals(transformedName)) {
extractMixinConfigPluginData(cn);
} else {
transformPlugin(cn, transformedName);
}
}
private static void transformIMixinPlugin(ClassNode cn) {
if (MixinInfo.isMixinBooterLegacy()) {
FPTransformer.LOG.info("Detected MixinBooterLegacy. Converting IMixinPlugin to compat mode.");
doRename(cn.methods, CLASSNODE_REGULAR, CLASSNODE_MIXINBOOTER);
private static void extractMixinConfigPluginData(ClassNode cn) {
for (val method : cn.methods) {
switch (method.name) {
case "preApply":
PREAPPLY_DESC = method.desc;
break;
case "postApply":
POSTAPPLY_DESC = method.desc;
break;
default:
continue;
}
if (CLASSNODE_REAL != null) {
for (val local: method.localVariables) {
if (local.desc.contains("ClassNode;")) {
local.desc = local.desc.replaceAll("L[a-zA-Z/$]+[a-zA-Z$]+/ClassNode;", CLASSNODE_REAL);
}
}
}
}
}
private static void transformPlugin(ClassNode cn, String transformedName) {
FPTransformer.LOG.info("Transforming " + transformedName + " to fit current mixin environment.");
if (!MixinInfo.isMixinBooterLegacy()) {
doRename(cn.methods, CLASSNODE_MIXINBOOTER, CLASSNODE_REGULAR);
} else {
doRename(cn.methods, CLASSNODE_REGULAR, CLASSNODE_MIXINBOOTER);
if (PREAPPLY_DESC == null) {
PREAPPLY_DESC = extractMethodWithReflection("preApply");
}
}
private static void doRename(List<MethodNode> methods, String from, String to) {
for (val method : methods) {
if (method.name.equals("preApply") || method.name.equals("postApply")) {
val newDesc = method.desc.replace(from, to);
if (!method.desc.equals(newDesc)) {
FPTransformer.LOG.debug(method.name + method.desc + " -> " + method.name + newDesc);
}
method.desc = newDesc;
for (val local: method.localVariables) {
local.desc = local.desc.replace(from, to);
}
if (POSTAPPLY_DESC == null) {
POSTAPPLY_DESC = extractMethodWithReflection("postApply");
}
for (val method : cn.methods) {
switch (method.name) {
case "preApply":
method.desc = PREAPPLY_DESC;
break;
case "postApply":
method.desc = POSTAPPLY_DESC;
break;
}
}
}
private static String extractMethodWithReflection(String m) {
for (val method: IMixinConfigPlugin.class.getDeclaredMethods()) {
if (method.getName().equals(m)) {
StringBuilder b = new StringBuilder("(");
for (val param: method.getParameterTypes()) {
if (param.getName().contains("ClassNode")) {
CLASSNODE_REAL = "L" + param.getName().replace('.', '/') + ";";
}
b.append(classToRaw(param));
}
b.append(")").append(classToRaw(method.getReturnType()));
return b.toString();
}
}
throw new RuntimeException("Could not extract " + m + " from IMixinConfigPlugin!");
}
private static String classToRaw(Class<?> clazz) {
if (primitiveDescriptors.containsKey(clazz)) {
return primitiveDescriptors.get(clazz);
} else {
return "L" + clazz.getName().replace('.', '/') + ";";
}
}
}
@@ -79,6 +79,11 @@ public final class MixinInfo {
} catch (ClassNotFoundException ignored) {
return MixinBootstrapperType.None;
}
try {
Class.forName("com.falsepattern.gasstation.core.GasStationCore");
return MixinBootstrapperType.GasStation;
} catch (ClassNotFoundException ignored) {
}
try {
Class.forName("ru.timeconqueror.spongemixins.core.SpongeMixinsCore");
return MixinBootstrapperType.SpongeMixins;
@@ -106,6 +111,7 @@ public final class MixinInfo {
@StableAPI(since = "0.10.2")
public enum MixinBootstrapperType {
@StableAPI.Expose None,
@StableAPI.Expose(since = "0.10.9") GasStation,
@StableAPI.Expose SpongeMixins,
@StableAPI.Expose Grimoire,
@StableAPI.Expose MixinBooterLegacy,