diff --git a/build.gradle b/build.gradle index 08d1d0b..29da338 100644 --- a/build.gradle +++ b/build.gradle @@ -28,7 +28,7 @@ if (useMirror) apply from: "mirror.gradle" apply plugin: "net.minecraftforge.gradle.forge" //Only edit below this line, the above code adds and enables the necessary things for Forge to be setup. -version = "1.5 for 1.12.2-1.8.8" +version = "1.6 for 1.12.2-1.8.8" group = "com.ideallandframework.silent_assassin" // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = "redirectionor" diff --git a/src/main/java/com/Hileb/teampotato.redirectionor/Redirectionor.java b/src/main/java/com/Hileb/teampotato.redirectionor/Redirectionor.java index 1424dd4..8a403ce 100644 --- a/src/main/java/com/Hileb/teampotato.redirectionor/Redirectionor.java +++ b/src/main/java/com/Hileb/teampotato.redirectionor/Redirectionor.java @@ -28,13 +28,16 @@ public static void makeFMLCorePluginContainsFMLMod(File file){ public static final String MODID = "redirectionor"; - public static final String TRANSFORMERCLASS = "com.Hileb.teampotato.redirectionor.RedirectionorTransformer"; + public static final Logger LOGGER = LogManager.getLogger(MODID); @Override public String[] getASMTransformerClass() { - return new String[]{TRANSFORMERCLASS}; + return new String[]{ + "com.Hileb.teampotato.redirectionor.RedirectionorTransformer", + "com.Hileb.teampotato.redirectionor.RedirectionorCrashTransformer" + }; } @Override diff --git a/src/main/java/com/Hileb/teampotato.redirectionor/RedirectionorConfig.java b/src/main/java/com/Hileb/teampotato.redirectionor/RedirectionorConfig.java index 294c137..2adf36e 100644 --- a/src/main/java/com/Hileb/teampotato.redirectionor/RedirectionorConfig.java +++ b/src/main/java/com/Hileb/teampotato.redirectionor/RedirectionorConfig.java @@ -7,20 +7,16 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; +import net.minecraft.crash.CrashReport; import net.minecraft.launchwrapper.Launch; -import net.minecraft.launchwrapper.LaunchClassLoader; import net.minecraftforge.fml.common.ICrashCallable; import java.io.File; import java.io.IOException; import java.io.PrintWriter; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.HashSet; import java.util.Locale; -import java.util.Map; /** * @Project Redirectionor @@ -66,13 +62,14 @@ public static boolean decode(JsonObject jsonObject){ public static JsonObject encode(){ JsonObject json = new JsonObject(); - json.addProperty("printTransformedClasses", Config.isBlock); + json.addProperty("printTransformedClasses", Config.printTransformedClasses); json.addProperty("type", Config.isBlock ? "block" : "allow"); JsonArray contains = new JsonArray(); for(String element : Config.contains){ contains.add(element); } + json.add("contains", contains); JsonArray prefix = new JsonArray(); for(String element : Config.prefix){ @@ -141,8 +138,6 @@ public static class CrashHandler implements ICrashCallable { @Override public String call() { - handleCrash(); - save(); return "An automatic prefix block config generated"; } @@ -151,30 +146,22 @@ public String getLabel() { return "Redirectionor is enabled. Check your enums!"; } - public static final Object lock = new Object(); - - public static void handleCrash(){ - synchronized (lock){ - if (Config.isBlock){ - Method untransformName; - try { - untransformName = Launch.classLoader.getClass().getDeclaredMethod("untransformName", String.class); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } - for(Map.Entry thread : Thread.getAllStackTraces().entrySet()){ - for(StackTraceElement elements : thread.getValue()){ - try { - if (RedirectionorFastUtil.isEnum(Launch.classLoader.getClassBytes((String) untransformName.invoke(Launch.classLoader, elements.getClassName())))){ - Config.prefix.add(elements.getClassName()); - } - } catch (IOException | InvocationTargetException | IllegalAccessException ignored) { - //declare but never throws + @SuppressWarnings("unused") // ASM invoke + public static void handleCrash(CrashReport crashReport){ + if ("ThisIsFake".equals(crashReport.getDescription())) return; + else if (Config.isBlock){ + for(StackTraceElement element : crashReport.getCrashCause().getStackTrace()){ + try{ + Class cls = Class.forName(element.getClassName(), false, Launch.classLoader); + if (cls.isEnum()){ + Config.prefix.add(cls.getName()); } + } catch (ClassNotFoundException ignored) { + // no ops } } + save(); } - } } } } diff --git a/src/main/java/com/Hileb/teampotato.redirectionor/RedirectionorContainer.java b/src/main/java/com/Hileb/teampotato.redirectionor/RedirectionorContainer.java index 88c2da2..8645201 100644 --- a/src/main/java/com/Hileb/teampotato.redirectionor/RedirectionorContainer.java +++ b/src/main/java/com/Hileb/teampotato.redirectionor/RedirectionorContainer.java @@ -22,7 +22,7 @@ public RedirectionorContainer(){ metadata.modId=Redirectionor.MODID; metadata.name="Redirectionor"; metadata.description="Redirectionor is the implementation of this concept, specifically for the Direction enum class stuff, to reduce the required memory of the game."; - metadata.version="1.5 for 1.12.2-1.8.8"; + metadata.version="1.6 for 1.12.2-1.8.8"; metadata.url="https://www.curseforge.com/minecraft/mc-mods/redirectionor"; metadata.logoFile="/icon_redirectionor.png"; metadata.authorList.add("MCTeamPotato"); diff --git a/src/main/java/com/Hileb/teampotato.redirectionor/RedirectionorCrashTransformer.java b/src/main/java/com/Hileb/teampotato.redirectionor/RedirectionorCrashTransformer.java new file mode 100644 index 0000000..b68706e --- /dev/null +++ b/src/main/java/com/Hileb/teampotato.redirectionor/RedirectionorCrashTransformer.java @@ -0,0 +1,91 @@ +package com.Hileb.teampotato.redirectionor; + +import net.minecraft.launchwrapper.IClassTransformer; +import net.minecraft.launchwrapper.Launch; +import net.minecraft.launchwrapper.LaunchClassLoader; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.InsnList; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.VarInsnNode; + +/** + * @Project Redirectionor + * @Author Hileb + * @Date 2024/9/8 22:32 + **/ +public class RedirectionorCrashTransformer implements IClassTransformer { + @Override + public byte[] transform(String name, String transformedName, byte[] basicClass) { + if ("net.minecraftforge.fml.common.FMLCommonHandler".equals(transformedName)){ + ClassReader classReader = new ClassReader(basicClass); + ClassNode cn = new ClassNode(); + classReader.accept(cn, 0); + for(MethodNode methodNode : cn.methods){ + if ("enhanceCrashReport".equals(methodNode.name)){ // The FML hook never changed it's name + InsnList hook = new InsnList(); + hook.add(new VarInsnNode(Opcodes.ALOAD, 1)); + hook.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/Hileb/teampotato/redirectionor/RedirectionorConfig$CrashHandler", "handleCrash", "(Lnet/minecraft/crash/CrashReport;)V", false)); + methodNode.instructions.insert(hook); + return new LaunchClassWriter(classReader, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES).toByteArray(); + } + } + } + return basicClass; + } + + //Fix the crash of calling getCommonSuperClass + //Usually, the crash from the obfuscated environment + public static class LaunchClassWriter extends ClassWriter{ + + public LaunchClassWriter(ClassReader classReader, int flags) { + super(classReader, flags); + } + + @Override + protected String getCommonSuperClass(String type1, String type2) { + return getCommonSuperClass0(type1, type2); + } + + public static String getCommonSuperClass0(final String type1, final String type2) { + ClassLoader classLoader = LaunchClassLoader.class.getClassLoader(); + Class class1; + try { + class1 = Class.forName(type1.replace('/', '.'), false, classLoader); + } catch (ClassNotFoundException e) { + try { + class1 = Class.forName(type1.replace('/', '.'), false, Launch.classLoader); + } catch (ClassNotFoundException e1) { + throw new TypeNotPresentException(type1, e1); + } + } + Class class2; + try { + class2 = Class.forName(type2.replace('/', '.'), false, classLoader); + } catch (ClassNotFoundException e) { + try { + class2 = Class.forName(type2.replace('/', '.'), false, Launch.classLoader); + } catch (ClassNotFoundException e2) { + throw new TypeNotPresentException(type2, e2); + } + } + if (class1.isAssignableFrom(class2)) { + return type1; + } + if (class2.isAssignableFrom(class1)) { + return type2; + } + if (class1.isInterface() || class2.isInterface()) { + return "java/lang/Object"; + } else { + do { + class1 = class1.getSuperclass(); + } while (!class1.isAssignableFrom(class2)); + return class1.getName().replace('.', '/'); + } + } + } +}