diff --git a/build.gradle b/build.gradle index 291fb830..279d6d44 100644 --- a/build.gradle +++ b/build.gradle @@ -186,6 +186,7 @@ dependencies { implementation libs.opencsv implementation libs.forge.diffpatch implementation libs.datafixerupper + implementation libs.at // Forge mods.toml parsing implementation libs.night.config.toml diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ba9738ba..ba1fdfe6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -28,6 +28,7 @@ opencsv = "5.4" forge-diffpatch = "2.0.7" night-config = "3.6.6" datafixerupper = "6.0.8" +at = "1.0.1" [libraries] # Loom compile libraries @@ -60,6 +61,7 @@ opencsv = { module = "com.opencsv:opencsv", version.ref = "opencsv" } forge-diffpatch = { module = "net.minecraftforge:DiffPatch", version.ref = "forge-diffpatch" } night-config-toml = { module = "com.electronwill.night-config:toml", version.ref = "night-config" } datafixerupper = { module = "com.mojang:datafixerupper", version.ref = "datafixerupper" } +at = { module = "dev.architectury:at", version.ref = "at" } [plugins] kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } diff --git a/gradle/runtime.libs.versions.toml b/gradle/runtime.libs.versions.toml index 58f32e91..b32fb2e9 100644 --- a/gradle/runtime.libs.versions.toml +++ b/gradle/runtime.libs.versions.toml @@ -18,6 +18,7 @@ access-transformers = "3.0.1" access-transformers-new = "8.0.5" unprotect = "1.2.0" asm = "9.3" +union-relauncher = "1.0.0" [libraries] # Decompilers @@ -41,3 +42,4 @@ access-transformers = { module = "net.minecraftforge:accesstransformers", versio access-transformers-new = { module = "net.minecraftforge:accesstransformers", version.ref = "access-transformers-new" } unprotect = { module = "io.github.juuxel:unprotect", version.ref = "unprotect" } asm = { module = "org.ow2.asm:asm", version.ref = "asm" } +union-relauncher = { module = "io.github.juuxel:union-relauncher", version.ref = "union-relauncher" } diff --git a/src/main/java/dev/architectury/loom/extensions/ModBuildExtensions.java b/src/main/java/dev/architectury/loom/extensions/ModBuildExtensions.java index 39f61a1f..d67755c4 100644 --- a/src/main/java/dev/architectury/loom/extensions/ModBuildExtensions.java +++ b/src/main/java/dev/architectury/loom/extensions/ModBuildExtensions.java @@ -16,9 +16,8 @@ import java.util.jar.Attributes; import java.util.jar.JarFile; import java.util.jar.Manifest; -import org.cadixdev.at.AccessTransformSet; -import org.cadixdev.at.io.AccessTransformFormats; -import org.cadixdev.lorenz.MappingSet; +import dev.architectury.at.AccessTransformSet; +import dev.architectury.at.io.AccessTransformFormats; import org.gradle.api.provider.Property; import org.gradle.api.provider.SetProperty; import org.jetbrains.annotations.Nullable; @@ -29,7 +28,6 @@ import net.fabricmc.loom.util.FileSystemUtil; import net.fabricmc.loom.util.LfWriter; import net.fabricmc.loom.util.aw2at.Aw2At; import net.fabricmc.loom.util.service.UnsafeWorkQueueHelper; -import net.fabricmc.lorenztiny.TinyMappingsReader; public final class ModBuildExtensions { public static Set readMixinConfigsFromManifest(File jarFile) { @@ -87,11 +85,7 @@ public final class ModBuildExtensions { } MappingsService service = UnsafeWorkQueueHelper.get(mappingBuildServiceUuid, MappingsService.class); - - try (TinyMappingsReader reader = new TinyMappingsReader(service.getMemoryMappingTree(), service.getFromNamespace(), service.getToNamespace())) { - MappingSet mappingSet = reader.read(); - at = at.remap(mappingSet); - } + at = at.remap(service.getMemoryMappingTree(), service.getFromNamespace(), service.getToNamespace()); try (Writer writer = new LfWriter(Files.newBufferedWriter(atPath))) { AccessTransformFormats.FML.write(writer, at); diff --git a/src/main/java/dev/architectury/loom/metadata/ArchitecturyCommonJson.java b/src/main/java/dev/architectury/loom/metadata/ArchitecturyCommonJson.java index c0e44898..238af4a4 100644 --- a/src/main/java/dev/architectury/loom/metadata/ArchitecturyCommonJson.java +++ b/src/main/java/dev/architectury/loom/metadata/ArchitecturyCommonJson.java @@ -18,6 +18,7 @@ import org.jetbrains.annotations.Nullable; import net.fabricmc.loom.LoomGradlePlugin; import net.fabricmc.loom.configuration.ifaceinject.InterfaceInjectionProcessor; +import net.fabricmc.loom.util.ModPlatform; public final class ArchitecturyCommonJson implements JsonBackedModMetadataFile, SingleIdModMetadataFile { public static final String FILE_NAME = "architectury.common.json"; @@ -68,6 +69,11 @@ public final class ArchitecturyCommonJson implements JsonBackedModMetadataFile, } } + @Override + public Set getAccessTransformers(ModPlatform platform) { + return Set.of(); + } + @Override public List getInjectedInterfaces(@Nullable String modId) { if (modId == null) { diff --git a/src/main/java/dev/architectury/loom/metadata/ErroringModMetadataFile.java b/src/main/java/dev/architectury/loom/metadata/ErroringModMetadataFile.java index 38d0b368..7e750934 100644 --- a/src/main/java/dev/architectury/loom/metadata/ErroringModMetadataFile.java +++ b/src/main/java/dev/architectury/loom/metadata/ErroringModMetadataFile.java @@ -7,6 +7,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.VisibleForTesting; import net.fabricmc.loom.configuration.ifaceinject.InterfaceInjectionProcessor; +import net.fabricmc.loom.util.ModPlatform; /** * A fallback mod metadata file that represents a non-fatal format error @@ -31,6 +32,11 @@ public final class ErroringModMetadataFile implements ModMetadataFile { return Set.of(); } + @Override + public Set getAccessTransformers(ModPlatform platform) { + return Set.of(); + } + @Override public List getInjectedInterfaces(@Nullable String modId) { return List.of(); diff --git a/src/main/java/dev/architectury/loom/metadata/ModMetadataFile.java b/src/main/java/dev/architectury/loom/metadata/ModMetadataFile.java index ded523d4..ee5444ce 100644 --- a/src/main/java/dev/architectury/loom/metadata/ModMetadataFile.java +++ b/src/main/java/dev/architectury/loom/metadata/ModMetadataFile.java @@ -6,6 +6,7 @@ import java.util.Set; import org.jetbrains.annotations.Nullable; import net.fabricmc.loom.configuration.ifaceinject.InterfaceInjectionProcessor; +import net.fabricmc.loom.util.ModPlatform; import net.fabricmc.loom.util.function.CollectionUtil; /** @@ -32,6 +33,13 @@ public interface ModMetadataFile { */ Set getAccessWideners(); + /** + * {@return the paths to the access transformer files of this mod, or an empty set if absent}. + * + * @param platform the platform to run the query on + */ + Set getAccessTransformers(ModPlatform platform); + /** * {@return the injected interface data in this mod metadata file}. * diff --git a/src/main/java/dev/architectury/loom/metadata/ModsToml.java b/src/main/java/dev/architectury/loom/metadata/ModsToml.java index 5546a853..cd698a74 100644 --- a/src/main/java/dev/architectury/loom/metadata/ModsToml.java +++ b/src/main/java/dev/architectury/loom/metadata/ModsToml.java @@ -6,6 +6,7 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; +import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -19,6 +20,7 @@ import org.jetbrains.annotations.Nullable; import net.fabricmc.loom.configuration.ifaceinject.InterfaceInjectionProcessor; import net.fabricmc.loom.util.ExceptionUtil; +import net.fabricmc.loom.util.ModPlatform; public final class ModsToml implements ModMetadataFile { public static final String FILE_PATH = "META-INF/mods.toml"; @@ -72,6 +74,26 @@ public final class ModsToml implements ModMetadataFile { return Set.of(); } + @Override + public Set getAccessTransformers(ModPlatform platform) { + if (platform == ModPlatform.NEOFORGE) { + final List ats = config.get("accessTransformers"); + + if (ats != null) { + final Set result = new HashSet<>(); + + for (Config atEntry : ats) { + final String file = atEntry.get("file"); + if (file != null) result.add(file); + } + + return result; + } + } + + return Set.of(); + } + @Override public List getInjectedInterfaces(@Nullable String modId) { return List.of(); diff --git a/src/main/java/dev/architectury/loom/metadata/QuiltModJson.java b/src/main/java/dev/architectury/loom/metadata/QuiltModJson.java index 05044f99..311831b4 100644 --- a/src/main/java/dev/architectury/loom/metadata/QuiltModJson.java +++ b/src/main/java/dev/architectury/loom/metadata/QuiltModJson.java @@ -20,6 +20,7 @@ import org.slf4j.LoggerFactory; import net.fabricmc.loom.LoomGradlePlugin; import net.fabricmc.loom.configuration.ifaceinject.InterfaceInjectionProcessor; +import net.fabricmc.loom.util.ModPlatform; import net.fabricmc.loom.util.function.CollectionUtil; public final class QuiltModJson implements JsonBackedModMetadataFile, SingleIdModMetadataFile { @@ -84,6 +85,11 @@ public final class QuiltModJson implements JsonBackedModMetadataFile, SingleIdMo } } + @Override + public Set getAccessTransformers(ModPlatform platform) { + return Set.of(); + } + @Override public List getInjectedInterfaces(@Nullable String modId) { try { diff --git a/src/main/java/dev/architectury/loom/neoforge/NeoForgeModDependencies.java b/src/main/java/dev/architectury/loom/neoforge/NeoForgeModDependencies.java new file mode 100644 index 00000000..dda85162 --- /dev/null +++ b/src/main/java/dev/architectury/loom/neoforge/NeoForgeModDependencies.java @@ -0,0 +1,43 @@ +package dev.architectury.loom.neoforge; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Set; + +import dev.architectury.at.AccessTransformSet; +import dev.architectury.at.io.AccessTransformFormats; +import dev.architectury.loom.metadata.ModMetadataFile; +import dev.architectury.loom.metadata.ModMetadataFiles; + +import net.fabricmc.loom.util.Constants; +import net.fabricmc.loom.util.FileSystemUtil; +import net.fabricmc.loom.util.ModPlatform; +import net.fabricmc.mappingio.tree.MappingTreeView; + +public final class NeoForgeModDependencies { + public static void remapAts(Path jar, MappingTreeView mappings, String from, String to) throws IOException { + final ModMetadataFile modMetadata = ModMetadataFiles.fromJar(jar); + Set atPaths = Set.of(Constants.Forge.ACCESS_TRANSFORMER_PATH); + + if (modMetadata != null) { + final Set modsTomlAts = modMetadata.getAccessTransformers(ModPlatform.NEOFORGE); + + if (!modsTomlAts.isEmpty()) { + atPaths = modsTomlAts; + } + } + + try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(jar)) { + for (String atPathStr : atPaths) { + final Path atPath = fs.getPath(atPathStr); + + if (Files.exists(atPath)) { + AccessTransformSet ats = AccessTransformFormats.FML.read(atPath); + ats = ats.remap(mappings, from, to); + AccessTransformFormats.FML.write(atPath, ats); + } + } + } + } +} diff --git a/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java b/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java index de27d66a..a856c681 100644 --- a/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java +++ b/src/main/java/net/fabricmc/loom/LoomGradlePlugin.java @@ -49,6 +49,7 @@ import net.fabricmc.loom.extension.LoomFiles; import net.fabricmc.loom.extension.LoomGradleExtensionImpl; import net.fabricmc.loom.task.LoomTasks; import net.fabricmc.loom.task.RemapTaskConfiguration; +import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.LibraryLocationLogger; public class LoomGradlePlugin implements BootstrappedPlugin { @@ -85,7 +86,11 @@ public class LoomGradlePlugin implements BootstrappedPlugin { loggedVersions.add(LOOM_VERSION); System.setProperty("loom.printed.logged", String.join(",", loggedVersions)); project.getLogger().lifecycle("Architectury Loom: " + LOOM_VERSION); - project.getLogger().lifecycle("This version of Architectury Loom is in beta! Please report any issues you encounter: https://github.com/architectury/architectury-loom/issues"); + if (Constants.PLUGIN_BETA) { + project.getLogger().lifecycle("This version of Architectury Loom is in beta! Please report any issues you encounter: https://github.com/architectury/architectury-loom/issues"); + } else if (Constants.PLUGIN_DEPRECATED) { + project.getLogger().lifecycle("You are using an outdated version of Architectury Loom! This version will not receive any support, please consider updating!"); + } } LibraryLocationLogger.logLibraryVersions(); diff --git a/src/main/java/net/fabricmc/loom/configuration/accesstransformer/AccessTransformerJarProcessor.java b/src/main/java/net/fabricmc/loom/configuration/accesstransformer/AccessTransformerJarProcessor.java index 39c0b86f..52528301 100644 --- a/src/main/java/net/fabricmc/loom/configuration/accesstransformer/AccessTransformerJarProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/accesstransformer/AccessTransformerJarProcessor.java @@ -40,9 +40,9 @@ import javax.inject.Inject; import com.google.common.hash.Hashing; import com.google.common.io.MoreFiles; +import dev.architectury.at.AccessTransformSet; +import dev.architectury.at.io.AccessTransformFormats; import dev.architectury.loom.util.TempFiles; -import org.cadixdev.at.AccessTransformSet; -import org.cadixdev.at.io.AccessTransformFormats; import org.gradle.api.Project; import org.gradle.api.file.FileCollection; import org.gradle.api.logging.Logger; @@ -61,7 +61,6 @@ import net.fabricmc.loom.util.ExceptionUtil; import net.fabricmc.loom.util.ForgeToolExecutor; import net.fabricmc.loom.util.LoomVersions; import net.fabricmc.loom.util.fmj.FabricModJson; -import net.fabricmc.lorenztiny.TinyMappingsReader; public class AccessTransformerJarProcessor implements MinecraftJarProcessor { private static final Logger LOGGER = Logging.getLogger(AccessTransformerJarProcessor.class); @@ -139,7 +138,7 @@ public class AccessTransformerJarProcessor implements MinecraftJarProcessor classTweakers = List.copyOf(fabricModJson.getClassTweakers().keySet()); if (classTweakers.isEmpty()) { diff --git a/src/main/java/net/fabricmc/loom/configuration/mods/ArtifactMetadata.java b/src/main/java/net/fabricmc/loom/configuration/mods/ArtifactMetadata.java index a96b69af..f076fbbf 100644 --- a/src/main/java/net/fabricmc/loom/configuration/mods/ArtifactMetadata.java +++ b/src/main/java/net/fabricmc/loom/configuration/mods/ArtifactMetadata.java @@ -93,6 +93,12 @@ public record ArtifactMetadata(boolean isFabricMod, RemapRequirements remapRequi if (loomVersion != null && refmapRemapType != MixinRemapType.STATIC) { validateLoomVersion(loomVersion, currentLoomVersion); } + + // Check to see if the jar was built with a newer version of loom. + // This version of loom does not support the remap type value so throw an exception. + if (mainAttributes.getValue("Fabric-Loom-Mixin-Remap-Type") != null) { + throw new IllegalStateException("This version of loom does not support the mixin remap type value. Please update to the latest version of loom."); + } } final String installerFile = platform == ModPlatform.QUILT ? QUILT_INSTALLER_PATH : INSTALLER_PATH; 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 b93eed82..31b31cfe 100644 --- a/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/mods/ModProcessor.java @@ -43,6 +43,7 @@ import java.util.regex.Pattern; import com.google.common.base.Stopwatch; import com.google.gson.JsonObject; +import dev.architectury.loom.neoforge.NeoForgeModDependencies; import dev.architectury.loom.util.MappingOption; import org.gradle.api.Project; import org.gradle.api.artifacts.Configuration; @@ -64,7 +65,7 @@ import net.fabricmc.loom.util.ZipUtils; import net.fabricmc.loom.util.kotlin.KotlinClasspathService; import net.fabricmc.loom.util.kotlin.KotlinRemapperClassloader; import net.fabricmc.loom.util.service.SharedServiceManager; -import net.fabricmc.loom.util.srg.AtRemapper; +import net.fabricmc.loom.util.srg.AtClassRemapper; import net.fabricmc.loom.util.srg.CoreModClassRemapper; import net.fabricmc.mappingio.tree.MemoryMappingTree; import net.fabricmc.tinyremapper.InputTag; @@ -285,7 +286,14 @@ public class ModProcessor { remapJarManifestEntries(output); if (extension.isForgeLike()) { - AtRemapper.remap(project, output, mappings); + if (extension.isNeoForge()) { + // NeoForge: Fully map ATs + NeoForgeModDependencies.remapAts(output, mappings, fromM, toM); + } else { + // Forge: only map class names, the rest are mapped srg -> named at runtime + AtClassRemapper.remap(project, output, mappings); + } + CoreModClassRemapper.remapJar(project, extension.getPlatform().get(), output, mappings); } 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 a3545813..81d9e916 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 @@ -32,6 +32,7 @@ import org.gradle.api.Project; import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.configuration.DependencyInfo; import net.fabricmc.loom.util.Constants; +import net.fabricmc.loom.util.LoomVersions; import net.fabricmc.loom.util.ModPlatform; public class ForgeProvider extends DependencyProvider { @@ -49,6 +50,10 @@ public class ForgeProvider extends DependencyProvider { version = new ForgeVersion(dependency.getResolvedVersion()); 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) { + addDependency(LoomVersions.UNION_RELAUNCHER.mavenNotation(), Constants.Configurations.FORGE_EXTRA); + } } public ForgeVersion getVersion() { @@ -86,6 +91,7 @@ public class ForgeProvider extends DependencyProvider { private final String combined; private final String minecraftVersion; private final String forgeVersion; + private final int majorVersion; public ForgeVersion(String combined) { this.combined = combined; @@ -93,6 +99,7 @@ public class ForgeProvider extends DependencyProvider { if (combined == null) { this.minecraftVersion = "NO_VERSION"; this.forgeVersion = "NO_VERSION"; + this.majorVersion = -1; return; } @@ -105,6 +112,21 @@ public class ForgeProvider extends DependencyProvider { this.minecraftVersion = "NO_VERSION"; this.forgeVersion = combined; } + + int dotIndex = forgeVersion.indexOf('.'); + int major; + + try { + if (dotIndex >= 0) { + major = Integer.parseInt(forgeVersion.substring(0, dotIndex)); + } else { + major = Integer.parseInt(forgeVersion); + } + } catch (NumberFormatException e) { + major = -1; + } + + this.majorVersion = major; } public String getCombined() { @@ -118,5 +140,9 @@ public class ForgeProvider extends DependencyProvider { public String getForgeVersion() { return forgeVersion; } + + public int getMajorVersion() { + return majorVersion; + } } } 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 ceb0dac2..210d33ee 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 @@ -109,5 +109,12 @@ public record ForgeRunTemplate( // Add MOD_CLASSES, this is something that ForgeGradle does settings.getEnvironmentVariables().computeIfAbsent("MOD_CLASSES", $ -> ConfigValue.of("{source_roots}").resolve(configValueResolver)); + + final ForgeProvider forgeProvider = settings.getExtension().getForgeProvider(); + + if (settings.getExtension().isForge() && forgeProvider.getVersion().getMajorVersion() >= Constants.Forge.MIN_UNION_RELAUNCHER_VERSION) { + settings.defaultMainClass(Constants.Forge.UNION_RELAUNCHER_MAIN_CLASS); + settings.property(Constants.Forge.UNION_RELAUNCHER_MAIN_CLASS_PROPERTY, main); + } } } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/McpConfigData.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/McpConfigData.java index 26afb5d3..adcd08ce 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/McpConfigData.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/McpConfigData.java @@ -35,6 +35,7 @@ import com.google.gson.JsonObject; /** * Data extracted from the MCPConfig JSON file. * + * @param version the Minecraft version - the value of the {@code version} property * @param data the value of the {@code data} property * @param mappingsPath the path to srg mappings inside the MCP zip * @param official the value of the {@code official} property @@ -42,6 +43,7 @@ import com.google.gson.JsonObject; * @param functions the MCP function definitions by name */ public record McpConfigData( + String version, JsonObject data, String mappingsPath, boolean official, @@ -49,6 +51,7 @@ public record McpConfigData( Map functions ) { public static McpConfigData fromJson(JsonObject json) { + String version = json.get("version").getAsString(); JsonObject data = json.getAsJsonObject("data"); String mappingsPath = data.get("mappings").getAsString(); boolean official = json.has("official") && json.getAsJsonPrimitive("official").getAsBoolean(); @@ -73,6 +76,6 @@ public record McpConfigData( functionsBuilder.put(key, McpConfigFunction.fromJson(functionsJson.getAsJsonObject(key))); } - return new McpConfigData(data, mappingsPath, official, stepsBuilder.build(), functionsBuilder.build()); + return new McpConfigData(version, data, mappingsPath, official, stepsBuilder.build(), functionsBuilder.build()); } } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/McpExecutor.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/McpExecutor.java index e5b93b44..ca50f3a8 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/McpExecutor.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/McpExecutor.java @@ -55,6 +55,7 @@ import org.jetbrains.annotations.Nullable; import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.configuration.providers.forge.ConfigValue; +import net.fabricmc.loom.configuration.providers.forge.ForgeProvider; import net.fabricmc.loom.configuration.providers.forge.mcpconfig.steplogic.ConstantLogic; import net.fabricmc.loom.configuration.providers.forge.mcpconfig.steplogic.DownloadManifestFileLogic; import net.fabricmc.loom.configuration.providers.forge.mcpconfig.steplogic.FunctionLogic; @@ -69,6 +70,7 @@ import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.ForgeToolExecutor; import net.fabricmc.loom.util.download.DownloadBuilder; import net.fabricmc.loom.util.function.CollectionUtil; +import net.fabricmc.loom.util.gradle.GradleUtils; public final class McpExecutor { private static final LogLevel STEP_LOG_LEVEL = LogLevel.LIFECYCLE; @@ -92,9 +94,35 @@ public final class McpExecutor { this.dependencySet.skip(step -> getStepLogic(step.name(), step.type()) instanceof NoOpLogic); this.dependencySet.setIgnoreDependenciesFilter(step -> getStepLogic(step.name(), step.type()).hasNoContext()); + checkMinecraftVersion(provider); addDefaultFiles(provider, environment); } + private void checkMinecraftVersion(McpConfigProvider provider) { + final String expected = provider.getData().version(); + final String actual = minecraftProvider.minecraftVersion(); + + if (!expected.equals(actual)) { + final LoomGradleExtension extension = LoomGradleExtension.get(project); + final ForgeProvider forgeProvider = extension.getForgeProvider(); + final String message = "%s %s is not for Minecraft %s (expected: %s)." + .formatted( + extension.getPlatform().get().displayName(), + forgeProvider.getVersion().getCombined(), + actual, + expected + ); + + if (GradleUtils.getBooleanProperty(project, Constants.Properties.ALLOW_MISMATCHED_PLATFORM_VERSION)) { + project.getLogger().warn(message); + } else { + final String fullMessage = "%s\nYou can suppress this error by adding '%s = true' to gradle.properties." + .formatted(message, Constants.Properties.ALLOW_MISMATCHED_PLATFORM_VERSION); + throw new UnsupportedOperationException(fullMessage); + } + } + } + private void addDefaultFiles(McpConfigProvider provider, String environment) { for (Map.Entry entry : provider.getData().data().entrySet()) { if (entry.getValue().isJsonPrimitive()) { diff --git a/src/main/java/net/fabricmc/loom/util/Constants.java b/src/main/java/net/fabricmc/loom/util/Constants.java index 34235666..8478ccef 100644 --- a/src/main/java/net/fabricmc/loom/util/Constants.java +++ b/src/main/java/net/fabricmc/loom/util/Constants.java @@ -28,6 +28,8 @@ import org.objectweb.asm.Opcodes; public class Constants { public static final String PLUGIN_ID = "dev.architectury.loom"; + public static final boolean PLUGIN_BETA = false; + public static final boolean PLUGIN_DEPRECATED = false; public static final String LIBRARIES_BASE = "https://libraries.minecraft.net/"; public static final String RESOURCES_BASE = "https://resources.download.minecraft.net/"; public static final String VERSION_MANIFESTS = "https://piston-meta.mojang.com/mc/game/version_manifest_v2.json"; @@ -148,6 +150,7 @@ public class Constants { public static final String DISABLE_REMAPPED_VARIANTS = "fabric.loom.disableRemappedVariants"; public static final String DISABLE_PROJECT_DEPENDENT_MODS = "fabric.loom.disableProjectDependentMods"; public static final String LIBRARY_PROCESSORS = "fabric.loom.libraryProcessors"; + public static final String ALLOW_MISMATCHED_PLATFORM_VERSION = "loom.allowMismatchedPlatformVersion"; } public static final class Manifest { @@ -175,6 +178,13 @@ public class Constants { public static final String ACCESS_TRANSFORMER_PATH = "META-INF/accesstransformer.cfg"; public static final String MIXIN_CONFIGS_MANIFEST_KEY = "MixinConfigs"; + /** + * The minimum Forge version that needs Union Relauncher to use {@code MOD_CLASSES}. + */ + public static final int MIN_UNION_RELAUNCHER_VERSION = 49; + public static final String UNION_RELAUNCHER_MAIN_CLASS = "juuxel.unionrelauncher.UnionRelauncher"; + public static final String UNION_RELAUNCHER_MAIN_CLASS_PROPERTY = "unionRelauncher.mainClass"; + private Forge() { } } diff --git a/src/main/java/net/fabricmc/loom/util/aw2at/Aw2At.java b/src/main/java/net/fabricmc/loom/util/aw2at/Aw2At.java index e18f5efd..72662d51 100644 --- a/src/main/java/net/fabricmc/loom/util/aw2at/Aw2At.java +++ b/src/main/java/net/fabricmc/loom/util/aw2at/Aw2At.java @@ -1,7 +1,7 @@ /* * This file is part of fabric-loom, licensed under the MIT License (MIT). * - * Copyright (c) 2021 FabricMC + * Copyright (c) 2021-2023 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 @@ -29,10 +29,10 @@ import java.io.File; import java.io.IOException; import java.nio.file.Path; -import org.cadixdev.at.AccessChange; -import org.cadixdev.at.AccessTransform; -import org.cadixdev.at.AccessTransformSet; -import org.cadixdev.at.ModifierChange; +import dev.architectury.at.AccessChange; +import dev.architectury.at.AccessTransform; +import dev.architectury.at.AccessTransformSet; +import dev.architectury.at.ModifierChange; import org.cadixdev.bombe.type.signature.MethodSignature; import org.gradle.api.Project; import org.gradle.api.tasks.SourceSet; diff --git a/src/main/java/net/fabricmc/loom/util/srg/AtRemapper.java b/src/main/java/net/fabricmc/loom/util/srg/AtClassRemapper.java similarity index 99% rename from src/main/java/net/fabricmc/loom/util/srg/AtRemapper.java rename to src/main/java/net/fabricmc/loom/util/srg/AtClassRemapper.java index cd3f56f0..f87c2371 100644 --- a/src/main/java/net/fabricmc/loom/util/srg/AtRemapper.java +++ b/src/main/java/net/fabricmc/loom/util/srg/AtClassRemapper.java @@ -48,7 +48,7 @@ import net.fabricmc.mappingio.tree.MappingTree; * * @author Juuz */ -public final class AtRemapper { +public final class AtClassRemapper { public static void remap(Project project, Path jar, MappingTree mappings) throws IOException { final Logger logger = project.getLogger(); final String sourceNamespace = IntermediaryNamespaces.intermediary(project); diff --git a/src/test/groovy/net/fabricmc/loom/test/unit/forge/Aw2AtTest.groovy b/src/test/groovy/net/fabricmc/loom/test/unit/forge/Aw2AtTest.groovy index 3fc25d46..62827ef5 100644 --- a/src/test/groovy/net/fabricmc/loom/test/unit/forge/Aw2AtTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/unit/forge/Aw2AtTest.groovy @@ -1,7 +1,7 @@ /* * This file is part of fabric-loom, licensed under the MIT License (MIT). * - * Copyright (c) 2022 FabricMC + * Copyright (c) 2022-2023 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 @@ -24,8 +24,8 @@ package net.fabricmc.loom.test.unit.forge -import org.cadixdev.at.AccessChange -import org.cadixdev.at.ModifierChange +import dev.architectury.at.AccessChange +import dev.architectury.at.ModifierChange import spock.lang.Specification import net.fabricmc.accesswidener.AccessWidenerReader