From 827698d5d18e501e92516017fe90670406ab8a3c Mon Sep 17 00:00:00 2001 From: Juuz <6596629+Juuxel@users.noreply.github.com> Date: Sun, 30 Apr 2023 01:34:06 +0300 Subject: [PATCH 1/8] FunctionLogic: Set output name to output.jar --- .../providers/forge/mcpconfig/steplogic/FunctionLogic.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/FunctionLogic.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/FunctionLogic.java index 8544a1a9..4fad74cb 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/FunctionLogic.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/FunctionLogic.java @@ -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 @@ -43,7 +43,10 @@ public final class FunctionLogic implements StepLogic { @Override public void execute(ExecutionContext context) throws IOException { - context.setOutput("output"); + // These are almost always jars, and it's expected by some tools such as ForgeFlower. + // The other tools seem to work with the name containing .jar anyway. + // Technically, FG supports an "outputExtension" config value for steps, but it's not used in practice. + context.setOutput("output.jar"); Path jar = context.download(function.getDownloadUrl()); String mainClass; From 2d6218686e4cdf39219a708b2eaabbcf4a2d6413 Mon Sep 17 00:00:00 2001 From: Juuz <6596629+Juuxel@users.noreply.github.com> Date: Sun, 30 Apr 2023 01:34:24 +0300 Subject: [PATCH 2/8] InjectLogic: Don't try to create null parent --- .../providers/forge/mcpconfig/steplogic/InjectLogic.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/InjectLogic.java b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/InjectLogic.java index ea812986..60fd852a 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/InjectLogic.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/forge/mcpconfig/steplogic/InjectLogic.java @@ -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 @@ -53,7 +53,11 @@ public final class InjectLogic implements StepLogic { Path from = iter.next(); Path relative = injectedFiles.relativize(from); Path to = fs.getPath(relative.toString().replace(relative.getFileSystem().getSeparator(), "/")); - Files.createDirectories(to.getParent()); + + if (to.getParent() != null) { + Files.createDirectories(to.getParent()); + } + Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING); } } From 5fb322a83d2e8a7b200becf616b0400034140067 Mon Sep 17 00:00:00 2001 From: Juuz <6596629+Juuxel@users.noreply.github.com> Date: Sun, 30 Apr 2023 02:41:57 +0300 Subject: [PATCH 3/8] GenerateForgePatchedSourcesTask: Apply AT and SAS before decompiling This makes the patches not get rejected, and the output actually looks like it should now. --- .../architectury/loom/forge/ForgeTools.java | 5 ++ .../forge/MinecraftPatchedProvider.java | 26 ++++++-- .../task/GenerateForgePatchedSourcesTask.java | 65 ++++++++++++++++++- 3 files changed, 86 insertions(+), 10 deletions(-) create mode 100644 src/main/java/dev/architectury/loom/forge/ForgeTools.java diff --git a/src/main/java/dev/architectury/loom/forge/ForgeTools.java b/src/main/java/dev/architectury/loom/forge/ForgeTools.java new file mode 100644 index 00000000..5a943029 --- /dev/null +++ b/src/main/java/dev/architectury/loom/forge/ForgeTools.java @@ -0,0 +1,5 @@ +package dev.architectury.loom.forge; + +public final class ForgeTools { + public static final String SIDE_STRIPPER = "net.minecraftforge:mergetool:1.1.6:fatjar"; +} 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 c892e68a..b388d8ac 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 @@ -51,7 +51,6 @@ import java.util.stream.Stream; import com.google.common.base.Preconditions; import com.google.common.base.Stopwatch; -import com.google.common.collect.ImmutableList; import de.oceanlabs.mcp.mcinjector.adaptors.ParameterAnnotationFixer; import dev.architectury.loom.util.TempFiles; import dev.architectury.tinyremapper.InputTag; @@ -360,17 +359,30 @@ public class MinecraftPatchedProvider { } private void accessTransformForge() throws IOException { - Stopwatch stopwatch = Stopwatch.createStarted(); - - logger.lifecycle(":access transforming minecraft"); - Path input = minecraftPatchedSrgJar; Path target = minecraftPatchedSrgAtJar; + accessTransform(project, input, target); + } + + public static void accessTransform(Project project, Path input, Path target) throws IOException { + Stopwatch stopwatch = Stopwatch.createStarted(); + + project.getLogger().lifecycle(":access transforming minecraft"); + + LoomGradleExtension extension = LoomGradleExtension.get(project); + List atSources = List.of( + extension.getForgeUniversalProvider().getForge().toPath(), + extension.getForgeUserdevProvider().getUserdevJar().toPath(), + ((ForgeMinecraftProvider) extension.getMinecraftProvider()) + .getPatchedProvider() + .getMinecraftPatchedSrgJar() + ); + Files.deleteIfExists(target); try (var tempFiles = new TempFiles()) { AccessTransformerJarProcessor.executeAt(project, input, target, args -> { - for (Path jar : ImmutableList.of(getForgeJar().toPath(), getExtension().getForgeUserdevProvider().getUserdevJar().toPath(), minecraftPatchedSrgJar)) { + for (Path jar : atSources) { byte[] atBytes = ZipUtils.unpackNullable(jar, Constants.Forge.ACCESS_TRANSFORMER_PATH); if (atBytes != null) { @@ -383,7 +395,7 @@ public class MinecraftPatchedProvider { }); } - logger.lifecycle(":access transformed minecraft in " + stopwatch.stop()); + project.getLogger().lifecycle(":access transformed minecraft in " + stopwatch.stop()); } private void remapPatchedJar(SharedServiceManager serviceManager) throws Exception { diff --git a/src/main/java/net/fabricmc/loom/task/GenerateForgePatchedSourcesTask.java b/src/main/java/net/fabricmc/loom/task/GenerateForgePatchedSourcesTask.java index 160aada3..d1d61951 100644 --- a/src/main/java/net/fabricmc/loom/task/GenerateForgePatchedSourcesTask.java +++ b/src/main/java/net/fabricmc/loom/task/GenerateForgePatchedSourcesTask.java @@ -27,13 +27,21 @@ package net.fabricmc.loom.task; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; import codechicken.diffpatch.cli.CliOperation; import codechicken.diffpatch.cli.PatchOperation; import codechicken.diffpatch.util.LoggingOutputStream; import codechicken.diffpatch.util.PatchMode; +import com.google.common.base.Stopwatch; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import dev.architectury.loom.forge.ForgeTools; import dev.architectury.loom.util.TempFiles; +import org.gradle.api.file.FileCollection; import org.gradle.api.file.RegularFileProperty; import org.gradle.api.logging.LogLevel; import org.gradle.api.tasks.InputFile; @@ -47,6 +55,9 @@ import net.fabricmc.loom.configuration.providers.forge.MinecraftPatchedProvider; import net.fabricmc.loom.configuration.providers.forge.mcpconfig.McpExecutor; import net.fabricmc.loom.configuration.providers.forge.mcpconfig.steplogic.ConstantLogic; import net.fabricmc.loom.configuration.sources.ForgeSourcesRemapper; +import net.fabricmc.loom.util.DependencyDownloader; +import net.fabricmc.loom.util.FileSystemUtil; +import net.fabricmc.loom.util.ForgeToolExecutor; import net.fabricmc.loom.util.SourceRemapper; import net.fabricmc.loom.util.service.ScopedSharedServiceManager; import net.fabricmc.loom.util.service.SharedServiceManager; @@ -86,8 +97,15 @@ public abstract class GenerateForgePatchedSourcesTask extends AbstractLoomTask { try (var tempFiles = new TempFiles(); var serviceManager = new ScopedSharedServiceManager()) { Path cache = tempFiles.directory("loom-decompilation"); + + // Transform game jar before decompiling + Path accessTransformed = cache.resolve("access-transformed.jar"); + MinecraftPatchedProvider.accessTransform(getProject(), getInputJar().get().getAsFile().toPath(), accessTransformed); + Path sideAnnotationStripped = cache.resolve("side-annotation-stripped.jar"); + stripSideAnnotations(accessTransformed, sideAnnotationStripped); + // Step 1: decompile and patch with MCP patches - Path rawDecompiled = decompileAndPatch(cache); + Path rawDecompiled = decompileAndPatch(cache, sideAnnotationStripped); // Step 2: patch with Forge patches getLogger().lifecycle(":applying Forge patches"); Path patched = sourcePatch(cache, rawDecompiled); @@ -98,7 +116,7 @@ public abstract class GenerateForgePatchedSourcesTask extends AbstractLoomTask { } } - private Path decompileAndPatch(Path cache) throws IOException { + private Path decompileAndPatch(Path cache, Path gameJar) throws IOException { Path mcpCache = cache.resolve("mcp"); Files.createDirectory(mcpCache); @@ -106,7 +124,7 @@ public abstract class GenerateForgePatchedSourcesTask extends AbstractLoomTask { McpExecutor mcp = patchedProvider.createMcpExecutor(mcpCache); mcp.setStepLogicProvider((name, type) -> { if (name.equals("rename")) { - return Optional.of(new ConstantLogic(() -> getInputJar().get().getAsFile().toPath())); + return Optional.of(new ConstantLogic(() -> gameJar)); } return Optional.empty(); @@ -148,4 +166,45 @@ public abstract class GenerateForgePatchedSourcesTask extends AbstractLoomTask { }); remapper.remapAll(); } + + private void stripSideAnnotations(Path input, Path output) throws IOException { + final Stopwatch stopwatch = Stopwatch.createStarted(); + getLogger().lifecycle(":stripping side annotations"); + + try (var tempFiles = new TempFiles()) { + final ForgeUserdevProvider userdevProvider = getExtension().getForgeUserdevProvider(); + final JsonArray sass = userdevProvider.getJson().getAsJsonArray("sass"); + final List sasPaths = new ArrayList<>(); + + try (FileSystemUtil.Delegate fs = FileSystemUtil.getJarFileSystem(userdevProvider.getUserdevJar(), false)) { + for (JsonElement sasPath : sass) { + try { + final Path from = fs.getPath(sasPath.getAsString()); + final Path to = tempFiles.file(null, ".sas"); + Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING); + sasPaths.add(to); + } catch (IOException e) { + throw new IOException("Could not extract SAS " + sasPath.getAsString()); + } + } + } + + final FileCollection classpath = DependencyDownloader.download(getProject(), ForgeTools.SIDE_STRIPPER, false, true); + + ForgeToolExecutor.exec(getProject(), spec -> { + spec.setClasspath(classpath); + spec.args( + "--strip", + "--input", input.toAbsolutePath().toString(), + "--output", output.toAbsolutePath().toString() + ); + + for (Path sasPath : sasPaths) { + spec.args("--data", sasPath.toAbsolutePath().toString()); + } + }); + } + + getLogger().lifecycle(":side annotations stripped in " + stopwatch.stop()); + } } From e35789b39201487c0d3e5275982a193b6d5b58a3 Mon Sep 17 00:00:00 2001 From: Juuz <6596629+Juuxel@users.noreply.github.com> Date: Sun, 30 Apr 2023 13:58:58 +0300 Subject: [PATCH 4/8] JarManifestService: Fix "Could not determine fabric loader version" log spam ...by restoring this file to exactly how it is upstream. --- .../loom/task/service/JarManifestService.java | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/main/java/net/fabricmc/loom/task/service/JarManifestService.java b/src/main/java/net/fabricmc/loom/task/service/JarManifestService.java index c6b93492..9651c2b2 100644 --- a/src/main/java/net/fabricmc/loom/task/service/JarManifestService.java +++ b/src/main/java/net/fabricmc/loom/task/service/JarManifestService.java @@ -41,6 +41,7 @@ import org.gradle.util.GradleVersion; import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradlePlugin; +import net.fabricmc.loom.configuration.InstallerData; import net.fabricmc.loom.util.Constants; public abstract class JarManifestService implements BuildService { @@ -65,7 +66,7 @@ public abstract class JarManifestService implements BuildService extension.getMinecraftProvider().minecraftVersion())); params.getTinyRemapperVersion().set(tinyRemapperVersion.orElse("unknown")); - params.getFabricLoaderVersion().set(getLoaderVersion(project).orElse("unknown")); + params.getFabricLoaderVersion().set(project.provider(() -> Optional.ofNullable(extension.getInstallerData()).map(InstallerData::version).orElse("unknown"))); params.getMixinVersion().set(getMixinVersion(project)); }); }); @@ -98,18 +99,6 @@ public abstract class JarManifestService implements BuildService getLoaderVersion(Project project) { - LoomGradleExtension extension = LoomGradleExtension.get(project); - if (extension.isForge()) return Optional.empty(); - - if (extension.getInstallerData() == null) { - project.getLogger().warn("Could not determine fabric loader version for jar manifest"); - return Optional.empty(); - } - - return Optional.of(extension.getInstallerData().version()); - } - private record MixinVersion(String group, String version) implements Serializable { } private static Provider getMixinVersion(Project project) { From 433798698294d981d19bb121b1a4cfaefe69abf9 Mon Sep 17 00:00:00 2001 From: Juuz <6596629+Juuxel@users.noreply.github.com> Date: Sun, 30 Apr 2023 00:23:00 +0300 Subject: [PATCH 5/8] ForgeToolExecutor: Use project Java toolchain if available --- .../fabricmc/loom/util/ForgeToolExecutor.java | 47 ++++++++++++++++++- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/fabricmc/loom/util/ForgeToolExecutor.java b/src/main/java/net/fabricmc/loom/util/ForgeToolExecutor.java index ef630ec3..87eccfd8 100644 --- a/src/main/java/net/fabricmc/loom/util/ForgeToolExecutor.java +++ b/src/main/java/net/fabricmc/loom/util/ForgeToolExecutor.java @@ -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,19 +24,32 @@ package net.fabricmc.loom.util; +import javax.inject.Inject; + import org.apache.commons.io.output.NullOutputStream; import org.gradle.api.Action; import org.gradle.api.Project; import org.gradle.api.logging.LogLevel; import org.gradle.api.logging.configuration.ShowStacktrace; +import org.gradle.api.plugins.JavaPluginExtension; +import org.gradle.jvm.toolchain.JavaLauncher; +import org.gradle.jvm.toolchain.JavaToolchainService; +import org.gradle.jvm.toolchain.JavaToolchainSpec; import org.gradle.process.ExecResult; import org.gradle.process.JavaExecSpec; +import org.jetbrains.annotations.Nullable; /** * Contains helpers for executing Forge's command line tools * with suppressed output streams to prevent annoying log spam. */ -public final class ForgeToolExecutor { +public abstract class ForgeToolExecutor { + @Inject + protected abstract JavaToolchainService getToolchainService(); + + @Inject + protected abstract Project getProject(); + public static boolean shouldShowVerboseStdout(Project project) { // if running with INFO or DEBUG logging return project.getGradle().getStartParameter().getLogLevel().compareTo(LogLevel.LIFECYCLE) < 0; @@ -55,6 +68,12 @@ public final class ForgeToolExecutor { * @return the execution result */ public static ExecResult exec(Project project, Action configurator) { + return project.getObjects().newInstance(ForgeToolExecutor.class) + .exec(configurator); + } + + private ExecResult exec(Action configurator) { + final Project project = getProject(); return project.javaexec(spec -> { configurator.execute(spec); @@ -69,6 +88,30 @@ public final class ForgeToolExecutor { } else { spec.setErrorOutput(NullOutputStream.NULL_OUTPUT_STREAM); } + + // Use project toolchain for executing if possible. + // Note: This feature cannot be tested using the test kit since + // - Gradle disables native services in test kit environments. + // - The only resolver plugin I could find, foojay-resolver, + // requires the services for finding the OS architecture. + final @Nullable String executable = findJavaToolchainExecutable(project); + + if (executable != null) { + spec.setExecutable(executable); + } }); } + + private @Nullable String findJavaToolchainExecutable(Project project) { + final JavaPluginExtension java = project.getExtensions().getByType(JavaPluginExtension.class); + final JavaToolchainSpec toolchain = java.getToolchain(); + + if (!toolchain.getLanguageVersion().isPresent()) { + // Toolchain not configured, we'll use the runtime Java version. + return null; + } + + final JavaLauncher launcher = getToolchainService().launcherFor(toolchain).get(); + return launcher.getExecutablePath().getAsFile().getAbsolutePath(); + } } From da08cf93309d0189f0b99e4918bb97e90275c512 Mon Sep 17 00:00:00 2001 From: Juuz <6596629+Juuxel@users.noreply.github.com> Date: Wed, 10 May 2023 18:36:03 +0300 Subject: [PATCH 6/8] AtRemapper: Work around Gradle 8.1 bug causing Files.readString(path) to call Path.toFile() Same issue and fix as in 4ff9f726e1f36e1b5de4af70f8c4877aedb5791c, just a different class. Fixes #129. --- src/main/java/net/fabricmc/loom/util/srg/AtRemapper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/fabricmc/loom/util/srg/AtRemapper.java b/src/main/java/net/fabricmc/loom/util/srg/AtRemapper.java index ea1e03cd..7ad7f55a 100644 --- a/src/main/java/net/fabricmc/loom/util/srg/AtRemapper.java +++ b/src/main/java/net/fabricmc/loom/util/srg/AtRemapper.java @@ -52,7 +52,7 @@ public final class AtRemapper { Path atPath = fs.getPath(Constants.Forge.ACCESS_TRANSFORMER_PATH); if (Files.exists(atPath)) { - String atContent = Files.readString(atPath); + String atContent = Files.readString(atPath, StandardCharsets.UTF_8); String[] lines = atContent.split("\n"); List output = new ArrayList<>(lines.length); From 479bb0ba175d3d46b46c9d6358034e4ad4f5cdc9 Mon Sep 17 00:00:00 2001 From: Juuz <6596629+Juuxel@users.noreply.github.com> Date: Mon, 12 Jun 2023 20:45:12 +0300 Subject: [PATCH 7/8] Fix architectury.common.json etc being used over fabric.mod.json (#140) Fixes #136. --- .../loom/util/fmj/FabricModJsonFactory.java | 72 ++++++++++--------- .../architectury/ModMetadataFilesTest.groovy | 58 +++++++++++++++ 2 files changed, 98 insertions(+), 32 deletions(-) diff --git a/src/main/java/net/fabricmc/loom/util/fmj/FabricModJsonFactory.java b/src/main/java/net/fabricmc/loom/util/fmj/FabricModJsonFactory.java index f0ed534c..21653eee 100644 --- a/src/main/java/net/fabricmc/loom/util/fmj/FabricModJsonFactory.java +++ b/src/main/java/net/fabricmc/loom/util/fmj/FabricModJsonFactory.java @@ -72,35 +72,28 @@ public final class FabricModJsonFactory { } public static FabricModJson createFromZip(Path zipPath) { - try { - @Nullable ModMetadataFile modMetadata = ModMetadataFiles.fromJar(zipPath); - - if (modMetadata != null) { - return new ModMetadataFabricModJson(modMetadata, new FabricModJsonSource.ZipSource(zipPath)); - } - } catch (IOException e) { - throw new UncheckedIOException("Failed to read mod metadata file in zip: " + zipPath, e); - } - try { return create(ZipUtils.unpackGson(zipPath, FABRIC_MOD_JSON, JsonObject.class), new FabricModJsonSource.ZipSource(zipPath)); } catch (IOException e) { + // Try another mod metadata file if fabric.mod.json wasn't found. + try { + @Nullable ModMetadataFile modMetadata = ModMetadataFiles.fromJar(zipPath); + + if (modMetadata != null) { + return new ModMetadataFabricModJson(modMetadata, new FabricModJsonSource.ZipSource(zipPath)); + } + } catch (IOException e2) { + var unchecked = new UncheckedIOException("Failed to read mod metadata file in zip: " + zipPath, e2); + unchecked.addSuppressed(e); + throw unchecked; + } + throw new UncheckedIOException("Failed to read fabric.mod.json file in zip: " + zipPath, e); } } @Nullable public static FabricModJson createFromZipNullable(Path zipPath) { - try { - final @Nullable ModMetadataFile modMetadata = ModMetadataFiles.fromJar(zipPath); - - if (modMetadata != null) { - return new ModMetadataFabricModJson(modMetadata, new FabricModJsonSource.ZipSource(zipPath)); - } - } catch (IOException e) { - throw new UncheckedIOException("Failed to read mod metadata file in zip: " + zipPath, e); - } - JsonObject jsonObject; try { @@ -110,6 +103,17 @@ public final class FabricModJsonFactory { } if (jsonObject == null) { + // Try another mod metadata file if fabric.mod.json wasn't found. + try { + final @Nullable ModMetadataFile modMetadata = ModMetadataFiles.fromJar(zipPath); + + if (modMetadata != null) { + return new ModMetadataFabricModJson(modMetadata, new FabricModJsonSource.ZipSource(zipPath)); + } + } catch (IOException e) { + throw new UncheckedIOException("Failed to read mod metadata file in zip: " + zipPath, e); + } + return null; } @@ -121,14 +125,17 @@ public final class FabricModJsonFactory { } public static FabricModJson createFromDirectory(Path directory) throws IOException { - final @Nullable ModMetadataFile modMetadata = ModMetadataFiles.fromDirectory(directory); - - if (modMetadata != null) { - return new ModMetadataFabricModJson(modMetadata, new FabricModJsonSource.DirectorySource(directory)); - } - final Path path = directory.resolve(FABRIC_MOD_JSON); + // Try another mod metadata file if fabric.mod.json wasn't found. + if (Files.notExists(path)) { + final @Nullable ModMetadataFile modMetadata = ModMetadataFiles.fromDirectory(directory); + + if (modMetadata != null) { + return new ModMetadataFabricModJson(modMetadata, new FabricModJsonSource.DirectorySource(directory)); + } + } + try (Reader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) { return create(LoomGradlePlugin.GSON.fromJson(reader, JsonObject.class), new FabricModJsonSource.DirectorySource(directory)); } @@ -136,15 +143,16 @@ public final class FabricModJsonFactory { @Nullable public static FabricModJson createFromSourceSetsNullable(SourceSet... sourceSets) throws IOException { - final @Nullable ModMetadataFile modMetadata = ModMetadataFiles.fromSourceSets(sourceSets); - - if (modMetadata != null) { - return new ModMetadataFabricModJson(modMetadata, new FabricModJsonSource.SourceSetSource(sourceSets)); - } - final File file = SourceSetHelper.findFirstFileInResource(FABRIC_MOD_JSON, sourceSets); if (file == null) { + // Try another mod metadata file if fabric.mod.json wasn't found. + final @Nullable ModMetadataFile modMetadata = ModMetadataFiles.fromSourceSets(sourceSets); + + if (modMetadata != null) { + return new ModMetadataFabricModJson(modMetadata, new FabricModJsonSource.SourceSetSource(sourceSets)); + } + return null; } diff --git a/src/test/groovy/net/fabricmc/loom/test/unit/architectury/ModMetadataFilesTest.groovy b/src/test/groovy/net/fabricmc/loom/test/unit/architectury/ModMetadataFilesTest.groovy index 534b0c41..2efdc409 100644 --- a/src/test/groovy/net/fabricmc/loom/test/unit/architectury/ModMetadataFilesTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/unit/architectury/ModMetadataFilesTest.groovy @@ -36,6 +36,8 @@ import spock.lang.TempDir import net.fabricmc.loom.test.unit.forge.ModsTomlTest import net.fabricmc.loom.util.ZipUtils +import net.fabricmc.loom.util.fmj.FabricModJsonFactory +import net.fabricmc.loom.util.fmj.ModMetadataFabricModJson class ModMetadataFilesTest extends Specification { @TempDir @@ -115,4 +117,60 @@ class ModMetadataFilesTest extends Specification { modMetadata instanceof ErroringModMetadataFile modMetadata.fileName == 'mods.toml [erroring]' } + + def "read fabric.mod.json from directory"() { + given: + workingDir.resolve('fabric.mod.json').text = ''' + { + "schemaVersion": 1, + "id": "test", + "version": 1 + } + '''.stripIndent() + workingDir.resolve('architectury.common.json').text = '{}' + when: + def fmj = FabricModJsonFactory.createFromDirectory(workingDir) + then: + !(fmj instanceof ModMetadataFabricModJson) + fmj.id == 'test' + } + + def "read fabric.mod.json from zip"() { + given: + def jar = workingDir.resolve("my_mod.jar") + zipContents.resolve('fabric.mod.json').text = ''' + { + "schemaVersion": 1, + "id": "test", + "version": 1 + } + '''.stripIndent() + zipContents.resolve('architectury.common.json').text = '{}' + ZipUtils.pack(zipContents, jar) + when: + def fmj = FabricModJsonFactory.createFromZip(jar) + then: + !(fmj instanceof ModMetadataFabricModJson) + fmj.id == 'test' + } + + def "read fabric.mod.json from zip (nullable)"() { + given: + def jar = workingDir.resolve("my_mod.jar") + zipContents.resolve('fabric.mod.json').text = ''' + { + "schemaVersion": 1, + "id": "test", + "version": 1 + } + '''.stripIndent() + zipContents.resolve('architectury.common.json').text = '{}' + ZipUtils.pack(zipContents, jar) + when: + def fmj = FabricModJsonFactory.createFromZipNullable(jar) + then: + fmj != null + !(fmj instanceof ModMetadataFabricModJson) + fmj.id == 'test' + } } From b7f3c674f91c89da1ae2e9469f8790fd12013378 Mon Sep 17 00:00:00 2001 From: Juuz <6596629+Juuxel@users.noreply.github.com> Date: Mon, 12 Jun 2023 20:45:55 +0300 Subject: [PATCH 8/8] ModMetadataFiles: Prefer quilt.mod.json over architectury.common.json --- .../java/dev/architectury/loom/metadata/ModMetadataFiles.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/dev/architectury/loom/metadata/ModMetadataFiles.java b/src/main/java/dev/architectury/loom/metadata/ModMetadataFiles.java index ef2ebc15..9bc235c4 100644 --- a/src/main/java/dev/architectury/loom/metadata/ModMetadataFiles.java +++ b/src/main/java/dev/architectury/loom/metadata/ModMetadataFiles.java @@ -23,8 +23,8 @@ import net.fabricmc.loom.util.gradle.SourceSetHelper; public final class ModMetadataFiles { private static final Logger LOGGER = Logging.getLogger(ModMetadataFiles.class); private static final Map> SINGLE_FILE_METADATA_TYPES = ImmutableMap.>builder() - .put(ArchitecturyCommonJson.FILE_NAME, ArchitecturyCommonJson::of) .put(QuiltModJson.FILE_NAME, QuiltModJson::of) + .put(ArchitecturyCommonJson.FILE_NAME, ArchitecturyCommonJson::of) .put(ModsToml.FILE_PATH, onError(ModsToml::of, "Could not load mods.toml", () -> new ErroringModMetadataFile("mods.toml"))) .build();