diff --git a/build.gradle b/build.gradle index df9ff55b..cd63f8b7 100644 --- a/build.gradle +++ b/build.gradle @@ -80,9 +80,9 @@ dependencies { implementation ('net.minecraftforge:binarypatcher:1.1.1') implementation ('org.cadixdev:lorenz:0.5.3') implementation ('org.cadixdev:lorenz-asm:0.5.3') - implementation ('net.minecraftforge.gradle:ForgeGradle:3.0.179') implementation ('net.minecraftforge:accesstransformers:2.2.0') implementation ('de.oceanlabs.mcp:mcinjector:3.8.0') + implementation ('net.md-5:SpecialSource:1.8.3') // Forge injection forgeInjectShadow ('net.fabricmc:tiny-mappings-parser:0.2.2.14') diff --git a/src/main/java/net/fabricmc/loom/providers/MinecraftPatchedProvider.java b/src/main/java/net/fabricmc/loom/providers/MinecraftPatchedProvider.java index bdaea503..dafa09eb 100644 --- a/src/main/java/net/fabricmc/loom/providers/MinecraftPatchedProvider.java +++ b/src/main/java/net/fabricmc/loom/providers/MinecraftPatchedProvider.java @@ -25,18 +25,19 @@ package net.fabricmc.loom.providers; import com.google.common.collect.ImmutableMap; +import com.google.gson.JsonParser; import de.oceanlabs.mcp.mcinjector.adaptors.ParameterAnnotationFixer; import net.fabricmc.loom.util.*; import net.fabricmc.loom.util.function.FsPathConsumer; import net.fabricmc.loom.util.srg.InnerClassRemapper; +import net.fabricmc.loom.util.srg.SpecialSourceExecutor; import net.fabricmc.mapping.tree.TinyTree; import net.fabricmc.tinyremapper.OutputConsumerPath; import net.fabricmc.tinyremapper.TinyRemapper; import net.minecraftforge.accesstransformer.TransformerProcessor; import net.minecraftforge.binarypatcher.ConsoleTool; -import net.minecraftforge.gradle.mcp.util.MCPRuntime; -import net.minecraftforge.gradle.mcp.util.MCPWrapper; import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; import org.apache.commons.io.output.NullOutputStream; import org.gradle.api.Project; import org.gradle.api.logging.Logger; @@ -52,6 +53,8 @@ import org.zeroturnaround.zip.ZipUtil; import java.io.*; import java.net.URI; import java.net.URISyntaxException; +import java.net.URL; +import java.nio.charset.StandardCharsets; import java.nio.file.FileSystem; import java.nio.file.*; import java.util.*; @@ -192,27 +195,33 @@ public class MinecraftPatchedProvider extends DependencyProvider { } private void createSrgJars(Logger logger) throws Exception { - // TODO: FORGE: Get rid of *this* - logger.lifecycle(":remapping minecraft (MCPRuntime, official -> srg)"); - McpConfigProvider mcpProvider = getExtension().getMcpConfigProvider(); - File root = new File(getExtension().getUserCache(), "mcp_root"); - root.mkdirs(); - MCPWrapper wrapper = new MCPWrapper(mcpProvider.getMcp(), root); - // Client - { - MCPRuntime runtime = wrapper.getRuntime(getProject(), "client"); - File output = runtime.execute(logger, "rename"); - FileUtils.copyFile(output, minecraftClientSrgJar); + logger.lifecycle(":remapping minecraft (SpecialSource, official -> srg)"); + MinecraftProvider minecraftProvider = getExtension().getMinecraftProvider(); + + String[] mappingsPath = {null}; + if (!ZipUtil.handle(mcpProvider.getMcp(), "config.json", (in, zipEntry) -> { + mappingsPath[0] = new JsonParser().parse(new InputStreamReader(in)).getAsJsonObject().get("data").getAsJsonObject().get("mappings").getAsString(); + })) { + throw new IllegalStateException("Failed to find 'config.json' in " + mcpProvider.getMcp().getAbsolutePath() + "!"); } - // Server - { - MCPRuntime runtime = wrapper.getRuntime(getProject(), "server"); - File output = runtime.execute(logger, "rename"); - FileUtils.copyFile(output, minecraftServerSrgJar); + Path[] tmpSrg = {null}; + if (!ZipUtil.handle(mcpProvider.getMcp(), mappingsPath[0], (in, zipEntry) -> { + tmpSrg[0] = Files.createTempFile(null, null); + try (BufferedWriter writer = Files.newBufferedWriter(tmpSrg[0])) { + IOUtils.copy(in, writer, StandardCharsets.UTF_8); + } + })) { + throw new IllegalStateException("Failed to find mappings '" + mappingsPath[0] + "' in " + mcpProvider.getMcp().getAbsolutePath() + "!"); } + + File specialSourceJar = new File(getExtension().getUserCache(), "SpecialSource-1.8.3-shaded.jar"); + DownloadUtil.downloadIfChanged(new URL("https://repo1.maven.org/maven2/net/md-5/SpecialSource/1.8.3/SpecialSource-1.8.3-shaded.jar"), specialSourceJar, getProject().getLogger(), true); + + Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), specialSourceJar,minecraftProvider.minecraftClientJar.toPath(), tmpSrg[0]), minecraftClientSrgJar.toPath()); + Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), specialSourceJar, minecraftProvider.minecraftServerJar.toPath(), tmpSrg[0]), minecraftServerSrgJar.toPath()); } private void fixParameterAnnotation(File jarFile) throws Exception { @@ -319,9 +328,9 @@ public class MinecraftPatchedProvider extends DependencyProvider { Path input = environment.patchedSrgJar.apply(this).toPath(); Path output = environment.patchedOfficialJar.apply(this).toPath(); - + Files.deleteIfExists(output); - + TinyRemapper remapper = TinyRemapper.newRemapper() .withMappings(TinyRemapperMappingsHelper.create(mappingsWithSrg, "srg", "official", true)) .withMappings(InnerClassRemapper.of(input, mappingsWithSrg, "srg", "official")) @@ -349,10 +358,7 @@ public class MinecraftPatchedProvider extends DependencyProvider { future.get(); } } - - - private void patchJars(Logger logger) throws Exception { logger.lifecycle(":patching jars"); diff --git a/src/main/java/net/fabricmc/loom/util/srg/AtRemapper.java b/src/main/java/net/fabricmc/loom/util/srg/AtRemapper.java index b08fdcb9..7b9d9e12 100644 --- a/src/main/java/net/fabricmc/loom/util/srg/AtRemapper.java +++ b/src/main/java/net/fabricmc/loom/util/srg/AtRemapper.java @@ -26,7 +26,7 @@ package net.fabricmc.loom.util.srg; import net.fabricmc.loom.util.function.CollectionUtil; import net.fabricmc.mapping.tree.TinyTree; -import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.util.Strings; import org.gradle.api.logging.Logger; import org.zeroturnaround.zip.ZipUtil; import org.zeroturnaround.zip.transform.StringZipEntryTransformer; @@ -52,15 +52,15 @@ public final class AtRemapper { protected String transform(ZipEntry zipEntry, String input) { String[] lines = input.split("\n"); List output = new ArrayList<>(lines.length); - + for (int i = 0; i < lines.length; i++) { String line = lines[i].trim(); - - if (line.startsWith("#") || StringUtils.isBlank(line)) { + + if (line.startsWith("#") || Strings.isBlank(line)) { output.add(i, line); continue; } - + String[] parts = line.split("\\s+"); if (parts.length < 2) { logger.warn("Invalid AT Line: " + line); @@ -82,15 +82,15 @@ public final class AtRemapper { }); } } - + output.add(i, String.join(" ", parts)); } - + return String.join("\n", output); } }))}); } - + private static String remapDescriptor(String original, UnaryOperator classMappings) { try { StringReader reader = new StringReader(original); diff --git a/src/main/java/net/fabricmc/loom/util/srg/SpecialSourceExecutor.java b/src/main/java/net/fabricmc/loom/util/srg/SpecialSourceExecutor.java new file mode 100644 index 00000000..b5765ae1 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/util/srg/SpecialSourceExecutor.java @@ -0,0 +1,78 @@ +package net.fabricmc.loom.util.srg; + +import com.google.common.collect.ImmutableMap; +import net.fabricmc.loom.LoomGradleExtension; +import org.apache.commons.io.IOUtils; +import org.gradle.api.Project; +import org.gradle.api.tasks.JavaExec; +import org.gradle.util.GradleVersion; +import org.zeroturnaround.zip.ZipUtil; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.nio.file.*; +import java.util.Arrays; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +public class SpecialSourceExecutor { + public static Path produceSrgJar(Project project, File specialSourceJar, Path officialJar, Path srgPath) throws Exception { + Set filter = Files.readAllLines(srgPath, StandardCharsets.UTF_8).stream() + .filter(s -> !s.startsWith("\t")) + .map(s -> s.split(" ")[0] + ".class") + .collect(Collectors.toSet()); + Path stripped = project.getExtensions().getByType(LoomGradleExtension.class).getProjectBuildCache().toPath().resolve(officialJar.getFileName().toString().substring(0, officialJar.getFileName().toString().length() - 3) + "-filtered.jar"); + Files.deleteIfExists(stripped); + try (FileSystem strippedFs = FileSystems.newFileSystem(URI.create("jar:" + stripped.toUri()), ImmutableMap.of("create", true))) { + ZipUtil.iterate(officialJar.toFile(), (in, zipEntry) -> { + if (filter.contains(zipEntry.getName())) { + Path path = strippedFs.getPath(zipEntry.getName()); + if (path.getParent() != null) { + Files.createDirectories(path.getParent()); + } + Files.write(path, IOUtils.toByteArray(in), StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW); + } + }); + } + Path output = tmpFile(); + + String[] args = new String[]{ + "--in-jar", + stripped.toAbsolutePath().toString(), + "--out-jar", + output.toAbsolutePath().toString(), + "--srg-in", + srgPath.toAbsolutePath().toString() + }; + + JavaExec java = project.getTasks().create("PleaseIgnore_JavaExec_" + UUID.randomUUID().toString().replace("-", ""), JavaExec.class); + java.setArgs(Arrays.asList(args)); + java.setClasspath(project.files(specialSourceJar)); + java.setWorkingDir(tmpDir().toFile()); + java.setMain("net.md_5.specialsource.SpecialSource"); + java.setStandardOutput(System.out); + java.exec(); + if (GradleVersion.current().compareTo(GradleVersion.version("6.0.0")) >= 0) { + java.setEnabled(false); + } else { + project.getTasks().remove(java); + } + + // TODO: Figure out why doing this produces a different result? Possible different class path? + // SpecialSource.main(args); + + Files.deleteIfExists(stripped); + return output; + } + + private static Path tmpFile() throws IOException { + return Files.createTempFile(null, null); + } + + private static Path tmpDir() throws IOException { + return Files.createTempDirectory(null); + } +}