diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 43723b8..2b75c4e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,6 +20,7 @@ jobs: "--forge --version 1.21.11-61.1.0", "--forge --version 1.20.1-47.4.0", "--forge --version 1.12.2-14.23.5.2859 --mappings snapshot:20171003-1.12", + "--forge --version 26.1-62.0.0", "--client --version 1.20.1", "--server --version 1.20.1", "--mc --version 1.20.1", diff --git a/settings.gradle b/settings.gradle index fb50dc5..48ae8b0 100644 --- a/settings.gradle +++ b/settings.gradle @@ -31,7 +31,7 @@ dependencyResolutionManagement.versionCatalogs.register('libs') { library 'gson', 'com.google.code.gson', 'gson' version '2.10.1' library 'jopt', 'net.sf.jopt-simple', 'jopt-simple' version '6.0-alpha-3' library 'jver', 'net.minecraftforge', 'java-provisioner' version '2.0.4' - library 'srgutils', 'net.minecraftforge', 'srgutils' version '0.6.1' + library 'srgutils', 'net.minecraftforge', 'srgutils' version '0.6.3' library 'diff', 'io.codechicken', 'DiffPatch' version '2.0.0.36' // Fuzzy patching library 'fastcsv', 'de.siegmar', 'fastcsv' version '3.4.0' diff --git a/src/main/java/net/minecraftforge/mcmaven/impl/mappings/Mappings.java b/src/main/java/net/minecraftforge/mcmaven/impl/mappings/Mappings.java index c6438a2..80db428 100644 --- a/src/main/java/net/minecraftforge/mcmaven/impl/mappings/Mappings.java +++ b/src/main/java/net/minecraftforge/mcmaven/impl/mappings/Mappings.java @@ -5,16 +5,21 @@ package net.minecraftforge.mcmaven.impl.mappings; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; import net.minecraftforge.mcmaven.impl.Mavenizer; +import net.minecraftforge.mcmaven.impl.repo.mcpconfig.MCPConfigRepo; import net.minecraftforge.mcmaven.impl.repo.mcpconfig.MCPSide; import net.minecraftforge.mcmaven.impl.repo.mcpconfig.MinecraftTasks; import net.minecraftforge.mcmaven.impl.util.Artifact; @@ -153,12 +158,19 @@ public Task getCsvZip(MCPSide side) { var mc = side.getMCP().getMinecraftTasks(); var srg = side.getTasks().getMappings(); - var client = mc.versionFile(MinecraftTasks.MCFile.CLIENT_MAPPINGS); - var server = mc.versionFile(MinecraftTasks.MCFile.SERVER_MAPPINGS); - ret = Task.named("srg2names[" + this + ']', - Task.deps(srg, client, server), - () -> getMappings(side, srg, client, server) - ); + + if (MCPConfigRepo.isObfuscated(mc.getVersion())) { + var client = mc.versionFile(MinecraftTasks.MCFile.CLIENT_MAPPINGS); + var server = mc.versionFile(MinecraftTasks.MCFile.SERVER_MAPPINGS); + ret = Task.named("srg2names[" + this + ']', + Task.deps(srg, client, server), + () -> getMappings(side, srg, client, server) + ); + } else { + // Create an empty srg->mapped zip file when requested. This is needed by old MCPConfig setups until we bump it to a version that doesn't require the concept of mappings at all + ret = Task.named("srg2names[" + this + "][Empty]", () -> makeEmptyCsv(side)); + } + tasks.put(key, ret); return ret; } @@ -187,6 +199,36 @@ private Task getTsrg(MCPSide side, Tasks type) { return ret; } + private File makeEmptyCsv(MCPSide side) { + var root = getFolder(new File(side.getMCP().getBuildFolder(), "data/mapings")); + var output = new File(root, "official.zip"); + + var cache = Util.cache(output); + + if (Mavenizer.checkCache(output, cache)) + return output; + + if (!output.getParentFile().exists()) + output.getParentFile().mkdirs(); + + byte[] header = String.join(",", "searge", "name", "side", "desc").getBytes(StandardCharsets.UTF_8); + + try (var fos = new FileOutputStream(output); + var out = new ZipOutputStream(fos)) { + out.putNextEntry(new ZipEntry("fields.csv")); + out.write(header); + out.closeEntry(); + out.putNextEntry(new ZipEntry("methods.csv")); + out.write(header); + out.closeEntry(); + } catch (IOException e) { + Util.sneak(e); + } + + cache.save(); + return output; + } + private File getMappings(MCPSide side, Task srgMappings, Task clientTask, Task serverTask) { var tool = side.getMCP().getCache().maven().download(Constants.INSTALLER_TOOLS); diff --git a/src/main/java/net/minecraftforge/mcmaven/impl/repo/Repo.java b/src/main/java/net/minecraftforge/mcmaven/impl/repo/Repo.java index 6191959..f3e3e8c 100644 --- a/src/main/java/net/minecraftforge/mcmaven/impl/repo/Repo.java +++ b/src/main/java/net/minecraftforge/mcmaven/impl/repo/Repo.java @@ -8,6 +8,7 @@ import net.minecraftforge.mcmaven.impl.cache.Cache; import net.minecraftforge.mcmaven.impl.data.GradleModule; import net.minecraftforge.mcmaven.impl.mappings.Mappings; +import net.minecraftforge.mcmaven.impl.repo.mcpconfig.MCPConfigRepo; import net.minecraftforge.mcmaven.impl.repo.mcpconfig.MCPSide; import net.minecraftforge.mcmaven.impl.util.Artifact; import net.minecraftforge.mcmaven.impl.util.GradleAttributes; @@ -280,14 +281,23 @@ public PendingArtifact withVariants(Supplier variants) { * channel-verson-map2srg.tsrg.gz: gzip compressed tsrg file for mapped names to srg (intermediate) names */ protected List mappingArtifacts(File cache, Mappings mappings, MCPSide side, Map> outputJson) { + if (outputJson != null) { + outputJson.put("mappings.channel", mappings::channel); + outputJson.put("mappings.version", mappings::version); + } + + // 26.1 has no mappings as they are not obfed, so just output the channel. + // In theory we need to add support for arbitrary mappings not just SRG. + // So i'll have to change this later, but we'll cross that bridge when we come to it. + if (!MCPConfigRepo.isObfuscated(side.getMCP().getMinecraftTasks().getVersion())) + return List.of(); + var coords = mappings.getArtifact(side); var csvs = pending("Mappings Zip", mappings.getCsvZip(side), coords, false); var pom = pending("Mappings POM", simplePom(cache, coords), coords.withExtension("pom"), false); var m2o = pending("Mappings map2obf", mappings.getMapped2Obf(side), coords.withClassifier("map2obf").withExtension("tsrg.gz"), false); var m2s = pending("Mappings map2srg", mappings.getMapped2Srg(side), coords.withClassifier("map2srg").withExtension("tsrg.gz"), false); if (outputJson != null) { - outputJson.put("mappings.channel", mappings::channel); - outputJson.put("mappings.version", mappings::version); outputJson.put("mappings.csv.artifact", csvs.artifact()::toString); outputJson.put("mappings.csv.file", csvs.task().filePathSupplier()); outputJson.put("mappings.obf.artifact", m2o.artifact()::toString); diff --git a/src/main/java/net/minecraftforge/mcmaven/impl/repo/mcpconfig/MCPConfigRepo.java b/src/main/java/net/minecraftforge/mcmaven/impl/repo/mcpconfig/MCPConfigRepo.java index 8fb824e..5d192ff 100644 --- a/src/main/java/net/minecraftforge/mcmaven/impl/repo/mcpconfig/MCPConfigRepo.java +++ b/src/main/java/net/minecraftforge/mcmaven/impl/repo/mcpconfig/MCPConfigRepo.java @@ -101,7 +101,7 @@ public Task getLauncherManifestTask() { // Mojang stopped obfusciating their released with the 26.1-snapshot-1 private static final ComparableVersion LAST_OBFUSCATED = new ComparableVersion("1.21.11"); - public boolean isObfuscated(String version) { + public static boolean isObfuscated(String version) { return new ComparableVersion(version).compareTo(LAST_OBFUSCATED) <= 0; } diff --git a/src/main/java/net/minecraftforge/mcmaven/impl/repo/mcpconfig/MCPTaskFactory.java b/src/main/java/net/minecraftforge/mcmaven/impl/repo/mcpconfig/MCPTaskFactory.java index 18c4c17..468b2c6 100644 --- a/src/main/java/net/minecraftforge/mcmaven/impl/repo/mcpconfig/MCPTaskFactory.java +++ b/src/main/java/net/minecraftforge/mcmaven/impl/repo/mcpconfig/MCPTaskFactory.java @@ -64,8 +64,8 @@ public class MCPTaskFactory { private final Map tasks = new LinkedHashMap<>(); private final Task preStrip; private final Task rawJar; - private final Task mappings; - private final Task srgJar; + private final @Nullable Task mappings; + private final @Nullable Task srgJar; private final Task preDecomp; private final Task last; @@ -172,11 +172,13 @@ public MCPTaskFactory(MCPSide side, File build) { if (rawJar == null) throw except("Could not find `%s` task".formatted(MCPSide.JOINED.equals(side.getName()) ? "merge" : "strip")); - if (mappings == null) - throw except("Could not find `mappings` task"); + if (MCPConfigRepo.isObfuscated(this.cfg.version)) { + if (mappings == null) + throw except("Could not find `mappings` task"); - if (srgJar == null) - throw except("Could not find `rename` task"); + if (srgJar == null) + throw except("Could not find `rename` task"); + } if (predecomp == null) throw except("Could not find `decompile` step"); @@ -209,11 +211,11 @@ public Task getRawJar() { return this.rawJar; } - public Task getMappings() { + public @Nullable Task getMappings() { return this.mappings; } - public Task getSrgJar() { + public @Nullable Task getSrgJar() { return this.srgJar; } @@ -409,11 +411,13 @@ private Task strip(String name, Map step) { private File strip(Task inputTask, boolean whitelist, File output) { var input = inputTask.execute(); - var mappings = this.mappings.execute(); var cache = Util.cache(output) - .add("input", input) - .add("mappings", mappings); + .add("input", input); + + var mappings = this.mappings == null ? null : this.mappings.execute(); + if (mappings != null) + cache.add("mappings", mappings); if (Mavenizer.checkCache(output, cache)) return output; @@ -424,17 +428,28 @@ private File strip(Task inputTask, boolean whitelist, File output) { FileUtils.ensureParent(output); try { - var map = IMappingFile.load(mappings); var classes = new HashSet<>(); - for (var cls : map.getClasses()) - classes.add(cls.getOriginal() + ".class"); + + if (mappings != null) { + var map = IMappingFile.load(mappings); + for (var cls : map.getClasses()) + classes.add(cls.getOriginal() + ".class"); + } try (var is = new JarInputStream(new FileInputStream(input)); var os = new JarOutputStream(new FileOutputStream(output))) { JarEntry entry; while ((entry = is.getNextJarEntry()) != null) { - if (entry.isDirectory() || classes.contains(entry.getName()) != whitelist) + if (entry.isDirectory()) continue; + // If we don't have any mappings, then we're in unobfed 26.1+ so we just want classes + if (classes.isEmpty()) { + if (!entry.getName().endsWith(".class")) + continue; + } else { + if (classes.contains(entry.getName()) != whitelist) + continue; + } os.putNextEntry(FileUtils.getStableEntry(entry)); is.transferTo(os); os.closeEntry(); @@ -722,29 +737,50 @@ public int compareTo(LibLine o) { public Task getExtra() { return Task.named("extra[" + this.side.getName() + ']', Task.deps(this.preStrip, this.mappings), - () -> getExtra(this.preStrip, mappings) + () -> getExtra(this.preStrip, this.mappings) ); } - private File getExtra(Task prestripTask, Task mappingsTask) { + private File getExtra(Task prestripTask, @Nullable Task mappingsTask) { var prestrip = prestripTask.execute(); - var mappings = mappingsTask.execute(); var output = new File(this.build, "extra.jar"); var cache = Util.cache(output) - .add("prestrip", prestrip) - .add("mappings", mappings); + .add("prestrip", prestrip); + + var mappings = mappingsTask == null ? null : mappingsTask.execute(); + if (mappings != null) + cache.add("mappings", mappings); if (Mavenizer.checkCache(output, cache)) return output; try { - var whitelist = IMappingFile - .load(mappings).getClasses().stream() - .map(IMappingFile.IClass::getOriginal) - .collect(Collectors.toSet()); - FileUtils.splitJar(prestrip, whitelist, output, false, false); + if (!output.getParentFile().exists()) + output.getParentFile().mkdirs(); + + // If we don't have mappings then we're in a non-obfed version (26.1+) so just strip out all classes + var whitelist = new HashSet(); + if (mappings != null) { + var map = IMappingFile.load(mappings); + for (var cls : map.getClasses()) + whitelist.add(cls.getOriginal()); + FileUtils.splitJar(prestrip, whitelist, output, false, false); + } else { + try (var zin = new ZipInputStream(new FileInputStream(prestrip)); + var fos = new FileOutputStream(output); + var out = new ZipOutputStream(fos)) { + for (ZipEntry entry = null; (entry = zin.getNextEntry()) != null; ) { + // Skip classes and directories (directories are optional in zips) + if (entry.getName().endsWith(".class") || entry.getName().endsWith("/")) + continue; + out.putNextEntry(new ZipEntry(entry.getName())); + zin.transferTo(out); + out.closeEntry(); + } + } + } } catch (IOException e) { Util.sneak(e); } diff --git a/src/main/java/net/minecraftforge/mcmaven/impl/util/Constants.java b/src/main/java/net/minecraftforge/mcmaven/impl/util/Constants.java index 80bcc6a..1907fba 100644 --- a/src/main/java/net/minecraftforge/mcmaven/impl/util/Constants.java +++ b/src/main/java/net/minecraftforge/mcmaven/impl/util/Constants.java @@ -25,16 +25,16 @@ public final class Constants { public static final String LAUNCHER_MANIFEST = "https://launchermeta.mojang.com/mc/game/version_manifest_v2.json"; public static final String MOJANG_MAVEN = "https://libraries.minecraft.net/"; - public static final Artifact ACCESS_TRANSFORMER = Artifact.from("net.minecraftforge:accesstransformers:8.2.1:fatjar"); + public static final Artifact ACCESS_TRANSFORMER = Artifact.from("net.minecraftforge:accesstransformers:8.2.14:fatjar"); public static final int ACCESS_TRANSFORMER_JAVA_VERSION = 8; - public static final Artifact SIDE_STRIPPER = Artifact.from("net.minecraftforge:mergetool:1.2.0:fatjar"); + public static final Artifact SIDE_STRIPPER = Artifact.from("net.minecraftforge:mergetool:1.2.5:fatjar"); public static final int SIDE_STRIPPER_JAVA_VERSION = 8; - public static final Artifact INSTALLER_TOOLS = Artifact.from("net.minecraftforge:installertools:1.4.3:fatjar"); + public static final Artifact INSTALLER_TOOLS = Artifact.from("net.minecraftforge:installertools:1.4.5:fatjar"); public static final int INSTALLER_TOOLS_JAVA_VERSION = 8; - public static final Artifact RENAMER = Artifact.from("net.minecraftforge:ForgeAutoRenamingTool:1.1.2:all"); + public static final Artifact RENAMER = Artifact.from("net.minecraftforge:renamer:2.0.4:all"); public static final int RENAMER_JAVA_VERSION = 8; public static final Artifact STUBIFY = Artifact.from("net.minecraftforge:jar-stubify:1.0.0");