diff options
author | shedaniel <daniel@shedaniel.me> | 2021-05-08 12:50:17 +0800 |
---|---|---|
committer | shedaniel <daniel@shedaniel.me> | 2021-05-08 12:50:17 +0800 |
commit | 3f576a44abe93e6f85cd2abe36f5a4a9ec415c9e (patch) | |
tree | 10b3a44809f41b979767b293bb98bbfb1b1bedfc /src | |
parent | d91d7c096ca33d2ba91fb22065b331f102014053 (diff) | |
download | architectury-loom-3f576a44abe93e6f85cd2abe36f5a4a9ec415c9e.tar.gz architectury-loom-3f576a44abe93e6f85cd2abe36f5a4a9ec415c9e.tar.bz2 architectury-loom-3f576a44abe93e6f85cd2abe36f5a4a9ec415c9e.zip |
Migration Mappings Detection
Still having issues with source locations, would need to check it out first
Signed-off-by: shedaniel <daniel@shedaniel.me>
Diffstat (limited to 'src')
9 files changed, 344 insertions, 49 deletions
diff --git a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java index 0fcdec86..039d5991 100644 --- a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java +++ b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java @@ -60,6 +60,7 @@ import net.fabricmc.loom.configuration.launch.LaunchProviderSettings; import net.fabricmc.loom.configuration.processors.JarProcessor; import net.fabricmc.loom.configuration.processors.JarProcessorManager; import net.fabricmc.loom.configuration.providers.MinecraftProvider; +import net.fabricmc.loom.configuration.providers.forge.FieldMigratedMappingsProvider; import net.fabricmc.loom.configuration.providers.forge.ForgeProvider; import net.fabricmc.loom.configuration.providers.forge.ForgeUniversalProvider; import net.fabricmc.loom.configuration.providers.forge.ForgeUserdevProvider; @@ -387,7 +388,7 @@ public class LoomGradleExtension { } public MappingsProvider getMappingsProvider() { - return getDependencyManager().getProvider(MappingsProvider.class); + return getDependencyManager().getProvider(isForge() ? FieldMigratedMappingsProvider.class : MappingsProvider.class); } public McpConfigProvider getMcpConfigProvider() { diff --git a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java index a3e7e448..7b31059d 100644 --- a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java +++ b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java @@ -40,6 +40,7 @@ import net.fabricmc.loom.build.mixin.ScalaApInvoker; import net.fabricmc.loom.configuration.ide.SetupIntelijRunConfigs; import net.fabricmc.loom.configuration.providers.LaunchProvider; import net.fabricmc.loom.configuration.providers.MinecraftProvider; +import net.fabricmc.loom.configuration.providers.forge.FieldMigratedMappingsProvider; import net.fabricmc.loom.configuration.providers.forge.ForgeProvider; import net.fabricmc.loom.configuration.providers.forge.ForgeUniversalProvider; import net.fabricmc.loom.configuration.providers.forge.ForgeUserdevProvider; @@ -173,7 +174,7 @@ public final class CompileConfiguration { dependencyManager.addProvider(new ForgeUniversalProvider(project)); } - dependencyManager.addProvider(new MappingsProvider(project)); + dependencyManager.addProvider(extension.isForge() ? new FieldMigratedMappingsProvider(project) : new MappingsProvider(project)); dependencyManager.addProvider(new LaunchProvider(project)); dependencyManager.handleDependencies(project); diff --git a/src/main/java/net/fabricmc/loom/configuration/LoomDependencyManager.java b/src/main/java/net/fabricmc/loom/configuration/LoomDependencyManager.java index 8b97f81e..d325457b 100644 --- a/src/main/java/net/fabricmc/loom/configuration/LoomDependencyManager.java +++ b/src/main/java/net/fabricmc/loom/configuration/LoomDependencyManager.java @@ -72,7 +72,7 @@ public class LoomDependencyManager { return provider; } - public <T> T getProvider(Class<T> clazz) { + public <T> T getProvider(Class<? extends T> clazz) { for (DependencyProvider provider : dependencyProviderList) { if (provider.getClass() == clazz) { return (T) provider; 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 new file mode 100644 index 00000000..44935cbb --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/FieldMigratedMappingsProvider.java @@ -0,0 +1,258 @@ +package net.fabricmc.loom.configuration.providers.forge; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Consumer; + +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.Table; +import com.google.common.reflect.TypeToken; +import com.google.gson.Gson; +import dev.architectury.mappingslayers.api.mutable.MappingsEntry; +import dev.architectury.mappingslayers.api.mutable.MutableClassDef; +import dev.architectury.mappingslayers.api.mutable.MutableFieldDef; +import dev.architectury.mappingslayers.api.mutable.MutableTinyTree; +import dev.architectury.mappingslayers.api.utils.MappingsUtils; +import dev.architectury.refmapremapper.utils.DescriptorRemapper; +import org.gradle.api.Project; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.Opcodes; + +import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.LoomGradlePlugin; +import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; +import net.fabricmc.loom.util.FileSystemUtil; +import net.fabricmc.loom.util.ThreadingUtils; +import net.fabricmc.loom.util.srg.SrgMerger; +import net.fabricmc.mapping.tree.ClassDef; +import net.fabricmc.mapping.tree.FieldDef; +import net.fabricmc.mapping.tree.TinyMappingFactory; +import net.fabricmc.mapping.tree.TinyTree; + +public class FieldMigratedMappingsProvider extends MappingsProvider { + private List<Map.Entry<FieldMember, String>> migratedFields = new ArrayList<>(); + public Path migratedFieldsCache; + public Path rawTinyMappings; + public Path rawTinyMappingsWithSrg; + + public FieldMigratedMappingsProvider(Project project) { + super(project); + } + + @Override + public void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws Exception { + LoomGradleExtension extension = getExtension(); + PatchProvider patchProvider = getExtension().getPatchProvider(); + migratedFieldsCache = patchProvider.getProjectCacheFolder().resolve("migrated-fields.json"); + migratedFields.clear(); + + if (LoomGradlePlugin.refreshDeps) { + Files.deleteIfExists(migratedFieldsCache); + } else if (Files.exists(migratedFieldsCache)) { + try (BufferedReader reader = Files.newBufferedReader(migratedFieldsCache)) { + Map<String, String> map = new Gson().fromJson(reader, new TypeToken<Map<String, String>>() { + }.getType()); + migratedFields = new ArrayList<>(); + map.forEach((key, newDescriptor) -> { + String[] split = key.split("#"); + migratedFields.add(new AbstractMap.SimpleEntry<>(new FieldMember(split[0], split[1]), newDescriptor)); + }); + } + } + + super.provide(dependency, postPopulationScheduler); + } + + @Override + public void manipulateMappings(Path mappingsJar) throws IOException { + LoomGradleExtension extension = getExtension(); + Path mappingsFolder = mappingsDir.resolve(extension.getMinecraftProvider().getMinecraftVersion() + "/forge-" + extension.getPatchProvider().forgeVersion); + this.rawTinyMappings = tinyMappings.toPath(); + this.rawTinyMappingsWithSrg = tinyMappingsWithSrg; + String mappingsJarName = mappingsJar.getFileName().toString(); + + if (getExtension().shouldGenerateSrgTiny()) { + if (Files.notExists(rawTinyMappingsWithSrg) || isRefreshDeps()) { + // Merge tiny mappings with srg + SrgMerger.mergeSrg(getExtension().getSrgProvider().getSrg().toPath(), rawTinyMappings, rawTinyMappingsWithSrg, true); + } + } + + 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(); + + try { + updateFieldMigration(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public void updateFieldMigration() throws IOException { + if (!Files.exists(migratedFieldsCache)) { + generateNewFieldMigration(); + Map<String, String> map = new HashMap<>(); + migratedFields.forEach(entry -> { + map.put(entry.getKey().owner + "#" + entry.getKey().field, entry.getValue()); + }); + Files.write(migratedFieldsCache, new Gson().toJson(map).getBytes(StandardCharsets.UTF_8)); + Files.deleteIfExists(tinyMappings.toPath()); + } + + if (!Files.exists(tinyMappings.toPath())) { + Table<String, String, String> fieldDescriptorMap = HashBasedTable.create(); + + for (Map.Entry<FieldMember, String> entry : migratedFields) { + fieldDescriptorMap.put(entry.getKey().owner, entry.getKey().field, entry.getValue()); + } + + MutableTinyTree mappings; + + try (BufferedReader reader = Files.newBufferedReader(rawTinyMappings)) { + mappings = MappingsUtils.copyAsMutable(TinyMappingFactory.loadWithDetection(reader)); + + for (MutableClassDef classDef : mappings.getClassesMutable()) { + Map<String, String> row = fieldDescriptorMap.row(classDef.getIntermediary()); + + if (!row.isEmpty()) { + for (MutableFieldDef fieldDef : classDef.getFieldsMutable()) { + String newDescriptor = row.get(fieldDef.getIntermediary()); + + if (newDescriptor != null) { + fieldDef.setDescriptor(MappingsEntry.NS_INTERMEDIARY, newDescriptor); + } + } + } + } + } + + Files.write(tinyMappings.toPath(), MappingsUtils.serializeToString(mappings).getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE); + } + } + + private void generateNewFieldMigration() throws IOException { + Map<FieldMember, String> fieldDescriptorMap = new ConcurrentHashMap<>(); + LoomGradleExtension extension = getExtension(); + ThreadingUtils.TaskCompleter completer = ThreadingUtils.taskCompleter(); + + class Visitor extends ClassVisitor { + private final ThreadLocal<String> lastClass = new ThreadLocal<>(); + + Visitor(int api) { + super(api); + } + + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + lastClass.set(name); + } + + @Override + public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { + fieldDescriptorMap.put(new FieldMember(lastClass.get(), name), descriptor); + return super.visitField(access, name, descriptor, signature, value); + } + } + + Visitor visitor = new Visitor(Opcodes.ASM9); + + for (MinecraftPatchedProvider.Environment environment : MinecraftPatchedProvider.Environment.values()) { + File patchedSrgJar = environment.patchedSrgJar.apply(extension.getMappingsProvider().patchedProvider); + FileSystemUtil.FileSystemDelegate system = FileSystemUtil.getJarFileSystem(patchedSrgJar, false); + completer.onComplete(value -> system.close()); + + for (Path fsPath : (Iterable<? extends Path>) Files.walk(system.get().getPath("/"))::iterator) { + if (Files.isRegularFile(fsPath) && fsPath.toString().endsWith(".class")) { + completer.add(() -> { + byte[] bytes = Files.readAllBytes(fsPath); + new ClassReader(bytes).accept(visitor, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); + }); + } + } + } + + completer.complete(); + Map<FieldMember, String> migratedFields = new HashMap<>(); + + try (BufferedReader reader = Files.newBufferedReader(rawTinyMappingsWithSrg)) { + TinyTree mappings = TinyMappingFactory.loadWithDetection(reader); + Map<String, String> srgToIntermediary = new HashMap<>(); + + for (ClassDef aClass : mappings.getClasses()) { + srgToIntermediary.put(aClass.getName("srg"), aClass.getName("intermediary")); + } + + for (ClassDef classDef : mappings.getClasses()) { + String ownerSrg = classDef.getName("srg"); + String ownerIntermediary = classDef.getName("intermediary"); + + for (FieldDef fieldDef : classDef.getFields()) { + String fieldSrg = fieldDef.getName("srg"); + String descriptorSrg = fieldDef.getDescriptor("srg"); + + FieldMember member = new FieldMember(ownerSrg, fieldSrg); + String newDescriptor = fieldDescriptorMap.get(member); + + if (newDescriptor != null && !newDescriptor.equals(descriptorSrg)) { + String fieldIntermediary = fieldDef.getName("intermediary"); + String descriptorIntermediary = fieldDef.getDescriptor("intermediary"); + String newDescriptorRemapped = DescriptorRemapper.remapDescriptor(newDescriptor, + clazz -> srgToIntermediary.getOrDefault(clazz, clazz)); + migratedFields.put(new FieldMember(ownerIntermediary, fieldIntermediary), newDescriptorRemapped); + getProject().getLogger().info(ownerIntermediary + "#" + fieldIntermediary + ": " + descriptorIntermediary + " -> " + newDescriptorRemapped); + } + } + } + } + + this.migratedFields.clear(); + this.migratedFields.addAll(migratedFields.entrySet()); + } + + public static class FieldMember { + public String owner; + public String field; + + public FieldMember(String owner, String field) { + this.owner = owner; + this.field = field; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + FieldMember that = (FieldMember) o; + return Objects.equals(owner, that.owner) && Objects.equals(field, that.field); + } + + @Override + public int hashCode() { + return Objects.hash(owner, field); + } + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/MinecraftPatchedProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/MinecraftPatchedProvider.java index 170f2b65..666b8530 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/MinecraftPatchedProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/MinecraftPatchedProvider.java @@ -77,7 +77,6 @@ import org.zeroturnaround.zip.ZipUtil; import net.fabricmc.loom.configuration.DependencyProvider; import net.fabricmc.loom.configuration.providers.MinecraftProvider; -import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider; import net.fabricmc.loom.util.Checksum; import net.fabricmc.loom.util.Constants; @@ -92,7 +91,6 @@ import net.fabricmc.loom.util.srg.SpecialSourceExecutor; import net.fabricmc.mapping.tree.TinyTree; public class MinecraftPatchedProvider extends DependencyProvider { - private final MappingsProvider mappingsProvider; // Step 1: Remap Minecraft to SRG private File minecraftClientSrgJar; private File minecraftServerSrgJar; @@ -112,9 +110,8 @@ public class MinecraftPatchedProvider extends DependencyProvider { private File projectAt = null; private boolean atDirty = false; - public MinecraftPatchedProvider(MappingsProvider mappingsProvider, Project project) { + public MinecraftPatchedProvider(Project project) { super(project); - this.mappingsProvider = mappingsProvider; } public void initFiles() throws IOException { @@ -149,26 +146,28 @@ public class MinecraftPatchedProvider extends DependencyProvider { MinecraftProvider minecraftProvider = getExtension().getMinecraftProvider(); PatchProvider patchProvider = getExtension().getPatchProvider(); String minecraftVersion = minecraftProvider.getMinecraftVersion(); - String jarSuffix = "-patched-forge-" + patchProvider.forgeVersion; + String patchId = "forge-" + patchProvider.forgeVersion; if (getExtension().useFabricMixin) { - jarSuffix += "-fabric-mixin"; + patchId += "-fabric-mixin"; } - minecraftProvider.setJarSuffix(jarSuffix); - File globalCache = getExtension().getUserCache(); File cache = usesProjectCache() ? getExtension().getProjectPersistentCache() : globalCache; + File globalDir = new File(globalCache, patchId); + File projectDir = new File(cache, patchId); + globalDir.mkdirs(); + projectDir.mkdirs(); minecraftClientSrgJar = new File(globalCache, "minecraft-" + minecraftVersion + "-client-srg.jar"); minecraftServerSrgJar = new File(globalCache, "minecraft-" + minecraftVersion + "-server-srg.jar"); - minecraftClientPatchedSrgJar = new File(globalCache, "minecraft-" + minecraftVersion + "-client-srg" + jarSuffix + ".jar"); - minecraftServerPatchedSrgJar = new File(globalCache, "minecraft-" + minecraftVersion + "-server-srg" + jarSuffix + ".jar"); - minecraftClientPatchedSrgATJar = new File(cache, "minecraft-" + minecraftVersion + "-client-srg-at" + jarSuffix + ".jar"); - minecraftServerPatchedSrgATJar = new File(cache, "minecraft-" + minecraftVersion + "-server-srg-at" + jarSuffix + ".jar"); - minecraftClientPatchedOfficialJar = new File(cache, "minecraft-" + minecraftVersion + "-client" + jarSuffix + ".jar"); - minecraftServerPatchedOfficialJar = new File(cache, "minecraft-" + minecraftVersion + "-server" + jarSuffix + ".jar"); - minecraftMergedPatchedJar = new File(cache, "minecraft-" + minecraftVersion + "-merged" + jarSuffix + ".jar"); + minecraftClientPatchedSrgJar = new File(globalDir, "client-srg-patched.jar"); + minecraftServerPatchedSrgJar = new File(globalDir, "server-srg-patched.jar"); + minecraftClientPatchedSrgATJar = new File(projectDir, "client-srg-at-patched.jar"); + minecraftServerPatchedSrgATJar = new File(projectDir, "server-srg-at-patched.jar"); + minecraftClientPatchedOfficialJar = new File(projectDir, "client-patched.jar"); + minecraftServerPatchedOfficialJar = new File(projectDir, "server-patched.jar"); + minecraftMergedPatchedJar = new File(projectDir, "merged-patched.jar"); if (isRefreshDeps() || Stream.of(getGlobalCaches()).anyMatch(Predicates.not(File::exists))) { cleanAllCache(); @@ -210,6 +209,8 @@ public class MinecraftPatchedProvider extends DependencyProvider { }; } + private boolean dirty; + @Override public void provide(DependencyInfo dependency, Consumer<Runnable> postPopulationScheduler) throws Exception { initFiles(); @@ -218,22 +219,24 @@ public class MinecraftPatchedProvider extends DependencyProvider { getProject().getLogger().lifecycle(":found dirty access transformers"); } - boolean dirty = false; + this.dirty = false; if (!minecraftClientSrgJar.exists() || !minecraftServerSrgJar.exists()) { - dirty = true; + this.dirty = true; // Remap official jars to MCPConfig remapped srg jars createSrgJars(getProject().getLogger()); } if (!minecraftClientPatchedSrgJar.exists() || !minecraftServerPatchedSrgJar.exists()) { - dirty = true; + this.dirty = true; patchJars(getProject().getLogger()); injectForgeClasses(getProject().getLogger()); } + } + public void finishProvide() throws Exception { if (atDirty || !minecraftClientPatchedSrgATJar.exists() || !minecraftServerPatchedSrgATJar.exists()) { - dirty = true; + this.dirty = true; accessTransformForge(getProject().getLogger()); } @@ -244,6 +247,8 @@ public class MinecraftPatchedProvider extends DependencyProvider { if (dirty || !minecraftMergedPatchedJar.exists()) { mergeJars(getProject().getLogger()); } + + this.dirty = false; } private void writeAtHash() throws IOException { @@ -285,9 +290,9 @@ public class MinecraftPatchedProvider extends DependencyProvider { 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); ThreadingUtils.run(() -> { - Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), mappingsProvider, "client", specialSourceJar, minecraftProvider.minecraftClientJar.toPath(), tmpSrg[0]), minecraftClientSrgJar.toPath()); + Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), "client", specialSourceJar, minecraftProvider.minecraftClientJar.toPath(), tmpSrg[0]), minecraftClientSrgJar.toPath()); }, () -> { - Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), mappingsProvider, "server", specialSourceJar, minecraftProvider.minecraftServerJar.toPath(), tmpSrg[0]), minecraftServerSrgJar.toPath()); + Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), "server", specialSourceJar, minecraftProvider.minecraftServerJar.toPath(), tmpSrg[0]), minecraftServerSrgJar.toPath()); }); } @@ -327,7 +332,7 @@ public class MinecraftPatchedProvider extends DependencyProvider { private void injectForgeClasses(Logger logger) throws IOException { logger.lifecycle(":injecting forge classes into minecraft"); - ThreadingUtils.run(Arrays.asList(Environment.values()), environment -> { + ThreadingUtils.run(Environment.values(), environment -> { copyAll(getExtension().getForgeUniversalProvider().getForge(), environment.patchedSrgJar.apply(this)); copyUserdevFiles(getExtension().getForgeUserdevProvider().getUserdevJar(), environment.patchedSrgJar.apply(this)); }); @@ -392,7 +397,7 @@ public class MinecraftPatchedProvider extends DependencyProvider { ((Map<?, ?>) field.get(list)).clear(); } - private enum Environment { + public enum Environment { CLIENT(provider -> provider.minecraftClientSrgJar, provider -> provider.minecraftClientPatchedSrgJar, provider -> provider.minecraftClientPatchedSrgATJar, @@ -427,7 +432,7 @@ public class MinecraftPatchedProvider extends DependencyProvider { private void remapPatchedJars(Logger logger) throws Exception { Path[] libraries = MinecraftMappedProvider.getRemapClasspath(getProject()); - ThreadingUtils.run(Arrays.asList(Environment.values()), environment -> { + ThreadingUtils.run(Environment.values(), environment -> { logger.lifecycle(":remapping minecraft (TinyRemapper, " + environment.side() + ", srg -> official)"); TinyTree mappingsWithSrg = getExtension().getMappingsProvider().getMappingsWithSrg(); @@ -464,7 +469,7 @@ public class MinecraftPatchedProvider extends DependencyProvider { patchJars(minecraftClientSrgJar, minecraftClientPatchedSrgJar, patchProvider.clientPatches); patchJars(minecraftServerSrgJar, minecraftServerPatchedSrgJar, patchProvider.serverPatches); - ThreadingUtils.run(Arrays.asList(Environment.values()), environment -> { + ThreadingUtils.run(Environment.values(), environment -> { copyMissingClasses(environment.srgJar.apply(this), environment.patchedSrgJar.apply(this)); fixParameterAnnotation(environment.patchedSrgJar.apply(this)); }); @@ -474,7 +479,7 @@ public class MinecraftPatchedProvider extends DependencyProvider { PrintStream previous = System.out; try { - System.setOut(new PrintStream(new NullOutputStream())); + System.setOut(new PrintStream(NullOutputStream.NULL_OUTPUT_STREAM)); } catch (SecurityException ignored) { // Failed to replace logger filter, just ignore } @@ -507,7 +512,7 @@ public class MinecraftPatchedProvider extends DependencyProvider { private void walkFileSystems(File source, File target, Predicate<Path> filter, Function<FileSystem, Iterable<Path>> toWalk, FsPathConsumer action) throws IOException { try (FileSystemUtil.FileSystemDelegate sourceFs = FileSystemUtil.getJarFileSystem(source, false); - FileSystemUtil.FileSystemDelegate targetFs = FileSystemUtil.getJarFileSystem(target, false)) { + FileSystemUtil.FileSystemDelegate targetFs = FileSystemUtil.getJarFileSystem(target, false)) { for (Path sourceDir : toWalk.apply(sourceFs.get())) { Path dir = sourceDir.toAbsolutePath(); Files.walk(dir) diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/PatchProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/PatchProvider.java index 24f1c866..b9924a16 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/PatchProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/PatchProvider.java @@ -24,6 +24,8 @@ package net.fabricmc.loom.configuration.providers.forge; +import java.io.IOException; +import java.io.UncheckedIOException; import java.net.URI; import java.nio.file.FileSystem; import java.nio.file.FileSystems; @@ -42,6 +44,7 @@ public class PatchProvider extends DependencyProvider { public Path clientPatches; public Path serverPatches; public String forgeVersion; + public Path projectCacheFolder; public PatchProvider(Project project) { super(project); @@ -65,8 +68,19 @@ public class PatchProvider extends DependencyProvider { private void init(String forgeVersion) { this.forgeVersion = forgeVersion; - clientPatches = getExtension().getProjectPersistentCache().toPath().resolve("patches-" + forgeVersion + "-client.lzma"); - serverPatches = getExtension().getProjectPersistentCache().toPath().resolve("patches-" + forgeVersion + "-server.lzma"); + projectCacheFolder = getExtension().getProjectPersistentCache().toPath().resolve(forgeVersion); + clientPatches = projectCacheFolder.resolve("patches-client.lzma"); + serverPatches = projectCacheFolder.resolve("patches-server.lzma"); + + try { + Files.createDirectories(projectCacheFolder); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public Path getProjectCacheFolder() { + return projectCacheFolder; } @Override diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProvider.java index c7160bea..632515df 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProvider.java @@ -86,7 +86,7 @@ public class MappingsProvider extends DependencyProvider { public String minecraftVersion; public String mappingsVersion; - private final Path mappingsDir; + protected final Path mappingsDir; private final Path mappingsStepsDir; private Path intermediaryTiny; private boolean hasRefreshed = false; @@ -94,8 +94,8 @@ public class MappingsProvider extends DependencyProvider { private Path baseTinyMappings; // The mappings we use in practice public File tinyMappings; + // tinyMappings wrapped in a jar public File tinyMappingsJar; - public File mappingsMixinExport; public Path tinyMappingsWithSrg; public File mixinTinyMappingsWithSrg; // FORGE: The mixin mappings have srg names in intermediary. public File srgToNamedSrg; // FORGE: srg to named in srg file format @@ -181,12 +181,13 @@ public class MappingsProvider extends DependencyProvider { jarClassifier = jarClassifier + depStringSplit[3]; } - tinyMappings = mappingsDir.resolve(StringUtils.removeSuffix(mappingsJar.getName(), ".jar") + ".tiny").toFile(); - unpickDefinitionsFile = mappingsDir.resolve(StringUtils.removeSuffix(mappingsJar.getName(), ".jar") + ".unpick").toFile(); - tinyMappingsJar = new File(getExtension().getUserCache(), mappingsJar.getName().replace(".jar", "-" + jarClassifier + ".jar")); - tinyMappingsWithSrg = mappingsDir.resolve(StringUtils.removeSuffix(mappingsJar.getName(), ".jar") + "-srg.tiny"); - mixinTinyMappingsWithSrg = mappingsDir.resolve(StringUtils.removeSuffix(mappingsJar.getName(), ".jar") + "-mixin-srg.tiny").toFile(); - srgToNamedSrg = mappingsDir.resolve(StringUtils.removeSuffix(mappingsJar.getName(), ".jar") + "-srg-named.srg").toFile(); + String removeSuffix = StringUtils.removeSuffix(mappingsJar.getName(), ".jar"); + tinyMappings = mappingsDir.resolve(removeSuffix + ".tiny").toFile(); + unpickDefinitionsFile = mappingsDir.resolve(removeSuffix + ".unpick").toFile(); + tinyMappingsJar = new File(getExtension().getUserCache(), removeSuffix + "-" + jarClassifier + ".jar"); + tinyMappingsWithSrg = mappingsDir.resolve(removeSuffix + "-srg.tiny"); + mixinTinyMappingsWithSrg = mappingsDir.resolve(removeSuffix + "-mixin-srg.tiny").toFile(); + srgToNamedSrg = mappingsDir.resolve(removeSuffix + "-srg-named.srg").toFile(); if (!tinyMappings.exists() || isRefreshDeps()) { storeMappings(getProject(), minecraftProvider, mappingsJar.toPath(), postPopulationScheduler); @@ -196,6 +197,20 @@ public class MappingsProvider extends DependencyProvider { } } + 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.toPath(), tinyMappingsWithSrg, true); + } + } + if (!tinyMappingsJar.exists() || isRefreshDeps()) { ZipUtil.pack(new ZipEntrySource[] {new FileSource("mappings/mappings.tiny", tinyMappings)}, tinyMappingsJar); } @@ -211,12 +226,6 @@ public class MappingsProvider extends DependencyProvider { populateUnpickClasspath(); } - if (getExtension().shouldGenerateSrgTiny()) { - if (Files.notExists(tinyMappingsWithSrg) || isRefreshDeps()) { - SrgMerger.mergeSrg(getExtension().getSrgProvider().getSrg().toPath(), tinyMappings.toPath(), tinyMappingsWithSrg, true); - } - } - if (getExtension().isForge()) { if (!getExtension().shouldGenerateSrgTiny()) { throw new IllegalStateException("We have to generate srg tiny in a forge environment!"); @@ -247,8 +256,7 @@ public class MappingsProvider extends DependencyProvider { processorManager.setupProcessors(); if (extension.isForge()) { - patchedProvider = new MinecraftPatchedProvider(this, getProject()); - patchedProvider.provide(dependency, postPopulationScheduler); + patchedProvider.finishProvide(); } if (processorManager.active() || (extension.isForge() && patchedProvider.usesProjectCache())) { @@ -262,6 +270,8 @@ public class MappingsProvider extends DependencyProvider { mappedProvider.provide(dependency, postPopulationScheduler); } + public void manipulateMappings(Path mappingsJar) throws IOException { } + private void storeMappings(Project project, MinecraftProvider minecraftProvider, Path yarnJar, Consumer<Runnable> postPopulationScheduler) throws Exception { project.getLogger().info(":extracting " + yarnJar.getFileName()); diff --git a/src/main/java/net/fabricmc/loom/util/ThreadingUtils.java b/src/main/java/net/fabricmc/loom/util/ThreadingUtils.java index e61a297c..0645f319 100644 --- a/src/main/java/net/fabricmc/loom/util/ThreadingUtils.java +++ b/src/main/java/net/fabricmc/loom/util/ThreadingUtils.java @@ -40,6 +40,12 @@ import java.util.stream.Collectors; import com.google.common.base.Stopwatch; public class ThreadingUtils { + public static <T> void run(T[] values, UnsafeConsumer<T> action) { + run(Arrays.stream(values) + .<UnsafeRunnable>map(t -> () -> action.accept(t)) + .collect(Collectors.toList())); + } + public static <T> void run(Collection<T> values, UnsafeConsumer<T> action) { run(values.stream() .<UnsafeRunnable>map(t -> () -> action.accept(t)) diff --git a/src/main/java/net/fabricmc/loom/util/srg/SpecialSourceExecutor.java b/src/main/java/net/fabricmc/loom/util/srg/SpecialSourceExecutor.java index 72a482cf..1da2266d 100644 --- a/src/main/java/net/fabricmc/loom/util/srg/SpecialSourceExecutor.java +++ b/src/main/java/net/fabricmc/loom/util/srg/SpecialSourceExecutor.java @@ -43,7 +43,7 @@ import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; public class SpecialSourceExecutor { - public static Path produceSrgJar(Project project, MappingsProvider provider, String side, File specialSourceJar, Path officialJar, Path srgPath) + public static Path produceSrgJar(Project project, String side, File specialSourceJar, Path officialJar, Path srgPath) throws Exception { Set<String> filter = Files.readAllLines(srgPath, StandardCharsets.UTF_8).stream() .filter(s -> !s.startsWith("\t")) |