diff --git a/build.gradle b/build.gradle index 0bcc25de..74da0962 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ if (ENV.BUILD_NUMBER) { build = 'jenkins #${ENV.BUILD_NUMBER}' version = baseVersion + '.' + ENV.BUILD_NUMBER } else { - version = baseVersion + '-forge.2' + version = baseVersion + '-forge.6' } repositories { @@ -71,6 +71,10 @@ dependencies { // Forge patches implementation ('net.minecraftforge:binarypatcher:1.1.1') + implementation ('org.cadixdev:lorenz:0.5.3') + implementation ('org.cadixdev:lorenz-asm:0.5.3') + implementation ('org.cadixdev:atlas:0.2.0') + implementation ('net.minecraftforge.gradle:ForgeGradle:3.0.179') // Testing testImplementation(gradleTestKit()) diff --git a/src/main/java/net/fabricmc/loom/AbstractPlugin.java b/src/main/java/net/fabricmc/loom/AbstractPlugin.java index fe39e7aa..fb216a6e 100644 --- a/src/main/java/net/fabricmc/loom/AbstractPlugin.java +++ b/src/main/java/net/fabricmc/loom/AbstractPlugin.java @@ -32,6 +32,7 @@ import java.util.Set; import com.google.common.collect.ImmutableMap; import groovy.util.Node; +import net.fabricmc.loom.providers.*; import org.gradle.api.Plugin; import org.gradle.api.Project; import org.gradle.api.Task; @@ -49,11 +50,6 @@ import org.gradle.api.tasks.bundling.AbstractArchiveTask; import org.gradle.api.tasks.javadoc.Javadoc; import org.gradle.plugins.ide.idea.model.IdeaModel; -import net.fabricmc.loom.providers.LaunchProvider; -import net.fabricmc.loom.providers.MappingsCache; -import net.fabricmc.loom.providers.MappingsProvider; -import net.fabricmc.loom.providers.MinecraftProvider; -import net.fabricmc.loom.providers.PatchProvider; import net.fabricmc.loom.task.AbstractLoomTask; import net.fabricmc.loom.task.RemapJarTask; import net.fabricmc.loom.task.RemapSourcesJarTask; @@ -122,6 +118,8 @@ public class AbstractPlugin implements Plugin { minecraftConfig.setTransitive(false); Configuration forgeConfig = project.getConfigurations().maybeCreate(Constants.FORGE); forgeConfig.setTransitive(false); + Configuration mcpConfig = project.getConfigurations().maybeCreate(Constants.MCP_CONFIG); + mcpConfig.setTransitive(false); Configuration includeConfig = project.getConfigurations().maybeCreate(Constants.INCLUDE); includeConfig.setTransitive(false); // Dont get transitive deps @@ -229,6 +227,7 @@ public class AbstractPlugin implements Plugin { LoomDependencyManager dependencyManager = new LoomDependencyManager(); extension.setDependencyManager(dependencyManager); + dependencyManager.addProvider(new McpConfigProvider(getProject())); dependencyManager.addProvider(new PatchProvider(getProject())); dependencyManager.addProvider(new MinecraftProvider(getProject())); dependencyManager.addProvider(new MappingsProvider(getProject())); diff --git a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java index a5c58ed7..bf058c1b 100644 --- a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java +++ b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java @@ -52,6 +52,7 @@ import net.fabricmc.loom.providers.MappingsProvider; import net.fabricmc.loom.providers.MinecraftMappedProvider; import net.fabricmc.loom.providers.MinecraftProvider; import net.fabricmc.loom.providers.PatchProvider; +import net.fabricmc.loom.providers.McpConfigProvider; import net.fabricmc.loom.util.LoomDependencyManager; public class LoomGradleExtension { @@ -331,6 +332,10 @@ public class LoomGradleExtension { return getDependencyManager().getProvider(MappingsProvider.class); } + public McpConfigProvider getMcpConfigProvider() { + return getDependencyManager().getProvider(McpConfigProvider.class); + } + public void setDependencyManager(LoomDependencyManager dependencyManager) { this.dependencyManager = dependencyManager; } diff --git a/src/main/java/net/fabricmc/loom/providers/McpConfigProvider.java b/src/main/java/net/fabricmc/loom/providers/McpConfigProvider.java new file mode 100644 index 00000000..4f4ef091 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/providers/McpConfigProvider.java @@ -0,0 +1,87 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.providers; + +import java.io.File; +import java.net.URI; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.function.Consumer; + +import com.google.common.collect.ImmutableMap; +import org.gradle.api.Project; + +import net.fabricmc.loom.util.Constants; +import net.fabricmc.loom.util.DependencyProvider; + +public class McpConfigProvider extends DependencyProvider { + private File mcp; + private File srg; + + public McpConfigProvider(Project project) { + super(project); + } + + @Override + public void provide(DependencyInfo dependency, Consumer postPopulationScheduler) throws Exception { + init(dependency.getDependency().getVersion()); + + if (mcp.exists() && srg.exists()) { + return; // No work for us to do here + } + + Path mcpZip = dependency.resolveFile().orElseThrow(() -> new IllegalStateException("Could not resolve MCPConfig")).toPath(); + + if (!mcp.exists()) { + Files.copy(mcpZip, mcp.toPath()); + } + + if (!srg.exists()) { + try (FileSystem fs = FileSystems.newFileSystem(new URI("jar:" + mcpZip.toUri()), ImmutableMap.of("create", false))) { + Files.copy(fs.getPath("config", "joined.tsrg"), srg.toPath()); + } + } + } + + private void init(String version) { + mcp = new File(getExtension().getUserCache(), "mcp-" + version + ".zip"); + srg = new File(getExtension().getUserCache(), "srg-" + version + ".tsrg"); + } + + public File getMcp() { + return mcp; + } + + public File getSrg() { + return srg; + } + + @Override + public String getTargetConfig() { + return Constants.MCP_CONFIG; + } +} diff --git a/src/main/java/net/fabricmc/loom/providers/MinecraftProvider.java b/src/main/java/net/fabricmc/loom/providers/MinecraftProvider.java index 7730fbf8..cd9608ae 100644 --- a/src/main/java/net/fabricmc/loom/providers/MinecraftProvider.java +++ b/src/main/java/net/fabricmc/loom/providers/MinecraftProvider.java @@ -27,17 +27,26 @@ package net.fabricmc.loom.providers; import java.io.File; import java.io.FileReader; import java.io.IOException; +import java.io.Reader; import java.net.URL; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.Optional; import java.util.function.Consumer; +import java.util.function.UnaryOperator; import java.util.zip.ZipError; import com.google.common.io.Files; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import net.minecraftforge.binarypatcher.ConsoleTool; +import net.minecraftforge.gradle.mcp.util.MCPRuntime; +import net.minecraftforge.gradle.mcp.util.MCPWrapper; +import org.cadixdev.atlas.Atlas; +import org.cadixdev.bombe.asm.jar.JarEntryRemappingTransformer; +import org.cadixdev.lorenz.MappingSet; +import org.cadixdev.lorenz.asm.LorenzRemapper; +import org.cadixdev.lorenz.io.srg.tsrg.TSrgReader; import org.gradle.api.GradleException; import org.gradle.api.Project; import org.gradle.api.logging.Logger; @@ -45,6 +54,7 @@ import org.gradle.api.logging.Logger; import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.DependencyProvider; import net.fabricmc.loom.util.DownloadUtil; +import net.fabricmc.loom.util.IoConsumer; import net.fabricmc.loom.util.ManifestVersion; import net.fabricmc.loom.util.MinecraftVersionInfo; import net.fabricmc.loom.util.StaticPathWatcher; @@ -59,6 +69,10 @@ public class MinecraftProvider extends DependencyProvider { private File minecraftJson; private File minecraftClientJar; private File minecraftServerJar; + private File minecraftClientSrgJar; + private File minecraftServerSrgJar; + private File minecraftClientPatchedSrgJar; + private File minecraftServerPatchedSrgJar; private File minecraftClientPatchedJar; private File minecraftServerPatchedJar; private File minecraftMergedJar; @@ -103,7 +117,15 @@ public class MinecraftProvider extends DependencyProvider { libraryProvider.provide(this, getProject()); if (!minecraftClientPatchedJar.exists() || !minecraftServerPatchedJar.exists()) { - patchJars(getProject().getLogger()); + if (!minecraftClientSrgJar.exists() || !minecraftServerSrgJar.exists()) { + createSrgJars(getProject().getLogger()); + } + + if (!minecraftClientPatchedSrgJar.exists() || !minecraftServerPatchedSrgJar.exists()) { + patchJars(getProject().getLogger()); + } + + createPatchedJars(getProject().getLogger()); } if (!minecraftMergedJar.exists() || isRefreshDeps()) { @@ -128,7 +150,11 @@ public class MinecraftProvider extends DependencyProvider { PatchProvider patchProvider = getExtension().getPatchProvider(); minecraftClientPatchedJar = new File(getExtension().getProjectPersistentCache(), "minecraft-" + minecraftVersion + "-client-patched-" + patchProvider.forgeVersion + ".jar"); minecraftServerPatchedJar = new File(getExtension().getProjectPersistentCache(), "minecraft-" + minecraftVersion + "-server-patched-" + patchProvider.forgeVersion + ".jar"); - minecraftMergedJar = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-merged.jar"); + minecraftClientSrgJar = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-client-srg.jar"); + minecraftServerSrgJar = new File(getExtension().getUserCache(), "minecraft-" + minecraftVersion + "-server-srg.jar"); + minecraftClientPatchedSrgJar = new File(getExtension().getProjectPersistentCache(), "minecraft-" + minecraftVersion + "-client-patched-srg-" + patchProvider.forgeVersion + ".jar"); + minecraftServerPatchedSrgJar = new File(getExtension().getProjectPersistentCache(), "minecraft-" + minecraftVersion + "-server-patched-srg-" + patchProvider.forgeVersion + ".jar"); + minecraftMergedJar = new File(getExtension().getProjectPersistentCache(), "minecraft-" + minecraftVersion + "-merged-patched-" + patchProvider.forgeVersion + ".jar"); } private void downloadMcJson(boolean offline) throws IOException { @@ -197,16 +223,66 @@ public class MinecraftProvider extends DependencyProvider { DownloadUtil.downloadIfChanged(new URL(versionInfo.downloads.get("server").url), minecraftServerJar, logger); } + private void createSrgJars(Logger logger) throws Exception { + logger.info(":remapping minecraft: official->srg"); + + McpConfigProvider volde = getExtension().getMcpConfigProvider(); + File root = new File(getExtension().getUserCache(), "mcp_root"); + root.mkdirs(); + MCPWrapper wrapper = new MCPWrapper(volde.getMcp(), root); + + // Client + { + MCPRuntime runtime = wrapper.getRuntime(getProject(), "client"); + File output = runtime.execute(logger, "rename"); + Files.copy(output, minecraftClientSrgJar); + } + + // Server + { + MCPRuntime runtime = wrapper.getRuntime(getProject(), "server"); + File output = runtime.execute(logger, "rename"); + Files.copy(output, minecraftServerSrgJar); + } + } + + private void createPatchedJars(Logger logger) throws IOException { + logger.info(":remapping minecraft: srg->official"); + + useAtlas(MappingSet::reverse, atlas -> { + atlas.run(minecraftClientPatchedSrgJar.toPath(), minecraftClientPatchedJar.toPath()); + atlas.run(minecraftServerPatchedSrgJar.toPath(), minecraftServerPatchedJar.toPath()); + }); + } + + private void useAtlas(UnaryOperator mappingOp, IoConsumer action) throws IOException { + try (Reader mappingReader = new FileReader(getExtension().getMcpConfigProvider().getSrg()); + TSrgReader reader = new TSrgReader(mappingReader); + Atlas atlas = new Atlas()) { + MappingSet mappings = mappingOp.apply(reader.read()); + + atlas.install(ctx -> new JarEntryRemappingTransformer( + new LorenzRemapper(mappings, ctx.inheritanceProvider()) + )); + + for (File library : getLibraryProvider().getLibraries()) { + atlas.use(library.toPath()); + } + + action.accept(atlas); + } + } + private void patchJars(Logger logger) throws IOException { logger.info(":patching jars"); PatchProvider patchProvider = getExtension().getPatchProvider(); - patchJars(minecraftClientJar, minecraftClientPatchedJar, patchProvider.clientPatches); - patchJars(minecraftServerJar, minecraftServerPatchedJar, patchProvider.serverPatches); + patchJars(minecraftClientSrgJar, minecraftClientPatchedSrgJar, patchProvider.clientPatches); + patchJars(minecraftServerSrgJar, minecraftServerPatchedSrgJar, patchProvider.serverPatches); } private void patchJars(File clean, File output, Path patches) throws IOException { - ConsoleTool.main(new String[] { + ConsoleTool.main(new String[]{ "--clean", clean.getAbsolutePath(), "--output", output.getAbsolutePath(), "--apply", patches.toAbsolutePath().toString() diff --git a/src/main/java/net/fabricmc/loom/util/IoConsumer.java b/src/main/java/net/fabricmc/loom/util/IoConsumer.java new file mode 100644 index 00000000..b47f751d --- /dev/null +++ b/src/main/java/net/fabricmc/loom/util/IoConsumer.java @@ -0,0 +1,38 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2016, 2017, 2018 FabricMC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package net.fabricmc.loom.util; + +import java.io.IOException; + +/** + * Like Consumer, but can throw IOException. + * + * @param the result type + * @author Juuz + */ +@FunctionalInterface +public interface IoConsumer { + void accept(A a) throws IOException; +}