From cb821ede0fa9c33551dc4cd25d8c7144c41ee2f6 Mon Sep 17 00:00:00 2001 From: shedaniel Date: Tue, 13 Apr 2021 16:31:15 +0800 Subject: [PATCH] Revert "WIP AT -> JarProcessor" This reverts commit 4fe9b81e --- .../decompilers/DecompilationMetadata.java | 11 +- .../AccessTransformerJarProcessor.java | 232 ------------------ .../AccessWidenerJarProcessor.java | 5 - .../loom/configuration/mods/ModProcessor.java | 2 +- .../processors/JarProcessor.java | 4 - .../processors/JarProcessorManager.java | 4 - .../MinecraftProcessedProvider.java | 4 +- .../forge/MinecraftPatchedProvider.java | 145 +++++++++-- .../providers/mappings/MappingsProvider.java | 9 +- .../minecraft/MinecraftMappedProvider.java | 10 +- .../decompilers/cfr/FabricCFRDecompiler.java | 16 -- .../AbstractFernFlowerDecompiler.java | 60 +---- .../fabricmc/loom/task/AbstractLoomTask.java | 3 +- .../fabricmc/loom/task/AbstractRunTask.java | 3 +- .../fabricmc/loom/task/CleanSourcesTask.java | 15 -- .../task/GenerateIncrementalSourcesTask.java | 128 ---------- .../loom/task/GenerateSourcesTask.java | 129 ++-------- .../net/fabricmc/loom/task/LoomTasks.java | 14 +- .../net/fabricmc/loom/util/Constants.java | 1 - .../fabricmc/loom/util/srg/AtRemapper.java | 135 +++++----- 20 files changed, 226 insertions(+), 704 deletions(-) delete mode 100644 src/main/java/net/fabricmc/loom/configuration/accesstransformer/AccessTransformerJarProcessor.java delete mode 100644 src/main/java/net/fabricmc/loom/task/CleanSourcesTask.java delete mode 100644 src/main/java/net/fabricmc/loom/task/GenerateIncrementalSourcesTask.java diff --git a/src/main/java/net/fabricmc/loom/api/decompilers/DecompilationMetadata.java b/src/main/java/net/fabricmc/loom/api/decompilers/DecompilationMetadata.java index 6524b3c3..35dcbfa6 100644 --- a/src/main/java/net/fabricmc/loom/api/decompilers/DecompilationMetadata.java +++ b/src/main/java/net/fabricmc/loom/api/decompilers/DecompilationMetadata.java @@ -26,24 +26,15 @@ package net.fabricmc.loom.api.decompilers; import java.nio.file.Path; import java.util.Collection; -import java.util.function.Function; -import java.util.function.Predicate; - -import org.jetbrains.annotations.Nullable; - -import net.fabricmc.loom.task.GenerateSourcesTask; public class DecompilationMetadata { public final int numberOfThreads; public final Path javaDocs; public final Collection libraries; - @Nullable - public final Predicate classFilter; - public DecompilationMetadata(int numberOfThreads, Path javaDocs, Collection libraries, Function classFilter) { + public DecompilationMetadata(int numberOfThreads, Path javaDocs, Collection libraries) { this.numberOfThreads = numberOfThreads; this.javaDocs = javaDocs; this.libraries = libraries; - this.classFilter = s -> GenerateSourcesTask.SkipState.SKIP != classFilter.apply(s); } } diff --git a/src/main/java/net/fabricmc/loom/configuration/accesstransformer/AccessTransformerJarProcessor.java b/src/main/java/net/fabricmc/loom/configuration/accesstransformer/AccessTransformerJarProcessor.java deleted file mode 100644 index 2f1c2590..00000000 --- a/src/main/java/net/fabricmc/loom/configuration/accesstransformer/AccessTransformerJarProcessor.java +++ /dev/null @@ -1,232 +0,0 @@ -package net.fabricmc.loom.configuration.accesstransformer; - -import java.io.File; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.lang.reflect.Field; -import java.nio.charset.StandardCharsets; -import java.nio.file.Path; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map; -import java.util.Objects; -import java.util.Set; - -import me.shedaniel.architectury.refmapremapper.remapper.SimpleReferenceRemapper; -import net.minecraftforge.accesstransformer.AccessTransformerEngine; -import net.minecraftforge.accesstransformer.TransformerProcessor; -import net.minecraftforge.accesstransformer.parser.AccessTransformerList; -import org.apache.commons.io.FileUtils; -import org.apache.logging.log4j.util.Strings; -import org.gradle.api.Project; -import org.gradle.api.plugins.JavaPluginConvention; -import org.gradle.api.tasks.SourceSet; -import org.jetbrains.annotations.Nullable; -import org.zeroturnaround.zip.ZipUtil; - -import net.fabricmc.loom.LoomGradleExtension; -import net.fabricmc.loom.configuration.processors.JarProcessor; -import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; -import net.fabricmc.loom.util.Checksum; -import net.fabricmc.loom.util.JarUtil; -import net.fabricmc.loom.util.srg.AtRemapper; -import net.fabricmc.mapping.tree.TinyTree; - -public class AccessTransformerJarProcessor implements JarProcessor { - private final Path projectAt; - private final Project project; - private final Set affectedClasses = new HashSet<>(); - private Path remappedProjectAt; - - public AccessTransformerJarProcessor(Path projectAt, Project project) { - this.projectAt = projectAt; - this.project = project; - } - - public static void addTo(Project project, LoomGradleExtension extension) { - SourceSet main = project.getConvention().findPlugin(JavaPluginConvention.class).getSourceSets().getByName("main"); - - for (File srcDir : main.getResources().getSrcDirs()) { - File projectAt = new File(srcDir, "META-INF/accesstransformer.cfg"); - - if (projectAt.exists()) { - extension.addJarProcessor(new AccessTransformerJarProcessor(projectAt.toPath(), project)); - return; - } - } - } - - @Override - public void setup() { - affectedClasses.clear(); - remappedProjectAt = null; - getRemappedAt(); - } - - @Override - public void process(File file) { - try { - accessTransformForge(file, file, false, getRemappedAt()); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - @Override - public boolean isInvalid(File file) { - byte[] hash = ZipUtil.unpackEntry(file, "loom-at.sha256"); - - if (hash == null) { - return true; - } - - return !Arrays.equals(getInputHash(false, getRemappedAt()), hash); - } - - @Override - public boolean doesProcessClass(String classInternalName) { - getRemappedAt(); - return affectedClasses.contains(classInternalName); - } - - private File getRemappedAt() { - if (remappedProjectAt == null) { - try { - LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); - MappingsProvider mappingsProvider = extension.getMappingsProvider(); - TinyTree mappings = extension.isForge() ? mappingsProvider.getMappingsWithSrg() : mappingsProvider.getMappings(); - - File file = File.createTempFile("at-remapped-", ".at"); - file.delete(); - String sourceAt = FileUtils.readFileToString(projectAt.toFile(), StandardCharsets.UTF_8); - String remappedAt = AtRemapper.remapAt(project.getLogger(), sourceAt, new SimpleReferenceRemapper.Remapper() { - @Override - @Nullable - public String mapClass(String value) { - return mappings.getClasses().stream() - .filter(classDef -> Objects.equals(classDef.getName("srg"), value)) - .findFirst() - .map(classDef -> classDef.getName("named")) - .orElse(null); - } - - @Override - @Nullable - public String mapMethod(@Nullable String className, String methodName, String methodDescriptor) { - return mappings.getClasses().stream() - .flatMap(classDef -> classDef.getMethods().stream()) - .filter(methodDef -> Objects.equals(methodDef.getName("srg"), methodName)) - .filter(methodDef -> Objects.equals(methodDef.getDescriptor("srg"), methodDescriptor)) - .findFirst() - .map(classDef -> classDef.getName("named")) - .orElse(null); - } - - @Override - @Nullable - public String mapField(@Nullable String className, String fieldName, String fieldDescriptor) { - return mappings.getClasses().stream() - .flatMap(classDef -> classDef.getFields().stream()) - .filter(methodDef -> Objects.equals(methodDef.getName("srg"), fieldName)) - .findFirst() - .map(classDef -> classDef.getName("named")) - .orElse(null); - } - }); - - for (String line : remappedAt.split("\n")) { - { - int indexOf = line.indexOf('#'); - - if (indexOf != -1) { - line = line.substring(0, indexOf); - } - - line = line.trim(); - } - - if (!Strings.isBlank(line)) { - affectedClasses.add(line.split("\\s+")[1].replace('.', '/')); - } - } - - FileUtils.write(file, remappedAt, StandardCharsets.UTF_8); - file.deleteOnExit(); - return (remappedProjectAt = file.toPath()).toFile(); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - return remappedProjectAt.toFile(); - } - - public static byte[] getInputHash(boolean addEmbeddedAt, File... extraAts) { - byte[] inputHash = new byte[] {(byte) (addEmbeddedAt ? 1 : 0)}; - - for (File extraAt : extraAts) { - inputHash = concat(inputHash, Checksum.sha256(extraAt)); - } - - return inputHash; - } - - public static byte[] concat(byte[] a, byte[] b) { - byte[] out = new byte[a.length + b.length]; - System.arraycopy(a, 0, out, 0, a.length); - System.arraycopy(b, 0, out, a.length, b.length); - return out; - } - - public static void accessTransformForge(File input, File target, boolean addEmbeddedAt, File... extraAts) throws Exception { - byte[] inputHash = getInputHash(addEmbeddedAt, extraAts); - File inputCopied = File.createTempFile("at-input-", ".jar"); - File at = File.createTempFile("at-", ".cfg"); - FileUtils.copyFile(input, inputCopied); - - if (target.exists()) { - byte[] hash = ZipUtil.unpackEntry(target, "loom-at.sha256"); - - if (hash != null && Arrays.equals(inputHash, hash)) { - return; - } - } - - target.delete(); - String[] args = new String[] { - "--inJar", inputCopied.getAbsolutePath(), - "--outJar", target.getAbsolutePath() - }; - - if (addEmbeddedAt) { - JarUtil.extractFile(inputCopied, "META-INF/accesstransformer.cfg", at); - args = Arrays.copyOf(args, args.length + 2); - args[args.length - 2] = "--atFile"; - args[args.length - 1] = at.getAbsolutePath(); - } - - for (File extraAt : extraAts) { - args = Arrays.copyOf(args, args.length + 2); - args[args.length - 2] = "--atFile"; - args[args.length - 1] = extraAt.getAbsolutePath(); - } - - resetAccessTransformerEngine(); - TransformerProcessor.main(args); - inputCopied.delete(); - at.delete(); - resetAccessTransformerEngine(); - - ZipUtil.addEntry(target, "loom-at.sha256", inputHash); - } - - private static void resetAccessTransformerEngine() throws Exception { - // Thank you Forge, I love you - Field field = AccessTransformerEngine.class.getDeclaredField("masterList"); - field.setAccessible(true); - AccessTransformerList list = (AccessTransformerList) field.get(AccessTransformerEngine.INSTANCE); - field = AccessTransformerList.class.getDeclaredField("accessTransformers"); - field.setAccessible(true); - ((Map) field.get(list)).clear(); - } -} diff --git a/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerJarProcessor.java b/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerJarProcessor.java index df0cf9e1..42f0e7bf 100644 --- a/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerJarProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerJarProcessor.java @@ -117,11 +117,6 @@ public class AccessWidenerJarProcessor implements JarProcessor { ZipUtil.addEntry(file, "aw.sha256", inputHash); } - @Override - public boolean doesProcessClass(String classInternalName) { - return accessWidener.getTargets().contains(classInternalName.replace('/', '.')); - } - private ZipEntryTransformerEntry[] getTransformers(Set classes) { return classes.stream() .map(string -> new ZipEntryTransformerEntry(string.replaceAll("\\.", "/") + ".class", getTransformer(string))) diff --git a/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java b/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java index 901ff2d8..990c042c 100644 --- a/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java @@ -211,7 +211,7 @@ public class ModProcessor { } if (extension.isForge()) { - AtRemapper.remapSrgToNamed(project.getLogger(), info.getRemappedOutput().toPath(), mappings); + AtRemapper.remap(project.getLogger(), info.getRemappedOutput().toPath(), mappings); CoreModClassRemapper.remapJar(info.getRemappedOutput().toPath(), mappings, project.getLogger()); if (ZipUtil.containsEntry(info.getRemappedOutput(), "META-INF/MANIFEST.MF")) { diff --git a/src/main/java/net/fabricmc/loom/configuration/processors/JarProcessor.java b/src/main/java/net/fabricmc/loom/configuration/processors/JarProcessor.java index 86ec8ca0..85624ce1 100644 --- a/src/main/java/net/fabricmc/loom/configuration/processors/JarProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/processors/JarProcessor.java @@ -38,8 +38,4 @@ public interface JarProcessor { * Return true to make all jar processors run again, return false to use the existing results of jar processing. */ boolean isInvalid(File file); - - default boolean doesProcessClass(String classInternalName) { - return false; - } } diff --git a/src/main/java/net/fabricmc/loom/configuration/processors/JarProcessorManager.java b/src/main/java/net/fabricmc/loom/configuration/processors/JarProcessorManager.java index 4c533903..634f4bba 100644 --- a/src/main/java/net/fabricmc/loom/configuration/processors/JarProcessorManager.java +++ b/src/main/java/net/fabricmc/loom/configuration/processors/JarProcessorManager.java @@ -50,10 +50,6 @@ public class JarProcessorManager { return jarProcessors.stream().anyMatch(jarProcessor -> jarProcessor.isInvalid(file)); } - public boolean doesProcessClass(String classInternalName) { - return jarProcessors.stream().anyMatch(jarProcessor -> jarProcessor.doesProcessClass(classInternalName)); - } - public void process(File file) { for (JarProcessor jarProcessor : jarProcessors) { jarProcessor.process(file); diff --git a/src/main/java/net/fabricmc/loom/configuration/processors/MinecraftProcessedProvider.java b/src/main/java/net/fabricmc/loom/configuration/processors/MinecraftProcessedProvider.java index adf85fd2..9673a9a4 100644 --- a/src/main/java/net/fabricmc/loom/configuration/processors/MinecraftProcessedProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/processors/MinecraftProcessedProvider.java @@ -50,7 +50,9 @@ public class MinecraftProcessedProvider extends MinecraftMappedProvider { @Override protected void addDependencies(DependencyInfo dependency, Consumer postPopulationScheduler) { - if (jarProcessorManager.isInvalid(projectMappedJar) || isRefreshDeps()) { + boolean isForgeAtDirty = getExtension().isForge() && getExtension().getMappingsProvider().patchedProvider.isAtDirty(); + + if (jarProcessorManager.isInvalid(projectMappedJar) || isRefreshDeps() || isForgeAtDirty) { getProject().getLogger().info(":processing mapped jar"); invalidateJars(); 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 73800c78..cccfc7f8 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 @@ -26,12 +26,15 @@ package net.fabricmc.loom.configuration.providers.forge; import java.io.BufferedWriter; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintStream; import java.io.UncheckedIOException; +import java.lang.reflect.Field; import java.net.URI; +import java.net.URL; import java.nio.charset.StandardCharsets; import java.nio.file.FileSystem; import java.nio.file.FileSystems; @@ -41,7 +44,7 @@ import java.nio.file.StandardCopyOption; import java.util.Arrays; import java.util.Collections; import java.util.Locale; -import java.util.Set; +import java.util.Map; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; @@ -51,13 +54,18 @@ import com.google.common.base.Predicates; import com.google.common.collect.ImmutableMap; import com.google.gson.JsonParser; import de.oceanlabs.mcp.mcinjector.adaptors.ParameterAnnotationFixer; +import net.minecraftforge.accesstransformer.AccessTransformerEngine; +import net.minecraftforge.accesstransformer.TransformerProcessor; +import net.minecraftforge.accesstransformer.parser.AccessTransformerList; import net.minecraftforge.binarypatcher.ConsoleTool; 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.artifacts.Dependency; import org.gradle.api.logging.Logger; +import org.gradle.api.plugins.JavaPluginConvention; +import org.gradle.api.tasks.SourceSet; +import org.jetbrains.annotations.Nullable; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; @@ -65,12 +73,14 @@ import org.objectweb.asm.tree.ClassNode; import org.zeroturnaround.zip.ZipUtil; import net.fabricmc.loom.configuration.DependencyProvider; -import net.fabricmc.loom.configuration.accesstransformer.AccessTransformerJarProcessor; 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; +import net.fabricmc.loom.util.DownloadUtil; import net.fabricmc.loom.util.FileSystemUtil; +import net.fabricmc.loom.util.JarUtil; import net.fabricmc.loom.util.ThreadingUtils; import net.fabricmc.loom.util.TinyRemapperMappingsHelper; import net.fabricmc.loom.util.function.FsPathConsumer; @@ -88,11 +98,18 @@ public class MinecraftPatchedProvider extends DependencyProvider { // Step 2: Binary Patch private File minecraftClientPatchedSrgJar; private File minecraftServerPatchedSrgJar; - // Step 3: Remap Patched Jar to Official + // Step 3: Access Transform + private File minecraftClientPatchedSrgATJar; + private File minecraftServerPatchedSrgATJar; + // Step 4: Remap Patched AT to Official private File minecraftClientPatchedOfficialJar; private File minecraftServerPatchedOfficialJar; - // Step 4: Merge + // Step 5: Merge private File minecraftMergedPatchedJar; + private File projectAtHash; + @Nullable + private File projectAt = null; + private boolean atDirty = false; public MinecraftPatchedProvider(MappingsProvider mappingsProvider, Project project) { super(project); @@ -100,6 +117,34 @@ public class MinecraftPatchedProvider extends DependencyProvider { } public void initFiles() throws IOException { + projectAtHash = new File(getExtension().getProjectPersistentCache(), "at.sha256"); + + SourceSet main = getProject().getConvention().findPlugin(JavaPluginConvention.class).getSourceSets().getByName("main"); + + for (File srcDir : main.getResources().getSrcDirs()) { + File projectAt = new File(srcDir, "META-INF/accesstransformer.cfg"); + + if (projectAt.exists()) { + this.projectAt = projectAt; + break; + } + } + + if (isRefreshDeps() || !projectAtHash.exists()) { + writeAtHash(); + atDirty = projectAt != null; + } else { + byte[] expected = com.google.common.io.Files.asByteSource(projectAtHash).read(); + byte[] current = projectAt != null ? Checksum.sha256(projectAt) : Checksum.sha256(""); + boolean mismatched = !Arrays.equals(current, expected); + + if (mismatched) { + writeAtHash(); + } + + atDirty = mismatched; + } + MinecraftProvider minecraftProvider = getExtension().getMinecraftProvider(); PatchProvider patchProvider = getExtension().getPatchProvider(); String minecraftVersion = minecraftProvider.getMinecraftVersion(); @@ -112,18 +157,21 @@ public class MinecraftPatchedProvider extends DependencyProvider { minecraftProvider.setJarSuffix(jarSuffix); File globalCache = getExtension().getUserCache(); + File cache = usesProjectCache() ? getExtension().getProjectPersistentCache() : globalCache; 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-patched" + jarSuffix + ".jar"); - minecraftServerPatchedSrgJar = new File(globalCache, "minecraft-" + minecraftVersion + "-server-srg-patched" + jarSuffix + ".jar"); - minecraftClientPatchedOfficialJar = new File(globalCache, "minecraft-" + minecraftVersion + "-client-patched" + jarSuffix + ".jar"); - minecraftServerPatchedOfficialJar = new File(globalCache, "minecraft-" + minecraftVersion + "-server-patched" + jarSuffix + ".jar"); - minecraftMergedPatchedJar = new File(globalCache, "minecraft-" + minecraftVersion + "-merged-patched" + jarSuffix + ".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"); if (isRefreshDeps() || Stream.of(getGlobalCaches()).anyMatch(Predicates.not(File::exists))) { cleanAllCache(); - } else if (Stream.of(getProjectCache()).anyMatch(Predicates.not(File::exists))) { + } else if (atDirty || Stream.of(getProjectCache()).anyMatch(Predicates.not(File::exists))) { cleanProjectCache(); } } @@ -153,6 +201,8 @@ public class MinecraftPatchedProvider extends DependencyProvider { private File[] getProjectCache() { return new File[] { + minecraftClientPatchedSrgATJar, + minecraftServerPatchedSrgATJar, minecraftClientPatchedOfficialJar, minecraftServerPatchedOfficialJar, minecraftMergedPatchedJar @@ -163,6 +213,10 @@ public class MinecraftPatchedProvider extends DependencyProvider { public void provide(DependencyInfo dependency, Consumer postPopulationScheduler) throws Exception { initFiles(); + if (atDirty) { + getProject().getLogger().lifecycle(":found dirty access transformers"); + } + boolean dirty = false; if (!minecraftClientSrgJar.exists() || !minecraftServerSrgJar.exists()) { @@ -175,6 +229,10 @@ public class MinecraftPatchedProvider extends DependencyProvider { dirty = true; patchJars(getProject().getLogger()); injectForgeClasses(getProject().getLogger()); + } + + if (atDirty || !minecraftClientPatchedSrgATJar.exists() || !minecraftServerPatchedSrgATJar.exists()) { + dirty = true; accessTransformForge(getProject().getLogger()); } @@ -187,6 +245,16 @@ public class MinecraftPatchedProvider extends DependencyProvider { } } + private void writeAtHash() throws IOException { + try (FileOutputStream out = new FileOutputStream(projectAtHash)) { + if (projectAt != null) { + out.write(Checksum.sha256(projectAt)); + } else { + out.write(Checksum.sha256("")); + } + } + } + private void createSrgJars(Logger logger) throws Exception { McpConfigProvider mcpProvider = getExtension().getMcpConfigProvider(); @@ -212,10 +280,8 @@ public class MinecraftPatchedProvider extends DependencyProvider { throw new IllegalStateException("Failed to find mappings '" + mappingsPath[0] + "' in " + mcpProvider.getMcp().getAbsolutePath() + "!"); } - Dependency dependency = getProject().getDependencies().create("net.md-5:SpecialSource:1.8.3:shaded"); - Set specialSourceJars = getProject().getConfigurations().detachedConfiguration(dependency).resolve(); - if (specialSourceJars.isEmpty()) throw new IllegalStateException("Failed to resolve net.md-5:SpecialSource:1.8.3:shaded"); - File specialSourceJar = specialSourceJars.iterator().next(); + 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); ThreadingUtils.run(() -> { Files.copy(SpecialSourceExecutor.produceSrgJar(getProject(), mappingsProvider, "client", specialSourceJar, minecraftProvider.minecraftClientJar.toPath(), tmpSrg[0]), minecraftClientSrgJar.toPath()); @@ -282,30 +348,65 @@ public class MinecraftPatchedProvider extends DependencyProvider { String side = environment.side(); logger.lifecycle(":access transforming minecraft (" + side + ")"); - File file = environment.patchedSrgJar.apply(this); - AccessTransformerJarProcessor.accessTransformForge(file, file, true); + File input = environment.patchedSrgJar.apply(this); + File inputCopied = File.createTempFile("at" + side, ".jar"); + FileUtils.copyFile(input, inputCopied); + File target = environment.patchedSrgATJar.apply(this); + target.delete(); + File at = File.createTempFile("at" + side, ".cfg"); + JarUtil.extractFile(inputCopied, "META-INF/accesstransformer.cfg", at); + String[] args = new String[] { + "--inJar", inputCopied.getAbsolutePath(), + "--outJar", target.getAbsolutePath(), + "--atFile", at.getAbsolutePath() + }; + + if (usesProjectCache()) { + args = Arrays.copyOf(args, args.length + 2); + args[args.length - 2] = "--atFile"; + args[args.length - 1] = projectAt.getAbsolutePath(); + } + + resetAccessTransformerEngine(); + TransformerProcessor.main(args); + inputCopied.delete(); } } + private void resetAccessTransformerEngine() throws Exception { + // Thank you Forge, I love you + Field field = AccessTransformerEngine.class.getDeclaredField("masterList"); + field.setAccessible(true); + AccessTransformerList list = (AccessTransformerList) field.get(AccessTransformerEngine.INSTANCE); + field = AccessTransformerList.class.getDeclaredField("accessTransformers"); + field.setAccessible(true); + ((Map) field.get(list)).clear(); + } + private enum Environment { CLIENT(provider -> provider.minecraftClientSrgJar, provider -> provider.minecraftClientPatchedSrgJar, + provider -> provider.minecraftClientPatchedSrgATJar, provider -> provider.minecraftClientPatchedOfficialJar ), SERVER(provider -> provider.minecraftServerSrgJar, provider -> provider.minecraftServerPatchedSrgJar, + provider -> provider.minecraftServerPatchedSrgATJar, provider -> provider.minecraftServerPatchedOfficialJar ); final Function srgJar; final Function patchedSrgJar; + final Function patchedSrgATJar; final Function patchedOfficialJar; Environment(Function srgJar, Function patchedSrgJar, + Function patchedSrgATJar, Function patchedOfficialJar) { this.srgJar = srgJar; this.patchedSrgJar = patchedSrgJar; + this.patchedSrgATJar = patchedSrgATJar; this.patchedOfficialJar = patchedOfficialJar; } @@ -321,7 +422,7 @@ public class MinecraftPatchedProvider extends DependencyProvider { logger.lifecycle(":remapping minecraft (TinyRemapper, " + environment.side() + ", srg -> official)"); TinyTree mappingsWithSrg = getExtension().getMappingsProvider().getMappingsWithSrg(); - Path input = environment.patchedSrgJar.apply(this).toPath(); + Path input = environment.patchedSrgATJar.apply(this).toPath(); Path output = environment.patchedOfficialJar.apply(this).toPath(); Files.deleteIfExists(output); @@ -469,6 +570,14 @@ public class MinecraftPatchedProvider extends DependencyProvider { return minecraftMergedPatchedJar; } + public boolean usesProjectCache() { + return projectAt != null; + } + + public boolean isAtDirty() { + return atDirty; + } + @Override public String getTargetConfig() { return Constants.Configurations.MINECRAFT; 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 da31d8f7..40ae05d0 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 @@ -47,8 +47,6 @@ import org.apache.commons.io.FileUtils; import org.apache.tools.ant.util.StringUtils; import org.gradle.api.Project; import org.gradle.api.artifacts.Configuration; -import org.gradle.api.plugins.JavaPluginConvention; -import org.gradle.api.tasks.SourceSet; import org.zeroturnaround.zip.FileSource; import org.zeroturnaround.zip.ZipEntrySource; import org.zeroturnaround.zip.ZipUtil; @@ -56,7 +54,6 @@ import org.zeroturnaround.zip.ZipUtil; import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradlePlugin; import net.fabricmc.loom.configuration.DependencyProvider; -import net.fabricmc.loom.configuration.accesstransformer.AccessTransformerJarProcessor; import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor; import net.fabricmc.loom.configuration.processors.JarProcessorManager; import net.fabricmc.loom.configuration.processors.MinecraftProcessedProvider; @@ -243,10 +240,6 @@ public class MappingsProvider extends DependencyProvider { extension.addJarProcessor(new AccessWidenerJarProcessor(getProject())); } - if (extension.isForge()) { - AccessTransformerJarProcessor.addTo(getProject(), extension); - } - JarProcessorManager processorManager = new JarProcessorManager(extension.getJarProcessors()); extension.setJarProcessorManager(processorManager); processorManager.setupProcessors(); @@ -256,7 +249,7 @@ public class MappingsProvider extends DependencyProvider { patchedProvider.provide(dependency, postPopulationScheduler); } - if (processorManager.active()) { + if (processorManager.active() || (extension.isForge() && patchedProvider.usesProjectCache())) { mappedProvider = new MinecraftProcessedProvider(getProject(), processorManager); getProject().getLogger().lifecycle("Using project based jar storage"); } else { 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 5b2d2b2e..88fd4338 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 @@ -89,7 +89,9 @@ public class MinecraftMappedProvider extends DependencyProvider { throw new RuntimeException("input merged jar not found"); } - if (!minecraftMappedJar.exists() || !getIntermediaryJar().exists() || (getExtension().isForge() && !getSrgJar().exists()) || isRefreshDeps()) { + boolean isForgeAtDirty = getExtension().isForge() && getExtension().getMappingsProvider().patchedProvider.isAtDirty(); + + if (!minecraftMappedJar.exists() || !getIntermediaryJar().exists() || (getExtension().isForge() && !getSrgJar().exists()) || isRefreshDeps() || isForgeAtDirty) { if (minecraftMappedJar.exists()) { minecraftMappedJar.delete(); } @@ -198,7 +200,7 @@ public class MinecraftMappedProvider extends DependencyProvider { } TinyTree yarnWithSrg = getExtension().getMappingsProvider().getMappingsWithSrg(); - AtRemapper.remapSrgToNamed(getProject().getLogger(), output, yarnWithSrg); + AtRemapper.remap(getProject().getLogger(), output, yarnWithSrg); CoreModClassRemapper.remapJar(output, yarnWithSrg, getProject().getLogger()); } } @@ -280,10 +282,6 @@ public class MinecraftMappedProvider extends DependencyProvider { return minecraftMappedJar; } - public final File getUnprocessedMappedJar() { - return minecraftMappedJar; - } - public File getUnpickedJar() { return new File(getJarDirectory(getExtension().getUserCache(), "mapped"), "minecraft-" + getJarVersionString("unpicked") + ".jar"); } diff --git a/src/main/java/net/fabricmc/loom/decompilers/cfr/FabricCFRDecompiler.java b/src/main/java/net/fabricmc/loom/decompilers/cfr/FabricCFRDecompiler.java index 388bdd60..ee2801ab 100644 --- a/src/main/java/net/fabricmc/loom/decompilers/cfr/FabricCFRDecompiler.java +++ b/src/main/java/net/fabricmc/loom/decompilers/cfr/FabricCFRDecompiler.java @@ -177,22 +177,6 @@ public class FabricCFRDecompiler implements LoomDecompiler { List> futures = new LinkedList<>(); for (String clazz : classes) { - if (metaData.classFilter != null) { - String classInternalName = clazz; - - if (classInternalName.length() >= 1 && classInternalName.charAt(0) == '/') { - classInternalName = classInternalName.substring(1); - } - - classInternalName = classInternalName.substring(0, classInternalName.length() - 6); - - if (!metaData.classFilter.test(classInternalName)) { - return; - } else { - System.out.println(classInternalName); - } - } - futures.add(executorService.submit(() -> { loggerMap.computeIfAbsent(Thread.currentThread().getId(), createLogger).progress(clazz); driver.analyse(Collections.singletonList(clazz)); diff --git a/src/main/java/net/fabricmc/loom/decompilers/fernflower/AbstractFernFlowerDecompiler.java b/src/main/java/net/fabricmc/loom/decompilers/fernflower/AbstractFernFlowerDecompiler.java index d12eedfd..a8844f22 100644 --- a/src/main/java/net/fabricmc/loom/decompilers/fernflower/AbstractFernFlowerDecompiler.java +++ b/src/main/java/net/fabricmc/loom/decompilers/fernflower/AbstractFernFlowerDecompiler.java @@ -26,25 +26,13 @@ package net.fabricmc.loom.decompilers.fernflower; import static java.text.MessageFormat.format; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.net.URI; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Stack; import java.util.function.Supplier; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; import org.gradle.api.Project; import org.gradle.api.internal.project.ProjectInternal; @@ -89,7 +77,7 @@ public abstract class AbstractFernFlowerDecompiler implements LoomDecompiler { List args = new ArrayList<>(); options.forEach((k, v) -> args.add(format("-{0}={1}", k, v))); - args.add(absolutePathOf(transformBinary(compiledJar, metaData))); + args.add(absolutePathOf(compiledJar)); args.add("-o=" + absolutePathOf(sourcesDestination)); args.add("-l=" + absolutePathOf(linemapDestination)); args.add("-m=" + absolutePathOf(metaData.javaDocs)); @@ -162,52 +150,6 @@ public abstract class AbstractFernFlowerDecompiler implements LoomDecompiler { result.assertNormalExitValue(); } - private Path transformBinary(Path compiledJar, DecompilationMetadata metaData) { - if (metaData.classFilter == null) return compiledJar; - - try { - Path tempFile = Files.createTempFile("loom-", null); - Files.deleteIfExists(tempFile); - tempFile.toFile().deleteOnExit(); - - try (ZipOutputStream tempZipOut = new ZipOutputStream(new FileOutputStream(tempFile.toFile()))) { - try (FileSystem compiledJarSystem = FileSystems.newFileSystem(URI.create("jar:" + compiledJar.toUri()), new HashMap<>())) { - Files.walkFileTree(compiledJarSystem.getPath("/"), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - if (file.toString().endsWith(".class")) { - String sourcePath = file.toString(); - - if (sourcePath.length() >= 1 && sourcePath.charAt(0) == '/') { - sourcePath = sourcePath.substring(1); - } - - sourcePath = sourcePath.substring(0, sourcePath.length() - 6); - - if (!metaData.classFilter.test(sourcePath)) { - return FileVisitResult.CONTINUE; - } else { - System.out.println(sourcePath); - } - } - - String resourcePath = file.toString(); - tempZipOut.putNextEntry(new ZipEntry(resourcePath)); - tempZipOut.write(Files.readAllBytes(file)); - tempZipOut.closeEntry(); - - return FileVisitResult.CONTINUE; - } - }); - } - } - - return tempFile; - } catch (IOException exception) { - throw new UncheckedIOException(exception); - } - } - private static String absolutePathOf(Path path) { return path.toAbsolutePath().toString(); } diff --git a/src/main/java/net/fabricmc/loom/task/AbstractLoomTask.java b/src/main/java/net/fabricmc/loom/task/AbstractLoomTask.java index e1f4db16..9dada304 100644 --- a/src/main/java/net/fabricmc/loom/task/AbstractLoomTask.java +++ b/src/main/java/net/fabricmc/loom/task/AbstractLoomTask.java @@ -28,11 +28,10 @@ import org.gradle.api.DefaultTask; import org.gradle.api.tasks.Internal; import net.fabricmc.loom.LoomGradleExtension; -import net.fabricmc.loom.util.Constants; public abstract class AbstractLoomTask extends DefaultTask { public AbstractLoomTask() { - setGroup(Constants.TASK_CATEGORY); + setGroup("fabric"); } @Internal diff --git a/src/main/java/net/fabricmc/loom/task/AbstractRunTask.java b/src/main/java/net/fabricmc/loom/task/AbstractRunTask.java index 111d074a..34f2dac8 100644 --- a/src/main/java/net/fabricmc/loom/task/AbstractRunTask.java +++ b/src/main/java/net/fabricmc/loom/task/AbstractRunTask.java @@ -35,14 +35,13 @@ import org.gradle.api.Project; import org.gradle.api.tasks.JavaExec; import net.fabricmc.loom.configuration.ide.RunConfig; -import net.fabricmc.loom.util.Constants; public abstract class AbstractRunTask extends JavaExec { private final RunConfig config; public AbstractRunTask(Function configProvider) { super(); - setGroup(Constants.TASK_CATEGORY); + setGroup("fabric"); this.config = configProvider.apply(getProject()); setClasspath(config.sourceSet.getRuntimeClasspath()); diff --git a/src/main/java/net/fabricmc/loom/task/CleanSourcesTask.java b/src/main/java/net/fabricmc/loom/task/CleanSourcesTask.java deleted file mode 100644 index de43fa19..00000000 --- a/src/main/java/net/fabricmc/loom/task/CleanSourcesTask.java +++ /dev/null @@ -1,15 +0,0 @@ -package net.fabricmc.loom.task; - -import static net.fabricmc.loom.task.GenerateSourcesTask.getMappedJarFileWithSuffix; - -import java.nio.file.Files; - -import org.gradle.api.tasks.TaskAction; - -public class CleanSourcesTask extends AbstractLoomTask { - @TaskAction - public void doTask() throws Throwable { - Files.deleteIfExists(getMappedJarFileWithSuffix(getProject(), "-sources.jar", false).toPath()); - Files.deleteIfExists(getMappedJarFileWithSuffix(getProject(), "-sources.jar", true).toPath()); - } -} diff --git a/src/main/java/net/fabricmc/loom/task/GenerateIncrementalSourcesTask.java b/src/main/java/net/fabricmc/loom/task/GenerateIncrementalSourcesTask.java deleted file mode 100644 index cd5d9683..00000000 --- a/src/main/java/net/fabricmc/loom/task/GenerateIncrementalSourcesTask.java +++ /dev/null @@ -1,128 +0,0 @@ -package net.fabricmc.loom.task; - -import java.io.File; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.net.URI; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.StandardCopyOption; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.function.Consumer; - -import javax.inject.Inject; - -import org.gradle.api.tasks.TaskAction; - -import net.fabricmc.loom.api.decompilers.LoomDecompiler; -import net.fabricmc.loom.configuration.processors.JarProcessorManager; -import net.fabricmc.loom.configuration.processors.MinecraftProcessedProvider; -import net.fabricmc.stitch.util.StitchUtil; - -public class GenerateIncrementalSourcesTask extends AbstractLoomTask { - public final LoomDecompiler decompiler; - - @Inject - public GenerateIncrementalSourcesTask(LoomDecompiler decompiler) { - this.decompiler = decompiler; - - getOutputs().upToDateWhen((o) -> false); - } - - @TaskAction - public void doTask() throws Throwable { - GenerateSourcesTask.generateSources(getProject(), getClass(), decompiler, null, false, true); - - if (getExtension().getMappingsProvider().mappedProvider instanceof MinecraftProcessedProvider) { - JarProcessorManager processorManager = getExtension().getJarProcessorManager(); - Path unprocessedCompiledJar = GenerateSourcesTask.getMappedJarFileWithSuffix(getProject(), null, false).toPath(); - Path compiledJar = GenerateSourcesTask.getMappedJarFileWithSuffix(getProject(), null, true).toPath(); - Path unprocessedSourcesDestination = GenerateSourcesTask.getMappedJarFileWithSuffix(getProject(), "-sources.jar", false).toPath(); - Map unprocessedSources = new HashMap<>(); - Set affectedSources = new HashSet<>(); - - try (FileSystem system = FileSystems.newFileSystem(URI.create("jar:" + unprocessedSourcesDestination.toUri()), new HashMap<>())) { - Files.walkFileTree(system.getPath("/"), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - if (file.toString().endsWith(".java")) { - String sourcePath = file.toString(); - - if (sourcePath.length() >= 1 && sourcePath.charAt(0) == '/') { - sourcePath = sourcePath.substring(1); - } - - sourcePath = sourcePath.substring(0, sourcePath.length() - 5); - unprocessedSources.put(sourcePath, Files.readAllBytes(file)); - - if (processorManager.doesProcessClass(sourcePath)) { - affectedSources.add(sourcePath); - } - } - - return FileVisitResult.CONTINUE; - } - }); - } catch (IOException exception) { - exception.printStackTrace(); - unprocessedSources.clear(); - } - - Consumer linemapConsumer = linemap -> { - try { - try (StitchUtil.FileSystemDelegate unprocessedFs = StitchUtil.getJarFileSystem(unprocessedCompiledJar.toFile(), true); - StitchUtil.FileSystemDelegate processedFs = StitchUtil.getJarFileSystem(compiledJar.toFile(), true)) { - int i = 0; - - for (Path path : (Iterable) Files.walk(processedFs.get().getPath("/"))::iterator) { - if (path.toString().endsWith(".class")) { - String sourcePath = path.toString(); - - if (sourcePath.length() >= 1 && sourcePath.charAt(0) == '/') { - sourcePath = sourcePath.substring(1); - } - - sourcePath = sourcePath.substring(0, sourcePath.length() - 6); - - Path unprocessedPath = unprocessedFs.get().getPath(path.toString()); - - if (Files.exists(unprocessedPath) && !processorManager.doesProcessClass(sourcePath)) { - i++; - Files.copy(unprocessedPath, path, StandardCopyOption.REPLACE_EXISTING); - } - } - } - - getLogger().lifecycle(":copied {} linemap remapped classes from unprocessed jar", i); - } - - GenerateSourcesTask.remapLinemap(getProject(), getClass(), compiledJar, linemap, true); - } catch (IOException exception) { - throw new UncheckedIOException(exception); - } - }; - - getLogger().lifecycle(":skipping {} unprocessed classes (excluding {} processed classes)", unprocessedSources.size() - affectedSources.size(), affectedSources.size()); - GenerateSourcesTask.generateSources(getProject(), getClass(), decompiler, className -> { - int i = className.indexOf('$'); - if (i >= 0) className = className.substring(0, i); - if (affectedSources.contains(className)) return GenerateSourcesTask.SkipState.GENERATE; - if (unprocessedSources.containsKey(className)) return GenerateSourcesTask.SkipState.SKIP; - return null; - }, true, true, linemapConsumer); - } - } - - public GenerateIncrementalSourcesTask setInputJar(File inputJar) { - this.inputJar = inputJar; - return this; - } -} diff --git a/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java b/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java index a9a0e0d4..25d6fe47 100644 --- a/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java +++ b/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java @@ -26,34 +26,19 @@ package net.fabricmc.loom.task; import java.io.File; import java.io.IOException; -import java.io.UncheckedIOException; -import java.net.URI; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; import java.nio.file.StandardCopyOption; -import java.nio.file.StandardOpenOption; -import java.nio.file.attribute.BasicFileAttributes; import java.util.Collection; -import java.util.HashMap; import java.util.Locale; -import java.util.Map; -import java.util.function.Consumer; -import java.util.function.Function; import java.util.stream.Collectors; import javax.inject.Inject; -import com.google.common.base.MoreObjects; -import org.gradle.api.Project; import org.gradle.api.tasks.InputFile; import org.gradle.api.tasks.TaskAction; import net.fabricmc.loom.LoomGradleExtension; -import net.fabricmc.loom.LoomGradlePlugin; import net.fabricmc.loom.api.decompilers.DecompilationMetadata; import net.fabricmc.loom.api.decompilers.LoomDecompiler; import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; @@ -71,100 +56,25 @@ public class GenerateSourcesTask extends AbstractLoomTask { public GenerateSourcesTask(LoomDecompiler decompiler) { this.decompiler = decompiler; + setGroup("fabric"); getOutputs().upToDateWhen((o) -> false); } @TaskAction public void doTask() throws Throwable { - generateSources(getProject(), getClass(), decompiler, null, true, false); - } - - public static void generateSources(Project project, Class taskClass, LoomDecompiler decompiler, Function additionalClassFilter, boolean processed, boolean incremental) - throws IOException { - generateSources(project, taskClass, decompiler, additionalClassFilter, processed, incremental, linemap -> { - try { - Path compiledJar = getMappedJarFileWithSuffix(project, null, processed).toPath(); - remapLinemap(project, taskClass, compiledJar, linemap, processed); - } catch (IOException exception) { - throw new UncheckedIOException(exception); - } - }); - } - - public static void generateSources(Project project, Class taskClass, LoomDecompiler decompiler, Function additionalClassFilter, boolean processed, boolean incremental, Consumer linemapConsumer) - throws IOException { - LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); int threads = Runtime.getRuntime().availableProcessors(); - Path javaDocs = extension.getMappingsProvider().tinyMappings.toPath(); - Collection libraries = project.getConfigurations().getByName(Constants.Configurations.MINECRAFT_DEPENDENCIES).getFiles() - .stream().map(File::toPath).collect(Collectors.toSet()); + Path javaDocs = getExtension().getMappingsProvider().tinyMappings.toPath(); + Collection libraries = getProject().getConfigurations().getByName(Constants.Configurations.MINECRAFT_DEPENDENCIES).getFiles() + .stream().map(File::toPath).collect(Collectors.toSet()); - Path runtimeJar = getMappedJarFileWithSuffix(project, null, processed).toPath(); - Path sourcesDestination = getMappedJarFileWithSuffix(project, "-sources.jar", processed).toPath(); - Path linemap = getMappedJarFileWithSuffix(project, "-sources.lmap", processed).toPath(); - Map remappedClasses = new HashMap<>(); - - if (!LoomGradlePlugin.refreshDeps && incremental && Files.exists(sourcesDestination)) { - try (FileSystem system = FileSystems.newFileSystem(URI.create("jar:" + sourcesDestination.toUri()), new HashMap<>())) { - Files.walkFileTree(system.getPath("/"), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - if (file.toString().endsWith(".java")) { - String sourcePath = file.toString(); - - if (sourcePath.length() >= 1 && sourcePath.charAt(0) == '/') { - sourcePath = sourcePath.substring(1); - } - - remappedClasses.put(sourcePath.substring(0, sourcePath.length() - 5), Files.readAllBytes(file)); - } - - return FileVisitResult.CONTINUE; - } - }); - } catch (IOException exception) { - exception.printStackTrace(); - remappedClasses.clear(); - } - } - - Files.deleteIfExists(sourcesDestination); - - if (incremental) { - project.getLogger().lifecycle(":incremental source generation: skipping {} classes", remappedClasses.size()); - } - - Function function = MoreObjects.firstNonNull(additionalClassFilter, s -> null); - Function classFilter = remappedClasses.isEmpty() ? function : s -> { - SkipState apply = function.apply(s); - if (apply != null) return apply; - int i = s.indexOf('$'); - if (i >= 0) s = s.substring(0, i); - return remappedClasses.containsKey(s) ? SkipState.SKIP : SkipState.GENERATE; - }; - DecompilationMetadata metadata = new DecompilationMetadata(threads, javaDocs, libraries, classFilter); + DecompilationMetadata metadata = new DecompilationMetadata(threads, javaDocs, libraries); + Path runtimeJar = getExtension().getMappingsProvider().mappedProvider.getMappedJar().toPath(); + Path sourcesDestination = getMappedJarFileWithSuffix("-sources.jar").toPath(); + Path linemap = getMappedJarFileWithSuffix("-sources.lmap").toPath(); decompiler.decompile(inputJar.toPath(), sourcesDestination, linemap, metadata); - if (incremental && !remappedClasses.isEmpty()) { - try (FileSystem system = FileSystems.newFileSystem(URI.create("jar:" + sourcesDestination.toUri()), new HashMap() { - { - put("create", "true"); - } - })) { - for (Map.Entry entry : remappedClasses.entrySet()) { - if (additionalClassFilter != null && SkipState.SKIP != additionalClassFilter.apply(entry.getKey())) continue; - Path path = system.getPath(entry.getKey() + ".java"); - Path parent = path.getParent(); - if (parent != null) Files.createDirectories(parent); - Files.write(path, entry.getValue(), StandardOpenOption.CREATE); - } - } - } - } - - public static void remapLinemap(Project project, Class taskClass, Path compiledJar, Path linemap, boolean processed) throws IOException { if (Files.exists(linemap)) { - Path linemappedJarDestination = getMappedJarFileWithSuffix(project, "-linemapped.jar", processed).toPath(); + Path linemappedJarDestination = getMappedJarFileWithSuffix("-linemapped.jar").toPath(); // Line map the actually jar used to run the game, not the one used to decompile remapLineNumbers(runtimeJar, linemap, linemappedJarDestination); @@ -174,13 +84,12 @@ public class GenerateSourcesTask extends AbstractLoomTask { } } - private static void remapLineNumbers(Project project, Class taskClass, Path oldCompiledJar, Path linemap, Path linemappedJarDestination) - throws IOException { - project.getLogger().info(":adjusting line numbers"); + private void remapLineNumbers(Path oldCompiledJar, Path linemap, Path linemappedJarDestination) throws IOException { + getProject().getLogger().info(":adjusting line numbers"); LineNumberRemapper remapper = new LineNumberRemapper(); remapper.readMappings(linemap.toFile()); - ProgressLogger progressLogger = ProgressLogger.getProgressFactory(project, taskClass.getName()); + ProgressLogger progressLogger = ProgressLogger.getProgressFactory(getProject(), getClass().getName()); progressLogger.start("Adjusting line numbers", "linemap"); try (StitchUtil.FileSystemDelegate inFs = StitchUtil.getJarFileSystem(oldCompiledJar.toFile(), true); @@ -191,27 +100,19 @@ public class GenerateSourcesTask extends AbstractLoomTask { progressLogger.completed(); } - public static File getMappedJarFileWithSuffix(Project project, String suffix, boolean processed) { - LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); + private File getMappedJarFileWithSuffix(String suffix) { + LoomGradleExtension extension = getProject().getExtensions().getByType(LoomGradleExtension.class); MappingsProvider mappingsProvider = extension.getMappingsProvider(); - File mappedJar = processed ? mappingsProvider.mappedProvider.getMappedJar() : mappingsProvider.mappedProvider.getUnprocessedMappedJar(); + File mappedJar = mappingsProvider.mappedProvider.getMappedJar(); String path = mappedJar.getAbsolutePath(); if (!path.toLowerCase(Locale.ROOT).endsWith(".jar")) { throw new RuntimeException("Invalid mapped JAR path: " + path); } - if (suffix == null) { - return new File(path); - } - return new File(path.substring(0, path.length() - 4) + suffix); } - public enum SkipState { - SKIP, GENERATE; - } - @InputFile public File getInputJar() { return inputJar; diff --git a/src/main/java/net/fabricmc/loom/task/LoomTasks.java b/src/main/java/net/fabricmc/loom/task/LoomTasks.java index 55cf282a..1b1de6a7 100644 --- a/src/main/java/net/fabricmc/loom/task/LoomTasks.java +++ b/src/main/java/net/fabricmc/loom/task/LoomTasks.java @@ -35,7 +35,6 @@ import net.fabricmc.loom.api.decompilers.LoomDecompiler; import net.fabricmc.loom.configuration.ide.RunConfigSettings; import net.fabricmc.loom.configuration.providers.mappings.MappingsProvider; import net.fabricmc.loom.decompilers.fernflower.FabricFernFlowerDecompiler; -import net.fabricmc.loom.util.Constants; public final class LoomTasks { private LoomTasks() { @@ -51,7 +50,7 @@ public final class LoomTasks { tasks.register("remapJar", RemapJarTask.class, t -> { t.setDescription("Remaps the built project jar to intermediary mappings."); - t.setGroup(Constants.TASK_CATEGORY); + t.setGroup("fabric"); }); tasks.register("downloadAssets", DownloadAssetsTask.class, t -> t.setDescription("Downloads required assets for Fabric.")); @@ -60,8 +59,6 @@ public final class LoomTasks { registerIDETasks(tasks); registerRunTasks(tasks, project); registerDecompileTasks(tasks, project); - - tasks.register("cleanSources", CleanSourcesTask.class); } private static void registerIDETasks(TaskContainer tasks) { @@ -100,6 +97,7 @@ public final class LoomTasks { tasks.register(taskName, RunGameTask.class, config).configure(t -> { t.setDescription("Starts the '" + config.getConfigName() + "' run configuration"); + t.setGroup("fabric"); if (config.getEnvironment().equals("client")) { t.dependsOn("downloadAssets"); @@ -132,7 +130,6 @@ public final class LoomTasks { for (LoomDecompiler decompiler : extension.getDecompilers()) { String taskName = decompiler instanceof FabricFernFlowerDecompiler ? "genSources" : "genSourcesWith" + decompiler.name(); - String incrementalTaskName = decompiler instanceof FabricFernFlowerDecompiler ? "genIncrementalSources" : "genIncrementalSourcesWith" + decompiler.name(); // decompiler will be passed to the constructor of GenerateSourcesTask GenerateSourcesTask generateSourcesTask = tasks.register(taskName, GenerateSourcesTask.class, decompiler).get(); generateSourcesTask.setInputJar(inputJar); @@ -140,13 +137,6 @@ public final class LoomTasks { if (mappingsProvider.hasUnpickDefinitions()) { generateSourcesTask.dependsOn(tasks.getByName("unpickJar")); } - - GenerateIncrementalSourcesTask generateIncrementalSourcesTask = tasks.register(incrementalTaskName, GenerateIncrementalSourcesTask.class, decompiler).get(); - generateIncrementalSourcesTask.setInputJar(inputJar); - - if (mappingsProvider.hasUnpickDefinitions()) { - generateIncrementalSourcesTask.dependsOn(tasks.getByName("unpickJar")); - } } }); } diff --git a/src/main/java/net/fabricmc/loom/util/Constants.java b/src/main/java/net/fabricmc/loom/util/Constants.java index 4e47c5dd..b9059217 100644 --- a/src/main/java/net/fabricmc/loom/util/Constants.java +++ b/src/main/java/net/fabricmc/loom/util/Constants.java @@ -35,7 +35,6 @@ import net.fabricmc.loom.util.gradle.GradleSupport; public class Constants { public static final String PLUGIN_ID = "forgified-fabric-loom"; - public static final String TASK_CATEGORY = "loom"; public static final String LIBRARIES_BASE = "https://libraries.minecraft.net/"; public static final String RESOURCES_BASE = "http://resources.download.minecraft.net/"; public static final String VERSION_MANIFESTS = "https://launchermeta.mojang.com/mc/game/version_manifest_v2.json"; 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 e14afeb9..467c15a4 100644 --- a/src/main/java/net/fabricmc/loom/util/srg/AtRemapper.java +++ b/src/main/java/net/fabricmc/loom/util/srg/AtRemapper.java @@ -24,108 +24,111 @@ package net.fabricmc.loom.util.srg; -import static me.shedaniel.architectury.refmapremapper.utils.DescriptorRemapper.remapDescriptor; - import java.io.IOException; +import java.io.StringReader; import java.nio.file.Path; -import java.util.Objects; +import java.util.ArrayList; +import java.util.List; +import java.util.function.UnaryOperator; import java.util.zip.ZipEntry; -import me.shedaniel.architectury.refmapremapper.remapper.SimpleReferenceRemapper; import org.apache.logging.log4j.util.Strings; import org.gradle.api.logging.Logger; -import org.jetbrains.annotations.Nullable; import org.zeroturnaround.zip.ZipUtil; import org.zeroturnaround.zip.transform.StringZipEntryTransformer; +import org.zeroturnaround.zip.transform.ZipEntryTransformerEntry; +import net.fabricmc.loom.util.function.CollectionUtil; import net.fabricmc.mapping.tree.TinyTree; /** - * Remaps AT contents. + * Remaps AT classes from SRG to Yarn. * * @author Juuz */ public final class AtRemapper { - public static void remapSrgToNamed(Logger logger, Path jar, TinyTree mappings) throws IOException { - ZipUtil.transformEntry(jar.toFile(), "META-INF/accesstransformer.cfg", new StringZipEntryTransformer() { + public static void remap(Logger logger, Path jar, TinyTree mappings) throws IOException { + ZipUtil.transformEntries(jar.toFile(), new ZipEntryTransformerEntry[] {(new ZipEntryTransformerEntry("META-INF/accesstransformer.cfg", new StringZipEntryTransformer() { @Override protected String transform(ZipEntry zipEntry, String input) { - return remapAt(logger, input, new SimpleReferenceRemapper.Remapper() { - @Override - @Nullable - public String mapClass(String value) { - return mappings.getClasses().stream() - .filter(classDef -> Objects.equals(classDef.getName("srg"), value)) - .findFirst() - .map(classDef -> classDef.getName("named")) - .orElse(null); + 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("#") || Strings.isBlank(line)) { + output.add(i, line); + continue; } - @Override - @Nullable - public String mapMethod(@Nullable String className, String methodName, String methodDescriptor) { - return null; + String[] parts = line.split("\\s+"); + + if (parts.length < 2) { + logger.warn("Invalid AT Line: " + line); + output.add(i, line); + continue; } - @Override - @Nullable - public String mapField(@Nullable String className, String fieldName, String fieldDescriptor) { - return null; + String name = parts[1].replace('.', '/'); + parts[1] = CollectionUtil.find( + mappings.getClasses(), + def -> def.getName("srg").equals(name) + ).map(def -> def.getName("named")).orElse(name).replace('/', '.'); + + if (parts.length >= 3) { + if (parts[2].contains("(")) { + parts[2] = parts[2].substring(0, parts[2].indexOf('(')) + remapDescriptor(parts[2].substring(parts[2].indexOf('(')), s -> { + return CollectionUtil.find( + mappings.getClasses(), + def -> def.getName("srg").equals(s) + ).map(def -> def.getName("named")).orElse(s); + }); + } } - }); - } - }); - } - public static String remapAt(Logger logger, String sourceAt, SimpleReferenceRemapper.Remapper remapper) { - String[] lines = sourceAt.split("\n"); - StringBuilder builder = new StringBuilder(); - - for (String line : lines) { - { - int indexOf = line.indexOf('#'); - - if (indexOf != -1) { - line = line.substring(0, indexOf); + output.add(i, String.join(" ", parts)); } - line = line.trim(); + return String.join("\n", output); } + }))}); + } - if (Strings.isBlank(line)) { - builder.append(line).append('\n'); - continue; - } + private static String remapDescriptor(String original, UnaryOperator classMappings) { + try { + StringReader reader = new StringReader(original); + StringBuilder result = new StringBuilder(); + boolean insideClassName = false; + StringBuilder className = new StringBuilder(); - String[] parts = line.split("\\s+"); + while (true) { + int c = reader.read(); - if (parts.length < 2) { - logger.warn("Invalid AT Line: " + line); - builder.append(line).append('\n'); - continue; - } + if (c == -1) { + break; + } - String originalClassName = parts[1].replace('.', '/'); - parts[1] = either(remapper.mapClass(originalClassName), parts[1]).replace('/', '.'); + if ((char) c == ';') { + insideClassName = false; + result.append(classMappings.apply(className.toString())); + } - if (parts.length >= 3) { - if (parts[2].contains("(")) { - String methodName = parts[2].substring(0, parts[2].indexOf('(')); - String methodDescriptor = parts[2].substring(parts[2].indexOf('(')); - parts[2] = either(remapper.mapMethod(originalClassName, methodName, methodDescriptor), methodName) - + remapDescriptor(methodDescriptor, it -> either(remapper.mapClass(it), it)); + if (insideClassName) { + className.append((char) c); } else { - parts[2] = either(remapper.mapField(originalClassName, parts[2], null), parts[2]); + result.append((char) c); + } + + if (!insideClassName && (char) c == 'L') { + insideClassName = true; + className.setLength(0); } } - builder.append(String.join(" ", parts)).append('\n'); + return result.toString(); + } catch (IOException e) { + throw new AssertionError(e); } - - return builder.toString(); - } - - private static T either(@Nullable T first, @Nullable T second) { - return first == null ? second : first; } }