Add server only jar configuration option. (#574)

* Add server only option.

* Fix crash.

* Fix unpick jar task name.

* Revert test memory change

* Dont add client only libraries.

* Fixes

* Move option to the extension
dev/0.11
modmuss50 2022-01-17 22:11:08 +00:00 committed by GitHub
parent d71af0cfd7
commit e9d1f005d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 551 additions and 117 deletions

View File

@ -38,6 +38,7 @@ import net.fabricmc.loom.api.decompilers.DecompilerOptions;
import net.fabricmc.loom.api.mappings.layered.spec.LayeredMappingSpecBuilder; import net.fabricmc.loom.api.mappings.layered.spec.LayeredMappingSpecBuilder;
import net.fabricmc.loom.configuration.ide.RunConfigSettings; import net.fabricmc.loom.configuration.ide.RunConfigSettings;
import net.fabricmc.loom.configuration.processors.JarProcessor; import net.fabricmc.loom.configuration.processors.JarProcessor;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJarConfiguration;
import net.fabricmc.loom.util.DeprecationHelper; import net.fabricmc.loom.util.DeprecationHelper;
/** /**
@ -138,4 +139,17 @@ public interface LoomGradleExtensionAPI {
* @return the property controlling interface injection. * @return the property controlling interface injection.
*/ */
Property<Boolean> getEnableInterfaceInjection(); Property<Boolean> getEnableInterfaceInjection();
@ApiStatus.Experimental
Property<MinecraftJarConfiguration> getMinecraftJarConfiguration();
@ApiStatus.Experimental
default void serverOnlyMinecraftJar() {
getMinecraftJarConfiguration().set(MinecraftJarConfiguration.SERVER_ONLY);
}
@ApiStatus.Experimental
default void splitMinecraftJar() {
getMinecraftJarConfiguration().set(MinecraftJarConfiguration.SPLIT);
}
} }

View File

@ -42,18 +42,13 @@ import net.fabricmc.loom.build.mixin.KaptApInvoker;
import net.fabricmc.loom.build.mixin.ScalaApInvoker; import net.fabricmc.loom.build.mixin.ScalaApInvoker;
import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor; import net.fabricmc.loom.configuration.accesswidener.AccessWidenerJarProcessor;
import net.fabricmc.loom.configuration.accesswidener.TransitiveAccessWidenerJarProcessor; 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.ifaceinject.InterfaceInjectionProcessor;
import net.fabricmc.loom.configuration.processors.JarProcessorManager; import net.fabricmc.loom.configuration.processors.JarProcessorManager;
import net.fabricmc.loom.configuration.providers.mappings.MappingsProviderImpl; 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.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.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.NamedMinecraftProvider;
import net.fabricmc.loom.configuration.providers.minecraft.mapped.ProcessedNamedMinecraftProvider;
import net.fabricmc.loom.extension.MixinExtension; import net.fabricmc.loom.extension.MixinExtension;
import net.fabricmc.loom.util.Constants; 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. // 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 { private static synchronized void setupMinecraft(Project project) throws Exception {
final LoomGradleExtension extension = LoomGradleExtension.get(project); final LoomGradleExtension extension = LoomGradleExtension.get(project);
final MinecraftJarConfiguration jarConfiguration = extension.getMinecraftJarConfiguration().get();
boolean split = project.getProperties().get("fabric.loom.experimental.splitMcJars") != null;
// Provide the vanilla mc jars -- TODO share across projects. // 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); extension.setMinecraftProvider(minecraftProvider);
minecraftProvider.provide(); minecraftProvider.provide();
@ -204,26 +198,14 @@ public final class CompileConfiguration {
mappingsProvider.applyToProject(project, mappingsDep); mappingsProvider.applyToProject(project, mappingsDep);
// Provide the remapped mc jars // Provide the remapped mc jars
final IntermediaryMinecraftProvider<?> intermediaryMinecraftProvider; final IntermediaryMinecraftProvider<?> intermediaryMinecraftProvider = jarConfiguration.getIntermediaryMinecraftProviderBiFunction().apply(project, minecraftProvider);
NamedMinecraftProvider<?> namedMinecraftProvider; NamedMinecraftProvider<?> namedMinecraftProvider = jarConfiguration.getNamedMinecraftProviderBiFunction().apply(project, minecraftProvider);
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 JarProcessorManager jarProcessorManager = createJarProcessorManager(project); final JarProcessorManager jarProcessorManager = createJarProcessorManager(project);
if (jarProcessorManager.active()) { if (jarProcessorManager.active()) {
// Wrap the named MC provider for one that will provide the processed jars // Wrap the named MC provider for one that will provide the processed jars
if (split) { namedMinecraftProvider = jarConfiguration.getProcessedNamedMinecraftProviderBiFunction().apply(namedMinecraftProvider, jarProcessorManager);
namedMinecraftProvider = new ProcessedNamedMinecraftProvider.SplitImpl((NamedMinecraftProvider.SplitImpl) namedMinecraftProvider, jarProcessorManager);
} else {
namedMinecraftProvider = new ProcessedNamedMinecraftProvider.MergedImpl((NamedMinecraftProvider.MergedImpl) namedMinecraftProvider, jarProcessorManager);
}
} }
extension.setIntermediaryMinecraftProvider(intermediaryMinecraftProvider); extension.setIntermediaryMinecraftProvider(intermediaryMinecraftProvider);
@ -289,13 +271,8 @@ public final class CompileConfiguration {
private static void configureDecompileTasks(Project project) { private static void configureDecompileTasks(Project project) {
final LoomGradleExtension extension = LoomGradleExtension.get(project); final LoomGradleExtension extension = LoomGradleExtension.get(project);
if (extension.getNamedMinecraftProvider() instanceof MappedMinecraftProvider.Merged mergedMappedMinecraftProvider) { extension.getMinecraftJarConfiguration().get().getDecompileConfigurationBiFunction()
new MergedDecompileConfiguration(project, mergedMappedMinecraftProvider).afterEvaluation(); .apply(project, extension.getNamedMinecraftProvider()).afterEvaluation();
} else if (extension.getNamedMinecraftProvider() instanceof MappedMinecraftProvider.Split splitMinecraftProvider) {
new SplitDecompileConfiguration(project, splitMinecraftProvider).afterEvaluation();
} else {
throw new UnsupportedOperationException();
}
} }
private static void extendsFrom(String a, String b, Project project) { private static void extendsFrom(String a, String b, Project project) {

View File

@ -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<T extends MappedMinecraftProvider> {
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<UnpickJarTask> 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);
});
}
}

