diff --git a/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java b/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java index 98cf6db..0fd99c3 100644 --- a/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java +++ b/src/main/java/net/fabricmc/loom/api/LoomGradleExtensionAPI.java @@ -38,6 +38,7 @@ import net.fabricmc.loom.api.decompilers.DecompilerOptions; import net.fabricmc.loom.api.mappings.layered.spec.LayeredMappingSpecBuilder; import net.fabricmc.loom.configuration.ide.RunConfigSettings; import net.fabricmc.loom.configuration.processors.JarProcessor; +import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJarConfiguration; import net.fabricmc.loom.util.DeprecationHelper; /** @@ -138,4 +139,17 @@ public interface LoomGradleExtensionAPI { * @return the property controlling interface injection. */ Property getEnableInterfaceInjection(); + + @ApiStatus.Experimental + Property getMinecraftJarConfiguration(); + + @ApiStatus.Experimental + default void serverOnlyMinecraftJar() { + getMinecraftJarConfiguration().set(MinecraftJarConfiguration.SERVER_ONLY); + } + + @ApiStatus.Experimental + default void splitMinecraftJar() { + getMinecraftJarConfiguration().set(MinecraftJarConfiguration.SPLIT); + } } diff --git a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java index 0204278..1c62290 100644 --- a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java +++ b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java @@ -42,18 +42,13 @@ import net.fabricmc.loom.build.mixin.KaptApInvoker; import net.fabricmc.loom.build.mixin.ScalaApInvoker; import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor; import net.fabricmc.loom.configuration.accesswidener.TransitiveAccessWidenerJarProcessor; -import net.fabricmc.loom.configuration.decompile.MergedDecompileConfiguration; -import net.fabricmc.loom.configuration.decompile.SplitDecompileConfiguration; import net.fabricmc.loom.configuration.ifaceinject.InterfaceInjectionProcessor; import net.fabricmc.loom.configuration.processors.JarProcessorManager; import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; -import net.fabricmc.loom.configuration.providers.minecraft.MergedMinecraftProvider; +import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJarConfiguration; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider; -import net.fabricmc.loom.configuration.providers.minecraft.SplitMinecraftProvider; import net.fabricmc.loom.configuration.providers.minecraft.mapped.IntermediaryMinecraftProvider; -import net.fabricmc.loom.configuration.providers.minecraft.mapped.MappedMinecraftProvider; import net.fabricmc.loom.configuration.providers.minecraft.mapped.NamedMinecraftProvider; -import net.fabricmc.loom.configuration.providers.minecraft.mapped.ProcessedNamedMinecraftProvider; import net.fabricmc.loom.extension.MixinExtension; import net.fabricmc.loom.util.Constants; @@ -190,11 +185,10 @@ public final class CompileConfiguration { // This is not thread safe across projects synchronize it here just to be sure, might be possible to move this further down, but for now this will do. private static synchronized void setupMinecraft(Project project) throws Exception { final LoomGradleExtension extension = LoomGradleExtension.get(project); - - boolean split = project.getProperties().get("fabric.loom.experimental.splitMcJars") != null; + final MinecraftJarConfiguration jarConfiguration = extension.getMinecraftJarConfiguration().get(); // Provide the vanilla mc jars -- TODO share across projects. - final MinecraftProvider minecraftProvider = split ? new SplitMinecraftProvider(project) : new MergedMinecraftProvider(project); + final MinecraftProvider minecraftProvider = jarConfiguration.getMinecraftProviderFunction().apply(project); extension.setMinecraftProvider(minecraftProvider); minecraftProvider.provide(); @@ -204,26 +198,14 @@ public final class CompileConfiguration { mappingsProvider.applyToProject(project, mappingsDep); // Provide the remapped mc jars - final IntermediaryMinecraftProvider intermediaryMinecraftProvider; - NamedMinecraftProvider namedMinecraftProvider; - - if (split) { - intermediaryMinecraftProvider = new IntermediaryMinecraftProvider.SplitImpl(project, (SplitMinecraftProvider) minecraftProvider); - namedMinecraftProvider = new NamedMinecraftProvider.SplitImpl(project, (SplitMinecraftProvider) minecraftProvider); - } else { - intermediaryMinecraftProvider = new IntermediaryMinecraftProvider.MergedImpl(project, (MergedMinecraftProvider) minecraftProvider); - namedMinecraftProvider = new NamedMinecraftProvider.MergedImpl(project, (MergedMinecraftProvider) minecraftProvider); - } + final IntermediaryMinecraftProvider intermediaryMinecraftProvider = jarConfiguration.getIntermediaryMinecraftProviderBiFunction().apply(project, minecraftProvider); + NamedMinecraftProvider namedMinecraftProvider = jarConfiguration.getNamedMinecraftProviderBiFunction().apply(project, minecraftProvider); final JarProcessorManager jarProcessorManager = createJarProcessorManager(project); if (jarProcessorManager.active()) { // Wrap the named MC provider for one that will provide the processed jars - if (split) { - namedMinecraftProvider = new ProcessedNamedMinecraftProvider.SplitImpl((NamedMinecraftProvider.SplitImpl) namedMinecraftProvider, jarProcessorManager); - } else { - namedMinecraftProvider = new ProcessedNamedMinecraftProvider.MergedImpl((NamedMinecraftProvider.MergedImpl) namedMinecraftProvider, jarProcessorManager); - } + namedMinecraftProvider = jarConfiguration.getProcessedNamedMinecraftProviderBiFunction().apply(namedMinecraftProvider, jarProcessorManager); } extension.setIntermediaryMinecraftProvider(intermediaryMinecraftProvider); @@ -289,13 +271,8 @@ public final class CompileConfiguration { private static void configureDecompileTasks(Project project) { final LoomGradleExtension extension = LoomGradleExtension.get(project); - if (extension.getNamedMinecraftProvider() instanceof MappedMinecraftProvider.Merged mergedMappedMinecraftProvider) { - new MergedDecompileConfiguration(project, mergedMappedMinecraftProvider).afterEvaluation(); - } else if (extension.getNamedMinecraftProvider() instanceof MappedMinecraftProvider.Split splitMinecraftProvider) { - new SplitDecompileConfiguration(project, splitMinecraftProvider).afterEvaluation(); - } else { - throw new UnsupportedOperationException(); - } + extension.getMinecraftJarConfiguration().get().getDecompileConfigurationBiFunction() + .apply(project, extension.getNamedMinecraftProvider()).afterEvaluation(); } private static void extendsFrom(String a, String b, Project project) { diff --git a/src/main/java/net/fabricmc/loom/configuration/decompile/DecompileConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/decompile/DecompileConfiguration.java new file mode 100644 index 0000000..17718e8 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/decompile/DecompileConfiguration.java @@ -0,0 +1,59 @@ +/* + * 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.configuration.decompile; + +import java.io.File; + +import org.gradle.api.Project; +import org.gradle.api.tasks.TaskProvider; + +import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; +import net.fabricmc.loom.configuration.providers.minecraft.mapped.MappedMinecraftProvider; +import net.fabricmc.loom.task.UnpickJarTask; + +public abstract class DecompileConfiguration { + protected final Project project; + protected final T minecraftProvider; + protected final LoomGradleExtension extension; + protected final MappingsProviderImpl mappingsProvider; + + public DecompileConfiguration(Project project, T minecraftProvider) { + this.project = project; + this.minecraftProvider = minecraftProvider; + this.extension = LoomGradleExtension.get(project); + this.mappingsProvider = extension.getMappingsProvider(); + } + + public abstract void afterEvaluation(); + + protected final TaskProvider createUnpickJarTask(String name, File inputJar, File outputJar) { + return project.getTasks().register(name, UnpickJarTask.class, unpickJarTask -> { + unpickJarTask.getUnpickDefinitions().set(mappingsProvider.getUnpickDefinitionsFile()); + unpickJarTask.getInputJar().set(inputJar); + unpickJarTask.getOutputJar().set(outputJar); + }); + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/decompile/MergedDecompileConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/decompile/SingleJarDecompileConfiguration.java similarity index 70% rename from src/main/java/net/fabricmc/loom/configuration/decompile/MergedDecompileConfiguration.java rename to src/main/java/net/fabricmc/loom/configuration/decompile/SingleJarDecompileConfiguration.java index a0b0793..ccaf627 100644 --- a/src/main/java/net/fabricmc/loom/configuration/decompile/MergedDecompileConfiguration.java +++ b/src/main/java/net/fabricmc/loom/configuration/decompile/SingleJarDecompileConfiguration.java @@ -1,7 +1,7 @@ /* * This file is part of fabric-loom, licensed under the MIT License (MIT). * - * Copyright (c) 2021 FabricMC + * 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 @@ -25,40 +25,33 @@ package net.fabricmc.loom.configuration.decompile; import java.io.File; +import java.nio.file.Path; +import java.util.List; import org.gradle.api.Project; import net.fabricmc.loom.LoomGradleExtension; -import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; import net.fabricmc.loom.configuration.providers.minecraft.mapped.MappedMinecraftProvider; import net.fabricmc.loom.task.GenerateSourcesTask; -import net.fabricmc.loom.task.UnpickJarTask; import net.fabricmc.loom.util.Constants; -public final class MergedDecompileConfiguration { - private final Project project; - private final MappedMinecraftProvider.Merged minecraftProvider; - private final LoomGradleExtension extension; - private final MappingsProviderImpl mappingsProvider; - - public MergedDecompileConfiguration(Project project, MappedMinecraftProvider.Merged minecraftProvider) { - this.project = project; - this.minecraftProvider = minecraftProvider; - this.extension = LoomGradleExtension.get(project); - this.mappingsProvider = extension.getMappingsProvider(); +public class SingleJarDecompileConfiguration extends DecompileConfiguration { + public SingleJarDecompileConfiguration(Project project, MappedMinecraftProvider minecraftProvider) { + super(project, minecraftProvider); } - public void afterEvaluation() { - File mappedJar = minecraftProvider.getMergedJar().toFile(); + @Override + public final void afterEvaluation() { + List minecraftJars = minecraftProvider.getMinecraftJars(); + assert minecraftJars.size() == 1; + + final File namedJar = minecraftJars.get(0).toFile(); + + File mappedJar = namedJar; if (mappingsProvider.hasUnpickDefinitions()) { File outputJar = new File(extension.getMappingsProvider().mappingsWorkingDir().toFile(), "minecraft-unpicked.jar"); - - project.getTasks().register("unpickJar", UnpickJarTask.class, unpickJarTask -> { - unpickJarTask.getUnpickDefinitions().set(mappingsProvider.getUnpickDefinitionsFile()); - unpickJarTask.getInputJar().set(minecraftProvider.getMergedJar().toFile()); - unpickJarTask.getOutputJar().set(outputJar); - }); + createUnpickJarTask("unpickJar", namedJar, outputJar); mappedJar = outputJar; } @@ -71,7 +64,7 @@ public final class MergedDecompileConfiguration { // Decompiler will be passed to the constructor of GenerateSourcesTask project.getTasks().register(taskName, GenerateSourcesTask.class, options).configure(task -> { task.getInputJar().set(inputJar); - task.getRuntimeJar().set(minecraftProvider.getMergedJar().toFile()); + task.getRuntimeJar().set(namedJar); task.dependsOn(project.getTasks().named("validateAccessWidener")); task.setDescription("Decompile minecraft using %s.".formatted(decompilerName)); diff --git a/src/main/java/net/fabricmc/loom/configuration/decompile/SplitDecompileConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/decompile/SplitDecompileConfiguration.java index 8c2dde5..60cd793 100644 --- a/src/main/java/net/fabricmc/loom/configuration/decompile/SplitDecompileConfiguration.java +++ b/src/main/java/net/fabricmc/loom/configuration/decompile/SplitDecompileConfiguration.java @@ -31,26 +31,17 @@ import org.gradle.api.Project; import org.gradle.api.Task; import org.gradle.api.tasks.TaskProvider; -import net.fabricmc.loom.LoomGradleExtension; -import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; import net.fabricmc.loom.configuration.providers.minecraft.mapped.MappedMinecraftProvider; import net.fabricmc.loom.task.GenerateSourcesTask; import net.fabricmc.loom.task.UnpickJarTask; import net.fabricmc.loom.util.Constants; -public final class SplitDecompileConfiguration { - private final Project project; - private final MappedMinecraftProvider.Split minecraftProvider; - private final LoomGradleExtension extension; - private final MappingsProviderImpl mappingsProvider; - +public final class SplitDecompileConfiguration extends DecompileConfiguration { public SplitDecompileConfiguration(Project project, MappedMinecraftProvider.Split minecraftProvider) { - this.project = project; - this.minecraftProvider = minecraftProvider; - this.extension = LoomGradleExtension.get(project); - this.mappingsProvider = extension.getMappingsProvider(); + super(project, minecraftProvider); } + @Override public void afterEvaluation() { File commonJarToDecompile = minecraftProvider.getCommonJar().toFile(); File clientOnlyJarToDecompile = minecraftProvider.getClientOnlyJar().toFile(); @@ -62,8 +53,8 @@ public final class SplitDecompileConfiguration { commonJarToDecompile = new File(extension.getMappingsProvider().mappingsWorkingDir().toFile(), "minecraft-common-unpicked.jar"); clientOnlyJarToDecompile = new File(extension.getMappingsProvider().mappingsWorkingDir().toFile(), "minecraft-clientonly-unpicked.jar"); - unpickCommonJar = createUnpickJarTask("Common", minecraftProvider.getCommonJar().toFile(), commonJarToDecompile); - unpickClientOnlyJar = createUnpickJarTask("ClientOnly", minecraftProvider.getClientOnlyJar().toFile(), clientOnlyJarToDecompile); + unpickCommonJar = createUnpickJarTask("unpickCommonJar", minecraftProvider.getCommonJar().toFile(), commonJarToDecompile); + unpickClientOnlyJar = createUnpickJarTask("unpickClientOnlyJar", minecraftProvider.getClientOnlyJar().toFile(), clientOnlyJarToDecompile); } // Need to re-declare them as final to access them from the lambada @@ -102,18 +93,10 @@ public final class SplitDecompileConfiguration { }); } - private TaskProvider createUnpickJarTask(String name, File inputJar, File outputJar) { - return project.getTasks().register("unpick%sJar".formatted(name), UnpickJarTask.class, unpickJarTask -> { - unpickJarTask.getUnpickDefinitions().set(mappingsProvider.getUnpickDefinitionsFile()); - unpickJarTask.getInputJar().set(inputJar); - unpickJarTask.getOutputJar().set(outputJar); - }); - } - private TaskProvider createDecompileTasks(String name, Action configureAction) { extension.getDecompilerOptions().forEach(options -> { final String decompilerName = options.getName().substring(0, 1).toUpperCase() + options.getName().substring(1); - final String taskName = "gen%sSourcesWith%s".formatted(decompilerName, options.getName()); + final String taskName = "gen%sSourcesWith%s".formatted(name, decompilerName); project.getTasks().register(taskName, GenerateSourcesTask.class, options).configure(task -> { configureAction.execute(task); diff --git a/src/main/java/net/fabricmc/loom/configuration/ide/idea/IdeaConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/ide/idea/IdeaConfiguration.java index ce9c0dc..0933c8e 100644 --- a/src/main/java/net/fabricmc/loom/configuration/ide/idea/IdeaConfiguration.java +++ b/src/main/java/net/fabricmc/loom/configuration/ide/idea/IdeaConfiguration.java @@ -30,10 +30,12 @@ import org.gradle.api.Project; import org.gradle.api.tasks.TaskProvider; import org.gradle.execution.taskgraph.TaskExecutionGraphInternal; +import net.fabricmc.loom.task.LoomTasks; + public class IdeaConfiguration { public static void setup(Project project) { - TaskProvider ideaSyncTask = project.getTasks().register("ideaSyncTask", IdeaSyncTask.class, ideaSyncTask1 -> { - ideaSyncTask1.dependsOn(project.getTasks().named("configureLaunch")); + TaskProvider ideaSyncTask = project.getTasks().register("ideaSyncTask", IdeaSyncTask.class, task -> { + task.dependsOn(LoomTasks.getIDELaunchConfigureTaskName(project)); }); if (!IdeaUtils.isIdeaSync()) { diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java index 6100d54..9b2b78b 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/mappings/MappingsProviderImpl.java @@ -298,7 +298,7 @@ public class MappingsProviderImpl implements MappingsProvider, SharedService { private void suggestFieldNames(MergedMinecraftProvider minecraftProvider, Path oldMappings, Path newMappings) { Command command = new CommandProposeFieldNames(); - runCommand(command, minecraftProvider.getMergedJar().getAbsolutePath(), + runCommand(command, minecraftProvider.getMergedJar().toFile().getAbsolutePath(), oldMappings.toAbsolutePath().toString(), newMappings.toAbsolutePath().toString()); } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MergedMinecraftProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MergedMinecraftProvider.java index 672e958..008cd5c 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MergedMinecraftProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MergedMinecraftProvider.java @@ -26,6 +26,7 @@ package net.fabricmc.loom.configuration.providers.minecraft; import java.io.File; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import java.util.Objects; @@ -36,7 +37,7 @@ import net.fabricmc.loom.util.HashedDownloadUtil; import net.fabricmc.stitch.merge.JarMerger; public final class MergedMinecraftProvider extends MinecraftProvider { - private File minecraftMergedJar; + private Path minecraftMergedJar; public MergedMinecraftProvider(Project project) { super(project); @@ -45,25 +46,25 @@ public final class MergedMinecraftProvider extends MinecraftProvider { @Override protected void initFiles() { super.initFiles(); - minecraftMergedJar = file("minecraft-merged.jar"); + minecraftMergedJar = path("minecraft-merged.jar"); } @Override public List getMinecraftJars() { - return List.of(minecraftMergedJar.toPath()); + return List.of(minecraftMergedJar); } @Override public void provide() throws Exception { super.provide(); - if (!minecraftMergedJar.exists() || isRefreshDeps()) { + if (!Files.exists(minecraftMergedJar) || isRefreshDeps()) { try { mergeJars(); } catch (Throwable e) { HashedDownloadUtil.delete(getMinecraftClientJar()); HashedDownloadUtil.delete(getMinecraftServerJar()); - minecraftMergedJar.delete(); + Files.deleteIfExists(minecraftMergedJar); getProject().getLogger().error("Could not merge JARs! Deleting source JARs - please re-run the command and move on.", e); throw e; @@ -83,13 +84,13 @@ public final class MergedMinecraftProvider extends MinecraftProvider { Objects.requireNonNull(jarToMerge, "Cannot merge null input jar?"); - try (JarMerger jarMerger = new JarMerger(getMinecraftClientJar(), jarToMerge, minecraftMergedJar)) { + try (JarMerger jarMerger = new JarMerger(getMinecraftClientJar(), jarToMerge, minecraftMergedJar.toFile())) { jarMerger.enableSyntheticParamsOffset(); jarMerger.merge(); } } - public File getMergedJar() { + public Path getMergedJar() { return minecraftMergedJar; } } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftJarConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftJarConfiguration.java new file mode 100644 index 0000000..df94917 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftJarConfiguration.java @@ -0,0 +1,115 @@ +/* + * 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.configuration.providers.minecraft; + +import java.util.List; +import java.util.function.BiFunction; +import java.util.function.Function; + +import org.gradle.api.Project; + +import net.fabricmc.loom.configuration.decompile.DecompileConfiguration; +import net.fabricmc.loom.configuration.decompile.SingleJarDecompileConfiguration; +import net.fabricmc.loom.configuration.decompile.SplitDecompileConfiguration; +import net.fabricmc.loom.configuration.processors.JarProcessorManager; +import net.fabricmc.loom.configuration.providers.minecraft.mapped.IntermediaryMinecraftProvider; +import net.fabricmc.loom.configuration.providers.minecraft.mapped.MappedMinecraftProvider; +import net.fabricmc.loom.configuration.providers.minecraft.mapped.NamedMinecraftProvider; +import net.fabricmc.loom.configuration.providers.minecraft.mapped.ProcessedNamedMinecraftProvider; + +public enum MinecraftJarConfiguration { + MERGED( + MergedMinecraftProvider::new, + IntermediaryMinecraftProvider.MergedImpl::new, + NamedMinecraftProvider.MergedImpl::new, + ProcessedNamedMinecraftProvider.MergedImpl::new, + SingleJarDecompileConfiguration::new, + List.of("client", "server") + ), + SERVER_ONLY( + ServerOnlyMinecraftProvider::new, + IntermediaryMinecraftProvider.ServerOnlyImpl::new, + NamedMinecraftProvider.ServerOnlyImpl::new, + ProcessedNamedMinecraftProvider.ServerOnlyImpl::new, + SingleJarDecompileConfiguration::new, + List.of("server") + ), + SPLIT( + SplitMinecraftProvider::new, + IntermediaryMinecraftProvider.SplitImpl::new, + NamedMinecraftProvider.SplitImpl::new, + ProcessedNamedMinecraftProvider.SplitImpl::new, + SplitDecompileConfiguration::new, + List.of("client", "server") + ); + + private final Function minecraftProviderFunction; + private final BiFunction> intermediaryMinecraftProviderBiFunction; + private final BiFunction> namedMinecraftProviderBiFunction; + private final BiFunction, JarProcessorManager, ProcessedNamedMinecraftProvider> processedNamedMinecraftProviderBiFunction; + private final BiFunction> decompileConfigurationBiFunction; + private final List supportedEnvironments; + + @SuppressWarnings("unchecked") // Just a bit of a generic mess :) + , Q extends MappedMinecraftProvider> MinecraftJarConfiguration( + Function minecraftProviderFunction, + BiFunction> intermediaryMinecraftProviderBiFunction, + BiFunction namedMinecraftProviderBiFunction, + BiFunction> processedNamedMinecraftProviderBiFunction, + BiFunction> decompileConfigurationBiFunction, + List supportedEnvironments + ) { + this.minecraftProviderFunction = (Function) minecraftProviderFunction; + this.intermediaryMinecraftProviderBiFunction = (BiFunction>) (Object) intermediaryMinecraftProviderBiFunction; + this.namedMinecraftProviderBiFunction = (BiFunction>) namedMinecraftProviderBiFunction; + this.processedNamedMinecraftProviderBiFunction = (BiFunction, JarProcessorManager, ProcessedNamedMinecraftProvider>) (Object) processedNamedMinecraftProviderBiFunction; + this.decompileConfigurationBiFunction = (BiFunction>) decompileConfigurationBiFunction; + this.supportedEnvironments = supportedEnvironments; + } + + public Function getMinecraftProviderFunction() { + return minecraftProviderFunction; + } + + public BiFunction> getIntermediaryMinecraftProviderBiFunction() { + return intermediaryMinecraftProviderBiFunction; + } + + public BiFunction> getNamedMinecraftProviderBiFunction() { + return namedMinecraftProviderBiFunction; + } + + public BiFunction, JarProcessorManager, ProcessedNamedMinecraftProvider> getProcessedNamedMinecraftProviderBiFunction() { + return processedNamedMinecraftProviderBiFunction; + } + + public BiFunction> getDecompileConfigurationBiFunction() { + return decompileConfigurationBiFunction; + } + + public List getSupportedEnvironments() { + return supportedEnvironments; + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftLibraryProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftLibraryProvider.java index 0169ba8..567a147 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftLibraryProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftLibraryProvider.java @@ -30,6 +30,7 @@ import java.util.regex.Pattern; import org.gradle.api.Project; import org.gradle.api.artifacts.ExternalModuleDependency; +import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.configuration.providers.BundleMetadata; import net.fabricmc.loom.util.Constants; @@ -37,8 +38,9 @@ public class MinecraftLibraryProvider { private static final Pattern NATIVES_PATTERN = Pattern.compile("^(?.*)/(.*?)/(?.*)/((?.*?)-([0-9].*?)-)(?.*).jar$"); public void provide(MinecraftProvider minecraftProvider, Project project) { - MinecraftVersionMeta versionInfo = minecraftProvider.getVersionInfo(); - BundleMetadata serverBundleMetadata = minecraftProvider.getServerBundleMetadata(); + final MinecraftJarConfiguration jarConfiguration = LoomGradleExtension.get(project).getMinecraftJarConfiguration().get(); + final MinecraftVersionMeta versionInfo = minecraftProvider.getVersionInfo(); + final BundleMetadata serverBundleMetadata = minecraftProvider.getServerBundleMetadata(); final boolean overrideLWJGL = LWJGLVersionOverride.overrideByDefault() || LWJGLVersionOverride.forceOverride(project) || Boolean.getBoolean("loom.test.lwjgloverride"); @@ -54,7 +56,7 @@ public class MinecraftLibraryProvider { if (library.isValidForOS() && !library.hasNatives() && library.artifact() != null) { if (serverBundleMetadata != null && isLibraryInBundle(serverBundleMetadata, library)) { project.getDependencies().add(Constants.Configurations.MINECRAFT_SERVER_DEPENDENCIES, library.name()); - } else { + } else if (jarConfiguration.getSupportedEnvironments().contains("client")) { // Client only library, or legacy version project.getDependencies().add(Constants.Configurations.MINECRAFT_DEPENDENCIES, library.name()); } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftProvider.java index 47024c3..39df7e2 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/MinecraftProvider.java @@ -264,6 +264,10 @@ public abstract class MinecraftProvider { return new File(workingDir(), path); } + public Path path(String path) { + return file(path).toPath(); + } + public File getMinecraftClientJar() { return minecraftClientJar; } @@ -275,7 +279,6 @@ public abstract class MinecraftProvider { } // This may be the server bundler jar on newer versions prob not what you want. - @Deprecated public File getMinecraftServerJar() { return minecraftServerJar; } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/ServerOnlyMinecraftProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/ServerOnlyMinecraftProvider.java new file mode 100644 index 0000000..a12343f --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/ServerOnlyMinecraftProvider.java @@ -0,0 +1,102 @@ +/* + * 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.configuration.providers.minecraft; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +import org.gradle.api.Project; + +import net.fabricmc.loom.configuration.providers.BundleMetadata; +import net.fabricmc.tinyremapper.NonClassCopyMode; +import net.fabricmc.tinyremapper.OutputConsumerPath; +import net.fabricmc.tinyremapper.TinyRemapper; + +public final class ServerOnlyMinecraftProvider extends MinecraftProvider { + private Path minecraftServerOnlyJar; + + public ServerOnlyMinecraftProvider(Project project) { + super(project); + } + + @Override + protected void initFiles() { + super.initFiles(); + + minecraftServerOnlyJar = path("minecraft-server-only.jar"); + } + + @Override + public List getMinecraftJars() { + return List.of(minecraftServerOnlyJar); + } + + @Override + public void provide() throws Exception { + super.provide(); + + boolean requiresRefresh = isRefreshDeps() || Files.notExists(minecraftServerOnlyJar); + + if (!requiresRefresh) { + return; + } + + BundleMetadata serverBundleMetadata = getServerBundleMetadata(); + + if (serverBundleMetadata == null) { + throw new UnsupportedOperationException("Only Minecraft versions using a bundled server jar support server only configuration, please use a merged jar setup for this version of minecraft"); + } + + extractBundledServerJar(); + final Path serverJar = getMinecraftExtractedServerJar().toPath(); + + TinyRemapper remapper = null; + + try { + remapper = TinyRemapper.newRemapper().build(); + + Files.deleteIfExists(minecraftServerOnlyJar); + + // Pass through tiny remapper to fix the meta-inf + try (OutputConsumerPath outputConsumer = new OutputConsumerPath.Builder(minecraftServerOnlyJar).build()) { + outputConsumer.addNonClassFiles(serverJar, NonClassCopyMode.FIX_META_INF, remapper); + remapper.readInputs(serverJar); + remapper.apply(outputConsumer); + } + } catch (Exception e) { + Files.deleteIfExists(minecraftServerOnlyJar); + throw new RuntimeException("Failed to process server only jar", e); + } finally { + if (remapper != null) { + remapper.finish(); + } + } + } + + public Path getMinecraftServerOnlyJar() { + return minecraftServerOnlyJar; + } +} diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/SplitMinecraftProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/SplitMinecraftProvider.java index cca2d01..319b33e 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/SplitMinecraftProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/SplitMinecraftProvider.java @@ -24,7 +24,6 @@ package net.fabricmc.loom.configuration.providers.minecraft; -import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; @@ -34,8 +33,8 @@ import org.gradle.api.Project; import net.fabricmc.loom.configuration.providers.BundleMetadata; public final class SplitMinecraftProvider extends MinecraftProvider { - private File minecraftClientOnlyJar; - private File minecraftCommonJar; + private Path minecraftClientOnlyJar; + private Path minecraftCommonJar; public SplitMinecraftProvider(Project project) { super(project); @@ -45,20 +44,20 @@ public final class SplitMinecraftProvider extends MinecraftProvider { protected void initFiles() { super.initFiles(); - minecraftClientOnlyJar = file("minecraft-client-only.jar"); - minecraftCommonJar = file("minecraft-common.jar"); + minecraftClientOnlyJar = path("minecraft-client-only.jar"); + minecraftCommonJar = path("minecraft-common.jar"); } @Override public List getMinecraftJars() { - return List.of(minecraftClientOnlyJar.toPath(), minecraftCommonJar.toPath()); + return List.of(minecraftClientOnlyJar, minecraftCommonJar); } @Override public void provide() throws Exception { super.provide(); - boolean requiresRefresh = isRefreshDeps() || !minecraftClientOnlyJar.exists() || !minecraftCommonJar.exists(); + boolean requiresRefresh = isRefreshDeps() || Files.notExists(minecraftClientOnlyJar) || Files.notExists(minecraftCommonJar); if (!requiresRefresh) { return; @@ -80,20 +79,20 @@ public final class SplitMinecraftProvider extends MinecraftProvider { jarSplitter.sharedEntry("version.json"); jarSplitter.forcedClientEntry("assets/.mcassetsroot"); - jarSplitter.split(minecraftClientOnlyJar.toPath(), minecraftCommonJar.toPath()); + jarSplitter.split(minecraftClientOnlyJar, minecraftCommonJar); } catch (Exception e) { - Files.deleteIfExists(minecraftClientOnlyJar.toPath()); - Files.deleteIfExists(minecraftCommonJar.toPath()); + Files.deleteIfExists(minecraftClientOnlyJar); + Files.deleteIfExists(minecraftCommonJar); throw new RuntimeException("Failed to split minecraft", e); } } - public File getMinecraftClientOnlyJar() { + public Path getMinecraftClientOnlyJar() { return minecraftClientOnlyJar; } - public File getMinecraftCommonJar() { + public Path getMinecraftCommonJar() { return minecraftCommonJar; } } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/IntermediaryMinecraftProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/IntermediaryMinecraftProvider.java index 773c127..11ce20b 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/IntermediaryMinecraftProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/IntermediaryMinecraftProvider.java @@ -32,11 +32,12 @@ import org.gradle.api.Project; import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.configuration.providers.minecraft.MergedMinecraftProvider; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider; +import net.fabricmc.loom.configuration.providers.minecraft.ServerOnlyMinecraftProvider; import net.fabricmc.loom.configuration.providers.minecraft.SplitMinecraftProvider; import net.fabricmc.loom.util.SidedClassVisitor; import net.fabricmc.tinyremapper.TinyRemapper; -public abstract sealed class IntermediaryMinecraftProvider extends AbstractMappedMinecraftProvider permits IntermediaryMinecraftProvider.SplitImpl, IntermediaryMinecraftProvider.MergedImpl { +public abstract sealed class IntermediaryMinecraftProvider extends AbstractMappedMinecraftProvider permits IntermediaryMinecraftProvider.MergedImpl, IntermediaryMinecraftProvider.ServerOnlyImpl, IntermediaryMinecraftProvider.SplitImpl { public IntermediaryMinecraftProvider(Project project, M minecraftProvider) { super(project, minecraftProvider); } @@ -59,7 +60,7 @@ public abstract sealed class IntermediaryMinecraftProvider getRemappedJars() { return List.of( - new RemappedJars(minecraftProvider.getMergedJar().toPath(), getMergedJar(), MappingsNamespace.OFFICIAL) + new RemappedJars(minecraftProvider.getMergedJar(), getMergedJar(), MappingsNamespace.OFFICIAL) ); } } @@ -72,8 +73,8 @@ public abstract sealed class IntermediaryMinecraftProvider getRemappedJars() { return List.of( - new RemappedJars(minecraftProvider.getMinecraftCommonJar().toPath(), getCommonJar(), MappingsNamespace.OFFICIAL), - new RemappedJars(minecraftProvider.getMinecraftClientOnlyJar().toPath(), getClientOnlyJar(), MappingsNamespace.OFFICIAL, minecraftProvider.getMinecraftCommonJar().toPath()) + new RemappedJars(minecraftProvider.getMinecraftCommonJar(), getCommonJar(), MappingsNamespace.OFFICIAL), + new RemappedJars(minecraftProvider.getMinecraftClientOnlyJar(), getClientOnlyJar(), MappingsNamespace.OFFICIAL, minecraftProvider.getMinecraftCommonJar()) ); } @@ -84,4 +85,17 @@ public abstract sealed class IntermediaryMinecraftProvider implements ServerOnly { + public ServerOnlyImpl(Project project, ServerOnlyMinecraftProvider minecraftProvider) { + super(project, minecraftProvider); + } + + @Override + public List getRemappedJars() { + return List.of( + new RemappedJars(minecraftProvider.getMinecraftServerOnlyJar(), getServerOnlyJar(), MappingsNamespace.OFFICIAL) + ); + } + } } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/MappedMinecraftProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/MappedMinecraftProvider.java index 62464d1..7bbd61b 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/MappedMinecraftProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/MappedMinecraftProvider.java @@ -64,4 +64,17 @@ public interface MappedMinecraftProvider { return List.of(getCommonJar(), getClientOnlyJar()); } } + + interface ServerOnly extends ProviderImpl { + String SERVER_ONLY = "serverOnly"; + + default Path getServerOnlyJar() { + return getJar(SERVER_ONLY); + } + + @Override + default List getMinecraftJars() { + return List.of(getServerOnlyJar()); + } + } } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/NamedMinecraftProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/NamedMinecraftProvider.java index c3a127e..a143ae6 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/NamedMinecraftProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/NamedMinecraftProvider.java @@ -33,6 +33,7 @@ import org.gradle.api.Project; import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.configuration.providers.minecraft.MergedMinecraftProvider; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider; +import net.fabricmc.loom.configuration.providers.minecraft.ServerOnlyMinecraftProvider; import net.fabricmc.loom.configuration.providers.minecraft.SplitMinecraftProvider; import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.SidedClassVisitor; @@ -61,7 +62,7 @@ public abstract class NamedMinecraftProvider extend @Override public List getRemappedJars() { return List.of( - new RemappedJars(minecraftProvider.getMergedJar().toPath(), getMergedJar(), MappingsNamespace.OFFICIAL) + new RemappedJars(minecraftProvider.getMergedJar(), getMergedJar(), MappingsNamespace.OFFICIAL) ); } @@ -79,8 +80,8 @@ public abstract class NamedMinecraftProvider extend @Override public List getRemappedJars() { return List.of( - new RemappedJars(minecraftProvider.getMinecraftCommonJar().toPath(), getCommonJar(), MappingsNamespace.OFFICIAL), - new RemappedJars(minecraftProvider.getMinecraftClientOnlyJar().toPath(), getClientOnlyJar(), MappingsNamespace.OFFICIAL, minecraftProvider.getMinecraftCommonJar().toPath()) + new RemappedJars(minecraftProvider.getMinecraftCommonJar(), getCommonJar(), MappingsNamespace.OFFICIAL), + new RemappedJars(minecraftProvider.getMinecraftClientOnlyJar(), getClientOnlyJar(), MappingsNamespace.OFFICIAL, minecraftProvider.getMinecraftCommonJar()) ); } @@ -97,4 +98,22 @@ public abstract class NamedMinecraftProvider extend consumer.accept(Constants.Configurations.MINECRAFT_NAMED, CLIENT_ONLY); } } + + public static final class ServerOnlyImpl extends NamedMinecraftProvider implements ServerOnly { + public ServerOnlyImpl(Project project, ServerOnlyMinecraftProvider minecraftProvider) { + super(project, minecraftProvider); + } + + @Override + public List getRemappedJars() { + return List.of( + new RemappedJars(minecraftProvider.getMinecraftServerOnlyJar(), getServerOnlyJar(), MappingsNamespace.OFFICIAL) + ); + } + + @Override + protected void applyDependencies(BiConsumer consumer) { + consumer.accept(Constants.Configurations.MINECRAFT_NAMED, SERVER_ONLY); + } + } } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/ProcessedNamedMinecraftProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/ProcessedNamedMinecraftProvider.java index 496b312..de22cf0 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/ProcessedNamedMinecraftProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/mapped/ProcessedNamedMinecraftProvider.java @@ -36,6 +36,7 @@ import net.fabricmc.loom.LoomGradlePlugin; import net.fabricmc.loom.configuration.processors.JarProcessorManager; import net.fabricmc.loom.configuration.providers.minecraft.MergedMinecraftProvider; import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider; +import net.fabricmc.loom.configuration.providers.minecraft.ServerOnlyMinecraftProvider; import net.fabricmc.loom.configuration.providers.minecraft.SplitMinecraftProvider; public abstract class ProcessedNamedMinecraftProvider> extends NamedMinecraftProvider { @@ -154,4 +155,15 @@ public abstract class ProcessedNamedMinecraftProvider implements ServerOnly { + public ServerOnlyImpl(NamedMinecraftProvider.ServerOnlyImpl parentMinecraftProvide, JarProcessorManager jarProcessorManager) { + super(parentMinecraftProvide, jarProcessorManager); + } + + @Override + public Path getServerOnlyJar() { + return getProcessedPath(getParentMinecraftProvider().getServerOnlyJar()); + } + } } diff --git a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java index 053614b..282f47e 100644 --- a/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java +++ b/src/main/java/net/fabricmc/loom/extension/LoomGradleExtensionApiImpl.java @@ -45,6 +45,7 @@ import net.fabricmc.loom.configuration.providers.mappings.GradleMappingContext; import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpec; import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilderImpl; import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsDependency; +import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJarConfiguration; import net.fabricmc.loom.util.DeprecationHelper; /** @@ -62,6 +63,7 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA protected final Property transitiveAccessWideners; protected final Property intermediary; protected final Property enableInterfaceInjection; + private final Property minecraftJarConfiguration; private final ModVersionParser versionParser; @@ -97,6 +99,9 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA baseName -> new RunConfigSettings(project, baseName)); this.decompilers = project.getObjects().domainObjectContainer(DecompilerOptions.class); + this.minecraftJarConfiguration = project.getObjects().property(MinecraftJarConfiguration.class).convention(MinecraftJarConfiguration.MERGED); + this.minecraftJarConfiguration.finalizeValueOnRead(); + this.accessWidener.finalizeValueOnRead(); this.getGameJarProcessors().finalizeValueOnRead(); } @@ -203,6 +208,11 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA net.fabricmc.loom.configuration.MavenPublication.excludePublication(publication); } + @Override + public Property getMinecraftJarConfiguration() { + return minecraftJarConfiguration; + } + // This is here to ensure that LoomGradleExtensionApiImpl compiles without any unimplemented methods private final class EnsureCompile extends LoomGradleExtensionApiImpl { private EnsureCompile() { diff --git a/src/main/java/net/fabricmc/loom/task/LoomTasks.java b/src/main/java/net/fabricmc/loom/task/LoomTasks.java index 30a70d0..09b3652 100644 --- a/src/main/java/net/fabricmc/loom/task/LoomTasks.java +++ b/src/main/java/net/fabricmc/loom/task/LoomTasks.java @@ -26,11 +26,14 @@ package net.fabricmc.loom.task; import com.google.common.base.Preconditions; import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.provider.Provider; import org.gradle.api.tasks.TaskContainer; import org.gradle.api.tasks.TaskProvider; import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.configuration.ide.RunConfigSettings; +import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJarConfiguration; import net.fabricmc.loom.task.launch.GenerateDLIConfigTask; import net.fabricmc.loom.task.launch.GenerateLog4jConfigTask; import net.fabricmc.loom.task.launch.GenerateRemapClasspathTask; @@ -67,8 +70,6 @@ public final class LoomTasks { }); tasks.register("configureLaunch", task -> { - task.dependsOn(tasks.named("extractNatives")); - task.dependsOn(tasks.named("downloadAssets")); task.dependsOn(tasks.named("generateDLIConfig")); task.dependsOn(tasks.named("generateLog4jConfig")); task.dependsOn(tasks.named("generateRemapClasspath")); @@ -77,6 +78,15 @@ public final class LoomTasks { task.setGroup(Constants.TaskGroup.FABRIC); }); + tasks.register("configureClientLaunch", task -> { + task.dependsOn(tasks.named("extractNatives")); + task.dependsOn(tasks.named("downloadAssets")); + task.dependsOn(tasks.named("configureLaunch")); + + task.setDescription("Setup the required files to launch the Minecraft client"); + task.setGroup(Constants.TaskGroup.FABRIC); + }); + TaskProvider validateAccessWidener = tasks.register("validateAccessWidener", ValidateAccessWidenerTask.class, t -> { t.setDescription("Validate all the rules in the access widener against the Minecraft jar"); t.setGroup("verification"); @@ -91,13 +101,13 @@ public final class LoomTasks { private static void registerIDETasks(TaskContainer tasks) { tasks.register("genIdeaWorkspace", GenIdeaProjectTask.class, t -> { t.setDescription("Generates an IntelliJ IDEA workspace from this project."); - t.dependsOn("idea", "configureLaunch"); + t.dependsOn("idea", getIDELaunchConfigureTaskName(t.getProject())); t.setGroup(Constants.TaskGroup.IDE); }); tasks.register("genEclipseRuns", GenEclipseRunsTask.class, t -> { t.setDescription("Generates Eclipse run configurations for this project."); - t.dependsOn("configureLaunch"); + t.dependsOn(getIDELaunchConfigureTaskName(t.getProject())); t.setGroup(Constants.TaskGroup.IDE); }); @@ -108,7 +118,7 @@ public final class LoomTasks { tasks.register("vscode", GenVsCodeProjectTask.class, t -> { t.setDescription("Generates VSCode launch configurations."); - t.dependsOn("configureLaunch"); + t.dependsOn(getIDELaunchConfigureTaskName(t.getProject())); t.setGroup(Constants.TaskGroup.IDE); }); } @@ -125,11 +135,25 @@ public final class LoomTasks { tasks.register(taskName, RunGameTask.class, config).configure(t -> { t.setDescription("Starts the '" + config.getConfigName() + "' run configuration"); - t.dependsOn("configureLaunch"); + t.dependsOn(config.getEnvironment().equals("client") ? "configureClientLaunch" : "configureLaunch"); }); }); - extension.getRunConfigs().create("client", RunConfigSettings::client); extension.getRunConfigs().create("server", RunConfigSettings::server); + + // Remove the client run config when server only. Done by name to not remove any possible custom run configs + project.afterEvaluate(p -> { + if (extension.getMinecraftJarConfiguration().get() == MinecraftJarConfiguration.SERVER_ONLY) { + extension.getRunConfigs().removeIf(settings -> settings.getName().equals("client")); + } + }); + } + + public static Provider getIDELaunchConfigureTaskName(Project project) { + return project.provider(() -> { + final MinecraftJarConfiguration jarConfiguration = LoomGradleExtension.get(project).getMinecraftJarConfiguration().get(); + final String name = jarConfiguration == MinecraftJarConfiguration.SERVER_ONLY ? "configureLaunch" : "configureClientLaunch"; + return project.getTasks().getByName(name); + }); } } diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/MCJarConfigTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/MCJarConfigTest.groovy new file mode 100644 index 0000000..5df77f3 --- /dev/null +++ b/src/test/groovy/net/fabricmc/loom/test/integration/MCJarConfigTest.groovy @@ -0,0 +1,88 @@ +/* + * This file is part of fabric-loom, licensed under the MIT License (MIT). + * + * Copyright (c) 2021 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 + +import net.fabricmc.loom.test.util.GradleProjectTestTrait +import spock.lang.Specification +import spock.lang.Unroll + +import static net.fabricmc.loom.test.LoomTestConstants.STANDARD_TEST_VERSIONS +import static org.gradle.testkit.runner.TaskOutcome.SUCCESS + +class MCJarConfigTest extends Specification implements GradleProjectTestTrait { + @Unroll + def "server only (gradle #version)"() { + setup: + def gradle = gradleProject(project: "minimalBase", version: version) + + gradle.buildGradle << ''' + loom { + serverOnlyMinecraftJar() + } + + dependencies { + minecraft "com.mojang:minecraft:1.18.1" + mappings "net.fabricmc:yarn:1.18.1+build.18:v2" + modImplementation "net.fabricmc:fabric-loader:0.12.12" + } + ''' + + when: + def result = gradle.run(task: "build") + + then: + result.task(":build").outcome == SUCCESS + + where: + version << STANDARD_TEST_VERSIONS + } + + @Unroll + def "split (gradle #version)"() { + setup: + def gradle = gradleProject(project: "minimalBase", version: version) + + gradle.buildGradle << ''' + loom { + splitMinecraftJar() + } + + dependencies { + minecraft "com.mojang:minecraft:1.18.1" + mappings "net.fabricmc:yarn:1.18.1+build.18:v2" + modImplementation "net.fabricmc:fabric-loader:0.12.12" + } + ''' + + when: + def result = gradle.run(task: "build") + + then: + result.task(":build").outcome == SUCCESS + + where: + version << STANDARD_TEST_VERSIONS + } +} diff --git a/src/test/groovy/net/fabricmc/loom/test/util/GradleProjectTestTrait.groovy b/src/test/groovy/net/fabricmc/loom/test/util/GradleProjectTestTrait.groovy index 489d17a..45b5cb5 100644 --- a/src/test/groovy/net/fabricmc/loom/test/util/GradleProjectTestTrait.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/util/GradleProjectTestTrait.groovy @@ -199,6 +199,10 @@ trait GradleProjectTestTrait { return new File(getProjectDir(), "build.gradle") } + File getGradleProperties() { + return new File(getProjectDir(), "gradle.properties") + } + String getOutputZipEntry(String filename, String entryName) { def file = getOutputFile(filename) def bytes = ZipUtils.unpackNullable(file.toPath(), entryName)