From caa691ac94b6ec7c572e0bbe09bd4a2c02d6b742 Mon Sep 17 00:00:00 2001 From: 33 Date: Sat, 7 Jan 2023 22:24:07 +0800 Subject: [PATCH] Add: ITransformationService --- ForgeApi/build.gradle | 3 + .../fml/common/ICrashCallable.java | 1 + build.gradle | 1 + settings.gradle | 3 +- .../morecrashinfo/crash/CoreModList.java | 4 +- .../crash/CustomCrashExtender.java | 7 ++ .../me/xfl03/morecrashinfo/crash/ModList.java | 4 +- .../xfl03/morecrashinfo/fml/ModLocator.java | 61 +++++++++++++ .../morecrashinfo/handler/CrashHandler.java | 29 +++--- .../CrashReportExtenderTransformer.java | 88 +++++++++++++++++++ .../CustomCrashExtenderTransformer.java | 31 +++++++ .../modlauncher/TransformerService.java | 36 ++++++++ src/main/resources/META-INF/coremods.json | 3 - ...ods.modlauncher.api.ITransformationService | 1 + ...necraftforge.forgespi.locating.IModLocator | 1 + src/main/resources/crashtransformers.js | 73 --------------- 16 files changed, 252 insertions(+), 94 deletions(-) create mode 100644 ForgeApi/build.gradle rename {src => ForgeApi/src}/main/java/net/minecraftforge/fml/common/ICrashCallable.java (92%) create mode 100644 src/main/java/me/xfl03/morecrashinfo/crash/CustomCrashExtender.java create mode 100644 src/main/java/me/xfl03/morecrashinfo/fml/ModLocator.java create mode 100644 src/main/java/me/xfl03/morecrashinfo/modlauncher/CrashReportExtenderTransformer.java create mode 100644 src/main/java/me/xfl03/morecrashinfo/modlauncher/CustomCrashExtenderTransformer.java create mode 100644 src/main/java/me/xfl03/morecrashinfo/modlauncher/TransformerService.java delete mode 100644 src/main/resources/META-INF/coremods.json create mode 100644 src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService create mode 100644 src/main/resources/META-INF/services/net.minecraftforge.forgespi.locating.IModLocator delete mode 100644 src/main/resources/crashtransformers.js diff --git a/ForgeApi/build.gradle b/ForgeApi/build.gradle new file mode 100644 index 0000000..c5fc4ba --- /dev/null +++ b/ForgeApi/build.gradle @@ -0,0 +1,3 @@ +plugins { + id 'java' +} \ No newline at end of file diff --git a/src/main/java/net/minecraftforge/fml/common/ICrashCallable.java b/ForgeApi/src/main/java/net/minecraftforge/fml/common/ICrashCallable.java similarity index 92% rename from src/main/java/net/minecraftforge/fml/common/ICrashCallable.java rename to ForgeApi/src/main/java/net/minecraftforge/fml/common/ICrashCallable.java index 0036703..4143cef 100644 --- a/src/main/java/net/minecraftforge/fml/common/ICrashCallable.java +++ b/ForgeApi/src/main/java/net/minecraftforge/fml/common/ICrashCallable.java @@ -1,5 +1,6 @@ package net.minecraftforge.fml.common; +// 1.16.5- public interface ICrashCallable { String getLabel(); String call() throws Exception; diff --git a/build.gradle b/build.gradle index dca5c71..98cf37c 100644 --- a/build.gradle +++ b/build.gradle @@ -73,6 +73,7 @@ sourceSets.main.resources { srcDir 'src/generated/resources' } dependencies { minecraft 'net.minecraftforge:forge:1.19.3-44.1.2' + implementation project(":ForgeApi") } jar { diff --git a/settings.gradle b/settings.gradle index d56db65..2a1ef6a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,4 +4,5 @@ pluginManagement { maven { url = 'https://maven.minecraftforge.net/' } } } -//include "CrashMaker" \ No newline at end of file +//include "CrashMaker" +include "ForgeApi" \ No newline at end of file diff --git a/src/main/java/me/xfl03/morecrashinfo/crash/CoreModList.java b/src/main/java/me/xfl03/morecrashinfo/crash/CoreModList.java index 35da8b9..d49f897 100644 --- a/src/main/java/me/xfl03/morecrashinfo/crash/CoreModList.java +++ b/src/main/java/me/xfl03/morecrashinfo/crash/CoreModList.java @@ -3,14 +3,12 @@ import me.xfl03.morecrashinfo.util.ModHelper; import me.xfl03.morecrashinfo.util.PrintHelper; import net.minecraftforge.coremod.CoreMod; -import net.minecraftforge.fml.ISystemReportExtender; -import net.minecraftforge.fml.common.ICrashCallable; import net.minecraftforge.forgespi.coremod.ICoreModFile; import java.util.ArrayList; import java.util.List; -public class CoreModList implements ICrashCallable, ISystemReportExtender { +public class CoreModList implements CustomCrashExtender { @Override public String getLabel() { return "Forge CoreMods"; diff --git a/src/main/java/me/xfl03/morecrashinfo/crash/CustomCrashExtender.java b/src/main/java/me/xfl03/morecrashinfo/crash/CustomCrashExtender.java new file mode 100644 index 0000000..d57727c --- /dev/null +++ b/src/main/java/me/xfl03/morecrashinfo/crash/CustomCrashExtender.java @@ -0,0 +1,7 @@ +package me.xfl03.morecrashinfo.crash; + +import net.minecraftforge.fml.ISystemReportExtender; +import net.minecraftforge.fml.common.ICrashCallable; + +public interface CustomCrashExtender extends ICrashCallable, ISystemReportExtender { +} diff --git a/src/main/java/me/xfl03/morecrashinfo/crash/ModList.java b/src/main/java/me/xfl03/morecrashinfo/crash/ModList.java index 1ddc30b..dbc96f4 100644 --- a/src/main/java/me/xfl03/morecrashinfo/crash/ModList.java +++ b/src/main/java/me/xfl03/morecrashinfo/crash/ModList.java @@ -2,14 +2,12 @@ import me.xfl03.morecrashinfo.util.ModHelper; import me.xfl03.morecrashinfo.util.PrintHelper; -import net.minecraftforge.fml.ISystemReportExtender; -import net.minecraftforge.fml.common.ICrashCallable; import net.minecraftforge.forgespi.language.IModInfo; import java.util.ArrayList; import java.util.List; -public class ModList implements ICrashCallable, ISystemReportExtender { +public class ModList implements CustomCrashExtender { @Override public String getLabel() { return "Forge Mods"; diff --git a/src/main/java/me/xfl03/morecrashinfo/fml/ModLocator.java b/src/main/java/me/xfl03/morecrashinfo/fml/ModLocator.java new file mode 100644 index 0000000..9372609 --- /dev/null +++ b/src/main/java/me/xfl03/morecrashinfo/fml/ModLocator.java @@ -0,0 +1,61 @@ +package me.xfl03.morecrashinfo.fml; + +import net.minecraftforge.fml.loading.FMLPaths; +import net.minecraftforge.fml.loading.moddiscovery.AbstractJarFileModLocator; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Map; +import java.util.stream.Stream; +import java.util.zip.ZipFile; + +public class ModLocator extends AbstractJarFileModLocator { + private final Logger logger = LogManager.getLogger("MoreCrashInfoModLocator"); + private Path modPath = null; + + private void visitModFile(Path path) { +// logger.info("Try to Visit {} {} {}", path, Files.isRegularFile(path), path.toString().endsWith(".jar")); + if (!Files.isRegularFile(path) || !path.toString().endsWith(".jar")) { + return; + } + try (ZipFile zip = new ZipFile(new File(path.toUri()))) { +// logger.info("Visiting {}", path); + if (zip.getEntry("me/xfl03/morecrashinfo/MoreCrashInfo.class") != null) { + logger.info("MoreCrashInfo mod found at {}", path); + modPath = path; + } + } catch (Exception e) { + logger.warn("Error while loading {}", path); + } + } + + private void visitModDir(Path path) { + try (Stream paths = Files.list(path)) { + paths.forEach(this::visitModFile); + } catch (Exception e) { + logger.warn("Error while visiting mod dir"); + } + } + + @Override + public Stream scanCandidates() { + Path modFolder = FMLPaths.MODSDIR.get(); + logger.warn("Mod folder {}", modFolder); + visitModDir(modFolder); + logger.warn("Mod path {}", modPath); + return Stream.ofNullable(modPath); + } + + @Override + public String name() { + return "MoreCrashInfoModLocator"; + } + + @Override + public void initArguments(Map arguments) { + + } +} diff --git a/src/main/java/me/xfl03/morecrashinfo/handler/CrashHandler.java b/src/main/java/me/xfl03/morecrashinfo/handler/CrashHandler.java index 215d039..133e8d5 100644 --- a/src/main/java/me/xfl03/morecrashinfo/handler/CrashHandler.java +++ b/src/main/java/me/xfl03/morecrashinfo/handler/CrashHandler.java @@ -11,12 +11,12 @@ public class CrashHandler { private static final Map, Function> handlers = new HashMap<>(); - static { - CrashHandler.registerHandler(VerifyError.class, VerifyErrorHandler::new); - - net.minecraftforge.fml.CrashReportCallables.registerCrashCallable(new ModList());// 1.16.5- net.minecraftforge.fml.CrashReportExtender - net.minecraftforge.fml.CrashReportCallables.registerCrashCallable(new CoreModList());// 1.16.5- net.minecraftforge.fml.CrashReportExtender - } +// private static void init() { +// CrashHandler.registerHandler(VerifyError.class, VerifyErrorHandler::new); +// +// net.minecraftforge.fml.CrashReportCallables.registerCrashCallable(new ModList());// 1.16.5- net.minecraftforge.fml.CrashReportExtender +// net.minecraftforge.fml.CrashReportCallables.registerCrashCallable(new CoreModList());// 1.16.5- net.minecraftforge.fml.CrashReportExtender +// } private static ExceptionHandler handler; @@ -27,17 +27,24 @@ public static void registerHandler(Class exception, Function { + private static MethodNode redirectStaticMethod(MethodNode method, String className) { + Type[] args = Type.getArgumentTypes(method.desc); + int returnOp = -1; + for (AbstractInsnNode insnNode : method.instructions) { + if (insnNode.getOpcode() != -1) { + returnOp = insnNode.getOpcode(); + } + } + method.instructions.clear(); +// method.maxStack = Math.max(argNum, returnOp == Opcodes.RETURN ? 0 : 1); + + for (int i = 0; i < args.length; ++i) { + TransformerService.logger.info("ALOAD {}", i); + method.instructions.add(new VarInsnNode(Opcodes.ALOAD, i)); + } + TransformerService.logger.info("INVOKESTATIC {} {} {}", className, method.name, method.desc); + method.instructions.add(new MethodInsnNode( + Opcodes.INVOKESTATIC, className, method.name, method.desc, false)); + TransformerService.logger.info("{}", returnOp); + method.instructions.add(new InsnNode(returnOp)); + + return method; + } + + @Override + public @NotNull MethodNode transform(MethodNode input, ITransformerVotingContext context) { + TransformerService.logger.info("Transforming {} {}", input.name, input.desc); + return redirectStaticMethod(input, "me/xfl03/morecrashinfo/handler/CrashHandler"); + } + + @Override + public @NotNull TransformerVoteResult castVote(ITransformerVotingContext context) { + return TransformerVoteResult.YES; + } + + @Override + public @NotNull Set targets() { + Set targets = new LinkedHashSet<>(); + //Minecraft 1.16- + targets.add(Target.targetMethod( + "net/minecraftforge/fml/CrashReportExtender", + "addCrashReportHeader", + "(Ljava/lang/StringBuilder;Lnet/minecraft/crash/CrashReport;)V" + )); + targets.add(Target.targetMethod( + "net/minecraftforge/fml/CrashReportExtender", + "generateEnhancedStackTrace", + "(Ljava/lang/Throwable;)Ljava/lang/String;" + )); + //Minecraft 1.17 + targets.add(Target.targetMethod( + "net/minecraftforge/fmllegacy/CrashReportExtender", + "addCrashReportHeader", + "(Ljava/lang/StringBuilder;Lnet/minecraft/CrashReport;)V" + )); + targets.add(Target.targetMethod( + "net/minecraftforge/fmllegacy/CrashReportExtender", + "generateEnhancedStackTrace", + "(Ljava/lang/Throwable;)Ljava/lang/String;" + )); + //Minecraft 1.18+ + targets.add(Target.targetMethod( + "net/minecraftforge/logging/CrashReportExtender", + "addCrashReportHeader", + "(Ljava/lang/StringBuilder;Lnet/minecraft/CrashReport;)V" + )); + targets.add(Target.targetMethod( + "net/minecraftforge/logging/CrashReportExtender", + "generateEnhancedStackTrace", + "(Ljava/lang/Throwable;)Ljava/lang/String;" + )); + return targets; + } +} diff --git a/src/main/java/me/xfl03/morecrashinfo/modlauncher/CustomCrashExtenderTransformer.java b/src/main/java/me/xfl03/morecrashinfo/modlauncher/CustomCrashExtenderTransformer.java new file mode 100644 index 0000000..f02d910 --- /dev/null +++ b/src/main/java/me/xfl03/morecrashinfo/modlauncher/CustomCrashExtenderTransformer.java @@ -0,0 +1,31 @@ +package me.xfl03.morecrashinfo.modlauncher; + +import cpw.mods.modlauncher.api.ITransformer; +import cpw.mods.modlauncher.api.ITransformerVotingContext; +import cpw.mods.modlauncher.api.TransformerVoteResult; +import org.jetbrains.annotations.NotNull; +import org.objectweb.asm.tree.ClassNode; + +import java.util.LinkedHashSet; +import java.util.Set; + +public class CustomCrashExtenderTransformer implements ITransformer { + @Override + public @NotNull ClassNode transform(ClassNode input, ITransformerVotingContext context) { + TransformerService.logger.info("Transforming class {}", input.name); + input.interfaces.removeIf(it -> it.equals("net/minecraftforge/fml/common/ICrashCallable")); + return input; + } + + @Override + public @NotNull TransformerVoteResult castVote(ITransformerVotingContext context) { + return TransformerVoteResult.YES; + } + + @Override + public @NotNull Set targets() { + Set targets = new LinkedHashSet<>(); + targets.add(Target.targetClass("me/xfl03/morecrashinfo/crash/CustomCrashExtender")); + return targets; + } +} diff --git a/src/main/java/me/xfl03/morecrashinfo/modlauncher/TransformerService.java b/src/main/java/me/xfl03/morecrashinfo/modlauncher/TransformerService.java new file mode 100644 index 0000000..2d4b3da --- /dev/null +++ b/src/main/java/me/xfl03/morecrashinfo/modlauncher/TransformerService.java @@ -0,0 +1,36 @@ +package me.xfl03.morecrashinfo.modlauncher; + +import cpw.mods.modlauncher.api.IEnvironment; +import cpw.mods.modlauncher.api.ITransformationService; +import cpw.mods.modlauncher.api.ITransformer; +import cpw.mods.modlauncher.api.IncompatibleEnvironmentException; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +public class TransformerService implements ITransformationService { + public static Logger logger; + + @Override + public @NotNull String name() { + return "MoreCrashInfoTransformerService"; + } + + @Override + public void onLoad(IEnvironment env, Set otherServices) throws IncompatibleEnvironmentException { + logger = LogManager.getLogger("MoreCrashInfoTransformerService"); + } + + @Override + public void initialize(IEnvironment environment) { + } + + @Override + public @NotNull List transformers() { + return Arrays.asList(new CustomCrashExtenderTransformer(), new CrashReportExtenderTransformer()); + } +} diff --git a/src/main/resources/META-INF/coremods.json b/src/main/resources/META-INF/coremods.json deleted file mode 100644 index 697078e..0000000 --- a/src/main/resources/META-INF/coremods.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "crashtransformers": "crashtransformers.js" -} \ No newline at end of file diff --git a/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService b/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService new file mode 100644 index 0000000..8fecf3a --- /dev/null +++ b/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ITransformationService @@ -0,0 +1 @@ +me.xfl03.morecrashinfo.modlauncher.TransformerService \ No newline at end of file diff --git a/src/main/resources/META-INF/services/net.minecraftforge.forgespi.locating.IModLocator b/src/main/resources/META-INF/services/net.minecraftforge.forgespi.locating.IModLocator new file mode 100644 index 0000000..be0ac8f --- /dev/null +++ b/src/main/resources/META-INF/services/net.minecraftforge.forgespi.locating.IModLocator @@ -0,0 +1 @@ +me.xfl03.morecrashinfo.fml.ModLocator \ No newline at end of file diff --git a/src/main/resources/crashtransformers.js b/src/main/resources/crashtransformers.js deleted file mode 100644 index 6eb69fa..0000000 --- a/src/main/resources/crashtransformers.js +++ /dev/null @@ -1,73 +0,0 @@ -var InsnNode = Java.type('org.objectweb.asm.tree.InsnNode'); -var MethodInsnNode = Java.type('org.objectweb.asm.tree.MethodInsnNode'); -var VarInsnNode = Java.type('org.objectweb.asm.tree.VarInsnNode'); -var Opcodes = Java.type('org.objectweb.asm.Opcodes'); - -var ASMAPI = Java.type('net.minecraftforge.coremod.api.ASMAPI'); - -function transformCrashReportExtenderTransformer(cn) { - ASMAPI.log("INFO", "Transform class {}", cn.name); - cn.methods.forEach(function (mn) { - if (mn.name === 'addCrashReportHeader' && mn.desc === '(Ljava/lang/StringBuilder;Lnet/minecraft/crash/CrashReport;)V') { - ASMAPI.log("INFO", "Transform method {} {}", mn.name, mn.desc); - mn.instructions.clear(); - mn.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); - mn.instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); - mn.instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, - "me/xfl03/morecrashinfo/handler/CrashHandler", - "addCrashReportHeader", - "(Ljava/lang/StringBuilder;Lnet/minecraft/crash/CrashReport;)V", false)); - mn.instructions.add(new InsnNode(Opcodes.RETURN)); - ASMAPI.log("INFO", "Transform method finished"); - } else if (mn.name === 'addCrashReportHeader' && mn.desc === '(Ljava/lang/StringBuilder;Lnet/minecraft/CrashReport;)V') { - ASMAPI.log("INFO", "Transform method {} {}", mn.name, mn.desc); - mn.instructions.clear(); - mn.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); - mn.instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); - mn.instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, - "me/xfl03/morecrashinfo/handler/CrashHandler", - "addCrashReportHeader", - "(Ljava/lang/StringBuilder;Lnet/minecraft/CrashReport;)V", false)); - mn.instructions.add(new InsnNode(Opcodes.RETURN)); - ASMAPI.log("INFO", "Transform method finished"); - } else if (mn.name === 'generateEnhancedStackTrace' && mn.desc === '(Ljava/lang/Throwable;)Ljava/lang/String;') { - ASMAPI.log("INFO", "Transform method {} {}", mn.name, mn.desc); - mn.instructions.clear(); - mn.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); - mn.instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, - "me/xfl03/morecrashinfo/handler/CrashHandler", - "generateEnhancedStackTrace", - "(Ljava/lang/Throwable;)Ljava/lang/String;", false)); - mn.instructions.add(new InsnNode(Opcodes.ARETURN)); - ASMAPI.log("INFO", "Transform method finished"); - } - }); - ASMAPI.log("INFO", "Transform class finished"); - return cn; -} - -function initializeCoreMod() { - return { - 'CrashReportExtenderTransformer 13-16': { - 'target': { - 'type': 'CLASS', - 'name': 'net/minecraftforge/fml/CrashReportExtender' - }, - 'transformer': transformCrashReportExtenderTransformer - }, - 'CrashReportExtenderTransformer 17': { - 'target': { - 'type': 'CLASS', - 'name': 'net/minecraftforge/fmllegacy/CrashReportExtender' - }, - 'transformer': transformCrashReportExtenderTransformer - }, - 'CrashReportExtenderTransformer 18-19': { - 'target': { - 'type': 'CLASS', - 'name': 'net/minecraftforge/logging/CrashReportExtender' - }, - 'transformer': transformCrashReportExtenderTransformer - } - } -} \ No newline at end of file