View File

@ -1,7 +1,7 @@
/* /*
* This file is part of fabric-loom, licensed under the MIT License (MIT). * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -25,40 +25,33 @@
package net.fabricmc.loom.configuration.decompile; package net.fabricmc.loom.configuration.decompile;
import java.io.File; import java.io.File;
import java.nio.file.Path;
import java.util.List;
import org.gradle.api.Project; import org.gradle.api.Project;
import net.fabricmc.loom.LoomGradleExtension; 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.configuration.providers.minecraft.mapped.MappedMinecraftProvider;
import net.fabricmc.loom.task.GenerateSourcesTask; import net.fabricmc.loom.task.GenerateSourcesTask;
import net.fabricmc.loom.task.UnpickJarTask;
import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.Constants;
public final class MergedDecompileConfiguration { public class SingleJarDecompileConfiguration extends DecompileConfiguration<MappedMinecraftProvider> {
private final Project project; public SingleJarDecompileConfiguration(Project project, MappedMinecraftProvider minecraftProvider) {
private final MappedMinecraftProvider.Merged minecraftProvider; super(project, 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 void afterEvaluation() { @Override
File mappedJar = minecraftProvider.getMergedJar().toFile(); public final void afterEvaluation() {
List<Path> minecraftJars = minecraftProvider.getMinecraftJars();
assert minecraftJars.size() == 1;
final File namedJar = minecraftJars.get(0).toFile();
File mappedJar = namedJar;
if (mappingsProvider.hasUnpickDefinitions()) { if (mappingsProvider.hasUnpickDefinitions()) {
File outputJar = new File(extension.getMappingsProvider().mappingsWorkingDir().toFile(), "minecraft-unpicked.jar"); File outputJar = new File(extension.getMappingsProvider().mappingsWorkingDir().toFile(), "minecraft-unpicked.jar");
createUnpickJarTask("unpickJar", namedJar, outputJar);
project.getTasks().register("unpickJar", UnpickJarTask.class, unpickJarTask -> {
unpickJarTask.getUnpickDefinitions().set(mappingsProvider.getUnpickDefinitionsFile());
unpickJarTask.getInputJar().set(minecraftProvider.getMergedJar().toFile());
unpickJarTask.getOutputJar().set(outputJar);
});
mappedJar = outputJar; mappedJar = outputJar;
} }
@ -71,7 +64,7 @@ public final class MergedDecompileConfiguration {
// Decompiler will be passed to the constructor of GenerateSourcesTask // Decompiler will be passed to the constructor of GenerateSourcesTask
project.getTasks().register(taskName, GenerateSourcesTask.class, options).configure(task -> { project.getTasks().register(taskName, GenerateSourcesTask.class, options).configure(task -> {
task.getInputJar().set(inputJar); task.getInputJar().set(inputJar);
task.getRuntimeJar().set(minecraftProvider.getMergedJar().toFile()); task.getRuntimeJar().set(namedJar);
task.dependsOn(project.getTasks().named("validateAccessWidener")); task.dependsOn(project.getTasks().named("validateAccessWidener"));
task.setDescription("Decompile minecraft using %s.".formatted(decompilerName)); task.setDescription("Decompile minecraft using %s.".formatted(decompilerName));

View File

@ -31,26 +31,17 @@ import org.gradle.api.Project;
import org.gradle.api.Task; import org.gradle.api.Task;
import org.gradle.api.tasks.TaskProvider; 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.configuration.providers.minecraft.mapped.MappedMinecraftProvider;
import net.fabricmc.loom.task.GenerateSourcesTask; import net.fabricmc.loom.task.GenerateSourcesTask;
import net.fabricmc.loom.task.UnpickJarTask; import net.fabricmc.loom.task.UnpickJarTask;
import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.Constants;
public final class SplitDecompileConfiguration { public final class SplitDecompileConfiguration extends DecompileConfiguration<MappedMinecraftProvider.Split> {
private final Project project;
private final MappedMinecraftProvider.Split minecraftProvider;
private final LoomGradleExtension extension;
private final MappingsProviderImpl mappingsProvider;
public SplitDecompileConfiguration(Project project, MappedMinecraftProvider.Split minecraftProvider) { public SplitDecompileConfiguration(Project project, MappedMinecraftProvider.Split minecraftProvider) {
this.project = project; super(project, minecraftProvider);
this.minecraftProvider = minecraftProvider;
this.extension = LoomGradleExtension.get(project);
this.mappingsProvider = extension.getMappingsProvider();
} }
@Override
public void afterEvaluation() { public void afterEvaluation() {
File commonJarToDecompile = minecraftProvider.getCommonJar().toFile(); File commonJarToDecompile = minecraftProvider.getCommonJar().toFile();
File clientOnlyJarToDecompile = minecraftProvider.getClientOnlyJar().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"); commonJarToDecompile = new File(extension.getMappingsProvider().mappingsWorkingDir().toFile(), "minecraft-common-unpicked.jar");
clientOnlyJarToDecompile = new File(extension.getMappingsProvider().mappingsWorkingDir().toFile(), "minecraft-clientonly-unpicked.jar"); clientOnlyJarToDecompile = new File(extension.getMappingsProvider().mappingsWorkingDir().toFile(), "minecraft-clientonly-unpicked.jar");
unpickCommonJar = createUnpickJarTask("Common", minecraftProvider.getCommonJar().toFile(), commonJarToDecompile); unpickCommonJar = createUnpickJarTask("unpickCommonJar", minecraftProvider.getCommonJar().toFile(), commonJarToDecompile);
unpickClientOnlyJar = createUnpickJarTask("ClientOnly", minecraftProvider.getClientOnlyJar().toFile(), clientOnlyJarToDecompile); unpickClientOnlyJar = createUnpickJarTask("unpickClientOnlyJar", minecraftProvider.getClientOnlyJar().toFile(), clientOnlyJarToDecompile);
} }
// Need to re-declare them as final to access them from the lambada // Need to re-declare them as final to access them from the lambada
@ -102,18 +93,10 @@ public final class SplitDecompileConfiguration {
}); });
} }
private TaskProvider<UnpickJarTask> 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<Task> createDecompileTasks(String name, Action<GenerateSourcesTask> configureAction) { private TaskProvider<Task> createDecompileTasks(String name, Action<GenerateSourcesTask> configureAction) {
extension.getDecompilerOptions().forEach(options -> { extension.getDecompilerOptions().forEach(options -> {
final String decompilerName = options.getName().substring(0, 1).toUpperCase() + options.getName().substring(1); 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 -> { project.getTasks().register(taskName, GenerateSourcesTask.class, options).configure(task -> {
configureAction.execute(task); configureAction.execute(task);

View File

@ -30,10 +30,12 @@ import org.gradle.api.Project;
import org.gradle.api.tasks.TaskProvider; import org.gradle.api.tasks.TaskProvider;
import org.gradle.execution.taskgraph.TaskExecutionGraphInternal; import org.gradle.execution.taskgraph.TaskExecutionGraphInternal;
import net.fabricmc.loom.task.LoomTasks;
public class IdeaConfiguration { public class IdeaConfiguration {
public static void setup(Project project) { public static void setup(Project project) {
TaskProvider<IdeaSyncTask> ideaSyncTask = project.getTasks().register("ideaSyncTask", IdeaSyncTask.class, ideaSyncTask1 -> { TaskProvider<IdeaSyncTask> ideaSyncTask = project.getTasks().register("ideaSyncTask", IdeaSyncTask.class, task -> {
ideaSyncTask1.dependsOn(project.getTasks().named("configureLaunch")); task.dependsOn(LoomTasks.getIDELaunchConfigureTaskName(project));
}); });
if (!IdeaUtils.isIdeaSync()) { if (!IdeaUtils.isIdeaSync()) {

View File

@ -298,7 +298,7 @@ public class MappingsProviderImpl implements MappingsProvider, SharedService {
private void suggestFieldNames(MergedMinecraftProvider minecraftProvider, Path oldMappings, Path newMappings) { private void suggestFieldNames(MergedMinecraftProvider minecraftProvider, Path oldMappings, Path newMappings) {
Command command = new CommandProposeFieldNames(); Command command = new CommandProposeFieldNames();
runCommand(command, minecraftProvider.getMergedJar().getAbsolutePath(), runCommand(command, minecraftProvider.getMergedJar().toFile().getAbsolutePath(),
oldMappings.toAbsolutePath().toString(), oldMappings.toAbsolutePath().toString(),
newMappings.toAbsolutePath().toString()); newMappings.toAbsolutePath().toString());
} }

View File

@ -26,6 +26,7 @@ package net.fabricmc.loom.configuration.providers.minecraft;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@ -36,7 +37,7 @@ import net.fabricmc.loom.util.HashedDownloadUtil;
import net.fabricmc.stitch.merge.JarMerger; import net.fabricmc.stitch.merge.JarMerger;
public final class MergedMinecraftProvider extends MinecraftProvider { public final class MergedMinecraftProvider extends MinecraftProvider {
private File minecraftMergedJar; private Path minecraftMergedJar;
public MergedMinecraftProvider(Project project) { public MergedMinecraftProvider(Project project) {
super(project); super(project);
@ -45,25 +46,25 @@ public final class MergedMinecraftProvider extends MinecraftProvider {
@Override @Override
protected void initFiles() { protected void initFiles() {
super.initFiles(); super.initFiles();
minecraftMergedJar = file("minecraft-merged.jar"); minecraftMergedJar = path("minecraft-merged.jar");
} }
@Override @Override
public List<Path> getMinecraftJars() { public List<Path> getMinecraftJars() {
return List.of(minecraftMergedJar.toPath()); return List.of(minecraftMergedJar);
} }
@Override @Override
public void provide() throws Exception { public void provide() throws Exception {
super.provide(); super.provide();
if (!minecraftMergedJar.exists() || isRefreshDeps()) { if (!Files.exists(minecraftMergedJar) || isRefreshDeps()) {
try { try {
mergeJars(); mergeJars();
} catch (Throwable e) { } catch (Throwable e) {
HashedDownloadUtil.delete(getMinecraftClientJar()); HashedDownloadUtil.delete(getMinecraftClientJar());
HashedDownloadUtil.delete(getMinecraftServerJar()); 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); getProject().getLogger().error("Could not merge JARs! Deleting source JARs - please re-run the command and move on.", e);
throw e; throw e;
@ -83,13 +84,13 @@ public final class MergedMinecraftProvider extends MinecraftProvider {
Objects.requireNonNull(jarToMerge, "Cannot merge null input jar?"); 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.enableSyntheticParamsOffset();
jarMerger.merge(); jarMerger.merge();
} }
} }
public File getMergedJar() { public Path getMergedJar() {
return minecraftMergedJar; return minecraftMergedJar;
} }
} }

View File

@ -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<Project, MinecraftProvider> minecraftProviderFunction;
private final BiFunction<Project, MinecraftProvider, IntermediaryMinecraftProvider<?>> intermediaryMinecraftProviderBiFunction;
private final BiFunction<Project, MinecraftProvider, NamedMinecraftProvider<?>> namedMinecraftProviderBiFunction;
private final BiFunction<NamedMinecraftProvider<?>, JarProcessorManager, ProcessedNamedMinecraftProvider<?, ?>> processedNamedMinecraftProviderBiFunction;
private final BiFunction<Project, MappedMinecraftProvider, DecompileConfiguration<?>> decompileConfigurationBiFunction;
private final List<String> supportedEnvironments;
@SuppressWarnings("unchecked") // Just a bit of a generic mess :)
<M extends MinecraftProvider, P extends NamedMinecraftProvider<M>, Q extends MappedMinecraftProvider> MinecraftJarConfiguration(
Function<Project, M> minecraftProviderFunction,
BiFunction<Project, M, IntermediaryMinecraftProvider<M>> intermediaryMinecraftProviderBiFunction,
BiFunction<Project, M, P> namedMinecraftProviderBiFunction,
BiFunction<P, JarProcessorManager, ProcessedNamedMinecraftProvider<M, P>> processedNamedMinecraftProviderBiFunction,
BiFunction<Project, Q, DecompileConfiguration<?>> decompileConfigurationBiFunction,
List<String> supportedEnvironments
) {
this.minecraftProviderFunction = (Function<Project, MinecraftProvider>) minecraftProviderFunction;
this.intermediaryMinecraftProviderBiFunction = (BiFunction<Project, MinecraftProvider, IntermediaryMinecraftProvider<?>>) (Object) intermediaryMinecraftProviderBiFunction;
this.namedMinecraftProviderBiFunction = (BiFunction<Project, MinecraftProvider, NamedMinecraftProvider<?>>) namedMinecraftProviderBiFunction;
this.processedNamedMinecraftProviderBiFunction = (BiFunction<NamedMinecraftProvider<?>, JarProcessorManager, ProcessedNamedMinecraftProvider<?, ?>>) (Object) processedNamedMinecraftProviderBiFunction;
this.decompileConfigurationBiFunction = (BiFunction<Project, MappedMinecraftProvider, DecompileConfiguration<?>>) decompileConfigurationBiFunction;
this.supportedEnvironments = supportedEnvironments;
}
public Function<Project, MinecraftProvider> getMinecraftProviderFunction() {
return minecraftProviderFunction;
}
public BiFunction<Project, MinecraftProvider, IntermediaryMinecraftProvider<?>> getIntermediaryMinecraftProviderBiFunction() {
return intermediaryMinecraftProviderBiFunction;
}
public BiFunction<Project, MinecraftProvider, NamedMinecraftProvider<?>> getNamedMinecraftProviderBiFunction() {
return namedMinecraftProviderBiFunction;
}
public BiFunction<NamedMinecraftProvider<?>, JarProcessorManager, ProcessedNamedMinecraftProvider<?, ?>> getProcessedNamedMinecraftProviderBiFunction() {
return processedNamedMinecraftProviderBiFunction;
}
public BiFunction<Project, MappedMinecraftProvider, DecompileConfiguration<?>> getDecompileConfigurationBiFunction() {
return decompileConfigurationBiFunction;
}
public List<String> getSupportedEnvironments() {
return supportedEnvironments;
}
}

View File

@ -30,6 +30,7 @@ import java.util.regex.Pattern;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.artifacts.ExternalModuleDependency; import org.gradle.api.artifacts.ExternalModuleDependency;
import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.configuration.providers.BundleMetadata; import net.fabricmc.loom.configuration.providers.BundleMetadata;
import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.Constants;
@ -37,8 +38,9 @@ public class MinecraftLibraryProvider {
private static final Pattern NATIVES_PATTERN = Pattern.compile("^(?<group>.*)/(.*?)/(?<version>.*)/((?<name>.*?)-([0-9].*?)-)(?<classifier>.*).jar$"); private static final Pattern NATIVES_PATTERN = Pattern.compile("^(?<group>.*)/(.*?)/(?<version>.*)/((?<name>.*?)-([0-9].*?)-)(?<classifier>.*).jar$");
public void provide(MinecraftProvider minecraftProvider, Project project) { public void provide(MinecraftProvider minecraftProvider, Project project) {
MinecraftVersionMeta versionInfo = minecraftProvider.getVersionInfo(); final MinecraftJarConfiguration jarConfiguration = LoomGradleExtension.get(project).getMinecraftJarConfiguration().get();
BundleMetadata serverBundleMetadata = minecraftProvider.getServerBundleMetadata(); final MinecraftVersionMeta versionInfo = minecraftProvider.getVersionInfo();
final BundleMetadata serverBundleMetadata = minecraftProvider.getServerBundleMetadata();
final boolean overrideLWJGL = LWJGLVersionOverride.overrideByDefault() || LWJGLVersionOverride.forceOverride(project) || Boolean.getBoolean("loom.test.lwjgloverride"); 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 (library.isValidForOS() && !library.hasNatives() && library.artifact() != null) {
if (serverBundleMetadata != null && isLibraryInBundle(serverBundleMetadata, library)) { if (serverBundleMetadata != null && isLibraryInBundle(serverBundleMetadata, library)) {
project.getDependencies().add(Constants.Configurations.MINECRAFT_SERVER_DEPENDENCIES, library.name()); project.getDependencies().add(Constants.Configurations.MINECRAFT_SERVER_DEPENDENCIES, library.name());
} else { } else if (jarConfiguration.getSupportedEnvironments().contains("client")) {
// Client only library, or legacy version // Client only library, or legacy version
project.getDependencies().add(Constants.Configurations.MINECRAFT_DEPENDENCIES, library.name()); project.getDependencies().add(Constants.Configurations.MINECRAFT_DEPENDENCIES, library.name());
} }

View File

@ -264,6 +264,10 @@ public abstract class MinecraftProvider {
return new File(workingDir(), path); return new File(workingDir(), path);
} }
public Path path(String path) {
return file(path).toPath();
}
public File getMinecraftClientJar() { public File getMinecraftClientJar() {
return minecraftClientJar; 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. // This may be the server bundler jar on newer versions prob not what you want.
@Deprecated
public File getMinecraftServerJar() { public File getMinecraftServerJar() {
return minecraftServerJar; return minecraftServerJar;
} }

View File

@ -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<Path> 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;
}
}

View File

@ -24,7 +24,6 @@
package net.fabricmc.loom.configuration.providers.minecraft; package net.fabricmc.loom.configuration.providers.minecraft;
import java.io.File;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.List; import java.util.List;
@ -34,8 +33,8 @@ import org.gradle.api.Project;
import net.fabricmc.loom.configuration.providers.BundleMetadata; import net.fabricmc.loom.configuration.providers.BundleMetadata;
public final class SplitMinecraftProvider extends MinecraftProvider { public final class SplitMinecraftProvider extends MinecraftProvider {
private File minecraftClientOnlyJar; private Path minecraftClientOnlyJar;
private File minecraftCommonJar; private Path minecraftCommonJar;
public SplitMinecraftProvider(Project project) { public SplitMinecraftProvider(Project project) {
super(project); super(project);
@ -45,20 +44,20 @@ public final class SplitMinecraftProvider extends MinecraftProvider {
protected void initFiles() { protected void initFiles() {
super.initFiles(); super.initFiles();
minecraftClientOnlyJar = file("minecraft-client-only.jar"); minecraftClientOnlyJar = path("minecraft-client-only.jar");
minecraftCommonJar = file("minecraft-common.jar"); minecraftCommonJar = path("minecraft-common.jar");
} }
@Override @Override
public List<Path> getMinecraftJars() { public List<Path> getMinecraftJars() {
return List.of(minecraftClientOnlyJar.toPath(), minecraftCommonJar.toPath()); return List.of(minecraftClientOnlyJar, minecraftCommonJar);
} }
@Override @Override
public void provide() throws Exception { public void provide() throws Exception {
super.provide(); super.provide();
boolean requiresRefresh = isRefreshDeps() || !minecraftClientOnlyJar.exists() || !minecraftCommonJar.exists(); boolean requiresRefresh = isRefreshDeps() || Files.notExists(minecraftClientOnlyJar) || Files.notExists(minecraftCommonJar);
if (!requiresRefresh) { if (!requiresRefresh) {
return; return;
@ -80,20 +79,20 @@ public final class SplitMinecraftProvider extends MinecraftProvider {
jarSplitter.sharedEntry("version.json"); jarSplitter.sharedEntry("version.json");
jarSplitter.forcedClientEntry("assets/.mcassetsroot"); jarSplitter.forcedClientEntry("assets/.mcassetsroot");
jarSplitter.split(minecraftClientOnlyJar.toPath(), minecraftCommonJar.toPath()); jarSplitter.split(minecraftClientOnlyJar, minecraftCommonJar);
} catch (Exception e) { } catch (Exception e) {
Files.deleteIfExists(minecraftClientOnlyJar.toPath()); Files.deleteIfExists(minecraftClientOnlyJar);
Files.deleteIfExists(minecraftCommonJar.toPath()); Files.deleteIfExists(minecraftCommonJar);
throw new RuntimeException("Failed to split minecraft", e); throw new RuntimeException("Failed to split minecraft", e);
} }
} }
public File getMinecraftClientOnlyJar() { public Path getMinecraftClientOnlyJar() {
return minecraftClientOnlyJar; return minecraftClientOnlyJar;
} }
public File getMinecraftCommonJar() { public Path getMinecraftCommonJar() {
return minecraftCommonJar; return minecraftCommonJar;
} }
} }

View File

@ -32,11 +32,12 @@ import org.gradle.api.Project;
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
import net.fabricmc.loom.configuration.providers.minecraft.MergedMinecraftProvider; import net.fabricmc.loom.configuration.providers.minecraft.MergedMinecraftProvider;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider; 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.configuration.providers.minecraft.SplitMinecraftProvider;
import net.fabricmc.loom.util.SidedClassVisitor; import net.fabricmc.loom.util.SidedClassVisitor;
import net.fabricmc.tinyremapper.TinyRemapper; import net.fabricmc.tinyremapper.TinyRemapper;
public abstract sealed class IntermediaryMinecraftProvider<M extends MinecraftProvider> extends AbstractMappedMinecraftProvider<M> permits IntermediaryMinecraftProvider.SplitImpl, IntermediaryMinecraftProvider.MergedImpl { public abstract sealed class IntermediaryMinecraftProvider<M extends MinecraftProvider> extends AbstractMappedMinecraftProvider<M> permits IntermediaryMinecraftProvider.MergedImpl, IntermediaryMinecraftProvider.ServerOnlyImpl, IntermediaryMinecraftProvider.SplitImpl {
public IntermediaryMinecraftProvider(Project project, M minecraftProvider) { public IntermediaryMinecraftProvider(Project project, M minecraftProvider) {
super(project, minecraftProvider); super(project, minecraftProvider);
} }
@ -59,7 +60,7 @@ public abstract sealed class IntermediaryMinecraftProvider<M extends MinecraftPr
@Override @Override
public List<RemappedJars> getRemappedJars() { public List<RemappedJars> getRemappedJars() {
return List.of( 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<M extends MinecraftPr
@Override @Override
public List<RemappedJars> getRemappedJars() { public List<RemappedJars> getRemappedJars() {
return List.of( return List.of(
new RemappedJars(minecraftProvider.getMinecraftCommonJar().toPath(), getCommonJar(), MappingsNamespace.OFFICIAL), new RemappedJars(minecraftProvider.getMinecraftCommonJar(), getCommonJar(), MappingsNamespace.OFFICIAL),
new RemappedJars(minecraftProvider.getMinecraftClientOnlyJar().toPath(), getClientOnlyJar(), MappingsNamespace.OFFICIAL, minecraftProvider.getMinecraftCommonJar().toPath()) new RemappedJars(minecraftProvider.getMinecraftClientOnlyJar(), getClientOnlyJar(), MappingsNamespace.OFFICIAL, minecraftProvider.getMinecraftCommonJar())
); );
} }
@ -84,4 +85,17 @@ public abstract sealed class IntermediaryMinecraftProvider<M extends MinecraftPr
} }
} }
} }
public static final class ServerOnlyImpl extends IntermediaryMinecraftProvider<ServerOnlyMinecraftProvider> implements ServerOnly {
public ServerOnlyImpl(Project project, ServerOnlyMinecraftProvider minecraftProvider) {
super(project, minecraftProvider);
}
@Override
public List<RemappedJars> getRemappedJars() {
return List.of(
new RemappedJars(minecraftProvider.getMinecraftServerOnlyJar(), getServerOnlyJar(), MappingsNamespace.OFFICIAL)
);
}
}
} }

View File

@ -64,4 +64,17 @@ public interface MappedMinecraftProvider {
return List.of(getCommonJar(), getClientOnlyJar()); return List.of(getCommonJar(), getClientOnlyJar());
} }
} }
interface ServerOnly extends ProviderImpl {
String SERVER_ONLY = "serverOnly";
default Path getServerOnlyJar() {
return getJar(SERVER_ONLY);
}
@Override
default List<Path> getMinecraftJars() {
return List.of(getServerOnlyJar());
}
}
} }

View File

@ -33,6 +33,7 @@ import org.gradle.api.Project;
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace; import net.fabricmc.loom.api.mappings.layered.MappingsNamespace;
import net.fabricmc.loom.configuration.providers.minecraft.MergedMinecraftProvider; import net.fabricmc.loom.configuration.providers.minecraft.MergedMinecraftProvider;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider; 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.configuration.providers.minecraft.SplitMinecraftProvider;
import net.fabricmc.loom.util.Constants; import net.fabricmc.loom.util.Constants;
import net.fabricmc.loom.util.SidedClassVisitor; import net.fabricmc.loom.util.SidedClassVisitor;
@ -61,7 +62,7 @@ public abstract class NamedMinecraftProvider<M extends MinecraftProvider> extend
@Override @Override
public List<RemappedJars> getRemappedJars() { public List<RemappedJars> getRemappedJars() {
return List.of( 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<M extends MinecraftProvider> extend
@Override @Override
public List<RemappedJars> getRemappedJars() { public List<RemappedJars> getRemappedJars() {
return List.of( return List.of(
new RemappedJars(minecraftProvider.getMinecraftCommonJar().toPath(), getCommonJar(), MappingsNamespace.OFFICIAL), new RemappedJars(minecraftProvider.getMinecraftCommonJar(), getCommonJar(), MappingsNamespace.OFFICIAL),
new RemappedJars(minecraftProvider.getMinecraftClientOnlyJar().toPath(), getClientOnlyJar(), MappingsNamespace.OFFICIAL, minecraftProvider.getMinecraftCommonJar().toPath()) new RemappedJars(minecraftProvider.getMinecraftClientOnlyJar(), getClientOnlyJar(), MappingsNamespace.OFFICIAL, minecraftProvider.getMinecraftCommonJar())
); );
} }
@ -97,4 +98,22 @@ public abstract class NamedMinecraftProvider<M extends MinecraftProvider> extend
consumer.accept(Constants.Configurations.MINECRAFT_NAMED, CLIENT_ONLY); consumer.accept(Constants.Configurations.MINECRAFT_NAMED, CLIENT_ONLY);
} }
} }
public static final class ServerOnlyImpl extends NamedMinecraftProvider<ServerOnlyMinecraftProvider> implements ServerOnly {
public ServerOnlyImpl(Project project, ServerOnlyMinecraftProvider minecraftProvider) {
super(project, minecraftProvider);
}
@Override
public List<RemappedJars> getRemappedJars() {
return List.of(
new RemappedJars(minecraftProvider.getMinecraftServerOnlyJar(), getServerOnlyJar(), MappingsNamespace.OFFICIAL)
);
}
@Override
protected void applyDependencies(BiConsumer<String, String> consumer) {
consumer.accept(Constants.Configurations.MINECRAFT_NAMED, SERVER_ONLY);
}
}
} }

View File

@ -36,6 +36,7 @@ import net.fabricmc.loom.LoomGradlePlugin;
import net.fabricmc.loom.configuration.processors.JarProcessorManager; import net.fabricmc.loom.configuration.processors.JarProcessorManager;
import net.fabricmc.loom.configuration.providers.minecraft.MergedMinecraftProvider; import net.fabricmc.loom.configuration.providers.minecraft.MergedMinecraftProvider;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftProvider; 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.configuration.providers.minecraft.SplitMinecraftProvider;
public abstract class ProcessedNamedMinecraftProvider<M extends MinecraftProvider, P extends NamedMinecraftProvider<M>> extends NamedMinecraftProvider<M> { public abstract class ProcessedNamedMinecraftProvider<M extends MinecraftProvider, P extends NamedMinecraftProvider<M>> extends NamedMinecraftProvider<M> {
@ -154,4 +155,15 @@ public abstract class ProcessedNamedMinecraftProvider<M extends MinecraftProvide
return getProcessedPath(getParentMinecraftProvider().getClientOnlyJar()); return getProcessedPath(getParentMinecraftProvider().getClientOnlyJar());
} }
} }
public static final class ServerOnlyImpl extends ProcessedNamedMinecraftProvider<ServerOnlyMinecraftProvider, NamedMinecraftProvider.ServerOnlyImpl> implements ServerOnly {
public ServerOnlyImpl(NamedMinecraftProvider.ServerOnlyImpl parentMinecraftProvide, JarProcessorManager jarProcessorManager) {
super(parentMinecraftProvide, jarProcessorManager);
}
@Override
public Path getServerOnlyJar() {
return getProcessedPath(getParentMinecraftProvider().getServerOnlyJar());
}
}
} }

View File

@ -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.LayeredMappingSpec;
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilderImpl; import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingSpecBuilderImpl;
import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsDependency; import net.fabricmc.loom.configuration.providers.mappings.LayeredMappingsDependency;
import net.fabricmc.loom.configuration.providers.minecraft.MinecraftJarConfiguration;
import net.fabricmc.loom.util.DeprecationHelper; import net.fabricmc.loom.util.DeprecationHelper;
/** /**
@ -62,6 +63,7 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
protected final Property<Boolean> transitiveAccessWideners; protected final Property<Boolean> transitiveAccessWideners;
protected final Property<String> intermediary; protected final Property<String> intermediary;
protected final Property<Boolean> enableInterfaceInjection; protected final Property<Boolean> enableInterfaceInjection;
private final Property<MinecraftJarConfiguration> minecraftJarConfiguration;
private final ModVersionParser versionParser; private final ModVersionParser versionParser;
@ -97,6 +99,9 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
baseName -> new RunConfigSettings(project, baseName)); baseName -> new RunConfigSettings(project, baseName));
this.decompilers = project.getObjects().domainObjectContainer(DecompilerOptions.class); this.decompilers = project.getObjects().domainObjectContainer(DecompilerOptions.class);
this.minecraftJarConfiguration = project.getObjects().property(MinecraftJarConfiguration.class).convention(MinecraftJarConfiguration.MERGED);
this.minecraftJarConfiguration.finalizeValueOnRead();
this.accessWidener.finalizeValueOnRead(); this.accessWidener.finalizeValueOnRead();
this.getGameJarProcessors().finalizeValueOnRead(); this.getGameJarProcessors().finalizeValueOnRead();
} }
@ -203,6 +208,11 @@ public abstract class LoomGradleExtensionApiImpl implements LoomGradleExtensionA
net.fabricmc.loom.configuration.MavenPublication.excludePublication(publication); net.fabricmc.loom.configuration.MavenPublication.excludePublication(publication);
} }
@Override
public Property<MinecraftJarConfiguration> getMinecraftJarConfiguration() {
return minecraftJarConfiguration;
}
// This is here to ensure that LoomGradleExtensionApiImpl compiles without any unimplemented methods // This is here to ensure that LoomGradleExtensionApiImpl compiles without any unimplemented methods
private final class EnsureCompile extends LoomGradleExtensionApiImpl { private final class EnsureCompile extends LoomGradleExtensionApiImpl {
private EnsureCompile() { private EnsureCompile() {

View File

@ -26,11 +26,14 @@ package net.fabricmc.loom.task;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import org.gradle.api.Project; 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.TaskContainer;
import org.gradle.api.tasks.TaskProvider; import org.gradle.api.tasks.TaskProvider;
import net.fabricmc.loom.LoomGradleExtension; import net.fabricmc.loom.LoomGradleExtension;
import net.fabricmc.loom.configuration.ide.RunConfigSettings; 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.GenerateDLIConfigTask;
import net.fabricmc.loom.task.launch.GenerateLog4jConfigTask; import net.fabricmc.loom.task.launch.GenerateLog4jConfigTask;
import net.fabricmc.loom.task.launch.GenerateRemapClasspathTask; import net.fabricmc.loom.task.launch.GenerateRemapClasspathTask;
@ -67,8 +70,6 @@ public final class LoomTasks {
}); });
tasks.register("configureLaunch", task -> { tasks.register("configureLaunch", task -> {
task.dependsOn(tasks.named("extractNatives"));
task.dependsOn(tasks.named("downloadAssets"));
task.dependsOn(tasks.named("generateDLIConfig")); task.dependsOn(tasks.named("generateDLIConfig"));
task.dependsOn(tasks.named("generateLog4jConfig")); task.dependsOn(tasks.named("generateLog4jConfig"));
task.dependsOn(tasks.named("generateRemapClasspath")); task.dependsOn(tasks.named("generateRemapClasspath"));
@ -77,6 +78,15 @@ public final class LoomTasks {
task.setGroup(Constants.TaskGroup.FABRIC); 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<ValidateAccessWidenerTask> validateAccessWidener = tasks.register("validateAccessWidener", ValidateAccessWidenerTask.class, t -> { TaskProvider<ValidateAccessWidenerTask> validateAccessWidener = tasks.register("validateAccessWidener", ValidateAccessWidenerTask.class, t -> {
t.setDescription("Validate all the rules in the access widener against the Minecraft jar"); t.setDescription("Validate all the rules in the access widener against the Minecraft jar");
t.setGroup("verification"); t.setGroup("verification");
@ -91,13 +101,13 @@ public final class LoomTasks {
private static void registerIDETasks(TaskContainer tasks) { private static void registerIDETasks(TaskContainer tasks) {
tasks.register("genIdeaWorkspace", GenIdeaProjectTask.class, t -> { tasks.register("genIdeaWorkspace", GenIdeaProjectTask.class, t -> {
t.setDescription("Generates an IntelliJ IDEA workspace from this project."); 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); t.setGroup(Constants.TaskGroup.IDE);
}); });
tasks.register("genEclipseRuns", GenEclipseRunsTask.class, t -> { tasks.register("genEclipseRuns", GenEclipseRunsTask.class, t -> {
t.setDescription("Generates Eclipse run configurations for this project."); t.setDescription("Generates Eclipse run configurations for this project.");
t.dependsOn("configureLaunch"); t.dependsOn(getIDELaunchConfigureTaskName(t.getProject()));
t.setGroup(Constants.TaskGroup.IDE); t.setGroup(Constants.TaskGroup.IDE);
}); });
@ -108,7 +118,7 @@ public final class LoomTasks {
tasks.register("vscode", GenVsCodeProjectTask.class, t -> { tasks.register("vscode", GenVsCodeProjectTask.class, t -> {
t.setDescription("Generates VSCode launch configurations."); t.setDescription("Generates VSCode launch configurations.");
t.dependsOn("configureLaunch"); t.dependsOn(getIDELaunchConfigureTaskName(t.getProject()));
t.setGroup(Constants.TaskGroup.IDE); t.setGroup(Constants.TaskGroup.IDE);
}); });
} }
@ -125,11 +135,25 @@ public final class LoomTasks {
tasks.register(taskName, RunGameTask.class, config).configure(t -> { tasks.register(taskName, RunGameTask.class, config).configure(t -> {
t.setDescription("Starts the '" + config.getConfigName() + "' run configuration"); 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("client", RunConfigSettings::client);
extension.getRunConfigs().create("server", RunConfigSettings::server); 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<Task> 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);
});
} }
} }

View File

@ -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
}
}

View File

@ -199,6 +199,10 @@ trait GradleProjectTestTrait {
return new File(getProjectDir(), "build.gradle") return new File(getProjectDir(), "build.gradle")
} }
File getGradleProperties() {
return new File(getProjectDir(), "gradle.properties")
}
String getOutputZipEntry(String filename, String entryName) { String getOutputZipEntry(String filename, String entryName) {
def file = getOutputFile(filename) def file = getOutputFile(filename)
def bytes = ZipUtils.unpackNullable(file.toPath(), entryName) def bytes = ZipUtils.unpackNullable(file.toPath(), entryName)