From 27efc8d9990c1eace5213971dd8fb74bbb5292d0 Mon Sep 17 00:00:00 2001 From: hydos Date: Sat, 23 Apr 2022 12:11:20 -0700 Subject: [PATCH] Why does tiny remapper suck --- build.gradle.kts | 3 +- src/main/java/me/hydos/focu/ForgePatcher.java | 33 +++--- src/main/java/me/hydos/focu/Main.java | 14 ++- .../accesstransformer/AccessTransformer.java | 8 +- .../hydos/focu/mald/logic/MalderMarker.java | 17 --- .../focu/mald/logic/MalderWriterVisitor.java | 5 +- .../mald/logic/read/MalderReaderVisitor.java | 7 +- .../hydos/focu/providers/ForgeProvider.java | 46 ++++++++ .../java/me/hydos/focu/util/MappingUtils.java | 109 +++++++++++------- 9 files changed, 151 insertions(+), 91 deletions(-) delete mode 100644 src/main/java/me/hydos/focu/mald/logic/MalderMarker.java create mode 100644 src/main/java/me/hydos/focu/providers/ForgeProvider.java diff --git a/build.gradle.kts b/build.gradle.kts index cc07cef..8d7a4b2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,9 +12,10 @@ repositories { } dependencies { - implementation("net.fabricmc:tiny-remapper:0.8.1") + implementation("net.fabricmc:tiny-remapper:0.8.2") implementation("net.fabricmc:mapping-io:0.3.0") implementation ("net.minecraftforge:installertools:1.2.10") + implementation ("net.minecraftforge:ForgeAutoRenamingTool:0.1.22") implementation("org.ow2.asm:asm:9.3") implementation("org.ow2.asm:asm-analysis:9.3") diff --git a/src/main/java/me/hydos/focu/ForgePatcher.java b/src/main/java/me/hydos/focu/ForgePatcher.java index 61d2e2c..dcc8ed7 100644 --- a/src/main/java/me/hydos/focu/ForgePatcher.java +++ b/src/main/java/me/hydos/focu/ForgePatcher.java @@ -4,9 +4,11 @@ import me.hydos.focu.mald.logic.MalderLoader; import me.hydos.focu.mald.logic.MalderPatcher; import me.hydos.focu.mald.logic.read.InjectTarget; +import me.hydos.focu.providers.ForgeProvider; import me.hydos.focu.util.FileSystemUtil; import me.hydos.focu.util.MappingUtils; import net.fabricmc.tinyremapper.Main; +import org.objectweb.asm.Opcodes; import java.io.IOException; import java.nio.file.Files; @@ -16,15 +18,14 @@ @SuppressWarnings("ClassCanBeRecord") public class ForgePatcher { + public static final int ASM_VERSION = Opcodes.ASM9; public static final Path WORK_DIR = Paths.get(".work"); - public final Path minecraftDir; + public final ForgeProvider forge; public final MalderLoader malderLoader; - private final String forgeVersion; - public ForgePatcher(Path minecraftDir, MalderLoader malderLoader, String forgeVersion) { - this.minecraftDir = minecraftDir; + public ForgePatcher(ForgeProvider forge, MalderLoader malderLoader) { + this.forge = forge; this.malderLoader = malderLoader; - this.forgeVersion = forgeVersion; try { Files.createDirectories(WORK_DIR); @@ -34,12 +35,10 @@ public ForgePatcher(Path minecraftDir, MalderLoader malderLoader, String forgeVe } public void remapToIntermediary() throws IOException { - Path librariesDir = this.minecraftDir.resolve("libraries"); - Path forgeDir = librariesDir.resolve("net/minecraftforge/forge/" + forgeVersion); - Path clientDir = librariesDir.resolve("net/minecraft/client/1.18.2-20220404.173914/"); - - backupAndRemapJar(forgeDir.resolve("forge-" + forgeVersion + "-universal.jar")); - backupAndRemapJar(clientDir.resolve("client-1.18.2-20220404.173914-srg.jar")); + for (Path target : this.forge.targets()) { + System.out.println("Remapping " + target.getFileName().toString()); + backupAndRemapJar(target); + } } public void apply() { @@ -48,7 +47,7 @@ public void apply() { } catch (IOException e) { throw new RuntimeException(e); } - +/* Path librariesDir = this.minecraftDir.resolve("libraries"); Path forgePatches = librariesDir.resolve("net/minecraftforge/forge/1.18.2-40.0.52/forge-1.18.2-40.0.52-client.jar"); Path forgeIntermediary = forgePatches.getParent().resolve("forge-intermediary.jar"); @@ -85,10 +84,11 @@ public void apply() { } } catch (IOException e) { throw new RuntimeException("Failed to create output jar!", e); - } + }*/ } + private void backupAndRemapJar(Path inJar, Path outJar) throws IOException { - Path srgToIntermediaryMappings = MappingUtils.getFullMappings(); + Path srgToIntermediaryMappings = MappingUtils.getFullMappings(this.forge.minecraftSrg()); Path backupPath = inJar.getParent().resolve(inJar.getFileName().toString().replace(".jar", ".intermediary-backup.jar")); if (!Files.exists(backupPath)) { @@ -100,8 +100,7 @@ private void backupAndRemapJar(Path inJar, Path outJar) throws IOException { outJar.toAbsolutePath().toString(), srgToIntermediaryMappings.toAbsolutePath().toString(), "srg", - "intermediary", - "--fixPackageAccess" + "intermediary" }); try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(outJar); Stream files = Files.walk(fs.get().getPath("/"))) { @@ -116,7 +115,7 @@ private void backupAndRemapJar(Path inJar, Path outJar) throws IOException { // Hope it's an AccessTransformer AccessTransformer at = AccessTransformer.read(path); System.out.println("Remapping Access Widener"); - at.remap(MappingUtils.getFullMappings()); + at.remap(srgToIntermediaryMappings); System.out.println("Overwriting old Access Widener"); Files.delete(path); at.write(path); diff --git a/src/main/java/me/hydos/focu/Main.java b/src/main/java/me/hydos/focu/Main.java index ff56fd6..ff061b5 100644 --- a/src/main/java/me/hydos/focu/Main.java +++ b/src/main/java/me/hydos/focu/Main.java @@ -1,17 +1,23 @@ package me.hydos.focu; import me.hydos.focu.mald.logic.MalderLoader; +import me.hydos.focu.providers.ForgeProvider; -import java.nio.file.Paths; +import java.nio.file.Path; public class Main { public static void main(String[] args) { - MalderLoader malderLoader = new MalderLoader() - .loadMalder(Paths.get("malders/TitleScreen.class")); + ForgeProvider forge = ForgeProvider.createFromClient( + Path.of("C:/Users/hayde/AppData/Roaming/.minecraft"), + "1.18.2", + "40.1.0" + ); - ForgePatcher patcher = new ForgePatcher(Paths.get("C:/Users/hayde/AppData/Roaming/.minecraft"), malderLoader, "1.18.2-40.0.52"); + MalderLoader malderLoader = new MalderLoader(); + //.loadMalder(Paths.get("malders/TitleScreen.class")); + ForgePatcher patcher = new ForgePatcher(forge, malderLoader); patcher.apply(); } } diff --git a/src/main/java/me/hydos/focu/accesstransformer/AccessTransformer.java b/src/main/java/me/hydos/focu/accesstransformer/AccessTransformer.java index 4c2b39a..95d8061 100644 --- a/src/main/java/me/hydos/focu/accesstransformer/AccessTransformer.java +++ b/src/main/java/me/hydos/focu/accesstransformer/AccessTransformer.java @@ -107,7 +107,7 @@ public void remap(Path srgMappingsFile) throws IOException { this.fieldTransformers.put(fieldTransform, access); } else { MappingTree.FieldMapping fieldMapping = getField(classMapping, fieldTransform.field()); - this.fieldTransformers.put(new FieldTransform(classMapping.getDstName(intermediary), fieldMapping.getSrcName(), fieldTransform.removeFinal()), access); + this.fieldTransformers.put(new FieldTransform(classMapping.getDstName(intermediary), fieldMapping.getDstName(intermediary), fieldTransform.removeFinal()), access); } }); @@ -118,7 +118,7 @@ public void remap(Path srgMappingsFile) throws IOException { this.methodTransformers.put(methodTransform, access); } else { MappingTree.MethodMapping methodMapping = getMethod(classMapping, methodTransform.methodName()); - this.methodTransformers.put(new MethodTransform(classMapping.getDstName(intermediary), methodMapping.getDstDesc(intermediary), remapMethodDesc(srgMappings, methodTransform.methodSig()), methodTransform.removeFinal()), access); + this.methodTransformers.put(new MethodTransform(classMapping.getDstName(intermediary), methodMapping.getDstName(intermediary), methodMapping.getDstDesc(intermediary), methodTransform.removeFinal()), access); } }); } @@ -126,7 +126,7 @@ public void remap(Path srgMappingsFile) throws IOException { private MappingTree.FieldMapping getField(MappingTree.ClassMapping classMapping, String field) { for (MappingTree.FieldMapping fieldMapping : classMapping.getFields()) { - if (field.equals(fieldMapping.getSrcDesc())) { + if (field.equals(fieldMapping.getDstName(1))) { return fieldMapping; } } @@ -135,7 +135,7 @@ private MappingTree.FieldMapping getField(MappingTree.ClassMapping classMapping, private MappingTree.MethodMapping getMethod(MappingTree.ClassMapping classMapping, String methodName) { for (MappingTree.MethodMapping methodMapping : classMapping.getMethods()) { - if (methodName.equals(methodMapping.getSrcDesc())) { + if (methodName.equals(methodMapping.getDstName(1))) { return methodMapping; } } diff --git a/src/main/java/me/hydos/focu/mald/logic/MalderMarker.java b/src/main/java/me/hydos/focu/mald/logic/MalderMarker.java deleted file mode 100644 index e24b711..0000000 --- a/src/main/java/me/hydos/focu/mald/logic/MalderMarker.java +++ /dev/null @@ -1,17 +0,0 @@ -package me.hydos.focu.mald.logic; - -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - -public class MalderMarker extends ClassVisitor { - - protected MalderMarker(MalderWriterVisitor visitor) { - super(Opcodes.ASM9, visitor); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { - return super.visitMethod(access, name, descriptor, "MALD", exceptions); - } -} diff --git a/src/main/java/me/hydos/focu/mald/logic/MalderWriterVisitor.java b/src/main/java/me/hydos/focu/mald/logic/MalderWriterVisitor.java index f0d1ee8..4de9351 100644 --- a/src/main/java/me/hydos/focu/mald/logic/MalderWriterVisitor.java +++ b/src/main/java/me/hydos/focu/mald/logic/MalderWriterVisitor.java @@ -1,5 +1,6 @@ package me.hydos.focu.mald.logic; +import me.hydos.focu.ForgePatcher; import me.hydos.focu.mald.logic.read.InjectTarget; import me.hydos.focu.mald.logic.read.Malder; import org.objectweb.asm.*; @@ -12,7 +13,7 @@ public class MalderWriterVisitor extends ClassVisitor { private final InjectTarget target; public MalderWriterVisitor(ClassVisitor parent, ClassNode malderClass, Malder malder, InjectTarget target) { - super(Opcodes.ASM9, parent); + super(ForgePatcher.ASM_VERSION, parent); this.malderClass = malderClass; this.malder = malder; this.target = target; @@ -41,7 +42,7 @@ private static class MethodWriterVisitor extends MethodVisitor { private final InjectTarget target; protected MethodWriterVisitor(MethodVisitor methodVisitor, MethodNode method, InjectTarget target) { - super(Opcodes.ASM9, methodVisitor); + super(ForgePatcher.ASM_VERSION, methodVisitor); this.method = method; this.target = target; } diff --git a/src/main/java/me/hydos/focu/mald/logic/read/MalderReaderVisitor.java b/src/main/java/me/hydos/focu/mald/logic/read/MalderReaderVisitor.java index 715ccda..220a849 100644 --- a/src/main/java/me/hydos/focu/mald/logic/read/MalderReaderVisitor.java +++ b/src/main/java/me/hydos/focu/mald/logic/read/MalderReaderVisitor.java @@ -1,5 +1,6 @@ package me.hydos.focu.mald.logic.read; +import me.hydos.focu.ForgePatcher; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.MethodVisitor; @@ -11,7 +12,7 @@ public class MalderReaderVisitor extends ClassVisitor { private final MethodAnnotationVisitor methodAnnotationVisitor; public MalderReaderVisitor() { - super(Opcodes.ASM9); + super(ForgePatcher.ASM_VERSION); this.annotationVisitor = new TargetClassAnnotationVisitor(); this.methodAnnotationVisitor = new MethodAnnotationVisitor(this.annotationVisitor); } @@ -35,7 +36,7 @@ private static class MethodAnnotationVisitor extends MethodVisitor { private final AnnotationVisitor annotationVisitor; protected MethodAnnotationVisitor(AnnotationVisitor visitor) { - super(Opcodes.ASM9); + super(ForgePatcher.ASM_VERSION); this.annotationVisitor = visitor; } @@ -50,7 +51,7 @@ private static class TargetClassAnnotationVisitor extends AnnotationVisitor { public Malder malder = new Malder(); protected TargetClassAnnotationVisitor() { - super(Opcodes.ASM9); + super(ForgePatcher.ASM_VERSION); } // FIXME: assumptions bad. Please fix them soon diff --git a/src/main/java/me/hydos/focu/providers/ForgeProvider.java b/src/main/java/me/hydos/focu/providers/ForgeProvider.java new file mode 100644 index 0000000..b2c08ef --- /dev/null +++ b/src/main/java/me/hydos/focu/providers/ForgeProvider.java @@ -0,0 +1,46 @@ +package me.hydos.focu.providers; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.stream.Stream; + +public record ForgeProvider( + List targets, + Path mojmap, + Path minecraftSrg +) { + + public static ForgeProvider createFromClient(Path dotMinecraftDir, String minecraftVersion, String forgeVersion) { + String fullForgeVersion = minecraftVersion + "-" + forgeVersion; + String fullMinecraftVersion = detectFullMinecraftVersion(minecraftVersion, dotMinecraftDir); + Path librariesFolder = dotMinecraftDir.resolve("libraries"); + Path forgeOrgFolder = librariesFolder.resolve("net/minecraftforge/forge/" + fullForgeVersion); + Path minecraftOrgFolder = librariesFolder.resolve("net/minecraft/client/" + fullMinecraftVersion); + + Path mcSrg = minecraftOrgFolder.resolve("client-" + fullMinecraftVersion + "-srg.jar"); + return new ForgeProvider(List.of( + forgeOrgFolder.resolve("forge-" + fullForgeVersion + "-client.jar"), + forgeOrgFolder.resolve("forge-" + fullForgeVersion + "-universal.jar"), + mcSrg + ), minecraftOrgFolder, mcSrg); + } + + private static String detectFullMinecraftVersion(String minecraftVersion, Path dotMinecraftDir) { + try { + try (Stream list = Files.list(dotMinecraftDir.resolve("libraries/net/minecraft/client"))) { + List results = list.filter(Files::isDirectory).filter(path -> path.toString().contains(minecraftVersion)).toList(); + if (results.isEmpty()) { + throw new RuntimeException("Forge Installer has not been run!"); + } else if (results.size() > 1) { + System.out.println("More than one version of " + minecraftVersion + ". Patcher may not work!"); + } + + return minecraftVersion + results.get(0).getFileName().toString().substring(minecraftVersion.length()); + } + } catch (IOException e) { + throw new RuntimeException("Failed to detect full minecraft version", e); + } + } +} diff --git a/src/main/java/me/hydos/focu/util/MappingUtils.java b/src/main/java/me/hydos/focu/util/MappingUtils.java index 8b00316..acf4de8 100644 --- a/src/main/java/me/hydos/focu/util/MappingUtils.java +++ b/src/main/java/me/hydos/focu/util/MappingUtils.java @@ -9,84 +9,56 @@ import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.FieldVisitor; -import org.objectweb.asm.Opcodes; import java.io.IOException; import java.io.Writer; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.List; import java.util.stream.Stream; public class MappingUtils { - public static void fillInFieldSignatures(MemoryMappingTree mappings, Path jar, int namespaceId) throws IOException { - try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(jar); Stream classes = Files.walk(fs.get().getPath("/"))) { - classes.filter(path -> path.getFileName().toString().endsWith(".class")).forEach(path -> { + public static void fillInSignatures(Path srcJar, String dstNamespace, MemoryMappingTree mappings) throws IOException { + try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(srcJar); Stream classes = Files.walk(fs.get().getPath("/")).filter(path -> path.toString().endsWith(".class"))) { + classes.forEach(path -> { try { ClassReader reader = new ClassReader(Files.readAllBytes(path)); - ClassVisitor visitor = new FieldSignatureFillingVisitor(mappings, namespaceId); + ClassVisitor visitor = new SignatureFillingVisitor(dstNamespace, mappings); reader.accept(visitor, 0); } catch (IOException e) { - throw new RuntimeException(e); + throw new RuntimeException("Failed to read class while filling in signatures", e); } }); } } - private static class FieldSignatureFillingVisitor extends ClassVisitor { - - private final MemoryMappingTree mappings; - private final int namespaceId; - private String className; - - protected FieldSignatureFillingVisitor(MemoryMappingTree mappings, int namespaceId) { - super(Opcodes.ASM9); - this.mappings = mappings; - this.namespaceId = namespaceId; - } - - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - this.className = name; - super.visit(version, access, name, signature, superName, interfaces); - } - - @Override - public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { - MappingTree.FieldMapping field; - if(namespaceId == -1) { - // Src Target Namespace - field = this.mappings.getField(this.className, name, descriptor); - } else { - // Dst Target Namespace - field = this.mappings.getField(this.className, name, descriptor, this.namespaceId); - } - System.out.println(field); - return super.visitField(access, name, descriptor, signature, value); - } - } - /** * Generates official -> srg -> intermediary + * * @return A path to a tinyv2 file containing mappings * @throws IOException File IO may fail. */ - public static Path getFullMappings() throws IOException { + public static Path getFullMappings(Path srgMinecraftJar) throws IOException { Path fullMappingsPath = ForgePatcher.WORK_DIR.resolve("complete.tiny"); if (!Files.exists(fullMappingsPath)) { // TODO: pull from http://maven.minecraftforge.net/de/oceanlabs/mcp/mcp_config/1.18.2/mcp_config-1.18.2.zip - // TODO: and find official file. Its in one of the libraries folders. + // TODO: and pull from https://maven.fabricmc.net/net/fabricmc/intermediary/1.18.2/ // TODO: for now assume its already extracted in the work directory Path mcpConfig = ForgePatcher.WORK_DIR.resolve("joined.tsrg"); Path official = Paths.get("C:/Users/hayde/AppData/Roaming/.minecraft/libraries/net/minecraft/client/1.18.2-20220404.173914/client-1.18.2-20220404.173914-mappings.txt"); Path officialToSrg = createForgeMappings(mcpConfig, official); - Path intermediaries = ForgePatcher.WORK_DIR.resolve("intermediary.tiny"); + Path intermediaries = ForgePatcher.WORK_DIR.resolve("mappings.tiny"); MemoryMappingTree fullMappings = new MemoryMappingTree(); - MappingReader.read(officialToSrg, fullMappings); MappingReader.read(intermediaries, fullMappings); + fullMappings.setSrcNamespace("left"); + MappingReader.read(officialToSrg, fullMappings); + fullMappings.setSrcNamespace("official"); + fullMappings.setDstNamespaces(List.of("intermediary", "srg")); + fillInSignatures(srgMinecraftJar, "srg", fullMappings); try (Writer mappingWriter = Files.newBufferedWriter(fullMappingsPath)) { fullMappings.accept(new Tiny2Writer(mappingWriter, false)); @@ -114,4 +86,55 @@ private static Path createForgeMappings(Path mcpConfig, Path official) throws IO }); return mappings; } + + public static String remapFieldDescToSrc(MappingTree mappings, String methodDesc, int fromNamespace) { + int pointer = 0; + StringBuilder result = new StringBuilder(); + while (pointer < methodDesc.length()) { + if (methodDesc.charAt(pointer) == 'L') { + String className = methodDesc.substring(1, methodDesc.indexOf(";")); + MappingTree.ClassMapping classMapping = mappings.getClass(className, fromNamespace); + if(classMapping != null) { + className = classMapping.getSrcName(); + } + result.append("L").append(className).append(";"); + } else { + result.append(methodDesc.charAt(pointer)); + + } + pointer++; + } + return result.toString(); + } + + private static class SignatureFillingVisitor extends ClassVisitor { + + private final MemoryMappingTree mappings; + private final int dstNamespace; + private String className; + + protected SignatureFillingVisitor(String dstNamespace, MemoryMappingTree mappings) { + super(ForgePatcher.ASM_VERSION); + this.mappings = mappings; + this.dstNamespace = this.mappings.getNamespaceId(dstNamespace); + } + + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + this.className = name; + super.visit(version, access, name, signature, superName, interfaces); + } + + @Override + public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { + MappingTree.FieldMapping field = this.mappings.getField(this.className, name, descriptor, this.dstNamespace); + if(field == null) { + throw new RuntimeException("BROKEN JAR!!! REINSTALL FORGE"); + } + if (field.getSrcDesc() == null) { + field.setSrcDesc(remapFieldDescToSrc(this.mappings, descriptor, this.dstNamespace)); + } + return super.visitField(access, name, descriptor, signature, value); + } + } }