From 7cc384d43e38ad9a5b0cc9f5277afe1504257d0d Mon Sep 17 00:00:00 2001 From: Matyrobbrt Date: Fri, 6 Sep 2024 13:32:42 +0300 Subject: [PATCH] Add a task to reobfuscate jar --- legacytest/build.gradle | 21 ++- .../src/main/java/legacytest/LegacyTest.java | 6 + .../legacy/LegacyForgeMetadataTransform.java | 2 +- .../legacy/LegacyModDevPlugin.java | 41 +++++- .../legacy/McpMetadataTransform.java | 2 +- .../moddevgradle/legacy/RemapJarTask.java | 122 ++++++++++++++++++ .../moddevgradle/legacy/Reobfuscation.java | 56 ++++++++ 7 files changed, 241 insertions(+), 9 deletions(-) create mode 100644 src/legacy/java/net/neoforged/moddevgradle/legacy/RemapJarTask.java create mode 100644 src/legacy/java/net/neoforged/moddevgradle/legacy/Reobfuscation.java diff --git a/legacytest/build.gradle b/legacytest/build.gradle index e619c212..fbd027ba 100644 --- a/legacytest/build.gradle +++ b/legacytest/build.gradle @@ -1,7 +1,11 @@ plugins { - id 'net.neoforged.moddev' + id 'maven-publish' + id 'net.neoforged.moddev.legacy' } +group = 'com.example.legacy' +version = '1.0.0' + repositories { mavenLocal() } @@ -13,5 +17,18 @@ java { } neoForge { - mcpMinecraftVersion = '1.19.2' + neoFormVersion = '1.19.2' +} + +publishing { + publications { + maven(MavenPublication) { + from components.java + } + } + repositories { + maven { + url file('local') + } + } } diff --git a/legacytest/src/main/java/legacytest/LegacyTest.java b/legacytest/src/main/java/legacytest/LegacyTest.java index f3e601cc..1496c7e1 100644 --- a/legacytest/src/main/java/legacytest/LegacyTest.java +++ b/legacytest/src/main/java/legacytest/LegacyTest.java @@ -1,7 +1,10 @@ package legacytest; +import com.mojang.blaze3d.systems.RenderSystem; import net.minecraft.DetectedVersion; import net.minecraft.client.main.Main; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; public class LegacyTest { public static void main(String[] args) { @@ -9,5 +12,8 @@ public static void main(String[] args) { Main.main(new String[]{ }); + + System.out.println(new ItemStack(Items.ACACIA_LEAVES).getCount()); + RenderSystem.disableBlend(); } } diff --git a/src/legacy/java/net/neoforged/moddevgradle/legacy/LegacyForgeMetadataTransform.java b/src/legacy/java/net/neoforged/moddevgradle/legacy/LegacyForgeMetadataTransform.java index 3346c39b..d2434fc4 100644 --- a/src/legacy/java/net/neoforged/moddevgradle/legacy/LegacyForgeMetadataTransform.java +++ b/src/legacy/java/net/neoforged/moddevgradle/legacy/LegacyForgeMetadataTransform.java @@ -19,7 +19,7 @@ import java.util.jar.JarInputStream; // @CacheableTransform -public class LegacyForgeMetadataTransform implements ComponentMetadataRule { +class LegacyForgeMetadataTransform implements ComponentMetadataRule { private final ObjectFactory objects; private final RepositoryResourceAccessor repositoryResourceAccessor; diff --git a/src/legacy/java/net/neoforged/moddevgradle/legacy/LegacyModDevPlugin.java b/src/legacy/java/net/neoforged/moddevgradle/legacy/LegacyModDevPlugin.java index 59d06e62..8441dce3 100644 --- a/src/legacy/java/net/neoforged/moddevgradle/legacy/LegacyModDevPlugin.java +++ b/src/legacy/java/net/neoforged/moddevgradle/legacy/LegacyModDevPlugin.java @@ -1,14 +1,22 @@ package net.neoforged.moddevgradle.legacy; import net.neoforged.moddevgradle.dsl.NeoForgeExtension; +import net.neoforged.moddevgradle.internal.ModDevPlugin; import org.gradle.api.Plugin; import org.gradle.api.Project; +import org.gradle.api.file.RegularFile; +import org.gradle.api.plugins.JavaPlugin; +import org.gradle.api.tasks.SourceSet; +import org.gradle.api.tasks.SourceSetContainer; +import org.gradle.jvm.tasks.Jar; import java.net.URI; public class LegacyModDevPlugin implements Plugin { @Override public void apply(Project project) { + project.getPlugins().apply(ModDevPlugin.class); + project.getRepositories().maven(repo -> { repo.setName("MinecraftForge"); repo.setUrl(URI.create("https://maven.minecraftforge.net/")); @@ -18,11 +26,34 @@ public void apply(Project project) { project.getDependencies().getComponents().withModule("net.minecraftforge:forge", LegacyForgeMetadataTransform.class); project.getDependencies().getComponents().withModule("de.oceanlabs.mcp:mcp_config", McpMetadataTransform.class); - project.getPlugins().withId("net.neoforged.moddev", plugin -> { - project.getExtensions().configure(NeoForgeExtension.class, extension -> { - extension.getNeoForgeArtifact().set(extension.getVersion().map(version -> "net.minecraftforge:forge:" + version)); - extension.getNeoFormArtifact().set(extension.getNeoFormVersion().map(version -> "de.oceanlabs.mcp:mcp_config:" + version)); - }); + var depFactory = project.getDependencyFactory(); + var autoRenamingToolRuntime = project.getConfigurations().create("autoRenamingToolRuntime", spec -> { + spec.setDescription("The AutoRenamingTool CLI tool"); + spec.setCanBeConsumed(false); + spec.setCanBeResolved(true); + spec.setTransitive(false); + spec.defaultDependencies(dependencies -> dependencies.add(depFactory.create("net.neoforged:AutoRenamingTool:2.0.3:all"))); + }); + + // We use this directory to store intermediate files used during moddev + var modDevBuildDir = project.getLayout().getBuildDirectory().dir("moddev"); + var officialToSrg = modDevBuildDir.map(d -> d.file("officialToSrg.tsrg")); + + project.getExtensions().configure(NeoForgeExtension.class, extension -> { + extension.getNeoForgeArtifact().set(extension.getVersion().map(version -> "net.minecraftforge:forge:" + version)); + extension.getNeoFormArtifact().set(extension.getNeoFormVersion().map(version -> "de.oceanlabs.mcp:mcp_config:" + version)); + extension.getNeoFormRuntime().getAdditionalResults().put("officialToSrgMapping", officialToSrg.map(RegularFile::getAsFile)); }); + + var reobf = project.getExtensions().create("reobfuscation", Reobfuscation.class, project, officialToSrg, autoRenamingToolRuntime); + + var reobfJar = reobf.reobfuscate( + project.getTasks().named(JavaPlugin.JAR_TASK_NAME, Jar.class), + project.getExtensions().getByType(SourceSetContainer.class).getByName(SourceSet.MAIN_SOURCE_SET_NAME), + remapJarTask -> remapJarTask.getArchiveClassifier().set("") + ); + + project.getTasks().named(JavaPlugin.JAR_TASK_NAME, Jar.class).configure(jar -> jar.getArchiveClassifier().set("dev")); + project.getTasks().named("assemble", assemble -> assemble.dependsOn(reobfJar)); } } diff --git a/src/legacy/java/net/neoforged/moddevgradle/legacy/McpMetadataTransform.java b/src/legacy/java/net/neoforged/moddevgradle/legacy/McpMetadataTransform.java index 4485eb35..8fad9cc8 100644 --- a/src/legacy/java/net/neoforged/moddevgradle/legacy/McpMetadataTransform.java +++ b/src/legacy/java/net/neoforged/moddevgradle/legacy/McpMetadataTransform.java @@ -26,7 +26,7 @@ * https://maven.neoforged.net/releases/net/neoforged/neoform/1.21-20240613.152323/neoform-1.21-20240613.152323.module */ // @CacheableTransform -public class McpMetadataTransform implements ComponentMetadataRule { +class McpMetadataTransform implements ComponentMetadataRule { private static final Attribute JVM_VERSION = Attribute.of("org.gradle.jvm.version", String.class); private final ObjectFactory objects; private final RepositoryResourceAccessor repositoryResourceAccessor; diff --git a/src/legacy/java/net/neoforged/moddevgradle/legacy/RemapJarTask.java b/src/legacy/java/net/neoforged/moddevgradle/legacy/RemapJarTask.java new file mode 100644 index 00000000..2ddda3e8 --- /dev/null +++ b/src/legacy/java/net/neoforged/moddevgradle/legacy/RemapJarTask.java @@ -0,0 +1,122 @@ +package net.neoforged.moddevgradle.legacy; + +import net.neoforged.moddevgradle.internal.utils.NetworkSettingPassthrough; +import org.gradle.api.DefaultTask; +import org.gradle.api.file.ConfigurableFileCollection; +import org.gradle.api.file.DirectoryProperty; +import org.gradle.api.file.RegularFileProperty; +import org.gradle.api.plugins.JavaPluginExtension; +import org.gradle.api.provider.Property; +import org.gradle.api.tasks.Classpath; +import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.InputFile; +import org.gradle.api.tasks.InputFiles; +import org.gradle.api.tasks.Internal; +import org.gradle.api.tasks.Optional; +import org.gradle.api.tasks.OutputFile; +import org.gradle.api.tasks.TaskAction; +import org.gradle.jvm.toolchain.JavaToolchainService; +import org.gradle.process.ExecOperations; + +import javax.inject.Inject; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Task used to remap a jar using AutoRenamingTool. + */ +public abstract class RemapJarTask extends DefaultTask { + + @Inject + public RemapJarTask() { + final JavaPluginExtension extension = getProject().getExtensions().findByType(JavaPluginExtension.class); + if (extension != null) { + getJavaExecutable().convention(getToolchainService().launcherFor(extension.getToolchain()) + .map(launcher -> launcher.getExecutablePath().getAsFile().getAbsolutePath())); + } + + getOutput().convention(getProject().provider(() -> { + var path = getArchiveBaseName().get() + getArchiveVersion().map(v -> "-" + v).getOrElse("") + getArchiveClassifier().map(c -> "-" + c).getOrElse("") + ".jar"; + return getDestinationDirectory().file(path); + }).flatMap(regularFileProvider -> regularFileProvider)); + } + + @Input + public abstract Property getJavaExecutable(); + + @Inject + protected abstract ExecOperations getExecOperations(); + + @Inject + protected abstract JavaToolchainService getToolchainService(); + + @Classpath + @InputFiles + protected abstract ConfigurableFileCollection getToolClasspath(); + + @InputFile + public abstract RegularFileProperty getMappings(); + + /** + * The libraries to use for inheritance data during the renaming process. + */ + @Optional + @InputFiles + public abstract ConfigurableFileCollection getLibraries(); + + @InputFile + public abstract RegularFileProperty getInput(); + + @Internal + public abstract Property getArchiveBaseName(); + + @Internal + public abstract Property getArchiveVersion(); + + @Internal + public abstract Property getArchiveClassifier(); + + @Internal + public abstract DirectoryProperty getDestinationDirectory(); + + @OutputFile + public abstract RegularFileProperty getOutput(); + + @Internal + public abstract RegularFileProperty getLogFile(); + + @TaskAction + public void remap() throws IOException { + final List args = new ArrayList<>(); + + args.addAll(Arrays.asList("--input", getInput().get().getAsFile().getAbsolutePath())); + args.addAll(Arrays.asList("--output", getOutput().get().getAsFile().getAbsolutePath())); + args.addAll(Arrays.asList("--names", getMappings().get().getAsFile().getAbsolutePath())); + getLibraries().forEach(lib -> args.addAll(Arrays.asList("--lib", lib.getAbsolutePath()))); + args.add("--disable-abstract-param"); + + try (var log = getLogFile().isPresent() ? Files.newOutputStream(getLogFile().get().getAsFile().toPath()) : new OutputStream() { + @Override + public void write(int b) { + + } + }) { + getExecOperations().javaexec(execSpec -> { + // Pass through network properties + execSpec.systemProperties(NetworkSettingPassthrough.getNetworkSystemProperties()); + + // See https://github.com/gradle/gradle/issues/28959 + execSpec.jvmArgs("-Dstdout.encoding=UTF-8", "-Dstderr.encoding=UTF-8"); + + execSpec.executable(getJavaExecutable().get()); + execSpec.classpath(getToolClasspath()); + execSpec.args(args); + execSpec.setStandardOutput(log); + }).rethrowFailure().assertNormalExitValue(); + } + } +} diff --git a/src/legacy/java/net/neoforged/moddevgradle/legacy/Reobfuscation.java b/src/legacy/java/net/neoforged/moddevgradle/legacy/Reobfuscation.java new file mode 100644 index 00000000..04ec917e --- /dev/null +++ b/src/legacy/java/net/neoforged/moddevgradle/legacy/Reobfuscation.java @@ -0,0 +1,56 @@ +package net.neoforged.moddevgradle.legacy; + +import org.apache.commons.lang3.StringUtils; +import org.gradle.api.Action; +import org.gradle.api.Project; +import org.gradle.api.artifacts.Configuration; +import org.gradle.api.component.AdhocComponentWithVariants; +import org.gradle.api.file.RegularFile; +import org.gradle.api.plugins.JavaPlugin; +import org.gradle.api.provider.Provider; +import org.gradle.api.tasks.SourceSet; +import org.gradle.api.tasks.TaskProvider; +import org.gradle.api.tasks.bundling.AbstractArchiveTask; + +import javax.inject.Inject; +import java.util.List; + +public abstract class Reobfuscation { + private final Project project; + private final Provider officialToSrg; + private final Configuration autoRenamingToolRuntime; + + @Inject + public Reobfuscation(Project project, Provider officialToSrg, Configuration autoRenamingToolRuntime) { + this.project = project; + this.officialToSrg = officialToSrg; + this.autoRenamingToolRuntime = autoRenamingToolRuntime; + } + + public TaskProvider reobfuscate(TaskProvider jar, SourceSet sourceSet, Action configuration) { + var reobf = project.getTasks().register("reobf" + StringUtils.capitalize(jar.getName()), RemapJarTask.class, task -> { + task.getInput().set(jar.flatMap(AbstractArchiveTask::getArchiveFile)); + task.getMappings().set(officialToSrg); + task.getDestinationDirectory().convention(jar.flatMap(AbstractArchiveTask::getDestinationDirectory)); + task.getArchiveBaseName().convention(jar.flatMap(AbstractArchiveTask::getArchiveBaseName)); + task.getArchiveVersion().convention(jar.flatMap(AbstractArchiveTask::getArchiveVersion)); + task.getArchiveClassifier().convention(jar.flatMap(AbstractArchiveTask::getArchiveClassifier).map(c -> c + "-reobf")); + task.getLibraries().from(sourceSet.getCompileClasspath()); + task.getToolClasspath().from(autoRenamingToolRuntime); + configuration.execute(task); + }); + + jar.configure(jarTask -> jarTask.finalizedBy(reobf)); + + var java = (AdhocComponentWithVariants) project.getComponents().getByName("java"); + for (var configurationNames : List.of(JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME, JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME)) { + project.getArtifacts().add(configurationNames, reobf, artifact -> artifact.builtBy(reobf)); + + java.withVariantsFromConfiguration(project.getConfigurations().getByName(configurationNames), variant -> { + variant.getConfigurationVariant().getArtifacts().removeIf(artifact -> artifact.getFile().equals(jar.get().getArchiveFile().get().getAsFile())); + }); + } + + return reobf; + } +}