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
This commit is contained in:
		
							parent
							
								
									d71af0cfd7
								
							
						
					
					
						commit
						e9d1f005d9
					
				
					 21 changed files with 551 additions and 117 deletions
				
			
		|  | @ -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); | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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) { | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -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)); | ||||||
|  | @ -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); | ||||||
|  |  | ||||||
|  | @ -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()) { | ||||||
|  |  | ||||||
|  | @ -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()); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -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()); | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -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; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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()); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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()); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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() { | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|  | 		}); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -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) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue