diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/LaunchProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/LaunchProvider.java index 3eb84dd1..9fc55c0f 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/LaunchProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/LaunchProvider.java @@ -94,9 +94,9 @@ public class LaunchProvider extends DependencyProvider { .property("mixin.env.remapRefMap", "true"); if (getExtension().isUseFabricMixin()) { - launchConfig.property("mixin.forgeloom.inject.mappings.srg-named", getExtension().getMappingsProvider().mixinTinyMappingsWithSrg.getAbsolutePath()); + launchConfig.property("mixin.forgeloom.inject.mappings.srg-named", getExtension().getMappingsProvider().mixinTinyMappingsWithSrg.toAbsolutePath().toString()); } else { - launchConfig.property("net.minecraftforge.gradle.GradleStart.srg.srg-mcp", getExtension().getMappingsProvider().srgToNamedSrg.getAbsolutePath()); + launchConfig.property("net.minecraftforge.gradle.GradleStart.srg.srg-mcp", getExtension().getMappingsProvider().srgToNamedSrg.toAbsolutePath().toString()); } List mixinConfigs = getExtension().getMixinConfigs(); diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/FieldMigratedMappingsProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/FieldMigratedMappingsProvider.java index 24639702..518398df 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/FieldMigratedMappingsProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/FieldMigratedMappingsProvider.java @@ -101,11 +101,15 @@ public class FieldMigratedMappingsProvider extends MappingsProviderImpl { super.provide(dependency, postPopulationScheduler); } + @Override + protected String createMappingsIdentifier(String mappingsName, String version, String classifier) { + return super.createMappingsIdentifier(mappingsName, version, classifier) + "-forge-" + getExtension().getPatchProvider().forgeVersion; + } + @Override public void manipulateMappings(Path mappingsJar) throws IOException { LoomGradleExtension extension = getExtension(); - Path mappingsFolder = getMappedVersionedDir(removeSuffix).resolve("forge/" + extension.getPatchProvider().forgeVersion); - this.rawTinyMappings = tinyMappings.toPath(); + this.rawTinyMappings = tinyMappings; this.rawTinyMappingsWithSrg = tinyMappingsWithSrg; String mappingsJarName = mappingsJar.getFileName().toString(); @@ -116,17 +120,8 @@ public class FieldMigratedMappingsProvider extends MappingsProviderImpl { } } - try { - Files.createDirectories(mappingsFolder); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - - tinyMappings = mappingsFolder.resolve("mappings.tiny").toFile(); - tinyMappingsJar = mappingsFolder.resolve("mappings.jar").toFile(); - tinyMappingsWithSrg = mappingsFolder.resolve("mappings-srg.tiny"); - mixinTinyMappingsWithSrg = mappingsFolder.resolve("mixin-srg.tiny").toFile(); - srgToNamedSrg = mappingsFolder.resolve("srg-to-named.srg").toFile(); + tinyMappings = mappingsWorkingDir().resolve("mappings-updated.tiny"); + tinyMappingsWithSrg = mappingsWorkingDir().resolve("mappings-srg-updated.tiny"); try { updateFieldMigration(); @@ -143,10 +138,10 @@ public class FieldMigratedMappingsProvider extends MappingsProviderImpl { map.put(entry.getKey().owner + "#" + entry.getKey().field, entry.getValue()); }); Files.writeString(migratedFieldsCache, new Gson().toJson(map)); - Files.deleteIfExists(tinyMappings.toPath()); + Files.deleteIfExists(tinyMappings); } - if (!Files.exists(tinyMappings.toPath())) { + if (!Files.exists(tinyMappings)) { Table fieldDescriptorMap = HashBasedTable.create(); for (Map.Entry entry : migratedFields) { @@ -173,7 +168,7 @@ public class FieldMigratedMappingsProvider extends MappingsProviderImpl { } } - Files.writeString(tinyMappings.toPath(), MappingsUtils.serializeToString(mappings), StandardOpenOption.CREATE); + Files.writeString(tinyMappings, MappingsUtils.serializeToString(mappings), StandardOpenOption.CREATE); } } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java index f6bf99d6..bb2de17d 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/GradleMappingContext.java @@ -64,7 +64,7 @@ public class GradleMappingContext implements MappingContext { @Override public File workingDirectory() { if (workingDir == null) { - workingDir = new File(mappingsProvider().getMappingsDir().toFile(), "layered/" + minecraftProvider().minecraftVersion()); + workingDir = new File(mappingsProvider().mappingsWorkingDir().toFile(), "layered/" + minecraftProvider().minecraftVersion()); if (workingDir.exists()) { try { @@ -80,7 +80,7 @@ public class GradleMappingContext implements MappingContext { @Override public File workingDirectory(String name) { - return new File(minecraftProvider().dir("layered/working_dir/" + workingDirName), name); + return new File(workingDirectory(), name); } @Override diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java index 7767741e..edddf340 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java @@ -32,9 +32,13 @@ import java.nio.charset.StandardCharsets; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; +import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.StandardCopyOption; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; +import java.util.List; import java.util.function.Consumer; import com.google.common.base.Stopwatch; @@ -42,6 +46,7 @@ import com.google.common.net.UrlEscapers; import com.google.gson.JsonObject; import org.apache.tools.ant.util.StringUtils; import org.gradle.api.Project; +import org.gradle.api.artifacts.Configuration; import org.zeroturnaround.zip.FileSource; import org.zeroturnaround.zip.ZipEntrySource; import org.zeroturnaround.zip.ZipUtil; @@ -53,10 +58,16 @@ import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor; import net.fabricmc.loom.configuration.processors.JarProcessorManager; import net.fabricmc.loom.configuration.processors.MinecraftProcessedProvider; import net.fabricmc.loom.configuration.providers.MinecraftProviderImpl; +import net.fabricmc.loom.configuration.providers.forge.MinecraftPatchedProvider; +import net.fabricmc.loom.configuration.providers.forge.SrgProvider; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider; import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.DeletingFileVisitor; import net.fabricmc.loom.util.DownloadUtil; +import net.fabricmc.loom.util.srg.MCPReader; +import net.fabricmc.loom.util.srg.SrgMerger; +import net.fabricmc.loom.util.srg.SrgNamedWriter; +import net.fabricmc.mapping.reader.v2.TinyMetadata; import net.fabricmc.mapping.reader.v2.TinyV2Factory; import net.fabricmc.mapping.tree.TinyTree; import net.fabricmc.mappingio.adapter.MappingNsCompleter; @@ -68,9 +79,12 @@ import net.fabricmc.stitch.Command; import net.fabricmc.stitch.commands.CommandProposeFieldNames; import net.fabricmc.stitch.commands.tinyv2.CommandMergeTinyV2; import net.fabricmc.stitch.commands.tinyv2.CommandReorderTinyV2; +import net.fabricmc.stitch.commands.tinyv2.TinyFile; +import net.fabricmc.stitch.commands.tinyv2.TinyV2Writer; public class MappingsProviderImpl extends DependencyProvider implements MappingsProvider { public MinecraftMappedProvider mappedProvider; + public MinecraftPatchedProvider patchedProvider; public String mappingsIdentifier; @@ -82,6 +96,9 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings // The mappings we use in practice public Path tinyMappings; public Path tinyMappingsJar; + public Path tinyMappingsWithSrg; + public Path mixinTinyMappingsWithSrg; // FORGE: The mixin mappings have srg names in intermediary. + public Path srgToNamedSrg; // FORGE: srg to named in srg file format private Path unpickDefinitions; private boolean hasUnpickDefinitions; private UnpickMetadata unpickMetadata; @@ -94,6 +111,13 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings return MappingsCache.INSTANCE.get(tinyMappings); } + public TinyTree getMappingsWithSrg() throws IOException { + if (getExtension().shouldGenerateSrgTiny()) { + return MappingsCache.INSTANCE.get(tinyMappingsWithSrg); + } + throw new UnsupportedOperationException("Not running with Forge support / Tiny srg support."); + } + @Override public void provide(DependencyInfo dependency, Consumer postPopulationScheduler) throws Exception { MinecraftProviderImpl minecraftProvider = getDependencyManager().getProvider(MinecraftProviderImpl.class); @@ -110,13 +134,27 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings initFiles(); if (Files.notExists(tinyMappings) || isRefreshDeps()) { - storeMappings(getProject(), minecraftProvider, mappingsJar.toPath()); + storeMappings(getProject(), minecraftProvider, mappingsJar.toPath(), postPopulationScheduler); } else { try (FileSystem fileSystem = FileSystems.newFileSystem(mappingsJar.toPath(), (ClassLoader) null)) { extractUnpickDefinitions(fileSystem, unpickDefinitions); } } + if (getExtension().isForge()) { + patchedProvider = new MinecraftPatchedProvider(getProject()); + patchedProvider.provide(dependency, postPopulationScheduler); + } + + manipulateMappings(mappingsJar.toPath()); + + if (getExtension().shouldGenerateSrgTiny()) { + if (Files.notExists(tinyMappingsWithSrg) || isRefreshDeps()) { + // Merge tiny mappings with srg + SrgMerger.mergeSrg(getExtension().getSrgProvider().getSrg().toPath(), tinyMappings, tinyMappingsWithSrg, true); + } + } + if (Files.notExists(tinyMappingsJar) || isRefreshDeps()) { ZipUtil.pack(new ZipEntrySource[] {new FileSource("mappings/mappings.tiny", tinyMappings.toFile())}, tinyMappingsJar.toFile()); } @@ -132,6 +170,23 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings populateUnpickClasspath(); } + if (getExtension().isForge()) { + if (!getExtension().shouldGenerateSrgTiny()) { + throw new IllegalStateException("We have to generate srg tiny in a forge environment!"); + } + + if (Files.notExists(mixinTinyMappingsWithSrg) || isRefreshDeps()) { + List lines = new ArrayList<>(Files.readAllLines(tinyMappingsWithSrg)); + lines.set(0, lines.get(0).replace("intermediary", "yraidemretni").replace("srg", "intermediary")); + Files.deleteIfExists(mixinTinyMappingsWithSrg); + Files.write(mixinTinyMappingsWithSrg, lines); + } + + if (Files.notExists(srgToNamedSrg) || isRefreshDeps()) { + SrgNamedWriter.writeTo(getProject().getLogger(), srgToNamedSrg, getMappingsWithSrg(), "srg", "named"); + } + } + addDependency(tinyMappingsJar.toFile(), Constants.Configurations.MAPPINGS_FINAL); LoomGradleExtension extension = getExtension(); @@ -146,7 +201,11 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings extension.setJarProcessorManager(processorManager); processorManager.setupProcessors(); - if (processorManager.active()) { + if (extension.isForge()) { + patchedProvider.finishProvide(); + } + + if (processorManager.active() || (extension.isForge() && patchedProvider.usesProjectCache())) { mappedProvider = new MinecraftProcessedProvider(getProject(), processorManager); getProject().getLogger().lifecycle("Using project based jar storage"); } else { @@ -157,6 +216,8 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings mappedProvider.provide(dependency, postPopulationScheduler); } + public void manipulateMappings(Path mappingsJar) throws IOException { } + private String getMappingsClassifier(DependencyInfo dependency, boolean isV2) { String[] depStringSplit = dependency.getDepString().split(":"); @@ -181,21 +242,36 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings } // We can save reading the zip file + header by checking the file name - return mappingsJar.getName().endsWith("-v2.jar"); + return mappingsJar.getName().endsWith("-v2.jar") || mappingsJar.getName().endsWith("-mergedv2.jar"); } else { return doesJarContainV2Mappings(mappingsJar.toPath()); } } - private void storeMappings(Project project, MinecraftProviderImpl minecraftProvider, Path yarnJar) throws IOException { + private void storeMappings(Project project, MinecraftProviderImpl minecraftProvider, Path yarnJar, Consumer postPopulationScheduler) throws IOException { project.getLogger().info(":extracting " + yarnJar.getFileName()); + if (isMCP(yarnJar)) { + try { + readAndMergeMCP(yarnJar, postPopulationScheduler); + } catch (Exception e) { + throw new RuntimeException(e); + } + + return; + } + try (FileSystem fileSystem = FileSystems.newFileSystem(yarnJar, (ClassLoader) null)) { extractMappings(fileSystem, baseTinyMappings); extractUnpickDefinitions(fileSystem, unpickDefinitions); } - if (areMappingsV2(baseTinyMappings)) { + if (areMappingsMergedV2(baseTinyMappings)) { + // Architectury Loom Patch + // If a merged tiny v2 mappings file is provided + // Skip merging, should save a lot of time + Files.copy(baseTinyMappings, tinyMappings, StandardCopyOption.REPLACE_EXISTING); + } else if (areMappingsV2(baseTinyMappings)) { // These are unmerged v2 mappings mergeAndSaveMappings(project, baseTinyMappings, tinyMappings); } else { @@ -206,16 +282,52 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings } } + private void readAndMergeMCP(Path mcpJar, Consumer postPopulationScheduler) throws Exception { + Path intermediaryTinyPath = getIntermediaryTiny(); + SrgProvider provider = getExtension().getSrgProvider(); + + if (provider == null) { + if (!getExtension().shouldGenerateSrgTiny()) { + Configuration srg = getProject().getConfigurations().maybeCreate(Constants.Configurations.SRG); + srg.setTransitive(false); + } + + provider = new SrgProvider(getProject()); + getProject().getDependencies().add(provider.getTargetConfig(), "de.oceanlabs.mcp:mcp_config:" + getMinecraftProvider().minecraftVersion()); + Configuration configuration = getProject().getConfigurations().getByName(provider.getTargetConfig()); + provider.provide(DependencyInfo.create(getProject(), configuration.getDependencies().iterator().next(), configuration), postPopulationScheduler); + } + + Path srgPath = provider.getSrg().toPath(); + TinyFile file = new MCPReader(intermediaryTinyPath, srgPath).read(mcpJar); + TinyV2Writer.write(file, tinyMappings); + } + + private boolean isMCP(Path path) throws IOException { + try (FileSystem fs = FileSystems.newFileSystem(path, (ClassLoader) null)) { + return Files.exists(fs.getPath("fields.csv")) && Files.exists(fs.getPath("methods.csv")); + } + } + private static boolean areMappingsV2(Path path) throws IOException { try (BufferedReader reader = Files.newBufferedReader(path)) { TinyV2Factory.readMetadata(reader); return true; - } catch (IllegalArgumentException e) { + } catch (IllegalArgumentException | NoSuchFileException e) { // TODO: just check the mappings version when Parser supports V1 in readMetadata() return false; } } + private static boolean areMappingsMergedV2(Path path) throws IOException { + try (BufferedReader reader = Files.newBufferedReader(path)) { + TinyMetadata metadata = TinyV2Factory.readMetadata(reader); + return metadata.getNamespaces().containsAll(Arrays.asList("named", "intermediary", "official")); + } catch (IllegalArgumentException | NoSuchFileException e) { + return false; + } + } + private static boolean doesJarContainV2Mappings(Path path) throws IOException { try (FileSystem fs = FileSystems.newFileSystem(path, (ClassLoader) null)) { try (BufferedReader reader = Files.newBufferedReader(fs.getPath("mappings", "mappings.tiny"))) { @@ -344,6 +456,9 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings tinyMappings = mappingsWorkingDir.resolve("mappings.tiny"); tinyMappingsJar = mappingsWorkingDir.resolve("mappings.jar"); unpickDefinitions = mappingsWorkingDir.resolve("mappings.unpick"); + tinyMappingsWithSrg = mappingsWorkingDir.resolve("mappings-srg.tiny"); + mixinTinyMappingsWithSrg = mappingsWorkingDir.resolve("mappings-mixin-srg.tiny"); + srgToNamedSrg = mappingsWorkingDir.resolve("mappings-srg-named.srg"); if (isRefreshDeps()) { cleanFiles(); @@ -389,7 +504,7 @@ public class MappingsProviderImpl extends DependencyProvider implements Mappings return mappingsWorkingDir; } - private String createMappingsIdentifier(String mappingsName, String version, String classifier) { + protected String createMappingsIdentifier(String mappingsName, String version, String classifier) { // mappingsName . mcVersion . version classifier // Example: net.fabricmc.yarn . 1_16_5 . 1.16.5+build.5 -v2 return mappingsName + "." + getMinecraftProvider().minecraftVersion().replace(' ', '_').replace('.', '_').replace('-', '_') + "." + version + classifier; diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java index 513e457b..a396e5b4 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftMappedProvider.java @@ -353,15 +353,15 @@ public class MinecraftMappedProvider extends DependencyProvider { public void initFiles(MinecraftProviderImpl minecraftProvider, MappingsProviderImpl mappingsProvider) { this.minecraftProvider = minecraftProvider; minecraftIntermediaryJar = new File(getExtension().getMappingsProvider().mappingsWorkingDir().toFile(), "minecraft-intermediary.jar"); - minecraftSrgJar = !getExtension().isForge() ? null : new File(getDirectories().getUserCache(), "minecraft-" + getJarVersionString("srg") + ".jar"); + minecraftSrgJar = !getExtension().isForge() ? null : new File(getExtension().getMappingsProvider().mappingsWorkingDir().toFile(), "minecraft-srg.jar"); minecraftMappedJar = new File(getExtension().getMappingsProvider().mappingsWorkingDir().toFile(), "minecraft-mapped.jar"); inputJar = getExtension().isForge() ? mappingsProvider.patchedProvider.getMergedJar() : minecraftProvider.getMergedJar(); if (getExtension().isForge()) { inputForgeJar = mappingsProvider.patchedProvider.getForgeMergedJar(); - forgeIntermediaryJar = new File(getDirectories().getUserCache(), "forge-" + getJarVersionString("intermediary") + ".jar"); - forgeSrgJar = new File(getDirectories().getUserCache(), "forge-" + getJarVersionString("srg") + ".jar"); - forgeMappedJar = new File(getJarDirectory(getDirectories().getUserCache(), "mapped"), "forge/forge-" + getJarVersionString("mapped") + ".jar"); + forgeIntermediaryJar = new File(getExtension().getMappingsProvider().mappingsWorkingDir().toFile(), "forge-intermediary.jar"); + forgeSrgJar = new File(getExtension().getMappingsProvider().mappingsWorkingDir().toFile(), "forge-srg.jar"); + forgeMappedJar = new File(getExtension().getMappingsProvider().mappingsWorkingDir().toFile(), "forge/forge-mapped.jar"); } } diff --git a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java index 5feeafbe..6ff2c826 100644 --- a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java +++ b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java @@ -166,7 +166,7 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA LayeredMappingSpecBuilder builder = new LayeredMappingSpecBuilder(this); action.execute(builder); LayeredMappingSpec builtSpec = builder.build(); - return new LayeredMappingsDependency(new GradleMappingContext(getProject(), builtSpec.getVersion().replace("+", "_").replace(".", "_")), builtSpec, builtSpec.getVersion()); + return new LayeredMappingsDependency(new GradleMappingContext(getProject()), builtSpec); } protected abstract String getMinecraftVersion();