From 1138d0a5aa11731abd6a819bf2458e99a2024d2d Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Mon, 8 Jul 2024 21:19:32 +1000 Subject: [PATCH 01/32] fixme MixinExtensionApiImpl --- .../java/net/fabricmc/loom/extension/MixinExtensionApiImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/fabricmc/loom/extension/MixinExtensionApiImpl.java b/src/main/java/net/fabricmc/loom/extension/MixinExtensionApiImpl.java index bdcf7e657..9a56dc5e9 100644 --- a/src/main/java/net/fabricmc/loom/extension/MixinExtensionApiImpl.java +++ b/src/main/java/net/fabricmc/loom/extension/MixinExtensionApiImpl.java @@ -50,7 +50,7 @@ public abstract class MixinExtensionApiImpl implements MixinExtensionAPI { public MixinExtensionApiImpl(Project project) { this.project = Objects.requireNonNull(project); this.useMixinAp = project.getObjects().property(Boolean.class) - .convention(project.provider(() -> !LoomGradleExtension.get(project).isNeoForge() && (!LoomGradleExtension.get(project).isForge() || !LoomGradleExtension.get(project).getForgeProvider().usesMojangAtRuntime()))); + .convention(project.provider(() -> !LoomGradleExtension.get(project).isNeoForge() && (!LoomGradleExtension.get(project).isForge() || !LoomGradleExtension.get(project).getForgeProvider() /* FIXME Forge Provider might not be loaded yet */.usesMojangAtRuntime()))); this.refmapTargetNamespace = project.getObjects().property(String.class) .convention(project.provider(() -> IntermediaryNamespaces.runtimeIntermediary(project))); From 116f8eeefac1ca421eb37894847bdb3c12bb3f88 Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Mon, 8 Jul 2024 21:19:45 +1000 Subject: [PATCH 02/32] test example mod mixin --- .../resources/projects/forge/1206/build.gradle | 6 ++++++ .../examplemod/mixin/ExampleModMixin.java | 16 ++++++++++++++++ .../src/main/resources/examplemod.mixins.json | 14 ++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 src/test/resources/projects/forge/1206/src/main/java/com/example/examplemod/mixin/ExampleModMixin.java create mode 100644 src/test/resources/projects/forge/1206/src/main/resources/examplemod.mixins.json diff --git a/src/test/resources/projects/forge/1206/build.gradle b/src/test/resources/projects/forge/1206/build.gradle index 36bc2f7ba..65e7399ef 100644 --- a/src/test/resources/projects/forge/1206/build.gradle +++ b/src/test/resources/projects/forge/1206/build.gradle @@ -18,6 +18,12 @@ group = project.maven_group def mcVersion = "@MCVERSION@" def forgeVersion = "@FORGEVERSION@" +loom { + forge { + mixinConfig "examplemod.mixins.json" + } +} + repositories { // Add repositories to retrieve artifacts from in here. // You should only use this when depending on other mods because diff --git a/src/test/resources/projects/forge/1206/src/main/java/com/example/examplemod/mixin/ExampleModMixin.java b/src/test/resources/projects/forge/1206/src/main/java/com/example/examplemod/mixin/ExampleModMixin.java new file mode 100644 index 000000000..2a8df56ca --- /dev/null +++ b/src/test/resources/projects/forge/1206/src/main/java/com/example/examplemod/mixin/ExampleModMixin.java @@ -0,0 +1,16 @@ +package com.example.examplemod.mixin; + +import net.minecraft.client.Minecraft; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(Minecraft.class) +public class ExampleModMixin { + @Inject(method = "", at = @At("HEAD")) + private static void initInject(CallbackInfo info) { + System.out.println("Hello from the example mod mixin!"); + } +} \ No newline at end of file diff --git a/src/test/resources/projects/forge/1206/src/main/resources/examplemod.mixins.json b/src/test/resources/projects/forge/1206/src/main/resources/examplemod.mixins.json new file mode 100644 index 000000000..df6441709 --- /dev/null +++ b/src/test/resources/projects/forge/1206/src/main/resources/examplemod.mixins.json @@ -0,0 +1,14 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "com.example.examplemod.mixin", + "compatibilityLevel": "JAVA_17", + "mixins": [ + ], + "client": [ + "ExampleModMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} From faca2931479f0c441bc5cdd5eb256135e2cfec5e Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Mon, 8 Jul 2024 21:24:02 +1000 Subject: [PATCH 03/32] fix example mod mixin --- .../main/java/com/example/examplemod/mixin/ExampleModMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/resources/projects/forge/1206/src/main/java/com/example/examplemod/mixin/ExampleModMixin.java b/src/test/resources/projects/forge/1206/src/main/java/com/example/examplemod/mixin/ExampleModMixin.java index 2a8df56ca..2fea8a54f 100644 --- a/src/test/resources/projects/forge/1206/src/main/java/com/example/examplemod/mixin/ExampleModMixin.java +++ b/src/test/resources/projects/forge/1206/src/main/java/com/example/examplemod/mixin/ExampleModMixin.java @@ -9,7 +9,7 @@ @Mixin(Minecraft.class) public class ExampleModMixin { - @Inject(method = "", at = @At("HEAD")) + @Inject(method = "", at = @At("HEAD")) private static void initInject(CallbackInfo info) { System.out.println("Hello from the example mod mixin!"); } From b27d7211177b8fd16b6524c6a4c7811ee9418b86 Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Mon, 8 Jul 2024 21:24:17 +1000 Subject: [PATCH 04/32] output `useLegacyMixinAp` in the forge test --- src/test/resources/projects/forge/1206/build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/resources/projects/forge/1206/build.gradle b/src/test/resources/projects/forge/1206/build.gradle index 65e7399ef..13bacbabc 100644 --- a/src/test/resources/projects/forge/1206/build.gradle +++ b/src/test/resources/projects/forge/1206/build.gradle @@ -19,6 +19,9 @@ def mcVersion = "@MCVERSION@" def forgeVersion = "@FORGEVERSION@" loom { + mixin { + System.out.println(useLegacyMixinAp.get()) + } forge { mixinConfig "examplemod.mixins.json" } From 7ad1fa85deec9fd6f30a4b4a29ce2a5ad39ba3c0 Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Mon, 8 Jul 2024 21:32:54 +1000 Subject: [PATCH 05/32] require `useLegacyMixinAp` to be manually set to false on Forge 50+ --- .../java/net/fabricmc/loom/extension/MixinExtensionApiImpl.java | 2 +- src/test/resources/projects/forge/1206/build.gradle | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/fabricmc/loom/extension/MixinExtensionApiImpl.java b/src/main/java/net/fabricmc/loom/extension/MixinExtensionApiImpl.java index 9a56dc5e9..4452b2ad3 100644 --- a/src/main/java/net/fabricmc/loom/extension/MixinExtensionApiImpl.java +++ b/src/main/java/net/fabricmc/loom/extension/MixinExtensionApiImpl.java @@ -50,7 +50,7 @@ public abstract class MixinExtensionApiImpl implements MixinExtensionAPI { public MixinExtensionApiImpl(Project project) { this.project = Objects.requireNonNull(project); this.useMixinAp = project.getObjects().property(Boolean.class) - .convention(project.provider(() -> !LoomGradleExtension.get(project).isNeoForge() && (!LoomGradleExtension.get(project).isForge() || !LoomGradleExtension.get(project).getForgeProvider() /* FIXME Forge Provider might not be loaded yet */.usesMojangAtRuntime()))); + .convention(project.provider(() -> !LoomGradleExtension.get(project).isNeoForge())); // Set this manually to false if you are using Forge 50 or later. this.refmapTargetNamespace = project.getObjects().property(String.class) .convention(project.provider(() -> IntermediaryNamespaces.runtimeIntermediary(project))); diff --git a/src/test/resources/projects/forge/1206/build.gradle b/src/test/resources/projects/forge/1206/build.gradle index 13bacbabc..31529c592 100644 --- a/src/test/resources/projects/forge/1206/build.gradle +++ b/src/test/resources/projects/forge/1206/build.gradle @@ -21,6 +21,7 @@ def forgeVersion = "@FORGEVERSION@" loom { mixin { System.out.println(useLegacyMixinAp.get()) + useLegacyMixinAp = false } forge { mixinConfig "examplemod.mixins.json" From 294a30df0060a32f1e93022dc971a906ad041095 Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Mon, 8 Jul 2024 21:58:38 +1000 Subject: [PATCH 06/32] add JEI to the forge test --- src/test/resources/projects/forge/1206/build.gradle | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/test/resources/projects/forge/1206/build.gradle b/src/test/resources/projects/forge/1206/build.gradle index 31529c592..44618920e 100644 --- a/src/test/resources/projects/forge/1206/build.gradle +++ b/src/test/resources/projects/forge/1206/build.gradle @@ -34,11 +34,19 @@ repositories { // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. // See https://docs.gradle.org/current/userguide/declaring_repositories.html // for more information about repositories. + maven { + // location of the maven that hosts JEI files since January 2023 + name = "Jared's maven" + url = "https://maven.blamejared.com/" + } } dependencies { // To change the versions see the gradle.properties file minecraft "com.mojang:minecraft:$mcVersion" + modImplementation "mezz.jei:jei-1.20.6-forge:18.0.0.65", { + transitive = false + } if ("MAPPINGS".equals("loom.officialMojangMappings()")) { mappings loom.officialMojangMappings() } else { From 4de99f3188c939df15f28d4b304cdfb649f212b3 Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Mon, 8 Jul 2024 21:58:59 +1000 Subject: [PATCH 07/32] make MappingConfiguration aware of the project --- .../configuration/providers/mappings/MappingConfiguration.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingConfiguration.java index 2e52b85ba..3383dba9c 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingConfiguration.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingConfiguration.java @@ -99,6 +99,7 @@ public class MappingConfiguration { private boolean hasUnpickDefinitions; private UnpickMetadata unpickMetadata; private Map signatureFixes; + private LoomGradleExtension extension; protected MappingConfiguration(String mappingsIdentifier, Path mappingsWorkingDir) { this.mappingsIdentifier = mappingsIdentifier; @@ -205,7 +206,7 @@ protected void setup(Project project, SharedServiceManager serviceManager, Minec } public void setupPost(Project project) throws IOException { - LoomGradleExtension extension = LoomGradleExtension.get(project); + this.extension = LoomGradleExtension.get(project); if (extension.isNeoForge()) { // Generate the Mojmap-merged mappings if needed. From 90bcdc0cb7cf5599e4f26ad71035cda064f80725 Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Mon, 8 Jul 2024 21:59:32 +1000 Subject: [PATCH 08/32] make `getMappingsService` return the SRG service instead of the MOJANG one when running with Forge 50+ --- .../providers/mappings/MappingConfiguration.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingConfiguration.java index 3383dba9c..8e4b23054 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingConfiguration.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingConfiguration.java @@ -165,6 +165,11 @@ public TinyMappingsService getMappingsService(SharedServiceManager serviceManage } public TinyMappingsService getMappingsService(SharedServiceManager serviceManager, MappingOption mappingOption) { + if (extension.getForgeProvider().usesMojangAtRuntime() && mappingOption == MappingOption.WITH_MOJANG) { + // Mojang mappings are merged into the SRG file. + return getMappingsService(serviceManager, MappingOption.WITH_SRG); + } + final Path tinyMappings = switch (mappingOption) { case WITH_SRG -> { if (Files.notExists(this.tinyMappingsWithSrg)) { From 07664a301da736f9f24bf29ab2a59880f8b87f1d Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Tue, 9 Jul 2024 17:12:00 +1000 Subject: [PATCH 09/32] add new test for Forge mod dependencies --- .../integration/forge/Forge1206Test.groovy | 6 +- .../forge/Forge1206WithDependencyTest.groovy | 60 ++++++++++ .../forge/1206-with-dependency/build.gradle | 107 ++++++++++++++++++ .../1206-with-dependency/gradle.properties | 11 ++ .../1206-with-dependency/settings.gradle | 2 + .../java/com/example/examplemod/Config.java | 50 ++++++++ .../com/example/examplemod/ExampleMod.java | 67 +++++++++++ .../src/main/resources/META-INF/mods.toml | 73 ++++++++++++ .../src/main/resources/pack.mcmeta | 8 ++ .../projects/forge/1206/build.gradle | 8 -- .../projects/neoforge/1206/build.gradle | 8 ++ 11 files changed, 389 insertions(+), 11 deletions(-) create mode 100644 src/test/groovy/net/fabricmc/loom/test/integration/forge/Forge1206WithDependencyTest.groovy create mode 100644 src/test/resources/projects/forge/1206-with-dependency/build.gradle create mode 100644 src/test/resources/projects/forge/1206-with-dependency/gradle.properties create mode 100644 src/test/resources/projects/forge/1206-with-dependency/settings.gradle create mode 100644 src/test/resources/projects/forge/1206-with-dependency/src/main/java/com/example/examplemod/Config.java create mode 100644 src/test/resources/projects/forge/1206-with-dependency/src/main/java/com/example/examplemod/ExampleMod.java create mode 100644 src/test/resources/projects/forge/1206-with-dependency/src/main/resources/META-INF/mods.toml create mode 100644 src/test/resources/projects/forge/1206-with-dependency/src/main/resources/pack.mcmeta diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/forge/Forge1206Test.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/forge/Forge1206Test.groovy index f19cd9cc8..2f8b54798 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/forge/Forge1206Test.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/forge/Forge1206Test.groovy @@ -34,7 +34,7 @@ import static org.gradle.testkit.runner.TaskOutcome.SUCCESS class Forge1206Test extends Specification implements GradleProjectTestTrait { @Unroll - def "build #mcVersion #neoforgeVersion #mappings #patches"() { + def "build #mcVersion #forgeVersion #mappings #patches"() { if (Integer.valueOf(System.getProperty("java.version").split("\\.")[0]) < 21) { println("This test requires Java 21. Currently you have Java ${System.getProperty("java.version")}.") return @@ -43,7 +43,7 @@ class Forge1206Test extends Specification implements GradleProjectTestTrait { setup: def gradle = gradleProject(project: "forge/1206", version: DEFAULT_GRADLE) gradle.buildGradle.text = gradle.buildGradle.text.replace('@MCVERSION@', mcVersion) - .replace('@FORGEVERSION@', neoforgeVersion) + .replace('@FORGEVERSION@', forgeVersion) .replace('MAPPINGS', mappings) // Spotless doesn't like the @'s .replace('PATCHES', patches) @@ -54,7 +54,7 @@ class Forge1206Test extends Specification implements GradleProjectTestTrait { result.task(":build").outcome == SUCCESS where: - mcVersion | neoforgeVersion | mappings | patches + mcVersion | forgeVersion | mappings | patches '1.20.6' | '1.20.6-50.1.3' | 'loom.officialMojangMappings()' | '' } } diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/forge/Forge1206WithDependencyTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/forge/Forge1206WithDependencyTest.groovy new file mode 100644 index 000000000..7467d3839 --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/test/integration/forge/Forge1206WithDependencyTest.groovy @@ -0,0 +1,60 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2024 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.test.integration.forge + +import net.fabricmc.loom.test.util.GradleProjectTestTrait +import spock.lang.Specification +import spock.lang.Unroll + +import static net.fabricmc.loom.test.LoomTestConstants.DEFAULT_GRADLE +import static org.gradle.testkit.runner.TaskOutcome.SUCCESS + +class Forge1206WithDependencyTest extends Specification implements GradleProjectTestTrait { + @Unroll + def "build #mcVersion #forgeVersion #mappings #patches"() { + if (Integer.valueOf(System.getProperty("java.version").split("\\.")[0]) < 21) { + println("This test requires Java 21. Currently you have Java ${System.getProperty("java.version")}.") + return + } + + setup: + def gradle = gradleProject(project: "forge/1206-with-dependency", version: DEFAULT_GRADLE) + gradle.buildGradle.text = gradle.buildGradle.text.replace('@MCVERSION@', mcVersion) + .replace('@FORGEVERSION@', forgeVersion) + .replace('MAPPINGS', mappings) // Spotless doesn't like the @'s + .replace('PATCHES', patches) + + when: + def result = gradle.run(task: "build") + + then: + result.task(":build").outcome == SUCCESS + + where: + mcVersion | forgeVersion | mappings | patches + '1.20.6' | '1.20.6-50.1.3' | 'loom.officialMojangMappings()' | '' + '1.20.6' | '1.20.6-50.1.3' | "'net.fabricmc:yarn:1.20.6+build.1:v2'" | "'dev.architectury:yarn-mappings-patch-neoforge:1.20.5+build.3'" + } +} diff --git a/src/test/resources/projects/forge/1206-with-dependency/build.gradle b/src/test/resources/projects/forge/1206-with-dependency/build.gradle new file mode 100644 index 000000000..83508157d --- /dev/null +++ b/src/test/resources/projects/forge/1206-with-dependency/build.gradle @@ -0,0 +1,107 @@ +plugins { + id 'dev.architectury.loom' + id 'maven-publish' +} + +java { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 +} + +base { + archivesName = project.archives_base_name +} + +version = project.mod_version +group = project.maven_group + +def mcVersion = "@MCVERSION@" +def forgeVersion = "@FORGEVERSION@" + +loom { + mixin { + System.out.println(useLegacyMixinAp.get()) + useLegacyMixinAp = false + } +} + +repositories { + // Add repositories to retrieve artifacts from in here. + // You should only use this when depending on other mods because + // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. + // See https://docs.gradle.org/current/userguide/declaring_repositories.html + // for more information about repositories. + maven { + // location of the maven that hosts JEI files since January 2023 + name = "Jared's maven" + url = "https://maven.blamejared.com/" + } +} + +dependencies { + // To change the versions see the gradle.properties file + minecraft "com.mojang:minecraft:$mcVersion" + modImplementation "mezz.jei:jei-1.20.6-forge:18.0.0.65", { + transitive = false + } + if ("MAPPINGS".equals("loom.officialMojangMappings()")) { + mappings loom.officialMojangMappings() + } else { + mappings loom.layered { + it.mappings(MAPPINGS) + it.mappings(PATCHES) + } + } + + forge "net.minecraftforge:forge:$forgeVersion" +} + +tasks.withType(JavaCompile).configureEach { + it.options.release = 21 +} + +java { + // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task + // if it is present. + // If you remove this line, sources will not be generated. + withSourcesJar() +} + +jar { + from("LICENSE") { + rename { "${it}_${project.archivesBaseName}"} + } +} + +// configure the maven publication +publishing { + publications { + mavenJava(MavenPublication) { + // add all the jars that should be included when publishing to maven + artifact(remapJar) { + builtBy remapJar + } + artifact(sourcesJar) { + builtBy remapSourcesJar + } + } + } + + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + // Notice: This block does NOT have the same function as the block in the top level. + // The repositories here will be used for publishing your artifact, not for + // retrieving dependencies. + } +} +processResources { + doLast { + java.nio.file.Path.of(outputs.files.asPath).resolve("META-INF/MANIFEST.MF").text = "Manifest-Version: 1.0\n" + + "Automatic-Module-Name: ignoreme\n" + } +} + +configurations.all { + resolutionStrategy.force("net.sf.jopt-simple:jopt-simple:5.0.4") +} \ No newline at end of file diff --git a/src/test/resources/projects/forge/1206-with-dependency/gradle.properties b/src/test/resources/projects/forge/1206-with-dependency/gradle.properties new file mode 100644 index 000000000..b697f77e3 --- /dev/null +++ b/src/test/resources/projects/forge/1206-with-dependency/gradle.properties @@ -0,0 +1,11 @@ +# Done to increase the memory available to gradle. +org.gradle.jvmargs=-Xmx1G + +# Mod Properties +mod_version = 1.0.0 +maven_group = com.example +archives_base_name = fabric-example-mod + +# Dependencies +# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api +loom.platform = forge diff --git a/src/test/resources/projects/forge/1206-with-dependency/settings.gradle b/src/test/resources/projects/forge/1206-with-dependency/settings.gradle new file mode 100644 index 000000000..c162c363e --- /dev/null +++ b/src/test/resources/projects/forge/1206-with-dependency/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = "fabric-example-mod" + diff --git a/src/test/resources/projects/forge/1206-with-dependency/src/main/java/com/example/examplemod/Config.java b/src/test/resources/projects/forge/1206-with-dependency/src/main/java/com/example/examplemod/Config.java new file mode 100644 index 000000000..cfafe8fbd --- /dev/null +++ b/src/test/resources/projects/forge/1206-with-dependency/src/main/java/com/example/examplemod/Config.java @@ -0,0 +1,50 @@ +package com.example.examplemod; + +import net.minecraftforge.common.ForgeConfigSpec; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.config.ModConfigEvent; + +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +// An example config class. This is not required, but it's a good idea to have one to keep your config organized. +// Demonstrates how to use Forge's config APIs +@Mod.EventBusSubscriber(modid = ExampleMod.MODID, bus = Mod.EventBusSubscriber.Bus.MOD) +public class Config +{ + private static final ForgeConfigSpec.Builder BUILDER = new ForgeConfigSpec.Builder(); + + private static final ForgeConfigSpec.IntValue MAGIC_NUMBER = BUILDER + .comment("A magic number") + .defineInRange("magicNumber", 42, 0, Integer.MAX_VALUE); + + public static final ForgeConfigSpec.ConfigValue MAGIC_NUMBER_INTRODUCTION = BUILDER + .comment("What you want the introduction message to be for the magic number") + .define("magicNumberIntroduction", "The magic number is... "); + + // a list of strings that are treated as resource locations for items + private static final ForgeConfigSpec.ConfigValue> ITEM_STRINGS = BUILDER + .comment("A list of items to log on common setup.") + .defineListAllowEmpty("items", List.of("minecraft:iron_ingot"), Config::validateItemName); + + static final ForgeConfigSpec SPEC = BUILDER.build(); + + public static boolean logDirtBlock; + public static int magicNumber; + public static String magicNumberIntroduction; + + private static boolean validateItemName(final Object obj) + { + return obj instanceof String; + } + + @SubscribeEvent + static void onLoad(final ModConfigEvent event) + { + magicNumber = MAGIC_NUMBER.get(); + magicNumberIntroduction = MAGIC_NUMBER_INTRODUCTION.get(); + } +} \ No newline at end of file diff --git a/src/test/resources/projects/forge/1206-with-dependency/src/main/java/com/example/examplemod/ExampleMod.java b/src/test/resources/projects/forge/1206-with-dependency/src/main/java/com/example/examplemod/ExampleMod.java new file mode 100644 index 000000000..e6f9f4787 --- /dev/null +++ b/src/test/resources/projects/forge/1206-with-dependency/src/main/java/com/example/examplemod/ExampleMod.java @@ -0,0 +1,67 @@ +package com.example.examplemod; + +import com.mojang.logging.LogUtils; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.server.ServerStartingEvent; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.ModLoadingContext; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.config.ModConfig; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; +import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import org.slf4j.Logger; + +// The value here should match an entry in the META-INF/mods.toml file +@Mod(ExampleMod.MODID) +public class ExampleMod +{ + // Define mod id in a common place for everything to reference + public static final String MODID = "examplemod"; + // Directly reference a slf4j logger + private static final Logger LOGGER = LogUtils.getLogger(); + + public ExampleMod() + { + IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); + + // Register the commonSetup method for modloading + modEventBus.addListener(this::commonSetup); + + // Register ourselves for server and other game events we are interested in + MinecraftForge.EVENT_BUS.register(this); + + // Register our mod's ForgeConfigSpec so that Forge can create and load the config file for us + ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, Config.SPEC); + } + + private void commonSetup(final FMLCommonSetupEvent event) + { + // Some common setup code + LOGGER.info("HELLO FROM COMMON SETUP"); + + LOGGER.info(Config.magicNumberIntroduction + Config.magicNumber); + } + + // You can use SubscribeEvent and let the Event Bus discover methods to call + @SubscribeEvent + public void onServerStarting(ServerStartingEvent event) + { + // Do something when the server starts + LOGGER.info("HELLO from server starting"); + } + + // You can use EventBusSubscriber to automatically register all static methods in the class annotated with @SubscribeEvent + @Mod.EventBusSubscriber(modid = MODID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) + public static class ClientModEvents + { + @SubscribeEvent + public static void onClientSetup(FMLClientSetupEvent event) + { + // Some client setup code + LOGGER.info("HELLO FROM CLIENT SETUP"); + } + } +} \ No newline at end of file diff --git a/src/test/resources/projects/forge/1206-with-dependency/src/main/resources/META-INF/mods.toml b/src/test/resources/projects/forge/1206-with-dependency/src/main/resources/META-INF/mods.toml new file mode 100644 index 000000000..2022ef443 --- /dev/null +++ b/src/test/resources/projects/forge/1206-with-dependency/src/main/resources/META-INF/mods.toml @@ -0,0 +1,73 @@ +# This is an example mods.toml file. It contains the data relating to the loading mods. +# There are several mandatory fields (#mandatory), and many more that are optional (#optional). +# The overall format is standard TOML format, v0.5.0. +# Note that there are a couple of TOML lists in this file. +# Find more information on toml format here: https://github.com/toml-lang/toml +# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml +modLoader="javafml" #mandatory +# A version range to match for said mod loader - for regular FML @Mod it will be the forge version +loaderVersion="*" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. +# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties. +# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here. +license="Testmod" +# A URL to refer people to when problems occur with this mod +#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional +# If your mod is purely client-side and has no multiplayer functionality (be it dedicated servers or Open to LAN), +# set this to true, and Forge will set the correct displayTest for you and skip loading your mod on dedicated servers. +#clientSideOnly=true #optional - defaults to false if absent +# A list of mods - how many allowed here is determined by the individual mod loader +[[mods]] #mandatory +# The modid of the mod +modId="examplemod" #mandatory +# The version number of the mod +version="1.0.0" #mandatory +# A display name for the mod +displayName="Example Mod" #mandatory +# A URL to query for updates for this mod. See the JSON update specification https://docs.minecraftforge.net/en/latest/misc/updatechecker/ +#updateJSONURL="https://change.me.example.invalid/updates.json" #optional +# A URL for the "homepage" for this mod, displayed in the mod UI +#displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional +# A file name (in the root of the mod JAR) containing a logo for display +#logoFile="examplemod.png" #optional +# A text field displayed in the mod UI +#credits="" #optional +# A text field displayed in the mod UI +authors="Architectury" #optional +# Display Test controls the display for your mod in the server connection screen +# MATCH_VERSION means that your mod will cause a red X if the versions on client and server differ. This is the default behaviour and should be what you choose if you have server and client elements to your mod. +# IGNORE_SERVER_VERSION means that your mod will not cause a red X if it's present on the server but not on the client. This is what you should use if you're a server only mod. +# IGNORE_ALL_VERSION means that your mod will not cause a red X if it's present on the client or the server. This is a special case and should only be used if your mod has no server component. +# NONE means that no display test is set on your mod. You need to do this yourself, see IExtensionPoint.DisplayTest for more information. You can define any scheme you wish with this value. +# IMPORTANT NOTE: this is NOT an instruction as to which environments (CLIENT or DEDICATED SERVER) your mod loads on. Your mod should load (and maybe do nothing!) whereever it finds itself. +#displayTest="MATCH_VERSION" # if nothing is specified, MATCH_VERSION is the default when clientSideOnly=false, otherwise IGNORE_ALL_VERSION when clientSideOnly=true (#optional) + +# The description text for the mod (multi line!) (#mandatory) +description='''This is a test mod''' +# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. +[[dependencies.examplemod]] #optional +# the modid of the dependency +modId="forge" #mandatory +# Does this dependency have to exist - if not, ordering below must be specified +mandatory=true #mandatory +# The version range of the dependency +versionRange="[50,)" #mandatory +# An ordering relationship for the dependency - BEFORE or AFTER required if the dependency is not mandatory +# BEFORE - This mod is loaded BEFORE the dependency +# AFTER - This mod is loaded AFTER the dependency +ordering="NONE" +# Side this dependency is applied on - BOTH, CLIENT, or SERVER +side="BOTH" +# Here's another dependency +[[dependencies.examplemod]] +modId="minecraft" +mandatory=true +# This version range declares a minimum of the current minecraft version up to but not including the next major version +versionRange="[1.20.6,)" +ordering="NONE" +side="BOTH" + +# Features are specific properties of the game environment, that you may want to declare you require. This example declares +# that your mod requires GL version 3.2 or higher. Other features will be added. They are side aware so declaring this won't +# stop your mod loading on the server for example. +#[features.${mod_id}] +#openGLVersion="[3.2,)" \ No newline at end of file diff --git a/src/test/resources/projects/forge/1206-with-dependency/src/main/resources/pack.mcmeta b/src/test/resources/projects/forge/1206-with-dependency/src/main/resources/pack.mcmeta new file mode 100644 index 000000000..68e41fce2 --- /dev/null +++ b/src/test/resources/projects/forge/1206-with-dependency/src/main/resources/pack.mcmeta @@ -0,0 +1,8 @@ +{ + "pack": { + "forge:resource_pack_format": 32, + "forge:data_pack_format": 41, + "pack_format": 32, + "description": "Example mod" + } +} \ No newline at end of file diff --git a/src/test/resources/projects/forge/1206/build.gradle b/src/test/resources/projects/forge/1206/build.gradle index 44618920e..31529c592 100644 --- a/src/test/resources/projects/forge/1206/build.gradle +++ b/src/test/resources/projects/forge/1206/build.gradle @@ -34,19 +34,11 @@ repositories { // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. // See https://docs.gradle.org/current/userguide/declaring_repositories.html // for more information about repositories. - maven { - // location of the maven that hosts JEI files since January 2023 - name = "Jared's maven" - url = "https://maven.blamejared.com/" - } } dependencies { // To change the versions see the gradle.properties file minecraft "com.mojang:minecraft:$mcVersion" - modImplementation "mezz.jei:jei-1.20.6-forge:18.0.0.65", { - transitive = false - } if ("MAPPINGS".equals("loom.officialMojangMappings()")) { mappings loom.officialMojangMappings() } else { diff --git a/src/test/resources/projects/neoforge/1206/build.gradle b/src/test/resources/projects/neoforge/1206/build.gradle index 5ab5071ca..e6a339b91 100644 --- a/src/test/resources/projects/neoforge/1206/build.gradle +++ b/src/test/resources/projects/neoforge/1206/build.gradle @@ -25,11 +25,19 @@ repositories { // See https://docs.gradle.org/current/userguide/declaring_repositories.html // for more information about repositories. maven { url "https://maven.neoforged.net/releases/" } + maven { + // location of the maven that hosts JEI files since January 2023 + name = "Jared's maven" + url = "https://maven.blamejared.com/" + } } dependencies { // To change the versions see the gradle.properties file minecraft "com.mojang:minecraft:$mcVersion" + modImplementation "mezz.jei:jei-1.20.6-neoforge:18.0.0.65", { + transitive = false + } if ("MAPPINGS".equals("loom.officialMojangMappings()")) { mappings loom.officialMojangMappings() } else { From 4bba79144c1d16c1d82102777c5eb94be56a23b0 Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Tue, 9 Jul 2024 17:12:38 +1000 Subject: [PATCH 10/32] Fix `usesMojangAtRuntime` check --- .../configuration/providers/mappings/MappingConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingConfiguration.java index 8e4b23054..06279e2c0 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingConfiguration.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingConfiguration.java @@ -165,7 +165,7 @@ public TinyMappingsService getMappingsService(SharedServiceManager serviceManage } public TinyMappingsService getMappingsService(SharedServiceManager serviceManager, MappingOption mappingOption) { - if (extension.getForgeProvider().usesMojangAtRuntime() && mappingOption == MappingOption.WITH_MOJANG) { + if (extension.isForge() && extension.getForgeProvider().usesMojangAtRuntime() && mappingOption == MappingOption.WITH_MOJANG) { // Mojang mappings are merged into the SRG file. return getMappingsService(serviceManager, MappingOption.WITH_SRG); } From 8446f119057ee08ffd8c98f13f231c4b23262bd2 Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Tue, 9 Jul 2024 17:16:41 +1000 Subject: [PATCH 11/32] try to replace all srg names with mojang names --- .../loom/util/ForgeSrgToMojangUtil.java | 111 ++++++++++++++++++ .../loom/configuration/mods/ModProcessor.java | 2 + 2 files changed, 113 insertions(+) create mode 100644 src/main/java/dev/architectury/loom/util/ForgeSrgToMojangUtil.java diff --git a/src/main/java/dev/architectury/loom/util/ForgeSrgToMojangUtil.java b/src/main/java/dev/architectury/loom/util/ForgeSrgToMojangUtil.java new file mode 100644 index 000000000..74fcaca67 --- /dev/null +++ b/src/main/java/dev/architectury/loom/util/ForgeSrgToMojangUtil.java @@ -0,0 +1,111 @@ +package dev.architectury.loom.util; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; +import net.fabricmc.mappingio.tree.MappingTree; +import net.fabricmc.mappingio.tree.MemoryMappingTree; +import net.fabricmc.tinyremapper.ClassInstance; +import net.fabricmc.tinyremapper.MemberInstance; +import net.fabricmc.tinyremapper.TinyRemapper; +import net.fabricmc.tinyremapper.api.TrMember; + +public final class ForgeSrgToMojangUtil { + private ForgeSrgToMojangUtil() { + + } + + @SuppressWarnings("unchecked") + public static void replaceSrgWithMojangMappings(TinyRemapper remapper, MemoryMappingTree mappings) { + Map readClasses; + try { + Field readClassesField = TinyRemapper.class.getDeclaredField("readClasses"); + readClassesField.setAccessible(true); + readClasses = (Map) readClassesField.get(remapper); + } catch (Throwable t) {throw new RuntimeException(t);} + + for (ClassInstance value : readClasses.values()) { + replaceSrgWithMojangMappings(value, mappings); + } + } + + @SuppressWarnings("unchecked") + public static void replaceSrgWithMojangMappings(ClassInstance value, MemoryMappingTree tree) { + int srg = tree.getNamespaceId("srg"); + int mojang = tree.getNamespaceId("mojang"); + HashMap members; + try { + Field membersField = ClassInstance.class.getDeclaredField("members"); + membersField.setAccessible(true); + members = (HashMap) membersField.get(value); + } catch (Throwable t) { + throw new RuntimeException(t); + } + Map copy = (Map) members.clone(); + members.clear(); + int methods = 0; + int fields = 0; + int fixedMethods = 0; + int fixedFields = 0; + for (Map.Entry entry : copy.entrySet()) { + TrMember.MemberType type = entry.getValue().getType(); + // String key = entry.getKey(); + MemberInstance memberInstance = entry.getValue(); + // System.out.println("OLD: " + key + " -> " + memberInstance.getId()); + if (type == TrMember.MemberType.FIELD) { + fields++; + MappingTree.FieldMapping field = tree.getField(value.getName(), memberInstance.getName(), memberInstance.getDesc(), srg); + if (field == null) { + // String name = memberInstance.getOwner().getName(); + // System.out.println(name.substring(name.lastIndexOf("/") + 1) + "#" + memberInstance.getName() + " has no exact match! Trying again without the descriptor..."); + field = tree.getField(value.getName(), memberInstance.getName(), null, srg); + if (field == null) { + // System.out.println(name.substring(name.lastIndexOf("/") + 1) + "#" + memberInstance.getName() + " has no exact match! Tried with no descriptor!"); + members.put(memberInstance.getId(), memberInstance); + continue; + } + } + String name = field.getName(mojang); + MemberInstance instance = of(type, value, name, memberInstance.getDesc(), memberInstance.getAccess(), memberInstance.getIndex()); + members.put(instance.getId(), instance); + // memberInstance = instance; + // key = instance.getId(); + fixedFields++; + } else if (type == TrMember.MemberType.METHOD) { + methods++; + MappingTree.MethodMapping method = tree.getMethod(value.getName(), memberInstance.getName(), memberInstance.getDesc(), srg); + if (method == null) { + // String name = memberInstance.getOwner().getName(); + // System.out.println(name.substring(name.lastIndexOf("/") + 1) + "#" + memberInstance.getName() + " has no exact match! Trying again without the descriptor..."); + method = tree.getMethod(value.getName(), memberInstance.getName(), null, srg); + if (method == null) { + //System.out.println(name.substring(name.lastIndexOf("/") + 1) + "#" + memberInstance.getName() + " has no exact match! Tried with no descriptor!"); + members.put(memberInstance.getId(), memberInstance); + continue; + } + } + String name = method.getName(mojang); + MemberInstance instance = of(type, value, name, memberInstance.getDesc(), memberInstance.getAccess(), memberInstance.getIndex()); + members.put(instance.getId(), instance); + // memberInstance = instance; + // key = instance.getId(); + fixedMethods++; + } else { + members.put(memberInstance.getId(), memberInstance); + } + // System.out.println("NEW: " + key + " -> " + memberInstance.getId()); + } + System.out.println(value.getName() + ": Fields: " + fixedFields + "/" + fields + ", Methods: " + fixedMethods + "/" + methods); + } + + private static MemberInstance of(TrMember.MemberType type, ClassInstance cls, String name, String desc, int access, int index) { + try { + Constructor constructor = MemberInstance.class.getDeclaredConstructor(TrMember.MemberType.class, ClassInstance.class, String.class, String.class, int.class, int.class); + constructor.setAccessible(true); + return constructor.newInstance(type, cls, name, desc, access, index); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } +} 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 b5fab0bcc..15963a5e2 100644 --- a/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java @@ -44,6 +44,7 @@ import com.google.common.base.Stopwatch; import com.google.gson.JsonObject; import dev.architectury.loom.neoforge.NeoForgeModDependencies; +import dev.architectury.loom.util.ForgeSrgToMojangUtil; import dev.architectury.loom.util.MappingOption; import org.gradle.api.Project; import org.gradle.api.artifacts.Configuration; @@ -207,6 +208,7 @@ private void remapJars(List remapList) throws IOException { final TinyRemapper remapper = builder.build(); remapper.readClassPath(extension.getMinecraftJars(IntermediaryNamespaces.intermediaryNamespace(project)).toArray(Path[]::new)); + ForgeSrgToMojangUtil.replaceSrgWithMojangMappings(remapper, mappings); final Map tagMap = new HashMap<>(); final Map outputConsumerMap = new HashMap<>(); From 9feed2207fbd21865c8f1548339c9083f2e91c15 Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Tue, 9 Jul 2024 17:18:55 +1000 Subject: [PATCH 12/32] Update ForgeSrgToMojangUtil.java --- .../loom/util/ForgeSrgToMojangUtil.java | 35 ++++--------------- 1 file changed, 6 insertions(+), 29 deletions(-) diff --git a/src/main/java/dev/architectury/loom/util/ForgeSrgToMojangUtil.java b/src/main/java/dev/architectury/loom/util/ForgeSrgToMojangUtil.java index 74fcaca67..4ae0ffb38 100644 --- a/src/main/java/dev/architectury/loom/util/ForgeSrgToMojangUtil.java +++ b/src/main/java/dev/architectury/loom/util/ForgeSrgToMojangUtil.java @@ -44,59 +44,36 @@ public static void replaceSrgWithMojangMappings(ClassInstance value, MemoryMappi } Map copy = (Map) members.clone(); members.clear(); - int methods = 0; - int fields = 0; - int fixedMethods = 0; - int fixedFields = 0; for (Map.Entry entry : copy.entrySet()) { TrMember.MemberType type = entry.getValue().getType(); - // String key = entry.getKey(); MemberInstance memberInstance = entry.getValue(); - // System.out.println("OLD: " + key + " -> " + memberInstance.getId()); + String name; if (type == TrMember.MemberType.FIELD) { - fields++; MappingTree.FieldMapping field = tree.getField(value.getName(), memberInstance.getName(), memberInstance.getDesc(), srg); if (field == null) { - // String name = memberInstance.getOwner().getName(); - // System.out.println(name.substring(name.lastIndexOf("/") + 1) + "#" + memberInstance.getName() + " has no exact match! Trying again without the descriptor..."); field = tree.getField(value.getName(), memberInstance.getName(), null, srg); if (field == null) { - // System.out.println(name.substring(name.lastIndexOf("/") + 1) + "#" + memberInstance.getName() + " has no exact match! Tried with no descriptor!"); members.put(memberInstance.getId(), memberInstance); continue; } } - String name = field.getName(mojang); - MemberInstance instance = of(type, value, name, memberInstance.getDesc(), memberInstance.getAccess(), memberInstance.getIndex()); - members.put(instance.getId(), instance); - // memberInstance = instance; - // key = instance.getId(); - fixedFields++; + name = field.getName(mojang); } else if (type == TrMember.MemberType.METHOD) { - methods++; MappingTree.MethodMapping method = tree.getMethod(value.getName(), memberInstance.getName(), memberInstance.getDesc(), srg); if (method == null) { - // String name = memberInstance.getOwner().getName(); - // System.out.println(name.substring(name.lastIndexOf("/") + 1) + "#" + memberInstance.getName() + " has no exact match! Trying again without the descriptor..."); method = tree.getMethod(value.getName(), memberInstance.getName(), null, srg); if (method == null) { - //System.out.println(name.substring(name.lastIndexOf("/") + 1) + "#" + memberInstance.getName() + " has no exact match! Tried with no descriptor!"); members.put(memberInstance.getId(), memberInstance); continue; } } - String name = method.getName(mojang); - MemberInstance instance = of(type, value, name, memberInstance.getDesc(), memberInstance.getAccess(), memberInstance.getIndex()); - members.put(instance.getId(), instance); - // memberInstance = instance; - // key = instance.getId(); - fixedMethods++; + name = method.getName(mojang); } else { - members.put(memberInstance.getId(), memberInstance); + throw new AssertionError(); } - // System.out.println("NEW: " + key + " -> " + memberInstance.getId()); + MemberInstance instance = of(type, value, name, memberInstance.getDesc(), memberInstance.getAccess(), memberInstance.getIndex()); + members.put(instance.getId(), instance); } - System.out.println(value.getName() + ": Fields: " + fixedFields + "/" + fields + ", Methods: " + fixedMethods + "/" + methods); } private static MemberInstance of(TrMember.MemberType type, ClassInstance cls, String name, String desc, int access, int index) { From a01b9a64096ad1815bcc3f21eb384a8fd93d2597 Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Tue, 9 Jul 2024 17:20:10 +1000 Subject: [PATCH 13/32] Update ModProcessor.java --- .../net/fabricmc/loom/configuration/mods/ModProcessor.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 15963a5e2..0b87597ca 100644 --- a/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java @@ -208,7 +208,9 @@ private void remapJars(List remapList) throws IOException { final TinyRemapper remapper = builder.build(); remapper.readClassPath(extension.getMinecraftJars(IntermediaryNamespaces.intermediaryNamespace(project)).toArray(Path[]::new)); - ForgeSrgToMojangUtil.replaceSrgWithMojangMappings(remapper, mappings); + if (extension.isForge() && extension.getForgeProvider().usesMojangAtRuntime()) { + ForgeSrgToMojangUtil.replaceSrgWithMojangMappings(remapper, mappings); + } final Map tagMap = new HashMap<>(); final Map outputConsumerMap = new HashMap<>(); From b9aaba2779c0fb8266e1b72e6a66063d43ebd147 Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Tue, 9 Jul 2024 17:22:18 +1000 Subject: [PATCH 14/32] Update ForgeSrgToMojangUtil.java --- .../java/dev/architectury/loom/util/ForgeSrgToMojangUtil.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/dev/architectury/loom/util/ForgeSrgToMojangUtil.java b/src/main/java/dev/architectury/loom/util/ForgeSrgToMojangUtil.java index 4ae0ffb38..b85dc68e9 100644 --- a/src/main/java/dev/architectury/loom/util/ForgeSrgToMojangUtil.java +++ b/src/main/java/dev/architectury/loom/util/ForgeSrgToMojangUtil.java @@ -11,6 +11,7 @@ import net.fabricmc.tinyremapper.TinyRemapper; import net.fabricmc.tinyremapper.api.TrMember; +// FIXME: There has to be a better way to fix the mappings public final class ForgeSrgToMojangUtil { private ForgeSrgToMojangUtil() { From f7102f20ae9ec96ba4f6e3ca2523def0794e64e9 Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Tue, 9 Jul 2024 17:47:34 +1000 Subject: [PATCH 15/32] add NeoForge 1.21 test --- .../loom/test/integration/neoforge/NeoForge1210Test.groovy | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/neoforge/NeoForge1210Test.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/neoforge/NeoForge1210Test.groovy index c101a85ce..fcd8d58a4 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/neoforge/NeoForge1210Test.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/neoforge/NeoForge1210Test.groovy @@ -29,6 +29,7 @@ import spock.lang.Unroll import net.fabricmc.loom.test.util.GradleProjectTestTrait + import static net.fabricmc.loom.test.LoomTestConstants.DEFAULT_GRADLE import static org.gradle.testkit.runner.TaskOutcome.SUCCESS From 19425cde168f458e05f8807495538d6b9671e32f Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Tue, 9 Jul 2024 18:45:25 +1000 Subject: [PATCH 16/32] Fix NeoForge 1.21 test formatting --- .../loom/test/integration/neoforge/NeoForge1210Test.groovy | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/neoforge/NeoForge1210Test.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/neoforge/NeoForge1210Test.groovy index fcd8d58a4..c101a85ce 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/neoforge/NeoForge1210Test.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/neoforge/NeoForge1210Test.groovy @@ -29,7 +29,6 @@ import spock.lang.Unroll import net.fabricmc.loom.test.util.GradleProjectTestTrait - import static net.fabricmc.loom.test.LoomTestConstants.DEFAULT_GRADLE import static org.gradle.testkit.runner.TaskOutcome.SUCCESS From 81b7f4f8e0e594d01c051f976fdbf0d8282d409f Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Tue, 9 Jul 2024 18:45:37 +1000 Subject: [PATCH 17/32] fix forge 1.20.6 dependency test formatting --- .../test/integration/forge/Forge1206WithDependencyTest.groovy | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/forge/Forge1206WithDependencyTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/forge/Forge1206WithDependencyTest.groovy index 7467d3839..0eba0c429 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/forge/Forge1206WithDependencyTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/forge/Forge1206WithDependencyTest.groovy @@ -24,10 +24,11 @@ package net.fabricmc.loom.test.integration.forge -import net.fabricmc.loom.test.util.GradleProjectTestTrait import spock.lang.Specification import spock.lang.Unroll +import net.fabricmc.loom.test.util.GradleProjectTestTrait + import static net.fabricmc.loom.test.LoomTestConstants.DEFAULT_GRADLE import static org.gradle.testkit.runner.TaskOutcome.SUCCESS From 20334f5ea913a34c4fa8aa1f9baa5e86d2539200 Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Tue, 9 Jul 2024 18:51:45 +1000 Subject: [PATCH 18/32] fix checkstyle --- .../loom/util/ForgeSrgToMojangUtil.java | 21 +++++++++++++++---- .../loom/configuration/mods/ModProcessor.java | 1 + 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/main/java/dev/architectury/loom/util/ForgeSrgToMojangUtil.java b/src/main/java/dev/architectury/loom/util/ForgeSrgToMojangUtil.java index b85dc68e9..c31c38710 100644 --- a/src/main/java/dev/architectury/loom/util/ForgeSrgToMojangUtil.java +++ b/src/main/java/dev/architectury/loom/util/ForgeSrgToMojangUtil.java @@ -4,6 +4,7 @@ import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; + import net.fabricmc.mappingio.tree.MappingTree; import net.fabricmc.mappingio.tree.MemoryMappingTree; import net.fabricmc.tinyremapper.ClassInstance; @@ -13,18 +14,19 @@ // FIXME: There has to be a better way to fix the mappings public final class ForgeSrgToMojangUtil { - private ForgeSrgToMojangUtil() { - - } + private ForgeSrgToMojangUtil() { } @SuppressWarnings("unchecked") public static void replaceSrgWithMojangMappings(TinyRemapper remapper, MemoryMappingTree mappings) { Map readClasses; + try { Field readClassesField = TinyRemapper.class.getDeclaredField("readClasses"); readClassesField.setAccessible(true); readClasses = (Map) readClassesField.get(remapper); - } catch (Throwable t) {throw new RuntimeException(t);} + } catch (Throwable t) { + throw new RuntimeException(t); + } for (ClassInstance value : readClasses.values()) { replaceSrgWithMojangMappings(value, mappings); @@ -36,6 +38,7 @@ public static void replaceSrgWithMojangMappings(ClassInstance value, MemoryMappi int srg = tree.getNamespaceId("srg"); int mojang = tree.getNamespaceId("mojang"); HashMap members; + try { Field membersField = ClassInstance.class.getDeclaredField("members"); membersField.setAccessible(true); @@ -43,35 +46,45 @@ public static void replaceSrgWithMojangMappings(ClassInstance value, MemoryMappi } catch (Throwable t) { throw new RuntimeException(t); } + Map copy = (Map) members.clone(); members.clear(); + for (Map.Entry entry : copy.entrySet()) { TrMember.MemberType type = entry.getValue().getType(); MemberInstance memberInstance = entry.getValue(); String name; + if (type == TrMember.MemberType.FIELD) { MappingTree.FieldMapping field = tree.getField(value.getName(), memberInstance.getName(), memberInstance.getDesc(), srg); + if (field == null) { field = tree.getField(value.getName(), memberInstance.getName(), null, srg); + if (field == null) { members.put(memberInstance.getId(), memberInstance); continue; } } + name = field.getName(mojang); } else if (type == TrMember.MemberType.METHOD) { MappingTree.MethodMapping method = tree.getMethod(value.getName(), memberInstance.getName(), memberInstance.getDesc(), srg); + if (method == null) { method = tree.getMethod(value.getName(), memberInstance.getName(), null, srg); + if (method == null) { members.put(memberInstance.getId(), memberInstance); continue; } } + name = method.getName(mojang); } else { throw new AssertionError(); } + MemberInstance instance = of(type, value, name, memberInstance.getDesc(), memberInstance.getAccess(), memberInstance.getIndex()); members.put(instance.getId(), instance); } 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 0b87597ca..57e8773fa 100644 --- a/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java @@ -208,6 +208,7 @@ private void remapJars(List remapList) throws IOException { final TinyRemapper remapper = builder.build(); remapper.readClassPath(extension.getMinecraftJars(IntermediaryNamespaces.intermediaryNamespace(project)).toArray(Path[]::new)); + if (extension.isForge() && extension.getForgeProvider().usesMojangAtRuntime()) { ForgeSrgToMojangUtil.replaceSrgWithMojangMappings(remapper, mappings); } From aa43f5a0722d23109c8620781d33be9476e1e92a Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Tue, 9 Jul 2024 19:01:33 +1000 Subject: [PATCH 19/32] Update src/main/java/net/fabricmc/loom/extension/MixinExtensionApiImpl.java --- .../java/net/fabricmc/loom/extension/MixinExtensionApiImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/fabricmc/loom/extension/MixinExtensionApiImpl.java b/src/main/java/net/fabricmc/loom/extension/MixinExtensionApiImpl.java index 4452b2ad3..37a765017 100644 --- a/src/main/java/net/fabricmc/loom/extension/MixinExtensionApiImpl.java +++ b/src/main/java/net/fabricmc/loom/extension/MixinExtensionApiImpl.java @@ -50,7 +50,7 @@ public abstract class MixinExtensionApiImpl implements MixinExtensionAPI { public MixinExtensionApiImpl(Project project) { this.project = Objects.requireNonNull(project); this.useMixinAp = project.getObjects().property(Boolean.class) - .convention(project.provider(() -> !LoomGradleExtension.get(project).isNeoForge())); // Set this manually to false if you are using Forge 50 or later. + .convention(project.provider(() -> !LoomGradleExtension.get(project).isNeoForge())); // This needs to be manually set to false when using Forge 50 or later. this.refmapTargetNamespace = project.getObjects().property(String.class) .convention(project.provider(() -> IntermediaryNamespaces.runtimeIntermediary(project))); From 555e1e02c64d940bd0d8cea66d6f65e3fab7a052 Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Tue, 9 Jul 2024 21:03:28 +1000 Subject: [PATCH 20/32] Use union relauncher between 49.0.0 and 49.0.37, use bs-dev otherwise --- .../forge/ForgeLibrariesProvider.java | 7 +++ .../providers/forge/ForgeProvider.java | 43 ++++++++++++++----- .../providers/forge/ForgeRunTemplate.java | 14 +++++- 3 files changed, 52 insertions(+), 12 deletions(-) diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeLibrariesProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeLibrariesProvider.java index 7243f27d1..3deb5a778 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeLibrariesProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeLibrariesProvider.java @@ -96,6 +96,13 @@ public static void provide(MappingConfiguration mappingConfiguration, Project pr } } + if (lib.startsWith("net.minecraftforge:bootstrap:")) { + if (extension.isForge() && extension.getForgeProvider().usesBootstrapDev()) { + String version = lib.substring(lib.lastIndexOf(":")); + dependencies.add(project.getDependencies().create("net.minecraftforge:bootstrap-dev" + version)); + } + } + if (dep == null) { dep = lib; } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeProvider.java index b62a9d1cc..06b601006 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeProvider.java @@ -51,7 +51,7 @@ public void provide(DependencyInfo dependency) throws Exception { addDependency(dependency.getDepString() + ":userdev", Constants.Configurations.FORGE_USERDEV); addDependency(dependency.getDepString() + ":installer", Constants.Configurations.FORGE_INSTALLER); - if (getExtension().isForge() && version.getMajorVersion() >= Constants.Forge.MIN_UNION_RELAUNCHER_VERSION) { + if (getExtension().isForge() && usesUnionRelauncher()) { addDependency(LoomVersions.UNION_RELAUNCHER.mavenNotation(), Constants.Configurations.FORGE_EXTRA); } } @@ -61,7 +61,16 @@ public ForgeVersion getVersion() { } public boolean usesMojangAtRuntime() { - return platform == ModPlatform.NEOFORGE || version.getMajorVersion() >= Constants.Forge.MIN_USE_MOJANG_NS_VERSION; + return platform == ModPlatform.NEOFORGE || version.getMajorVersion() >= Constants.Forge.MIN_UNION_RELAUNCHER_VERSION; + } + + public boolean usesUnionRelauncher() { + return platform == ModPlatform.FORGE && version.getMajorVersion() >= Constants.Forge.MIN_UNION_RELAUNCHER_VERSION && !usesBootstrapDev(); + } + public boolean usesBootstrapDev() { + boolean forge50OrOver = version.getMajorVersion() >= Constants.Forge.MIN_UNION_RELAUNCHER_VERSION; + boolean point0dot38 = version.getMajorVersion() >= 50 || version.getMinorVersion() >= 1 || version.getPatchVersion() >= 38; + return platform == ModPlatform.FORGE && forge50OrOver && point0dot38; } public File getGlobalCache() { @@ -96,6 +105,8 @@ public static final class ForgeVersion { private final String minecraftVersion; private final String forgeVersion; private final int majorVersion; + private final int minorVersion; + private final int patchVersion; public ForgeVersion(String combined) { this.combined = combined; @@ -104,6 +115,8 @@ public ForgeVersion(String combined) { this.minecraftVersion = "NO_VERSION"; this.forgeVersion = "NO_VERSION"; this.majorVersion = -1; + this.minorVersion = -1; + this.patchVersion = -1; return; } @@ -117,20 +130,22 @@ public ForgeVersion(String combined) { this.forgeVersion = combined; } - int dotIndex = forgeVersion.indexOf('.'); - int major; + int major, minor, patch; try { - if (dotIndex >= 0) { - major = Integer.parseInt(forgeVersion.substring(0, dotIndex)); - } else { - major = Integer.parseInt(forgeVersion); - } - } catch (NumberFormatException e) { + String[] versionComponents = forgeVersion.split("\\."); + major = Integer.parseInt(versionComponents[0]); + minor = Integer.parseInt(versionComponents[1]); + patch = Integer.parseInt(versionComponents[2]); + } catch (Exception e) { major = -1; + minor = -1; + patch = -1; } this.majorVersion = major; + this.minorVersion = minor; + this.patchVersion = patch; } public String getCombined() { @@ -148,5 +163,13 @@ public String getForgeVersion() { public int getMajorVersion() { return majorVersion; } + + public int getMinorVersion() { + return minorVersion; + } + + public int getPatchVersion() { + return patchVersion; + } } } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeRunTemplate.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeRunTemplate.java index 3f56b844f..9d2bb54bf 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeRunTemplate.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeRunTemplate.java @@ -24,6 +24,7 @@ package net.fabricmc.loom.configuration.providers.forge; +import java.io.File; import java.io.Serializable; import java.util.HashMap; import java.util.List; @@ -110,12 +111,21 @@ public void applyTo(RunConfigSettings settings, ConfigValue.Resolver configValue settings.getEnvironmentVariables().putIfAbsent(key, resolved); }); + final ForgeProvider forgeProvider = settings.getExtension().getForgeProvider(); + // Add MOD_CLASSES, this is something that ForgeGradle does - settings.getEnvironmentVariables().computeIfAbsent("MOD_CLASSES", $ -> ConfigValue.of("{source_roots}").resolve(configValueResolver)); + settings.getEnvironmentVariables().computeIfAbsent("MOD_CLASSES", $ -> { + String modClasses = ConfigValue.of("{source_roots}").resolve(configValueResolver); + if (File.pathSeparatorChar == ':' && forgeProvider.usesBootstrapDev()) { + // bs-dev has a bug where ';' is used instead of File.pathSeparatorChar + modClasses = modClasses.replaceAll(":", ";"); + } + return modClasses; + }); final ForgeProvider forgeProvider = settings.getExtension().getForgeProvider(); - if (settings.getExtension().isForge() && forgeProvider.getVersion().getMajorVersion() >= Constants.Forge.MIN_UNION_RELAUNCHER_VERSION) { + if (settings.getExtension().isForge() && forgeProvider.usesUnionRelauncher()) { settings.defaultMainClass(Constants.Forge.UNION_RELAUNCHER_MAIN_CLASS); settings.property(Constants.Forge.UNION_RELAUNCHER_MAIN_CLASS_PROPERTY, main); } From 64441fe9845fc444d96405b9770d10b5d2c33afa Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Tue, 9 Jul 2024 21:04:23 +1000 Subject: [PATCH 21/32] change Automatic-Module-Name --- .../resources/projects/forge/1206-with-dependency/build.gradle | 3 +-- src/test/resources/projects/forge/1206/build.gradle | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/test/resources/projects/forge/1206-with-dependency/build.gradle b/src/test/resources/projects/forge/1206-with-dependency/build.gradle index 83508157d..a52c3c388 100644 --- a/src/test/resources/projects/forge/1206-with-dependency/build.gradle +++ b/src/test/resources/projects/forge/1206-with-dependency/build.gradle @@ -97,8 +97,7 @@ publishing { } processResources { doLast { - java.nio.file.Path.of(outputs.files.asPath).resolve("META-INF/MANIFEST.MF").text = "Manifest-Version: 1.0\n" + - "Automatic-Module-Name: ignoreme\n" + java.nio.file.Path.of(outputs.files.asPath).resolve("META-INF/MANIFEST.MF").text = "Manifest-Version: 1.0\nAutomatic-Module-Name: e${new Random().nextInt(10000)}\n" } } diff --git a/src/test/resources/projects/forge/1206/build.gradle b/src/test/resources/projects/forge/1206/build.gradle index 31529c592..0a9abe201 100644 --- a/src/test/resources/projects/forge/1206/build.gradle +++ b/src/test/resources/projects/forge/1206/build.gradle @@ -92,8 +92,7 @@ publishing { } processResources { doLast { - java.nio.file.Path.of(outputs.files.asPath).resolve("META-INF/MANIFEST.MF").text = "Manifest-Version: 1.0\n" + - "Automatic-Module-Name: ignoreme\n" + java.nio.file.Path.of(outputs.files.asPath).resolve("META-INF/MANIFEST.MF").text = "Manifest-Version: 1.0\nAutomatic-Module-Name: e${new Random().nextInt(10000)}\n" } } From 06ed9003b73ed684c1e5c5371c177b14d5784a19 Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Tue, 9 Jul 2024 21:12:20 +1000 Subject: [PATCH 22/32] Update ForgeRunTemplate.java --- .../loom/configuration/providers/forge/ForgeRunTemplate.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeRunTemplate.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeRunTemplate.java index 9d2bb54bf..20b99ba64 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeRunTemplate.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeRunTemplate.java @@ -123,8 +123,6 @@ public void applyTo(RunConfigSettings settings, ConfigValue.Resolver configValue return modClasses; }); - final ForgeProvider forgeProvider = settings.getExtension().getForgeProvider(); - if (settings.getExtension().isForge() && forgeProvider.usesUnionRelauncher()) { settings.defaultMainClass(Constants.Forge.UNION_RELAUNCHER_MAIN_CLASS); settings.property(Constants.Forge.UNION_RELAUNCHER_MAIN_CLASS_PROPERTY, main); From e052ae903dcaa5ea1cc359989e4a50396d2a5bfe Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Thu, 11 Jul 2024 12:39:56 +1000 Subject: [PATCH 23/32] add multiloader-forge project --- .../Forge1206WithCommonProjectTest.groovy | 60 +++++++++++++++ .../1206-with-common-project/build.gradle | 57 +++++++++++++++ .../common/build.gradle | 14 ++++ .../src/main/java/com/example/ExampleMod.java | 9 +++ .../main/resources/example_mod.mixins.json | 13 ++++ .../forge/build.gradle | 55 ++++++++++++++ .../forge/gradle.properties | 1 + .../com/example/forge/ExampleModForge.java | 13 ++++ .../src/main/resources/META-INF/mods.toml | 73 +++++++++++++++++++ .../forge/src/main/resources/pack.mcmeta | 8 ++ .../gradle.properties | 16 ++++ .../1206-with-common-project/settings.gradle | 13 ++++ 12 files changed, 332 insertions(+) create mode 100644 src/test/groovy/net/fabricmc/loom/test/integration/forge/Forge1206WithCommonProjectTest.groovy create mode 100644 src/test/resources/projects/forge/1206-with-common-project/build.gradle create mode 100644 src/test/resources/projects/forge/1206-with-common-project/common/build.gradle create mode 100644 src/test/resources/projects/forge/1206-with-common-project/common/src/main/java/com/example/ExampleMod.java create mode 100644 src/test/resources/projects/forge/1206-with-common-project/common/src/main/resources/example_mod.mixins.json create mode 100644 src/test/resources/projects/forge/1206-with-common-project/forge/build.gradle create mode 100644 src/test/resources/projects/forge/1206-with-common-project/forge/gradle.properties create mode 100644 src/test/resources/projects/forge/1206-with-common-project/forge/src/main/java/com/example/forge/ExampleModForge.java create mode 100644 src/test/resources/projects/forge/1206-with-common-project/forge/src/main/resources/META-INF/mods.toml create mode 100644 src/test/resources/projects/forge/1206-with-common-project/forge/src/main/resources/pack.mcmeta create mode 100644 src/test/resources/projects/forge/1206-with-common-project/gradle.properties create mode 100644 src/test/resources/projects/forge/1206-with-common-project/settings.gradle diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/forge/Forge1206WithCommonProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/forge/Forge1206WithCommonProjectTest.groovy new file mode 100644 index 000000000..f0fc00d40 --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/test/integration/forge/Forge1206WithCommonProjectTest.groovy @@ -0,0 +1,60 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2024 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.test.integration.forge + +import net.fabricmc.loom.test.util.GradleProjectTestTrait +import spock.lang.Specification +import spock.lang.Unroll + +import static net.fabricmc.loom.test.LoomTestConstants.DEFAULT_GRADLE +import static org.gradle.testkit.runner.TaskOutcome.SUCCESS + +class Forge1206WithCommonProjectTest extends Specification implements GradleProjectTestTrait { + @Unroll + def "build #mcVersion #forgeVersion #mappings #patches"() { + if (Integer.valueOf(System.getProperty("java.version").split("\\.")[0]) < 21) { + println("This test requires Java 21. Currently you have Java ${System.getProperty("java.version")}.") + return + } + + setup: + def gradle = gradleProject(project: "forge/1206-with-common-project", version: DEFAULT_GRADLE) + gradle.gradleProperties.text = gradle.gradleProperties.text.replace('@MCVERSION@', mcVersion) + .replace('@FORGEVERSION@', forgeVersion) + .replace('@MINECRAFTVERSION@', mcVersion) + .replace('MAPPINGS', mappings) // Spotless doesn't like the @'s + .replace('PATCHES', patches) + + when: + def result = gradle.run(task: ":forge:runClient") + + then: + result.task(":build").outcome == SUCCESS + + where: + mcVersion | forgeVersion | mappings | patches + '1.20.6' | '1.20.6-50.1.3' | "'net.fabricmc:yarn:1.20.6+build.1:v2'" | "'dev.architectury:yarn-mappings-patch-neoforge:1.20.5+build.3'" + } +} diff --git a/src/test/resources/projects/forge/1206-with-common-project/build.gradle b/src/test/resources/projects/forge/1206-with-common-project/build.gradle new file mode 100644 index 000000000..01b67c5a1 --- /dev/null +++ b/src/test/resources/projects/forge/1206-with-common-project/build.gradle @@ -0,0 +1,57 @@ +plugins { + id 'architectury-plugin' version '3.4-SNAPSHOT' + id 'dev.architectury.loom' version '1.7-9999' apply false + id 'com.github.johnrengelman.shadow' version '8.1.1' apply false +} + +architectury { + minecraft = project.minecraft_version +} + +subprojects { + apply plugin: 'dev.architectury.loom' + System.out.println("Applied loom for " + it) + + base { + // Set up a suffixed format for the mod jar names, e.g. `example-fabric`. + archivesName = "$rootProject.archives_name-$project.name" + } + + repositories { + // Add repositories to retrieve artifacts from in here. + // You should only use this when depending on other mods because + // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. + // See https://docs.gradle.org/current/userguide/declaring_repositories.html + // for more information about repositories. + } + + loom { + silentMojangMappingsLicense() + } + + dependencies { + minecraft "net.minecraft:minecraft:$rootProject.minecraft_version" + mappings loom.officialMojangMappings() + } + + java { + // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task + // if it is present. + // If you remove this line, sources will not be generated. + withSourcesJar() + + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 + } + + tasks.withType(JavaCompile).configureEach { + it.options.release = 21 + } +} + +allprojects { + apply plugin: 'architectury-plugin' + System.out.println("Applied architectury plugin") + group = rootProject.maven_group + version = rootProject.mod_version +} \ No newline at end of file diff --git a/src/test/resources/projects/forge/1206-with-common-project/common/build.gradle b/src/test/resources/projects/forge/1206-with-common-project/common/build.gradle new file mode 100644 index 000000000..fa864f52f --- /dev/null +++ b/src/test/resources/projects/forge/1206-with-common-project/common/build.gradle @@ -0,0 +1,14 @@ +loom { + System.out.println(":), " + ":F" + net.fabricmc.loom.LoomGradleExtension.class) +} + +//architectury { +// common rootProject.enabled_platforms.split(',') +//} + +dependencies { + // We depend on Fabric Loader here to use the Fabric @Environment annotations, + // which get remapped to the correct annotations on each platform. + // Do NOT use other classes from Fabric Loader. + modImplementation "net.fabricmc:fabric-loader:$rootProject.fabric_loader_version" +} diff --git a/src/test/resources/projects/forge/1206-with-common-project/common/src/main/java/com/example/ExampleMod.java b/src/test/resources/projects/forge/1206-with-common-project/common/src/main/java/com/example/ExampleMod.java new file mode 100644 index 000000000..f95a39887 --- /dev/null +++ b/src/test/resources/projects/forge/1206-with-common-project/common/src/main/java/com/example/ExampleMod.java @@ -0,0 +1,9 @@ +package com.example; + +public final class ExampleMod { + public static final String MOD_ID = "examplemod"; + + public static void init() { + // Write common init code here. + } +} diff --git a/src/test/resources/projects/forge/1206-with-common-project/common/src/main/resources/example_mod.mixins.json b/src/test/resources/projects/forge/1206-with-common-project/common/src/main/resources/example_mod.mixins.json new file mode 100644 index 000000000..f1a31bfd7 --- /dev/null +++ b/src/test/resources/projects/forge/1206-with-common-project/common/src/main/resources/example_mod.mixins.json @@ -0,0 +1,13 @@ +{ + "required": true, + "package": "com.example.mixin", + "compatibilityLevel": "JAVA_17", + "minVersion": "0.8", + "client": [ + ], + "mixins": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/src/test/resources/projects/forge/1206-with-common-project/forge/build.gradle b/src/test/resources/projects/forge/1206-with-common-project/forge/build.gradle new file mode 100644 index 000000000..62e0cf950 --- /dev/null +++ b/src/test/resources/projects/forge/1206-with-common-project/forge/build.gradle @@ -0,0 +1,55 @@ +plugins { + id 'com.github.johnrengelman.shadow' +} + +loom { + forge { + mixinConfig "example_mod.mixins.json" + } +} + +architectury { + platformSetupLoomIde() + forge() +} + +configurations { + common { + canBeResolved = true + canBeConsumed = false + } + compileClasspath.extendsFrom common + runtimeClasspath.extendsFrom common + developmentForge.extendsFrom common + + // Files in this configuration will be bundled into your mod using the Shadow plugin. + // Don't use the `shadow` configuration from the plugin itself as it's meant for excluding files. + shadowBundle { + canBeResolved = true + canBeConsumed = false + } +} + +dependencies { + forge "net.minecraftforge:forge:$rootProject.forge_version" + + common(project(path: ':common', configuration: 'namedElements')) { transitive false } + shadowBundle project(path: ':common', configuration: 'transformProductionForge') +} + +processResources { + inputs.property 'version', project.version + + filesMatching('META-INF/mods.toml') { + expand version: project.version + } +} + +shadowJar { + configurations = [project.configurations.shadowBundle] + archiveClassifier = 'dev-shadow' +} + +remapJar { + input.set shadowJar.archiveFile +} diff --git a/src/test/resources/projects/forge/1206-with-common-project/forge/gradle.properties b/src/test/resources/projects/forge/1206-with-common-project/forge/gradle.properties new file mode 100644 index 000000000..a58ba1416 --- /dev/null +++ b/src/test/resources/projects/forge/1206-with-common-project/forge/gradle.properties @@ -0,0 +1 @@ +loom.platform = forge diff --git a/src/test/resources/projects/forge/1206-with-common-project/forge/src/main/java/com/example/forge/ExampleModForge.java b/src/test/resources/projects/forge/1206-with-common-project/forge/src/main/java/com/example/forge/ExampleModForge.java new file mode 100644 index 000000000..ebb918d35 --- /dev/null +++ b/src/test/resources/projects/forge/1206-with-common-project/forge/src/main/java/com/example/forge/ExampleModForge.java @@ -0,0 +1,13 @@ +package com.example.forge; + +import net.minecraftforge.fml.common.Mod; + +import com.example.ExampleMod; + +@Mod(ExampleMod.MOD_ID) +public final class ExampleModForge { + public ExampleModForge() { + // Run our common setup. + ExampleMod.init(); + } +} diff --git a/src/test/resources/projects/forge/1206-with-common-project/forge/src/main/resources/META-INF/mods.toml b/src/test/resources/projects/forge/1206-with-common-project/forge/src/main/resources/META-INF/mods.toml new file mode 100644 index 000000000..2022ef443 --- /dev/null +++ b/src/test/resources/projects/forge/1206-with-common-project/forge/src/main/resources/META-INF/mods.toml @@ -0,0 +1,73 @@ +# This is an example mods.toml file. It contains the data relating to the loading mods. +# There are several mandatory fields (#mandatory), and many more that are optional (#optional). +# The overall format is standard TOML format, v0.5.0. +# Note that there are a couple of TOML lists in this file. +# Find more information on toml format here: https://github.com/toml-lang/toml +# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml +modLoader="javafml" #mandatory +# A version range to match for said mod loader - for regular FML @Mod it will be the forge version +loaderVersion="*" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. +# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties. +# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here. +license="Testmod" +# A URL to refer people to when problems occur with this mod +#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional +# If your mod is purely client-side and has no multiplayer functionality (be it dedicated servers or Open to LAN), +# set this to true, and Forge will set the correct displayTest for you and skip loading your mod on dedicated servers. +#clientSideOnly=true #optional - defaults to false if absent +# A list of mods - how many allowed here is determined by the individual mod loader +[[mods]] #mandatory +# The modid of the mod +modId="examplemod" #mandatory +# The version number of the mod +version="1.0.0" #mandatory +# A display name for the mod +displayName="Example Mod" #mandatory +# A URL to query for updates for this mod. See the JSON update specification https://docs.minecraftforge.net/en/latest/misc/updatechecker/ +#updateJSONURL="https://change.me.example.invalid/updates.json" #optional +# A URL for the "homepage" for this mod, displayed in the mod UI +#displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional +# A file name (in the root of the mod JAR) containing a logo for display +#logoFile="examplemod.png" #optional +# A text field displayed in the mod UI +#credits="" #optional +# A text field displayed in the mod UI +authors="Architectury" #optional +# Display Test controls the display for your mod in the server connection screen +# MATCH_VERSION means that your mod will cause a red X if the versions on client and server differ. This is the default behaviour and should be what you choose if you have server and client elements to your mod. +# IGNORE_SERVER_VERSION means that your mod will not cause a red X if it's present on the server but not on the client. This is what you should use if you're a server only mod. +# IGNORE_ALL_VERSION means that your mod will not cause a red X if it's present on the client or the server. This is a special case and should only be used if your mod has no server component. +# NONE means that no display test is set on your mod. You need to do this yourself, see IExtensionPoint.DisplayTest for more information. You can define any scheme you wish with this value. +# IMPORTANT NOTE: this is NOT an instruction as to which environments (CLIENT or DEDICATED SERVER) your mod loads on. Your mod should load (and maybe do nothing!) whereever it finds itself. +#displayTest="MATCH_VERSION" # if nothing is specified, MATCH_VERSION is the default when clientSideOnly=false, otherwise IGNORE_ALL_VERSION when clientSideOnly=true (#optional) + +# The description text for the mod (multi line!) (#mandatory) +description='''This is a test mod''' +# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. +[[dependencies.examplemod]] #optional +# the modid of the dependency +modId="forge" #mandatory +# Does this dependency have to exist - if not, ordering below must be specified +mandatory=true #mandatory +# The version range of the dependency +versionRange="[50,)" #mandatory +# An ordering relationship for the dependency - BEFORE or AFTER required if the dependency is not mandatory +# BEFORE - This mod is loaded BEFORE the dependency +# AFTER - This mod is loaded AFTER the dependency +ordering="NONE" +# Side this dependency is applied on - BOTH, CLIENT, or SERVER +side="BOTH" +# Here's another dependency +[[dependencies.examplemod]] +modId="minecraft" +mandatory=true +# This version range declares a minimum of the current minecraft version up to but not including the next major version +versionRange="[1.20.6,)" +ordering="NONE" +side="BOTH" + +# Features are specific properties of the game environment, that you may want to declare you require. This example declares +# that your mod requires GL version 3.2 or higher. Other features will be added. They are side aware so declaring this won't +# stop your mod loading on the server for example. +#[features.${mod_id}] +#openGLVersion="[3.2,)" \ No newline at end of file diff --git a/src/test/resources/projects/forge/1206-with-common-project/forge/src/main/resources/pack.mcmeta b/src/test/resources/projects/forge/1206-with-common-project/forge/src/main/resources/pack.mcmeta new file mode 100644 index 000000000..68e41fce2 --- /dev/null +++ b/src/test/resources/projects/forge/1206-with-common-project/forge/src/main/resources/pack.mcmeta @@ -0,0 +1,8 @@ +{ + "pack": { + "forge:resource_pack_format": 32, + "forge:data_pack_format": 41, + "pack_format": 32, + "description": "Example mod" + } +} \ No newline at end of file diff --git a/src/test/resources/projects/forge/1206-with-common-project/gradle.properties b/src/test/resources/projects/forge/1206-with-common-project/gradle.properties new file mode 100644 index 000000000..b82ccbb6e --- /dev/null +++ b/src/test/resources/projects/forge/1206-with-common-project/gradle.properties @@ -0,0 +1,16 @@ +# Done to increase the memory available to Gradle. +org.gradle.jvmargs=-Xmx2G +org.gradle.parallel=true + +# Mod properties +mod_version = 1.0.0 +maven_group = com.example +archives_name = example_mod +enabled_platforms = forge + +# Minecraft properties +minecraft_version = @MINECRAFTVERSION@ + +# Dependencies +fabric_loader_version = 0.15.11 +forge_version = @FORGEVERSION@ diff --git a/src/test/resources/projects/forge/1206-with-common-project/settings.gradle b/src/test/resources/projects/forge/1206-with-common-project/settings.gradle new file mode 100644 index 000000000..bba4d2549 --- /dev/null +++ b/src/test/resources/projects/forge/1206-with-common-project/settings.gradle @@ -0,0 +1,13 @@ +pluginManagement { + repositories { + maven { url "https://maven.fabricmc.net/" } + maven { url "https://maven.architectury.dev/" } + maven { url "https://files.minecraftforge.net/maven/" } + gradlePluginPortal() + } +} + +rootProject.name = 'fabric-example-mod' + +include 'common' +include 'forge' From 900f2cf83de560b158e486e2309e5dfbda5c7b06 Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Thu, 11 Jul 2024 17:22:47 +1000 Subject: [PATCH 24/32] try fix more forge stuff --- .../loom/util/ForgeSrgToMojangUtil.java | 1 + .../architectury/loom/util/MappingOption.java | 3 +- .../fabricmc/loom/LoomGradleExtension.java | 2 +- .../loom/build/IntermediaryNamespaces.java | 6 +-- .../configuration/CompileConfiguration.java | 3 +- .../loom/configuration/mods/ModProcessor.java | 5 --- .../forge/ForgeLibrariesProvider.java | 23 ++++++++++ .../providers/forge/ForgeProvider.java | 2 +- .../forge/MinecraftPatchedProvider.java | 44 ++++++++++++++----- .../task/launch/GenerateDLIConfigTask.java | 2 +- .../fabricmc/loom/util/SourceRemapper.java | 4 +- 11 files changed, 69 insertions(+), 26 deletions(-) diff --git a/src/main/java/dev/architectury/loom/util/ForgeSrgToMojangUtil.java b/src/main/java/dev/architectury/loom/util/ForgeSrgToMojangUtil.java index c31c38710..aafdf6a26 100644 --- a/src/main/java/dev/architectury/loom/util/ForgeSrgToMojangUtil.java +++ b/src/main/java/dev/architectury/loom/util/ForgeSrgToMojangUtil.java @@ -18,6 +18,7 @@ private ForgeSrgToMojangUtil() { } @SuppressWarnings("unchecked") public static void replaceSrgWithMojangMappings(TinyRemapper remapper, MemoryMappingTree mappings) { + if (true) return; Map readClasses; try { diff --git a/src/main/java/dev/architectury/loom/util/MappingOption.java b/src/main/java/dev/architectury/loom/util/MappingOption.java index 4946634e8..1d172c67b 100644 --- a/src/main/java/dev/architectury/loom/util/MappingOption.java +++ b/src/main/java/dev/architectury/loom/util/MappingOption.java @@ -1,5 +1,6 @@ package dev.architectury.loom.util; +import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.api.LoomGradleExtensionAPI; public enum MappingOption { @@ -9,7 +10,7 @@ public enum MappingOption { public static MappingOption forPlatform(LoomGradleExtensionAPI extension) { return switch (extension.getPlatform().get()) { - case FORGE -> WITH_SRG; + case FORGE -> ((LoomGradleExtension) extension).getForgeProvider().usesMojangAtRuntime() ? WITH_MOJANG : WITH_SRG; case NEOFORGE -> WITH_MOJANG; default -> DEFAULT; }; diff --git a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java index c870148e5..44c62684a 100644 --- a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java +++ b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java @@ -114,7 +114,7 @@ default List getMinecraftJars(MappingsNamespace mappingsNamespace) { yield getSrgMinecraftProvider().getMinecraftJarPaths(); } case MOJANG -> { - ModPlatform.assertPlatform(this, ModPlatform.NEOFORGE, () -> "Mojang-mapped jars are only available on NeoForge."); + assert this.isForgeLike() && this.getForgeProvider().usesMojangAtRuntime() : "Mojang-mapped jars are only available on Forge 50+ or NeoForge."; yield getMojangMappedMinecraftProvider().getMinecraftJarPaths(); } }; diff --git a/src/main/java/net/fabricmc/loom/build/IntermediaryNamespaces.java b/src/main/java/net/fabricmc/loom/build/IntermediaryNamespaces.java index f3a93922e..ec474bc60 100644 --- a/src/main/java/net/fabricmc/loom/build/IntermediaryNamespaces.java +++ b/src/main/java/net/fabricmc/loom/build/IntermediaryNamespaces.java @@ -50,16 +50,16 @@ public static String runtimeIntermediary(Project project) { * Returns the intermediary namespace of the project. */ public static MappingsNamespace intermediaryNamespace(Project project) { - return intermediaryNamespace(LoomGradleExtension.get(project).getPlatform().get()); + return intermediaryNamespace(LoomGradleExtension.get(project).getPlatform().get(), LoomGradleExtension.get(project)); } /** * Returns the intermediary namespace of the platform. */ - public static MappingsNamespace intermediaryNamespace(ModPlatform platform) { + public static MappingsNamespace intermediaryNamespace(ModPlatform platform, LoomGradleExtension extension) { return switch (platform) { case FABRIC, QUILT -> MappingsNamespace.INTERMEDIARY; - case FORGE -> MappingsNamespace.SRG; + case FORGE -> extension.getForgeProvider().usesMojangAtRuntime() ? MappingsNamespace.MOJANG : MappingsNamespace.SRG; case NEOFORGE -> MappingsNamespace.MOJANG; }; } diff --git a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java index 37053c9a8..e9adfa82b 100644 --- a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java +++ b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java @@ -268,7 +268,8 @@ private synchronized void setupMinecraft(ConfigContext configContext) throws Exc final SrgMinecraftProvider srgMinecraftProvider = jarConfiguration.createSrgMinecraftProvider(project); extension.setSrgMinecraftProvider(srgMinecraftProvider); srgMinecraftProvider.provide(provideContext); - } else if (extension.isNeoForge()) { + } + if (extension.isForgeLike() && extension.getForgeProvider().usesMojangAtRuntime()) { final MojangMappedMinecraftProvider mojangMappedMinecraftProvider = jarConfiguration.createMojangMappedMinecraftProvider(project); extension.setMojangMappedMinecraftProvider(mojangMappedMinecraftProvider); mojangMappedMinecraftProvider.provide(provideContext); 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 57e8773fa..b5fab0bcc 100644 --- a/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java @@ -44,7 +44,6 @@ import com.google.common.base.Stopwatch; import com.google.gson.JsonObject; import dev.architectury.loom.neoforge.NeoForgeModDependencies; -import dev.architectury.loom.util.ForgeSrgToMojangUtil; import dev.architectury.loom.util.MappingOption; import org.gradle.api.Project; import org.gradle.api.artifacts.Configuration; @@ -209,10 +208,6 @@ private void remapJars(List remapList) throws IOException { remapper.readClassPath(extension.getMinecraftJars(IntermediaryNamespaces.intermediaryNamespace(project)).toArray(Path[]::new)); - if (extension.isForge() && extension.getForgeProvider().usesMojangAtRuntime()) { - ForgeSrgToMojangUtil.replaceSrgWithMojangMappings(remapper, mappings); - } - final Map tagMap = new HashMap<>(); final Map outputConsumerMap = new HashMap<>(); final Map> accessWidenerMap = new HashMap<>(); diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeLibrariesProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeLibrariesProvider.java index 3deb5a778..651740531 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeLibrariesProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeLibrariesProvider.java @@ -63,6 +63,7 @@ public class ForgeLibrariesProvider { private static final String FANCYML_LOADER_GROUP = "net.neoforged.fancymodloader"; private static final String FANCYML_LOADER_NAME = "loader"; + private static final String FORGE_GAME_TEST_HOOLS_FILE = "net/minecraftforge/gametest/ForgeGameTestHooks.class"; private static final String FORGE_OBJECT_HOLDER_FILE = "net/minecraftforge/fml/common/asm/ObjectHolderDefinalize.class"; private static final String FORGE_MOD_DIR_TRANSFORMER_DISCOVERER_FILE = "net/minecraftforge/fml/loading/ModDirTransformerDiscoverer.class"; private static final String NEOFORGE_OBJECT_HOLDER_FILE = "net/neoforged/fml/common/asm/ObjectHolderDefinalize.class"; @@ -185,6 +186,10 @@ private static Object remapFmlLoader(Project project, ResolvedArtifact artifact, remapObjectHolder(project, outputJar, mappingConfiguration); } + if (Files.exists(fs.get().getPath(FORGE_GAME_TEST_HOOLS_FILE))) { + remapObjectHolder(project, outputJar, mappingConfiguration); + } + if (Files.exists(fs.getPath(FORGE_MOD_DIR_TRANSFORMER_DISCOVERER_FILE))) { ClassVisitorUtil.rewriteClassFile(fs.getPath(FORGE_MOD_DIR_TRANSFORMER_DISCOVERER_FILE), ModDirTransformerDiscovererPatch::new); } @@ -229,6 +234,24 @@ private static void remapObjectHolder(Project project, Path outputJar, MappingCo } } + private static void remapGameTestHooks(Project project, Path outputJar, MappingConfiguration mappingConfiguration) throws IOException { + try { + // Merge SRG mappings. The real SRG mapping file hasn't been created yet since the usual SRG merging + // process occurs after all Forge libraries have been provided. + // Forge libs are needed for MC, which is needed for the mappings. + final ForgeMappingsMerger.ExtraMappings extraMappings = ForgeMappingsMerger.ExtraMappings.ofMojmapTsrg(MappingConfiguration.getMojmapSrgFileIfPossible(project)); + final MemoryMappingTree mappings = ForgeMappingsMerger.mergeSrg(MappingConfiguration.getRawSrgFile(project), mappingConfiguration.tinyMappings, extraMappings, true); + + // Remap the game test hooks. + RemapObjectHolderVisitor.remapObjectHolder( + outputJar, "net.minecraftforge.gametest.ForgeGameTestHooks", mappings, + MappingsNamespace.SRG.toString(), MappingsNamespace.NAMED.toString() + ); + } catch (IOException e) { + throw new IOException("Could not remap object holders in " + outputJar, e); + } + } + private static void remapNeoForgeObjectHolder(Project project, Path outputJar, MappingConfiguration mappingConfiguration) throws IOException { try { // Merge Mojang mappings. The real Mojang mapping file hasn't been created yet since the usual Mojang merging diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeProvider.java index 06b601006..08868c143 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeProvider.java @@ -61,7 +61,7 @@ public ForgeVersion getVersion() { } public boolean usesMojangAtRuntime() { - return platform == ModPlatform.NEOFORGE || version.getMajorVersion() >= Constants.Forge.MIN_UNION_RELAUNCHER_VERSION; + return platform == ModPlatform.NEOFORGE || version.getMajorVersion() >= Constants.Forge.MIN_USE_MOJANG_NS_VERSION; } public boolean usesUnionRelauncher() { 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 e2b684bdd..fb3a06ef4 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 @@ -58,6 +58,7 @@ import org.gradle.api.Project; import org.gradle.api.logging.LogLevel; import org.gradle.api.logging.Logger; +import org.jetbrains.annotations.Nullable; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; @@ -111,6 +112,8 @@ public class MinecraftPatchedProvider { private Path minecraftPatchedIntermediateJar; // Step 3: Access Transform private Path minecraftPatchedIntermediateAtJar; + // Forge 1.20.6: Step 3.5: Remap Patched AT and Forge to mojmaps + private Path minecraftPatchedMojangAtJar; // Step 4: Remap Patched AT & Forge to official private Path minecraftPatchedJar; private Path minecraftClientExtra; @@ -151,6 +154,7 @@ private void initPatchedFiles() { minecraftIntermediateJar = forgeWorkingDir.resolve("minecraft-" + type.id + "-" + intermediateId + ".jar"); minecraftPatchedIntermediateJar = forgeWorkingDir.resolve("minecraft-" + type.id + "-" + intermediateId + "-patched.jar"); minecraftPatchedIntermediateAtJar = forgeWorkingDir.resolve("minecraft-" + type.id + "-" + intermediateId + "-at-patched.jar"); + minecraftPatchedMojangAtJar = forgeWorkingDir.resolve("minecraft-" + type.id + "-" + "mojang" + "-at-patched.jar"); minecraftPatchedJar = forgeWorkingDir.resolve("minecraft-" + type.id + "-patched.jar"); minecraftClientExtra = forgeWorkingDir.resolve("client-extra.jar"); } @@ -166,6 +170,7 @@ private Path[] getGlobalCaches() { minecraftIntermediateJar, minecraftPatchedIntermediateJar, minecraftPatchedIntermediateAtJar, + minecraftPatchedMojangAtJar, minecraftPatchedJar, minecraftClientExtra, }; @@ -201,7 +206,7 @@ public void provide() throws Exception { patchJars(); } - if (dirty || Files.notExists(minecraftPatchedIntermediateAtJar)) { + if (dirty || Files.notExists(minecraftPatchedIntermediateAtJar) || (getExtension().isForge() && getExtension().getForgeProvider().usesMojangAtRuntime() && Files.notExists(minecraftPatchedMojangAtJar))) { this.dirty = true; accessTransformForge(); } @@ -227,14 +232,16 @@ private void fillClientExtraJar() throws IOException { } private TinyRemapper buildRemapper(SharedServiceManager serviceManager, Path input) throws IOException { - final MappingOption mappingOption = MappingOption.forPlatform(getExtension()); + return buildRemapper(MappingOption.forPlatform(getExtension()), IntermediaryNamespaces.intermediary(project), "official", serviceManager, input); + } + + private TinyRemapper buildRemapper(final MappingOption mappingOption, final String sourceNamespace, final String to, SharedServiceManager serviceManager, Path input) throws IOException { TinyMappingsService mappingsService = getExtension().getMappingConfiguration().getMappingsService(serviceManager, mappingOption); - final String sourceNamespace = IntermediaryNamespaces.intermediary(project); MemoryMappingTree mappings = mappingsService.getMappingTree(); TinyRemapper.Builder builder = TinyRemapper.newRemapper() - .withMappings(TinyRemapperHelper.create(mappings, sourceNamespace, "official", true)) - .withMappings(InnerClassRemapper.of(InnerClassRemapper.readClassNames(input), mappings, sourceNamespace, "official")) + .withMappings(TinyRemapperHelper.create(mappings, sourceNamespace, to, true)) + .withMappings(InnerClassRemapper.of(InnerClassRemapper.readClassNames(input), mappings, sourceNamespace, to)) .renameInvalidLocals(true) .rebuildSourceFilenames(true); @@ -409,24 +416,39 @@ public static void accessTransform(Project project, Path input, Path target) thr } private void remapPatchedJar(SharedServiceManager serviceManager) throws Exception { - logger.lifecycle(":remapping minecraft (TinyRemapper, srg -> official)"); Path mcInput = minecraftPatchedIntermediateAtJar; + Path mcPatchedAt = minecraftPatchedMojangAtJar; Path mcOutput = minecraftPatchedJar; Path forgeJar = getForgeJar().toPath(); Path forgeUserdevJar = getForgeUserdevJar().toPath(); + Files.deleteIfExists(mcPatchedAt); Files.deleteIfExists(mcOutput); - TinyRemapper remapper = buildRemapper(serviceManager, mcInput); + if (getExtension().isForge() && getExtension().getForgeProvider().usesMojangAtRuntime()) { + logger.lifecycle(":remapping minecraft (TinyRemapper, srg -> mojang)"); + TinyRemapper remapper = buildRemapper(MappingOption.WITH_SRG, "srg", "mojang", serviceManager, mcInput); + remapJar(remapper, serviceManager, mcInput, mcPatchedAt, forgeJar, forgeUserdevJar, false); + logger.lifecycle(":remapping minecraft (TinyRemapper, mojang -> official)"); + TinyRemapper remapper2 = buildRemapper(MappingOption.WITH_MOJANG, "mojang", "official", serviceManager, mcInput); + remapJar(remapper2, serviceManager, mcPatchedAt, mcOutput, null, null, true); + } else { + logger.lifecycle(":remapping minecraft (TinyRemapper, %s -> official)".formatted(getExtension().isForge() ? "srg" : "mojang")); + TinyRemapper remapper = buildRemapper(serviceManager, mcInput); + remapJar(remapper, serviceManager, mcInput, mcOutput, forgeJar, forgeUserdevJar, true); + } + } + + private void remapJar(TinyRemapper remapper, SharedServiceManager serviceManager, Path mcInput, Path mcOutput, @Nullable Path forgeJar, @Nullable Path forgeUserdevJar, boolean remapCoreMods) throws Exception { try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(mcOutput).build()) { outputConsumer.addNonClassFiles(mcInput); - outputConsumer.addNonClassFiles(forgeJar, NonClassCopyMode.FIX_META_INF, remapper); + if (forgeJar != null) outputConsumer.addNonClassFiles(forgeJar, NonClassCopyMode.FIX_META_INF, remapper); InputTag mcTag = remapper.createInputTag(); InputTag forgeTag = remapper.createInputTag(); List> futures = new ArrayList<>(); futures.add(remapper.readInputsAsync(mcTag, mcInput)); - futures.add(remapper.readInputsAsync(forgeTag, forgeJar, forgeUserdevJar)); + if (forgeJar != null) futures.add(remapper.readInputsAsync(forgeTag, forgeJar, forgeUserdevJar)); CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join(); remapper.apply(outputConsumer, mcTag); remapper.apply(outputConsumer, forgeTag); @@ -434,8 +456,8 @@ private void remapPatchedJar(SharedServiceManager serviceManager) throws Excepti remapper.finish(); } - copyUserdevFiles(forgeUserdevJar, mcOutput); - remapCoreMods(mcOutput, serviceManager); + if (forgeUserdevJar != null) copyUserdevFiles(forgeUserdevJar, mcOutput); + if (remapCoreMods) remapCoreMods(mcOutput, serviceManager); applyLoomPatchVersion(mcOutput); } diff --git a/src/main/java/net/fabricmc/loom/task/launch/GenerateDLIConfigTask.java b/src/main/java/net/fabricmc/loom/task/launch/GenerateDLIConfigTask.java index cd5a90fee..3242209aa 100644 --- a/src/main/java/net/fabricmc/loom/task/launch/GenerateDLIConfigTask.java +++ b/src/main/java/net/fabricmc/loom/task/launch/GenerateDLIConfigTask.java @@ -234,7 +234,7 @@ public void run() throws IOException { .map(File::getAbsolutePath) .collect(Collectors.joining(File.pathSeparator)); - final String intermediateNs = IntermediaryNamespaces.intermediaryNamespace(platform).toString(); + final String intermediateNs = IntermediaryNamespaces.intermediaryNamespace(platform, getExtension()).toString(); final String mappingsPath = getPlatformMappingFile().get().getAsFile().getAbsolutePath(); launchConfig diff --git a/src/main/java/net/fabricmc/loom/util/SourceRemapper.java b/src/main/java/net/fabricmc/loom/util/SourceRemapper.java index ed4d718f5..17fca16e0 100644 --- a/src/main/java/net/fabricmc/loom/util/SourceRemapper.java +++ b/src/main/java/net/fabricmc/loom/util/SourceRemapper.java @@ -199,11 +199,11 @@ private Mercury getMercuryInstance() { mercury.getClassPath().add(intermediaryJar); } - if (extension.isForge()) { + if (extension.isForge() && !extension.getForgeProvider().usesMojangAtRuntime()) { for (Path srgJar : extension.getMinecraftJars(MappingsNamespace.SRG)) { mercury.getClassPath().add(srgJar); } - } else if (extension.isNeoForge()) { + } else if (extension.isForgeLike() && extension.getForgeProvider().usesMojangAtRuntime()) { for (Path mojangJar : extension.getMinecraftJars(MappingsNamespace.MOJANG)) { mercury.getClassPath().add(mojangJar); } From 81d92d6aefa4dc30e8ed6bb7c8b5732c82a5172f Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Thu, 11 Jul 2024 17:23:02 +1000 Subject: [PATCH 25/32] Revert "add multiloader-forge project" This reverts commit 9597bec5809934a3d7f43bd9b686bd842605e671. --- .../Forge1206WithCommonProjectTest.groovy | 60 --------------- .../1206-with-common-project/build.gradle | 57 --------------- .../common/build.gradle | 14 ---- .../src/main/java/com/example/ExampleMod.java | 9 --- .../main/resources/example_mod.mixins.json | 13 ---- .../forge/build.gradle | 55 -------------- .../forge/gradle.properties | 1 - .../com/example/forge/ExampleModForge.java | 13 ---- .../src/main/resources/META-INF/mods.toml | 73 ------------------- .../forge/src/main/resources/pack.mcmeta | 8 -- .../gradle.properties | 16 ---- .../1206-with-common-project/settings.gradle | 13 ---- 12 files changed, 332 deletions(-) delete mode 100644 src/test/groovy/net/fabricmc/loom/test/integration/forge/Forge1206WithCommonProjectTest.groovy delete mode 100644 src/test/resources/projects/forge/1206-with-common-project/build.gradle delete mode 100644 src/test/resources/projects/forge/1206-with-common-project/common/build.gradle delete mode 100644 src/test/resources/projects/forge/1206-with-common-project/common/src/main/java/com/example/ExampleMod.java delete mode 100644 src/test/resources/projects/forge/1206-with-common-project/common/src/main/resources/example_mod.mixins.json delete mode 100644 src/test/resources/projects/forge/1206-with-common-project/forge/build.gradle delete mode 100644 src/test/resources/projects/forge/1206-with-common-project/forge/gradle.properties delete mode 100644 src/test/resources/projects/forge/1206-with-common-project/forge/src/main/java/com/example/forge/ExampleModForge.java delete mode 100644 src/test/resources/projects/forge/1206-with-common-project/forge/src/main/resources/META-INF/mods.toml delete mode 100644 src/test/resources/projects/forge/1206-with-common-project/forge/src/main/resources/pack.mcmeta delete mode 100644 src/test/resources/projects/forge/1206-with-common-project/gradle.properties delete mode 100644 src/test/resources/projects/forge/1206-with-common-project/settings.gradle diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/forge/Forge1206WithCommonProjectTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/forge/Forge1206WithCommonProjectTest.groovy deleted file mode 100644 index f0fc00d40..000000000 --- a/src/test/groovy/net/fabricmc/loom/test/integration/forge/Forge1206WithCommonProjectTest.groovy +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is part of fabric-loom, licensed under the MIT License (MIT). - * - * Copyright (c) 2024 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.test.integration.forge - -import net.fabricmc.loom.test.util.GradleProjectTestTrait -import spock.lang.Specification -import spock.lang.Unroll - -import static net.fabricmc.loom.test.LoomTestConstants.DEFAULT_GRADLE -import static org.gradle.testkit.runner.TaskOutcome.SUCCESS - -class Forge1206WithCommonProjectTest extends Specification implements GradleProjectTestTrait { - @Unroll - def "build #mcVersion #forgeVersion #mappings #patches"() { - if (Integer.valueOf(System.getProperty("java.version").split("\\.")[0]) < 21) { - println("This test requires Java 21. Currently you have Java ${System.getProperty("java.version")}.") - return - } - - setup: - def gradle = gradleProject(project: "forge/1206-with-common-project", version: DEFAULT_GRADLE) - gradle.gradleProperties.text = gradle.gradleProperties.text.replace('@MCVERSION@', mcVersion) - .replace('@FORGEVERSION@', forgeVersion) - .replace('@MINECRAFTVERSION@', mcVersion) - .replace('MAPPINGS', mappings) // Spotless doesn't like the @'s - .replace('PATCHES', patches) - - when: - def result = gradle.run(task: ":forge:runClient") - - then: - result.task(":build").outcome == SUCCESS - - where: - mcVersion | forgeVersion | mappings | patches - '1.20.6' | '1.20.6-50.1.3' | "'net.fabricmc:yarn:1.20.6+build.1:v2'" | "'dev.architectury:yarn-mappings-patch-neoforge:1.20.5+build.3'" - } -} diff --git a/src/test/resources/projects/forge/1206-with-common-project/build.gradle b/src/test/resources/projects/forge/1206-with-common-project/build.gradle deleted file mode 100644 index 01b67c5a1..000000000 --- a/src/test/resources/projects/forge/1206-with-common-project/build.gradle +++ /dev/null @@ -1,57 +0,0 @@ -plugins { - id 'architectury-plugin' version '3.4-SNAPSHOT' - id 'dev.architectury.loom' version '1.7-9999' apply false - id 'com.github.johnrengelman.shadow' version '8.1.1' apply false -} - -architectury { - minecraft = project.minecraft_version -} - -subprojects { - apply plugin: 'dev.architectury.loom' - System.out.println("Applied loom for " + it) - - base { - // Set up a suffixed format for the mod jar names, e.g. `example-fabric`. - archivesName = "$rootProject.archives_name-$project.name" - } - - repositories { - // Add repositories to retrieve artifacts from in here. - // You should only use this when depending on other mods because - // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. - // See https://docs.gradle.org/current/userguide/declaring_repositories.html - // for more information about repositories. - } - - loom { - silentMojangMappingsLicense() - } - - dependencies { - minecraft "net.minecraft:minecraft:$rootProject.minecraft_version" - mappings loom.officialMojangMappings() - } - - java { - // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task - // if it is present. - // If you remove this line, sources will not be generated. - withSourcesJar() - - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 - } - - tasks.withType(JavaCompile).configureEach { - it.options.release = 21 - } -} - -allprojects { - apply plugin: 'architectury-plugin' - System.out.println("Applied architectury plugin") - group = rootProject.maven_group - version = rootProject.mod_version -} \ No newline at end of file diff --git a/src/test/resources/projects/forge/1206-with-common-project/common/build.gradle b/src/test/resources/projects/forge/1206-with-common-project/common/build.gradle deleted file mode 100644 index fa864f52f..000000000 --- a/src/test/resources/projects/forge/1206-with-common-project/common/build.gradle +++ /dev/null @@ -1,14 +0,0 @@ -loom { - System.out.println(":), " + ":F" + net.fabricmc.loom.LoomGradleExtension.class) -} - -//architectury { -// common rootProject.enabled_platforms.split(',') -//} - -dependencies { - // We depend on Fabric Loader here to use the Fabric @Environment annotations, - // which get remapped to the correct annotations on each platform. - // Do NOT use other classes from Fabric Loader. - modImplementation "net.fabricmc:fabric-loader:$rootProject.fabric_loader_version" -} diff --git a/src/test/resources/projects/forge/1206-with-common-project/common/src/main/java/com/example/ExampleMod.java b/src/test/resources/projects/forge/1206-with-common-project/common/src/main/java/com/example/ExampleMod.java deleted file mode 100644 index f95a39887..000000000 --- a/src/test/resources/projects/forge/1206-with-common-project/common/src/main/java/com/example/ExampleMod.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.example; - -public final class ExampleMod { - public static final String MOD_ID = "examplemod"; - - public static void init() { - // Write common init code here. - } -} diff --git a/src/test/resources/projects/forge/1206-with-common-project/common/src/main/resources/example_mod.mixins.json b/src/test/resources/projects/forge/1206-with-common-project/common/src/main/resources/example_mod.mixins.json deleted file mode 100644 index f1a31bfd7..000000000 --- a/src/test/resources/projects/forge/1206-with-common-project/common/src/main/resources/example_mod.mixins.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "required": true, - "package": "com.example.mixin", - "compatibilityLevel": "JAVA_17", - "minVersion": "0.8", - "client": [ - ], - "mixins": [ - ], - "injectors": { - "defaultRequire": 1 - } -} diff --git a/src/test/resources/projects/forge/1206-with-common-project/forge/build.gradle b/src/test/resources/projects/forge/1206-with-common-project/forge/build.gradle deleted file mode 100644 index 62e0cf950..000000000 --- a/src/test/resources/projects/forge/1206-with-common-project/forge/build.gradle +++ /dev/null @@ -1,55 +0,0 @@ -plugins { - id 'com.github.johnrengelman.shadow' -} - -loom { - forge { - mixinConfig "example_mod.mixins.json" - } -} - -architectury { - platformSetupLoomIde() - forge() -} - -configurations { - common { - canBeResolved = true - canBeConsumed = false - } - compileClasspath.extendsFrom common - runtimeClasspath.extendsFrom common - developmentForge.extendsFrom common - - // Files in this configuration will be bundled into your mod using the Shadow plugin. - // Don't use the `shadow` configuration from the plugin itself as it's meant for excluding files. - shadowBundle { - canBeResolved = true - canBeConsumed = false - } -} - -dependencies { - forge "net.minecraftforge:forge:$rootProject.forge_version" - - common(project(path: ':common', configuration: 'namedElements')) { transitive false } - shadowBundle project(path: ':common', configuration: 'transformProductionForge') -} - -processResources { - inputs.property 'version', project.version - - filesMatching('META-INF/mods.toml') { - expand version: project.version - } -} - -shadowJar { - configurations = [project.configurations.shadowBundle] - archiveClassifier = 'dev-shadow' -} - -remapJar { - input.set shadowJar.archiveFile -} diff --git a/src/test/resources/projects/forge/1206-with-common-project/forge/gradle.properties b/src/test/resources/projects/forge/1206-with-common-project/forge/gradle.properties deleted file mode 100644 index a58ba1416..000000000 --- a/src/test/resources/projects/forge/1206-with-common-project/forge/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -loom.platform = forge diff --git a/src/test/resources/projects/forge/1206-with-common-project/forge/src/main/java/com/example/forge/ExampleModForge.java b/src/test/resources/projects/forge/1206-with-common-project/forge/src/main/java/com/example/forge/ExampleModForge.java deleted file mode 100644 index ebb918d35..000000000 --- a/src/test/resources/projects/forge/1206-with-common-project/forge/src/main/java/com/example/forge/ExampleModForge.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.example.forge; - -import net.minecraftforge.fml.common.Mod; - -import com.example.ExampleMod; - -@Mod(ExampleMod.MOD_ID) -public final class ExampleModForge { - public ExampleModForge() { - // Run our common setup. - ExampleMod.init(); - } -} diff --git a/src/test/resources/projects/forge/1206-with-common-project/forge/src/main/resources/META-INF/mods.toml b/src/test/resources/projects/forge/1206-with-common-project/forge/src/main/resources/META-INF/mods.toml deleted file mode 100644 index 2022ef443..000000000 --- a/src/test/resources/projects/forge/1206-with-common-project/forge/src/main/resources/META-INF/mods.toml +++ /dev/null @@ -1,73 +0,0 @@ -# This is an example mods.toml file. It contains the data relating to the loading mods. -# There are several mandatory fields (#mandatory), and many more that are optional (#optional). -# The overall format is standard TOML format, v0.5.0. -# Note that there are a couple of TOML lists in this file. -# Find more information on toml format here: https://github.com/toml-lang/toml -# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml -modLoader="javafml" #mandatory -# A version range to match for said mod loader - for regular FML @Mod it will be the forge version -loaderVersion="*" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. -# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties. -# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here. -license="Testmod" -# A URL to refer people to when problems occur with this mod -#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional -# If your mod is purely client-side and has no multiplayer functionality (be it dedicated servers or Open to LAN), -# set this to true, and Forge will set the correct displayTest for you and skip loading your mod on dedicated servers. -#clientSideOnly=true #optional - defaults to false if absent -# A list of mods - how many allowed here is determined by the individual mod loader -[[mods]] #mandatory -# The modid of the mod -modId="examplemod" #mandatory -# The version number of the mod -version="1.0.0" #mandatory -# A display name for the mod -displayName="Example Mod" #mandatory -# A URL to query for updates for this mod. See the JSON update specification https://docs.minecraftforge.net/en/latest/misc/updatechecker/ -#updateJSONURL="https://change.me.example.invalid/updates.json" #optional -# A URL for the "homepage" for this mod, displayed in the mod UI -#displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional -# A file name (in the root of the mod JAR) containing a logo for display -#logoFile="examplemod.png" #optional -# A text field displayed in the mod UI -#credits="" #optional -# A text field displayed in the mod UI -authors="Architectury" #optional -# Display Test controls the display for your mod in the server connection screen -# MATCH_VERSION means that your mod will cause a red X if the versions on client and server differ. This is the default behaviour and should be what you choose if you have server and client elements to your mod. -# IGNORE_SERVER_VERSION means that your mod will not cause a red X if it's present on the server but not on the client. This is what you should use if you're a server only mod. -# IGNORE_ALL_VERSION means that your mod will not cause a red X if it's present on the client or the server. This is a special case and should only be used if your mod has no server component. -# NONE means that no display test is set on your mod. You need to do this yourself, see IExtensionPoint.DisplayTest for more information. You can define any scheme you wish with this value. -# IMPORTANT NOTE: this is NOT an instruction as to which environments (CLIENT or DEDICATED SERVER) your mod loads on. Your mod should load (and maybe do nothing!) whereever it finds itself. -#displayTest="MATCH_VERSION" # if nothing is specified, MATCH_VERSION is the default when clientSideOnly=false, otherwise IGNORE_ALL_VERSION when clientSideOnly=true (#optional) - -# The description text for the mod (multi line!) (#mandatory) -description='''This is a test mod''' -# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. -[[dependencies.examplemod]] #optional -# the modid of the dependency -modId="forge" #mandatory -# Does this dependency have to exist - if not, ordering below must be specified -mandatory=true #mandatory -# The version range of the dependency -versionRange="[50,)" #mandatory -# An ordering relationship for the dependency - BEFORE or AFTER required if the dependency is not mandatory -# BEFORE - This mod is loaded BEFORE the dependency -# AFTER - This mod is loaded AFTER the dependency -ordering="NONE" -# Side this dependency is applied on - BOTH, CLIENT, or SERVER -side="BOTH" -# Here's another dependency -[[dependencies.examplemod]] -modId="minecraft" -mandatory=true -# This version range declares a minimum of the current minecraft version up to but not including the next major version -versionRange="[1.20.6,)" -ordering="NONE" -side="BOTH" - -# Features are specific properties of the game environment, that you may want to declare you require. This example declares -# that your mod requires GL version 3.2 or higher. Other features will be added. They are side aware so declaring this won't -# stop your mod loading on the server for example. -#[features.${mod_id}] -#openGLVersion="[3.2,)" \ No newline at end of file diff --git a/src/test/resources/projects/forge/1206-with-common-project/forge/src/main/resources/pack.mcmeta b/src/test/resources/projects/forge/1206-with-common-project/forge/src/main/resources/pack.mcmeta deleted file mode 100644 index 68e41fce2..000000000 --- a/src/test/resources/projects/forge/1206-with-common-project/forge/src/main/resources/pack.mcmeta +++ /dev/null @@ -1,8 +0,0 @@ -{ - "pack": { - "forge:resource_pack_format": 32, - "forge:data_pack_format": 41, - "pack_format": 32, - "description": "Example mod" - } -} \ No newline at end of file diff --git a/src/test/resources/projects/forge/1206-with-common-project/gradle.properties b/src/test/resources/projects/forge/1206-with-common-project/gradle.properties deleted file mode 100644 index b82ccbb6e..000000000 --- a/src/test/resources/projects/forge/1206-with-common-project/gradle.properties +++ /dev/null @@ -1,16 +0,0 @@ -# Done to increase the memory available to Gradle. -org.gradle.jvmargs=-Xmx2G -org.gradle.parallel=true - -# Mod properties -mod_version = 1.0.0 -maven_group = com.example -archives_name = example_mod -enabled_platforms = forge - -# Minecraft properties -minecraft_version = @MINECRAFTVERSION@ - -# Dependencies -fabric_loader_version = 0.15.11 -forge_version = @FORGEVERSION@ diff --git a/src/test/resources/projects/forge/1206-with-common-project/settings.gradle b/src/test/resources/projects/forge/1206-with-common-project/settings.gradle deleted file mode 100644 index bba4d2549..000000000 --- a/src/test/resources/projects/forge/1206-with-common-project/settings.gradle +++ /dev/null @@ -1,13 +0,0 @@ -pluginManagement { - repositories { - maven { url "https://maven.fabricmc.net/" } - maven { url "https://maven.architectury.dev/" } - maven { url "https://files.minecraftforge.net/maven/" } - gradlePluginPortal() - } -} - -rootProject.name = 'fabric-example-mod' - -include 'common' -include 'forge' From acdc6dbc20f21ca5f9e0c539a5ba5a872235f420 Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Fri, 12 Jul 2024 18:45:32 +1000 Subject: [PATCH 26/32] fix checkstyle --- .../net/fabricmc/loom/configuration/CompileConfiguration.java | 1 + .../loom/configuration/providers/forge/ForgeProvider.java | 1 + .../loom/configuration/providers/forge/ForgeRunTemplate.java | 2 ++ .../configuration/providers/forge/MinecraftPatchedProvider.java | 1 - 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java index e9adfa82b..6b527d0c1 100644 --- a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java +++ b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java @@ -269,6 +269,7 @@ private synchronized void setupMinecraft(ConfigContext configContext) throws Exc extension.setSrgMinecraftProvider(srgMinecraftProvider); srgMinecraftProvider.provide(provideContext); } + if (extension.isForgeLike() && extension.getForgeProvider().usesMojangAtRuntime()) { final MojangMappedMinecraftProvider mojangMappedMinecraftProvider = jarConfiguration.createMojangMappedMinecraftProvider(project); extension.setMojangMappedMinecraftProvider(mojangMappedMinecraftProvider); diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeProvider.java index 08868c143..23c7d49b5 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeProvider.java @@ -67,6 +67,7 @@ public boolean usesMojangAtRuntime() { public boolean usesUnionRelauncher() { return platform == ModPlatform.FORGE && version.getMajorVersion() >= Constants.Forge.MIN_UNION_RELAUNCHER_VERSION && !usesBootstrapDev(); } + public boolean usesBootstrapDev() { boolean forge50OrOver = version.getMajorVersion() >= Constants.Forge.MIN_UNION_RELAUNCHER_VERSION; boolean point0dot38 = version.getMajorVersion() >= 50 || version.getMinorVersion() >= 1 || version.getPatchVersion() >= 38; diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeRunTemplate.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeRunTemplate.java index 20b99ba64..bd85bc6b1 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeRunTemplate.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeRunTemplate.java @@ -116,10 +116,12 @@ public void applyTo(RunConfigSettings settings, ConfigValue.Resolver configValue // Add MOD_CLASSES, this is something that ForgeGradle does settings.getEnvironmentVariables().computeIfAbsent("MOD_CLASSES", $ -> { String modClasses = ConfigValue.of("{source_roots}").resolve(configValueResolver); + if (File.pathSeparatorChar == ':' && forgeProvider.usesBootstrapDev()) { // bs-dev has a bug where ';' is used instead of File.pathSeparatorChar modClasses = modClasses.replaceAll(":", ";"); } + return modClasses; }); 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 fb3a06ef4..09ca461c4 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 @@ -439,7 +439,6 @@ private void remapPatchedJar(SharedServiceManager serviceManager) throws Excepti } private void remapJar(TinyRemapper remapper, SharedServiceManager serviceManager, Path mcInput, Path mcOutput, @Nullable Path forgeJar, @Nullable Path forgeUserdevJar, boolean remapCoreMods) throws Exception { - try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(mcOutput).build()) { outputConsumer.addNonClassFiles(mcInput); if (forgeJar != null) outputConsumer.addNonClassFiles(forgeJar, NonClassCopyMode.FIX_META_INF, remapper); From 9d33f3f139fa3f2f736ae99efda7379b7efa64ac Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Fri, 12 Jul 2024 18:46:27 +1000 Subject: [PATCH 27/32] Delete ForgeSrgToMojangUtil.java --- .../loom/util/ForgeSrgToMojangUtil.java | 103 ------------------ 1 file changed, 103 deletions(-) delete mode 100644 src/main/java/dev/architectury/loom/util/ForgeSrgToMojangUtil.java diff --git a/src/main/java/dev/architectury/loom/util/ForgeSrgToMojangUtil.java b/src/main/java/dev/architectury/loom/util/ForgeSrgToMojangUtil.java deleted file mode 100644 index aafdf6a26..000000000 --- a/src/main/java/dev/architectury/loom/util/ForgeSrgToMojangUtil.java +++ /dev/null @@ -1,103 +0,0 @@ -package dev.architectury.loom.util; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.Map; - -import net.fabricmc.mappingio.tree.MappingTree; -import net.fabricmc.mappingio.tree.MemoryMappingTree; -import net.fabricmc.tinyremapper.ClassInstance; -import net.fabricmc.tinyremapper.MemberInstance; -import net.fabricmc.tinyremapper.TinyRemapper; -import net.fabricmc.tinyremapper.api.TrMember; - -// FIXME: There has to be a better way to fix the mappings -public final class ForgeSrgToMojangUtil { - private ForgeSrgToMojangUtil() { } - - @SuppressWarnings("unchecked") - public static void replaceSrgWithMojangMappings(TinyRemapper remapper, MemoryMappingTree mappings) { - if (true) return; - Map readClasses; - - try { - Field readClassesField = TinyRemapper.class.getDeclaredField("readClasses"); - readClassesField.setAccessible(true); - readClasses = (Map) readClassesField.get(remapper); - } catch (Throwable t) { - throw new RuntimeException(t); - } - - for (ClassInstance value : readClasses.values()) { - replaceSrgWithMojangMappings(value, mappings); - } - } - - @SuppressWarnings("unchecked") - public static void replaceSrgWithMojangMappings(ClassInstance value, MemoryMappingTree tree) { - int srg = tree.getNamespaceId("srg"); - int mojang = tree.getNamespaceId("mojang"); - HashMap members; - - try { - Field membersField = ClassInstance.class.getDeclaredField("members"); - membersField.setAccessible(true); - members = (HashMap) membersField.get(value); - } catch (Throwable t) { - throw new RuntimeException(t); - } - - Map copy = (Map) members.clone(); - members.clear(); - - for (Map.Entry entry : copy.entrySet()) { - TrMember.MemberType type = entry.getValue().getType(); - MemberInstance memberInstance = entry.getValue(); - String name; - - if (type == TrMember.MemberType.FIELD) { - MappingTree.FieldMapping field = tree.getField(value.getName(), memberInstance.getName(), memberInstance.getDesc(), srg); - - if (field == null) { - field = tree.getField(value.getName(), memberInstance.getName(), null, srg); - - if (field == null) { - members.put(memberInstance.getId(), memberInstance); - continue; - } - } - - name = field.getName(mojang); - } else if (type == TrMember.MemberType.METHOD) { - MappingTree.MethodMapping method = tree.getMethod(value.getName(), memberInstance.getName(), memberInstance.getDesc(), srg); - - if (method == null) { - method = tree.getMethod(value.getName(), memberInstance.getName(), null, srg); - - if (method == null) { - members.put(memberInstance.getId(), memberInstance); - continue; - } - } - - name = method.getName(mojang); - } else { - throw new AssertionError(); - } - - MemberInstance instance = of(type, value, name, memberInstance.getDesc(), memberInstance.getAccess(), memberInstance.getIndex()); - members.put(instance.getId(), instance); - } - } - - private static MemberInstance of(TrMember.MemberType type, ClassInstance cls, String name, String desc, int access, int index) { - try { - Constructor constructor = MemberInstance.class.getDeclaredConstructor(TrMember.MemberType.class, ClassInstance.class, String.class, String.class, int.class, int.class); - constructor.setAccessible(true); - return constructor.newInstance(type, cls, name, desc, access, index); - } catch (Throwable t) { - throw new RuntimeException(t); - } - } -} From 4a15c820b18629edbb993a6e8e809148b8532075 Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Sat, 13 Jul 2024 16:18:21 +1000 Subject: [PATCH 28/32] fix more issues --- .../configuration/providers/forge/ForgeProvider.java | 2 +- .../providers/forge/MinecraftPatchedProvider.java | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeProvider.java index 23c7d49b5..301b3a50d 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeProvider.java @@ -70,7 +70,7 @@ public boolean usesUnionRelauncher() { public boolean usesBootstrapDev() { boolean forge50OrOver = version.getMajorVersion() >= Constants.Forge.MIN_UNION_RELAUNCHER_VERSION; - boolean point0dot38 = version.getMajorVersion() >= 50 || version.getMinorVersion() >= 1 || version.getPatchVersion() >= 38; + boolean point0dot38 = version.getMajorVersion() >= 50 || (version.getMajorVersion() == 49 && version.getMinorVersion() >= 1 || version.getMinorVersion() == 0 && version.getPatchVersion() >= 38); return platform == ModPlatform.FORGE && forge50OrOver && point0dot38; } 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 09ca461c4..d9fd5f3db 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 @@ -154,7 +154,11 @@ private void initPatchedFiles() { minecraftIntermediateJar = forgeWorkingDir.resolve("minecraft-" + type.id + "-" + intermediateId + ".jar"); minecraftPatchedIntermediateJar = forgeWorkingDir.resolve("minecraft-" + type.id + "-" + intermediateId + "-patched.jar"); minecraftPatchedIntermediateAtJar = forgeWorkingDir.resolve("minecraft-" + type.id + "-" + intermediateId + "-at-patched.jar"); - minecraftPatchedMojangAtJar = forgeWorkingDir.resolve("minecraft-" + type.id + "-" + "mojang" + "-at-patched.jar"); + + if (getExtension().isForge() && getExtension().getForgeProvider().usesMojangAtRuntime()) { + minecraftPatchedMojangAtJar = forgeWorkingDir.resolve("minecraft-" + type.id + "-mojang-at-patched.jar"); + } + minecraftPatchedJar = forgeWorkingDir.resolve("minecraft-" + type.id + "-patched.jar"); minecraftClientExtra = forgeWorkingDir.resolve("client-extra.jar"); } @@ -166,14 +170,14 @@ private void cleanAllCache() throws IOException { } private Path[] getGlobalCaches() { - Path[] files = { + Path[] files = Stream.of( minecraftIntermediateJar, minecraftPatchedIntermediateJar, minecraftPatchedIntermediateAtJar, minecraftPatchedMojangAtJar, minecraftPatchedJar, - minecraftClientExtra, - }; + minecraftClientExtra + ).filter(Objects::nonNull).toArray(Path[]::new); return files; } From e35e30b77c035806204382b751fac5606c7a7bf4 Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Sat, 13 Jul 2024 16:48:14 +1000 Subject: [PATCH 29/32] Update MinecraftPatchedProvider.java --- .../providers/forge/MinecraftPatchedProvider.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 d9fd5f3db..3e81eedc0 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 @@ -425,7 +425,11 @@ private void remapPatchedJar(SharedServiceManager serviceManager) throws Excepti Path mcOutput = minecraftPatchedJar; Path forgeJar = getForgeJar().toPath(); Path forgeUserdevJar = getForgeUserdevJar().toPath(); - Files.deleteIfExists(mcPatchedAt); + + if (mcPatchedAt != null) { + Files.deleteIfExists(mcPatchedAt); + } + Files.deleteIfExists(mcOutput); if (getExtension().isForge() && getExtension().getForgeProvider().usesMojangAtRuntime()) { From bef3ea8d82081dc013e3726265b2a67626ae31b9 Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Sun, 14 Jul 2024 16:51:59 +1000 Subject: [PATCH 30/32] Update Constants.java --- src/main/java/net/fabricmc/loom/util/Constants.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/net/fabricmc/loom/util/Constants.java b/src/main/java/net/fabricmc/loom/util/Constants.java index 14530ddac..414d88c1d 100644 --- a/src/main/java/net/fabricmc/loom/util/Constants.java +++ b/src/main/java/net/fabricmc/loom/util/Constants.java @@ -203,6 +203,11 @@ public static final class Forge { */ public static final int MIN_USE_MOJANG_NS_VERSION = 50; + /** + * The earliest timestamp of a Minecraft version that Forge uses runtime Mojang mappings for. + */ + public static final String MOJANG_MAPPED_FORGE_TIMESTAMP = "2024-04-23T00:00:00+00:00"; + private Forge() { } } From 1563c35d99dc1c43ecc218c59f72701541a6b482 Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Thu, 18 Jul 2024 11:51:43 +1000 Subject: [PATCH 31/32] fix forge gametest hooks --- .../forge/ForgeLibrariesProvider.java | 26 +---- .../forge/MinecraftPatchedProvider.java | 23 +++++ .../srg/RemapForgeGameTestHooksVisitor.java | 94 +++++++++++++++++++ 3 files changed, 120 insertions(+), 23 deletions(-) create mode 100644 src/main/java/net/fabricmc/loom/util/srg/RemapForgeGameTestHooksVisitor.java diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeLibrariesProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeLibrariesProvider.java index 651740531..992e1820d 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeLibrariesProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeLibrariesProvider.java @@ -35,6 +35,9 @@ import dev.architectury.loom.forge.ModDirTransformerDiscovererPatch; import dev.architectury.loom.neoforge.LaunchHandlerPatcher; import dev.architectury.loom.util.ClassVisitorUtil; + +import net.fabricmc.loom.util.srg.RemapForgeGameTestHooksVisitor; + import org.gradle.api.Project; import org.gradle.api.artifacts.Dependency; import org.gradle.api.artifacts.ModuleDependency; @@ -63,7 +66,6 @@ public class ForgeLibrariesProvider { private static final String FANCYML_LOADER_GROUP = "net.neoforged.fancymodloader"; private static final String FANCYML_LOADER_NAME = "loader"; - private static final String FORGE_GAME_TEST_HOOLS_FILE = "net/minecraftforge/gametest/ForgeGameTestHooks.class"; private static final String FORGE_OBJECT_HOLDER_FILE = "net/minecraftforge/fml/common/asm/ObjectHolderDefinalize.class"; private static final String FORGE_MOD_DIR_TRANSFORMER_DISCOVERER_FILE = "net/minecraftforge/fml/loading/ModDirTransformerDiscoverer.class"; private static final String NEOFORGE_OBJECT_HOLDER_FILE = "net/neoforged/fml/common/asm/ObjectHolderDefinalize.class"; @@ -186,10 +188,6 @@ private static Object remapFmlLoader(Project project, ResolvedArtifact artifact, remapObjectHolder(project, outputJar, mappingConfiguration); } - if (Files.exists(fs.get().getPath(FORGE_GAME_TEST_HOOLS_FILE))) { - remapObjectHolder(project, outputJar, mappingConfiguration); - } - if (Files.exists(fs.getPath(FORGE_MOD_DIR_TRANSFORMER_DISCOVERER_FILE))) { ClassVisitorUtil.rewriteClassFile(fs.getPath(FORGE_MOD_DIR_TRANSFORMER_DISCOVERER_FILE), ModDirTransformerDiscovererPatch::new); } @@ -234,24 +232,6 @@ private static void remapObjectHolder(Project project, Path outputJar, MappingCo } } - private static void remapGameTestHooks(Project project, Path outputJar, MappingConfiguration mappingConfiguration) throws IOException { - try { - // Merge SRG mappings. The real SRG mapping file hasn't been created yet since the usual SRG merging - // process occurs after all Forge libraries have been provided. - // Forge libs are needed for MC, which is needed for the mappings. - final ForgeMappingsMerger.ExtraMappings extraMappings = ForgeMappingsMerger.ExtraMappings.ofMojmapTsrg(MappingConfiguration.getMojmapSrgFileIfPossible(project)); - final MemoryMappingTree mappings = ForgeMappingsMerger.mergeSrg(MappingConfiguration.getRawSrgFile(project), mappingConfiguration.tinyMappings, extraMappings, true); - - // Remap the game test hooks. - RemapObjectHolderVisitor.remapObjectHolder( - outputJar, "net.minecraftforge.gametest.ForgeGameTestHooks", mappings, - MappingsNamespace.SRG.toString(), MappingsNamespace.NAMED.toString() - ); - } catch (IOException e) { - throw new IOException("Could not remap object holders in " + outputJar, e); - } - } - private static void remapNeoForgeObjectHolder(Project project, Path outputJar, MappingConfiguration mappingConfiguration) throws IOException { try { // Merge Mojang mappings. The real Mojang mapping file hasn't been created yet since the usual Mojang merging 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 3e81eedc0..c733cd071 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 @@ -55,6 +55,12 @@ import dev.architectury.loom.forge.UserdevConfig; import dev.architectury.loom.util.MappingOption; import dev.architectury.loom.util.TempFiles; + +import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; +import net.fabricmc.loom.configuration.providers.mappings.MappingConfiguration; +import net.fabricmc.loom.util.srg.ForgeMappingsMerger; +import net.fabricmc.loom.util.srg.RemapForgeGameTestHooksVisitor; + import org.gradle.api.Project; import org.gradle.api.logging.LogLevel; import org.gradle.api.logging.Logger; @@ -100,6 +106,7 @@ public class MinecraftPatchedProvider { private static final String LOOM_PATCH_VERSION_KEY = "Loom-Patch-Version"; private static final String CURRENT_LOOM_PATCH_VERSION = "9"; private static final String NAME_MAPPING_SERVICE_PATH = "/inject/META-INF/services/cpw.mods.modlauncher.api.INameMappingService"; + private static final String FORGE_GAME_TEST_HOOKS_FILE = "net/minecraftforge/gametest/ForgeGameTestHooks.class"; private final Project project; private final Logger logger; @@ -465,9 +472,25 @@ private void remapJar(TinyRemapper remapper, SharedServiceManager serviceManager if (forgeUserdevJar != null) copyUserdevFiles(forgeUserdevJar, mcOutput); if (remapCoreMods) remapCoreMods(mcOutput, serviceManager); + if (getExtension().isForge() && getExtension().getForgeProvider().usesMojangAtRuntime()) remapGameTestHooks(mcOutput, serviceManager); applyLoomPatchVersion(mcOutput); } + private void remapGameTestHooks(Path outputJar, SharedServiceManager serviceManager) throws IOException { + try { + final MappingOption mappingOption = MappingOption.forPlatform(getExtension()); + final TinyMappingsService mappingsService = getExtension().getMappingConfiguration().getMappingsService(serviceManager, mappingOption); + final MappingTree mappings = mappingsService.getMappingTree(); + // Remap the game test hooks. + RemapForgeGameTestHooksVisitor.remapForgeGameTestHooks( + outputJar, "net.minecraftforge.gametest.ForgeGameTestHooks", mappings, + MappingsNamespace.SRG.toString(), MappingsNamespace.NAMED.toString() + ); + } catch (IOException e) { + throw new IOException("Could not remap gametest hooks in " + outputJar, e); + } + } + private void remapCoreMods(Path patchedJar, SharedServiceManager serviceManager) throws Exception { final MappingOption mappingOption = MappingOption.forPlatform(getExtension()); final TinyMappingsService mappingsService = getExtension().getMappingConfiguration().getMappingsService(serviceManager, mappingOption); diff --git a/src/main/java/net/fabricmc/loom/util/srg/RemapForgeGameTestHooksVisitor.java b/src/main/java/net/fabricmc/loom/util/srg/RemapForgeGameTestHooksVisitor.java new file mode 100644 index 000000000..84cc14cc0 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/util/srg/RemapForgeGameTestHooksVisitor.java @@ -0,0 +1,94 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2022 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.srg; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.Collection; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.MethodVisitor; + +import net.fabricmc.loom.util.Constants; +import net.fabricmc.loom.util.FileSystemUtil; +import net.fabricmc.mappingio.tree.MappingTree; + +import org.objectweb.asm.Type; + +public class RemapForgeGameTestHooksVisitor extends ClassVisitor { + private final MappingTree mappings; + private final int from; + private final int to; + + public RemapForgeGameTestHooksVisitor(int api, ClassVisitor classVisitor, MappingTree mappings, String from, String to) { + super(api, classVisitor); + this.mappings = mappings; + this.from = this.mappings.getNamespaceId(from); + this.to = this.mappings.getNamespaceId(to); + } + + public static void remapForgeGameTestHooks(Path jar, String className, MappingTree mappings, String from, String to) throws IOException { + System.out.println("Remapping Forge GameTest hooks"); + try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(jar, false)) { + Path classPath = fs.get().getPath(className.replace('.', '/') + ".class"); + + if (Files.exists(classPath)) { + ClassReader reader = new ClassReader(Files.readAllBytes(classPath)); + ClassWriter writer = new ClassWriter(0); + ClassVisitor classVisitor = new RemapForgeGameTestHooksVisitor(Constants.ASM_VERSION, writer, mappings, from, to); + reader.accept(classVisitor, 0); + Files.write(classPath, writer.toByteArray(), StandardOpenOption.TRUNCATE_EXISTING); + } + } + } + + @Override + public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { + MethodVisitor methodVisitor = super.visitMethod(access, name, descriptor, signature, exceptions); + if ("getDefaultBatch".equals(name) && "()Ljava/lang/String;".equals(descriptor) && from != MappingTree.NULL_NAMESPACE_ID && to != MappingTree.NULL_NAMESPACE_ID) { + return new MethodVisitor(api, methodVisitor) { + Type type; + @Override + public void visitLdcInsn(Object value) { + if (value instanceof Type type && type.getClassName().startsWith("net.minecraft.")) { + this.type = type; + } + if (value instanceof String str && str.startsWith("m_")) { + // This should not fail + value = mappings.getClass(type.getInternalName(), from).getMethod(str, null, from).getName(to); + } + + super.visitLdcInsn(value); + } + }; + } + + return methodVisitor; + } +} From 36777efaeaaba9acd9dd5bcabacdac0d42f84ce5 Mon Sep 17 00:00:00 2001 From: Jab125 <67534807+Jab125@users.noreply.github.com> Date: Thu, 25 Jul 2024 20:45:51 +1000 Subject: [PATCH 32/32] Revert "fix forge gametest hooks" This reverts commit 1563c35d99dc1c43ecc218c59f72701541a6b482. --- .../forge/ForgeLibrariesProvider.java | 26 ++++- .../forge/MinecraftPatchedProvider.java | 23 ----- .../srg/RemapForgeGameTestHooksVisitor.java | 94 ------------------- 3 files changed, 23 insertions(+), 120 deletions(-) delete mode 100644 src/main/java/net/fabricmc/loom/util/srg/RemapForgeGameTestHooksVisitor.java diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeLibrariesProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeLibrariesProvider.java index 992e1820d..651740531 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeLibrariesProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/ForgeLibrariesProvider.java @@ -35,9 +35,6 @@ import dev.architectury.loom.forge.ModDirTransformerDiscovererPatch; import dev.architectury.loom.neoforge.LaunchHandlerPatcher; import dev.architectury.loom.util.ClassVisitorUtil; - -import net.fabricmc.loom.util.srg.RemapForgeGameTestHooksVisitor; - import org.gradle.api.Project; import org.gradle.api.artifacts.Dependency; import org.gradle.api.artifacts.ModuleDependency; @@ -66,6 +63,7 @@ public class ForgeLibrariesProvider { private static final String FANCYML_LOADER_GROUP = "net.neoforged.fancymodloader"; private static final String FANCYML_LOADER_NAME = "loader"; + private static final String FORGE_GAME_TEST_HOOLS_FILE = "net/minecraftforge/gametest/ForgeGameTestHooks.class"; private static final String FORGE_OBJECT_HOLDER_FILE = "net/minecraftforge/fml/common/asm/ObjectHolderDefinalize.class"; private static final String FORGE_MOD_DIR_TRANSFORMER_DISCOVERER_FILE = "net/minecraftforge/fml/loading/ModDirTransformerDiscoverer.class"; private static final String NEOFORGE_OBJECT_HOLDER_FILE = "net/neoforged/fml/common/asm/ObjectHolderDefinalize.class"; @@ -188,6 +186,10 @@ private static Object remapFmlLoader(Project project, ResolvedArtifact artifact, remapObjectHolder(project, outputJar, mappingConfiguration); } + if (Files.exists(fs.get().getPath(FORGE_GAME_TEST_HOOLS_FILE))) { + remapObjectHolder(project, outputJar, mappingConfiguration); + } + if (Files.exists(fs.getPath(FORGE_MOD_DIR_TRANSFORMER_DISCOVERER_FILE))) { ClassVisitorUtil.rewriteClassFile(fs.getPath(FORGE_MOD_DIR_TRANSFORMER_DISCOVERER_FILE), ModDirTransformerDiscovererPatch::new); } @@ -232,6 +234,24 @@ private static void remapObjectHolder(Project project, Path outputJar, MappingCo } } + private static void remapGameTestHooks(Project project, Path outputJar, MappingConfiguration mappingConfiguration) throws IOException { + try { + // Merge SRG mappings. The real SRG mapping file hasn't been created yet since the usual SRG merging + // process occurs after all Forge libraries have been provided. + // Forge libs are needed for MC, which is needed for the mappings. + final ForgeMappingsMerger.ExtraMappings extraMappings = ForgeMappingsMerger.ExtraMappings.ofMojmapTsrg(MappingConfiguration.getMojmapSrgFileIfPossible(project)); + final MemoryMappingTree mappings = ForgeMappingsMerger.mergeSrg(MappingConfiguration.getRawSrgFile(project), mappingConfiguration.tinyMappings, extraMappings, true); + + // Remap the game test hooks. + RemapObjectHolderVisitor.remapObjectHolder( + outputJar, "net.minecraftforge.gametest.ForgeGameTestHooks", mappings, + MappingsNamespace.SRG.toString(), MappingsNamespace.NAMED.toString() + ); + } catch (IOException e) { + throw new IOException("Could not remap object holders in " + outputJar, e); + } + } + private static void remapNeoForgeObjectHolder(Project project, Path outputJar, MappingConfiguration mappingConfiguration) throws IOException { try { // Merge Mojang mappings. The real Mojang mapping file hasn't been created yet since the usual Mojang merging 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 c733cd071..3e81eedc0 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 @@ -55,12 +55,6 @@ import dev.architectury.loom.forge.UserdevConfig; import dev.architectury.loom.util.MappingOption; import dev.architectury.loom.util.TempFiles; - -import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; -import net.fabricmc.loom.configuration.providers.mappings.MappingConfiguration; -import net.fabricmc.loom.util.srg.ForgeMappingsMerger; -import net.fabricmc.loom.util.srg.RemapForgeGameTestHooksVisitor; - import org.gradle.api.Project; import org.gradle.api.logging.LogLevel; import org.gradle.api.logging.Logger; @@ -106,7 +100,6 @@ public class MinecraftPatchedProvider { private static final String LOOM_PATCH_VERSION_KEY = "Loom-Patch-Version"; private static final String CURRENT_LOOM_PATCH_VERSION = "9"; private static final String NAME_MAPPING_SERVICE_PATH = "/inject/META-INF/services/cpw.mods.modlauncher.api.INameMappingService"; - private static final String FORGE_GAME_TEST_HOOKS_FILE = "net/minecraftforge/gametest/ForgeGameTestHooks.class"; private final Project project; private final Logger logger; @@ -472,25 +465,9 @@ private void remapJar(TinyRemapper remapper, SharedServiceManager serviceManager if (forgeUserdevJar != null) copyUserdevFiles(forgeUserdevJar, mcOutput); if (remapCoreMods) remapCoreMods(mcOutput, serviceManager); - if (getExtension().isForge() && getExtension().getForgeProvider().usesMojangAtRuntime()) remapGameTestHooks(mcOutput, serviceManager); applyLoomPatchVersion(mcOutput); } - private void remapGameTestHooks(Path outputJar, SharedServiceManager serviceManager) throws IOException { - try { - final MappingOption mappingOption = MappingOption.forPlatform(getExtension()); - final TinyMappingsService mappingsService = getExtension().getMappingConfiguration().getMappingsService(serviceManager, mappingOption); - final MappingTree mappings = mappingsService.getMappingTree(); - // Remap the game test hooks. - RemapForgeGameTestHooksVisitor.remapForgeGameTestHooks( - outputJar, "net.minecraftforge.gametest.ForgeGameTestHooks", mappings, - MappingsNamespace.SRG.toString(), MappingsNamespace.NAMED.toString() - ); - } catch (IOException e) { - throw new IOException("Could not remap gametest hooks in " + outputJar, e); - } - } - private void remapCoreMods(Path patchedJar, SharedServiceManager serviceManager) throws Exception { final MappingOption mappingOption = MappingOption.forPlatform(getExtension()); final TinyMappingsService mappingsService = getExtension().getMappingConfiguration().getMappingsService(serviceManager, mappingOption); diff --git a/src/main/java/net/fabricmc/loom/util/srg/RemapForgeGameTestHooksVisitor.java b/src/main/java/net/fabricmc/loom/util/srg/RemapForgeGameTestHooksVisitor.java deleted file mode 100644 index 84cc14cc0..000000000 --- a/src/main/java/net/fabricmc/loom/util/srg/RemapForgeGameTestHooksVisitor.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * This file is part of fabric-loom, licensed under the MIT License (MIT). - * - * Copyright (c) 2022 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.srg; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardOpenOption; -import java.util.Collection; - -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.MethodVisitor; - -import net.fabricmc.loom.util.Constants; -import net.fabricmc.loom.util.FileSystemUtil; -import net.fabricmc.mappingio.tree.MappingTree; - -import org.objectweb.asm.Type; - -public class RemapForgeGameTestHooksVisitor extends ClassVisitor { - private final MappingTree mappings; - private final int from; - private final int to; - - public RemapForgeGameTestHooksVisitor(int api, ClassVisitor classVisitor, MappingTree mappings, String from, String to) { - super(api, classVisitor); - this.mappings = mappings; - this.from = this.mappings.getNamespaceId(from); - this.to = this.mappings.getNamespaceId(to); - } - - public static void remapForgeGameTestHooks(Path jar, String className, MappingTree mappings, String from, String to) throws IOException { - System.out.println("Remapping Forge GameTest hooks"); - try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(jar, false)) { - Path classPath = fs.get().getPath(className.replace('.', '/') + ".class"); - - if (Files.exists(classPath)) { - ClassReader reader = new ClassReader(Files.readAllBytes(classPath)); - ClassWriter writer = new ClassWriter(0); - ClassVisitor classVisitor = new RemapForgeGameTestHooksVisitor(Constants.ASM_VERSION, writer, mappings, from, to); - reader.accept(classVisitor, 0); - Files.write(classPath, writer.toByteArray(), StandardOpenOption.TRUNCATE_EXISTING); - } - } - } - - @Override - public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { - MethodVisitor methodVisitor = super.visitMethod(access, name, descriptor, signature, exceptions); - if ("getDefaultBatch".equals(name) && "()Ljava/lang/String;".equals(descriptor) && from != MappingTree.NULL_NAMESPACE_ID && to != MappingTree.NULL_NAMESPACE_ID) { - return new MethodVisitor(api, methodVisitor) { - Type type; - @Override - public void visitLdcInsn(Object value) { - if (value instanceof Type type && type.getClassName().startsWith("net.minecraft.")) { - this.type = type; - } - if (value instanceof String str && str.startsWith("m_")) { - // This should not fail - value = mappings.getClass(type.getInternalName(), from).getMethod(str, null, from).getName(to); - } - - super.visitLdcInsn(value); - } - }; - } - - return methodVisitor; - } -}