Co-authored-by: ShadewRG <onankman@gmail.com> Co-authored-by: UndeadCat | Shadew <redgalaxysw@gmail.com> Co-authored-by: liach <7806504+liach@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									17fb2b4656
								
							
						
					
					
						commit
						6a315be278
					
				
					 17 changed files with 502 additions and 110 deletions
				
			
		|  | @ -106,7 +106,7 @@ license { | ||||||
| 
 | 
 | ||||||
| checkstyle { | checkstyle { | ||||||
| 	configFile = file('checkstyle.xml') | 	configFile = file('checkstyle.xml') | ||||||
| 	toolVersion = '8.25' | 	toolVersion = '8.39' | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| checkstyleMain { | checkstyleMain { | ||||||
|  |  | ||||||
|  | @ -41,15 +41,19 @@ import java.util.stream.Collectors; | ||||||
| import com.google.gson.JsonObject; | import com.google.gson.JsonObject; | ||||||
| import org.cadixdev.lorenz.MappingSet; | import org.cadixdev.lorenz.MappingSet; | ||||||
| import org.cadixdev.mercury.Mercury; | import org.cadixdev.mercury.Mercury; | ||||||
|  | import org.gradle.api.Action; | ||||||
|  | import org.gradle.api.NamedDomainObjectContainer; | ||||||
| import org.gradle.api.Project; | import org.gradle.api.Project; | ||||||
| import org.gradle.api.artifacts.Configuration; | import org.gradle.api.artifacts.Configuration; | ||||||
| import org.gradle.api.artifacts.Dependency; | import org.gradle.api.artifacts.Dependency; | ||||||
| import org.gradle.api.file.ConfigurableFileCollection; | import org.gradle.api.file.ConfigurableFileCollection; | ||||||
| import org.gradle.api.plugins.BasePluginConvention; | import org.gradle.api.plugins.BasePluginConvention; | ||||||
|  | import org.jetbrains.annotations.ApiStatus; | ||||||
| import org.jetbrains.annotations.Nullable; | import org.jetbrains.annotations.Nullable; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.api.decompilers.LoomDecompiler; | import net.fabricmc.loom.api.decompilers.LoomDecompiler; | ||||||
| import net.fabricmc.loom.configuration.LoomDependencyManager; | import net.fabricmc.loom.configuration.LoomDependencyManager; | ||||||
|  | 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.processors.JarProcessorManager; | import net.fabricmc.loom.configuration.processors.JarProcessorManager; | ||||||
| import net.fabricmc.loom.configuration.providers.MinecraftProvider; | import net.fabricmc.loom.configuration.providers.MinecraftProvider; | ||||||
|  | @ -58,7 +62,6 @@ import net.fabricmc.loom.configuration.providers.mappings.MojangMappingsDependen | ||||||
| import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider; | import net.fabricmc.loom.configuration.providers.minecraft.MinecraftMappedProvider; | ||||||
| 
 | 
 | ||||||
| public class LoomGradleExtension { | public class LoomGradleExtension { | ||||||
| 	public String runDir = "run"; |  | ||||||
| 	public String refmapName; | 	public String refmapName; | ||||||
| 	public String loaderLaunchMethod; | 	public String loaderLaunchMethod; | ||||||
| 	public boolean remapMod = true; | 	public boolean remapMod = true; | ||||||
|  | @ -82,6 +85,8 @@ public class LoomGradleExtension { | ||||||
| 	private Mercury[] srcMercuryCache = new Mercury[2]; | 	private Mercury[] srcMercuryCache = new Mercury[2]; | ||||||
| 	private Set<File> mixinMappings = Collections.synchronizedSet(new HashSet<>()); | 	private Set<File> mixinMappings = Collections.synchronizedSet(new HashSet<>()); | ||||||
| 
 | 
 | ||||||
|  | 	private NamedDomainObjectContainer<RunConfigSettings> runs; | ||||||
|  | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Loom will generate a new genSources task (with a new name, based off of {@link LoomDecompiler#name()}) | 	 * Loom will generate a new genSources task (with a new name, based off of {@link LoomDecompiler#name()}) | ||||||
| 	 * that uses the specified decompiler instead. | 	 * that uses the specified decompiler instead. | ||||||
|  | @ -117,6 +122,8 @@ public class LoomGradleExtension { | ||||||
| 		this.project = project; | 		this.project = project; | ||||||
| 		this.autoGenIDERuns = isRootProject(); | 		this.autoGenIDERuns = isRootProject(); | ||||||
| 		this.unmappedMods = project.files(); | 		this.unmappedMods = project.files(); | ||||||
|  | 		this.runs = project.container(RunConfigSettings.class, | ||||||
|  | 				baseName -> new RunConfigSettings(project, baseName)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
|  | @ -134,8 +141,8 @@ public class LoomGradleExtension { | ||||||
| 	@Deprecated | 	@Deprecated | ||||||
| 	public List<Path> getUnmappedMods() { | 	public List<Path> getUnmappedMods() { | ||||||
| 		return unmappedMods.getFiles().stream() | 		return unmappedMods.getFiles().stream() | ||||||
| 			.map(File::toPath) | 				.map(File::toPath) | ||||||
| 			.collect(Collectors.toList()); | 				.collect(Collectors.toList()); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public ConfigurableFileCollection getUnmappedModCollection() { | 	public ConfigurableFileCollection getUnmappedModCollection() { | ||||||
|  | @ -292,7 +299,7 @@ public class LoomGradleExtension { | ||||||
| 
 | 
 | ||||||
| 	@Nullable | 	@Nullable | ||||||
| 	private Dependency getMixinDependency() { | 	private Dependency getMixinDependency() { | ||||||
| 		return recurseProjects((p) -> { | 		return recurseProjects(p -> { | ||||||
| 			List<Configuration> configs = new ArrayList<>(); | 			List<Configuration> configs = new ArrayList<>(); | ||||||
| 			// check compile classpath first | 			// check compile classpath first | ||||||
| 			Configuration possibleCompileClasspath = p.getConfigurations().findByName("compileClasspath"); | 			Configuration possibleCompileClasspath = p.getConfigurations().findByName("compileClasspath"); | ||||||
|  | @ -309,11 +316,7 @@ public class LoomGradleExtension { | ||||||
| 					return true; | 					return true; | ||||||
| 				} | 				} | ||||||
| 
 | 
 | ||||||
| 				if (name.equalsIgnoreCase("sponge-mixin") && group.equalsIgnoreCase("net.fabricmc")) { | 				return name.equalsIgnoreCase("sponge-mixin") && group.equalsIgnoreCase("net.fabricmc"); | ||||||
| 					return true; |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				return false; |  | ||||||
| 			}); | 			}); | ||||||
| 		}); | 		}); | ||||||
| 	} | 	} | ||||||
|  | @ -426,4 +429,14 @@ public class LoomGradleExtension { | ||||||
| 	public List<LoomDecompiler> getDecompilers() { | 	public List<LoomDecompiler> getDecompilers() { | ||||||
| 		return decompilers; | 		return decompilers; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	@ApiStatus.Experimental | ||||||
|  | 	public void runs(Action<NamedDomainObjectContainer<RunConfigSettings>> action) { | ||||||
|  | 		action.execute(runs); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@ApiStatus.Experimental | ||||||
|  | 	public NamedDomainObjectContainer<RunConfigSettings> getRuns() { | ||||||
|  | 		return runs; | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,12 +24,10 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.configuration.ide; | package net.fabricmc.loom.configuration.ide; | ||||||
| 
 | 
 | ||||||
| import java.io.File; |  | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.io.InputStream; | import java.io.InputStream; | ||||||
| import java.nio.charset.StandardCharsets; | import java.nio.charset.StandardCharsets; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Locale; |  | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
| 
 | 
 | ||||||
| import com.google.common.base.Strings; | import com.google.common.base.Strings; | ||||||
|  | @ -37,9 +35,9 @@ import com.google.common.collect.ImmutableList; | ||||||
| import com.google.common.collect.ImmutableMap; | import com.google.common.collect.ImmutableMap; | ||||||
| import com.google.gson.JsonElement; | import com.google.gson.JsonElement; | ||||||
| import com.google.gson.JsonObject; | import com.google.gson.JsonObject; | ||||||
| import org.apache.commons.io.FileUtils; |  | ||||||
| import org.apache.commons.io.IOUtils; | import org.apache.commons.io.IOUtils; | ||||||
| import org.gradle.api.Project; | import org.gradle.api.Project; | ||||||
|  | import org.gradle.api.tasks.SourceSet; | ||||||
| import org.gradle.plugins.ide.eclipse.model.EclipseModel; | import org.gradle.plugins.ide.eclipse.model.EclipseModel; | ||||||
| import org.w3c.dom.Document; | import org.w3c.dom.Document; | ||||||
| import org.w3c.dom.Element; | import org.w3c.dom.Element; | ||||||
|  | @ -54,6 +52,7 @@ public class RunConfig { | ||||||
| 	public String eclipseProjectName; | 	public String eclipseProjectName; | ||||||
| 	public String ideaModuleName; | 	public String ideaModuleName; | ||||||
| 	public String mainClass; | 	public String mainClass; | ||||||
|  | 	public String runDirIdeaUrl; | ||||||
| 	public String runDir; | 	public String runDir; | ||||||
| 	public String vmArgs; | 	public String vmArgs; | ||||||
| 	public String programArgs; | 	public String programArgs; | ||||||
|  | @ -64,7 +63,7 @@ public class RunConfig { | ||||||
| 
 | 
 | ||||||
| 		this.addXml(root, "module", ImmutableMap.of("name", ideaModuleName)); | 		this.addXml(root, "module", ImmutableMap.of("name", ideaModuleName)); | ||||||
| 		this.addXml(root, "option", ImmutableMap.of("name", "MAIN_CLASS_NAME", "value", mainClass)); | 		this.addXml(root, "option", ImmutableMap.of("name", "MAIN_CLASS_NAME", "value", mainClass)); | ||||||
| 		this.addXml(root, "option", ImmutableMap.of("name", "WORKING_DIRECTORY", "value", runDir)); | 		this.addXml(root, "option", ImmutableMap.of("name", "WORKING_DIRECTORY", "value", runDirIdeaUrl)); | ||||||
| 
 | 
 | ||||||
| 		if (!Strings.isNullOrEmpty(vmArgs)) { | 		if (!Strings.isNullOrEmpty(vmArgs)) { | ||||||
| 			this.addXml(root, "option", ImmutableMap.of("name", "VM_PARAMETERS", "value", vmArgs)); | 			this.addXml(root, "option", ImmutableMap.of("name", "VM_PARAMETERS", "value", vmArgs)); | ||||||
|  | @ -94,8 +93,8 @@ public class RunConfig { | ||||||
| 		return e; | 		return e; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private static String getIdeaModuleName(Project project) { | 	private static String getIdeaModuleName(Project project, SourceSet srcs) { | ||||||
| 		String module = project.getName() + ".main"; | 		String module = project.getName() + "." + srcs.getName(); | ||||||
| 
 | 
 | ||||||
| 		while ((project = project.getParent()) != null) { | 		while ((project = project.getParent()) != null) { | ||||||
| 			module = project.getName() + "." + module; | 			module = project.getName() + "." + module; | ||||||
|  | @ -107,12 +106,11 @@ public class RunConfig { | ||||||
| 	private static void populate(Project project, LoomGradleExtension extension, RunConfig runConfig, String mode) { | 	private static void populate(Project project, LoomGradleExtension extension, RunConfig runConfig, String mode) { | ||||||
| 		runConfig.configName += extension.isRootProject() ? "" : " (" + project.getPath() + ")"; | 		runConfig.configName += extension.isRootProject() ? "" : " (" + project.getPath() + ")"; | ||||||
| 		runConfig.eclipseProjectName = project.getExtensions().getByType(EclipseModel.class).getProject().getName(); | 		runConfig.eclipseProjectName = project.getExtensions().getByType(EclipseModel.class).getProject().getName(); | ||||||
| 		runConfig.ideaModuleName = getIdeaModuleName(project); |  | ||||||
| 		runConfig.runDir = "file://$PROJECT_DIR$/" + extension.runDir; |  | ||||||
| 		runConfig.vmArgs = ""; | 		runConfig.vmArgs = ""; | ||||||
|  | 		runConfig.programArgs = ""; | ||||||
| 
 | 
 | ||||||
| 		if ("launchwrapper".equals(extension.getLoaderLaunchMethod())) { | 		if ("launchwrapper".equals(extension.getLoaderLaunchMethod())) { | ||||||
| 			runConfig.mainClass = "net.minecraft.launchwrapper.Launch"; | 			runConfig.mainClass = "net.minecraft.launchwrapper.Launch"; // TODO What about custom tweakers for run configs? | ||||||
| 			runConfig.programArgs += "--tweakClass " + ("client".equals(mode) ? Constants.LaunchWrapper.DEFAULT_FABRIC_CLIENT_TWEAKER : Constants.LaunchWrapper.DEFAULT_FABRIC_SERVER_TWEAKER); | 			runConfig.programArgs += "--tweakClass " + ("client".equals(mode) ? Constants.LaunchWrapper.DEFAULT_FABRIC_CLIENT_TWEAKER : Constants.LaunchWrapper.DEFAULT_FABRIC_SERVER_TWEAKER); | ||||||
| 		} else { | 		} else { | ||||||
| 			runConfig.mainClass = "net.fabricmc.devlaunchinjector.Main"; | 			runConfig.mainClass = "net.fabricmc.devlaunchinjector.Main"; | ||||||
|  | @ -149,35 +147,74 @@ public class RunConfig { | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public static RunConfig clientRunConfig(Project project) { | 	// Turns camelCase/PascalCase into Capital Case | ||||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | 	// caseConversionExample -> Case Conversion Example | ||||||
|  | 	private static String capitalizeCamelCaseName(String name) { | ||||||
|  | 		if (name.length() == 0) { | ||||||
|  | 			return ""; | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		RunConfig ideaClient = new RunConfig(); | 		return name.substring(0, 1).toUpperCase() + name.substring(1).replaceAll("([^A-Z])([A-Z])", "$1 $2"); | ||||||
| 		ideaClient.configName = "Minecraft Client"; |  | ||||||
| 		ideaClient.programArgs = ""; |  | ||||||
| 		populate(project, extension, ideaClient, "client"); |  | ||||||
| 		ideaClient.vmArgs += getOSClientJVMArgs(); |  | ||||||
| 		ideaClient.vmArgs += " -Dfabric.dli.main=" + getMainClass("client", extension); |  | ||||||
| 
 |  | ||||||
| 		return ideaClient; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public static RunConfig serverRunConfig(Project project) { | 	public static RunConfig runConfig(Project project, RunConfigSettings settings) { | ||||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
|  | 		String name = settings.getName(); | ||||||
| 
 | 
 | ||||||
| 		RunConfig ideaServer = new RunConfig(); | 		String configName = settings.getConfigName(); | ||||||
| 		ideaServer.configName = "Minecraft Server"; | 		String mode = settings.getMode(); | ||||||
| 		ideaServer.programArgs = "nogui "; | 		SourceSet sourceSet = settings.getSource(project); | ||||||
| 		populate(project, extension, ideaServer, "server"); |  | ||||||
| 		ideaServer.vmArgs += " -Dfabric.dli.main=" + getMainClass("server", extension); |  | ||||||
| 
 | 
 | ||||||
| 		return ideaServer; | 		String defaultMain = settings.getDefaultMainClass(); | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	// This can be removed at somepoint, its not ideal but its the best solution I could thing of | 		if (defaultMain == null) { | ||||||
| 	public static boolean needsUpgrade(File file) throws IOException { | 			throw new IllegalArgumentException("Run configuration '" + name + "' must specify 'defaultMainClass'"); | ||||||
| 		String contents = FileUtils.readFileToString(file, StandardCharsets.UTF_8); | 		} | ||||||
| 		return !(contents.contains("net.fabricmc.devlaunchinjector.Main")); | 
 | ||||||
|  | 		if (configName == null) { | ||||||
|  | 			configName = ""; | ||||||
|  | 			String srcName = sourceSet.getName(); | ||||||
|  | 
 | ||||||
|  | 			if (!srcName.equals(SourceSet.MAIN_SOURCE_SET_NAME)) { | ||||||
|  | 				configName += capitalizeCamelCaseName(srcName) + " "; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			configName += "Minecraft " + capitalizeCamelCaseName(name); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (mode == null) { | ||||||
|  | 			mode = name; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		String runDir = settings.getRunDir(); | ||||||
|  | 
 | ||||||
|  | 		if (runDir == null) { | ||||||
|  | 			runDir = "run"; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		RunConfig runConfig = new RunConfig(); | ||||||
|  | 		runConfig.configName = configName; | ||||||
|  | 		populate(project, extension, runConfig, mode); | ||||||
|  | 		runConfig.ideaModuleName = getIdeaModuleName(project, sourceSet); | ||||||
|  | 		runConfig.runDirIdeaUrl = "file://$PROJECT_DIR$/" + runDir; | ||||||
|  | 		runConfig.runDir = runDir; | ||||||
|  | 
 | ||||||
|  | 		// Custom parameters | ||||||
|  | 		for (String progArg : settings.getProgramArgs()) { | ||||||
|  | 			runConfig.programArgs += " " + progArg; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		for (String vmArg : settings.getVmArgs()) { | ||||||
|  | 			runConfig.vmArgs += " " + vmArg; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		runConfig.vmArgs += " -Dfabric.dli.main=" + getMainClass(mode, extension, defaultMain); | ||||||
|  | 
 | ||||||
|  | 		// Remove unnecessary leading/trailing whitespaces we might have generated | ||||||
|  | 		runConfig.programArgs = runConfig.programArgs.trim(); | ||||||
|  | 		runConfig.vmArgs = runConfig.vmArgs.trim(); | ||||||
|  | 
 | ||||||
|  | 		return runConfig; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public String fromDummy(String dummy) throws IOException { | 	public String fromDummy(String dummy) throws IOException { | ||||||
|  | @ -191,6 +228,7 @@ public class RunConfig { | ||||||
| 		dummyConfig = dummyConfig.replace("%MAIN_CLASS%", mainClass); | 		dummyConfig = dummyConfig.replace("%MAIN_CLASS%", mainClass); | ||||||
| 		dummyConfig = dummyConfig.replace("%ECLIPSE_PROJECT%", eclipseProjectName); | 		dummyConfig = dummyConfig.replace("%ECLIPSE_PROJECT%", eclipseProjectName); | ||||||
| 		dummyConfig = dummyConfig.replace("%IDEA_MODULE%", ideaModuleName); | 		dummyConfig = dummyConfig.replace("%IDEA_MODULE%", ideaModuleName); | ||||||
|  | 		dummyConfig = dummyConfig.replace("%RUN_DIRECTORY%", runDir); | ||||||
| 		dummyConfig = dummyConfig.replace("%PROGRAM_ARGS%", programArgs.replaceAll("\"", """)); | 		dummyConfig = dummyConfig.replace("%PROGRAM_ARGS%", programArgs.replaceAll("\"", """)); | ||||||
| 		dummyConfig = dummyConfig.replace("%VM_ARGS%", vmArgs.replaceAll("\"", """)); | 		dummyConfig = dummyConfig.replace("%VM_ARGS%", vmArgs.replaceAll("\"", """)); | ||||||
| 
 | 
 | ||||||
|  | @ -205,7 +243,7 @@ public class RunConfig { | ||||||
| 		return ""; | 		return ""; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private static String getMainClass(String side, LoomGradleExtension extension) { | 	private static String getMainClass(String side, LoomGradleExtension extension, String defaultMainClass) { | ||||||
| 		JsonObject installerJson = extension.getInstallerJson(); | 		JsonObject installerJson = extension.getInstallerJson(); | ||||||
| 
 | 
 | ||||||
| 		if (installerJson != null && installerJson.has("mainClass")) { | 		if (installerJson != null && installerJson.has("mainClass")) { | ||||||
|  | @ -231,7 +269,7 @@ public class RunConfig { | ||||||
| 			return "net.minecraft.launchwrapper.Launch"; | 			return "net.minecraft.launchwrapper.Launch"; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		return "net.fabricmc.loader.launch.knot.Knot" + side.substring(0, 1).toUpperCase(Locale.ROOT) + side.substring(1).toLowerCase(Locale.ROOT); | 		return defaultMainClass; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private static String encodeEscaped(String s) { | 	private static String encodeEscaped(String s) { | ||||||
|  |  | ||||||
|  | @ -0,0 +1,291 @@ | ||||||
|  | /* | ||||||
|  |  * This file is part of fabric-loom, licensed under the MIT License (MIT). | ||||||
|  |  * | ||||||
|  |  * Copyright (c) 2016, 2017, 2018 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.ide; | ||||||
|  | 
 | ||||||
|  | import java.io.File; | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.Arrays; | ||||||
|  | import java.util.Collection; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.function.Function; | ||||||
|  | 
 | ||||||
|  | import org.gradle.api.Named; | ||||||
|  | import org.gradle.api.Project; | ||||||
|  | import org.gradle.api.plugins.JavaPluginConvention; | ||||||
|  | import org.gradle.api.tasks.SourceSet; | ||||||
|  | import org.jetbrains.annotations.ApiStatus; | ||||||
|  | 
 | ||||||
|  | import net.fabricmc.loom.LoomGradleExtension; | ||||||
|  | import net.fabricmc.loom.util.Constants; | ||||||
|  | import net.fabricmc.loom.util.OperatingSystem; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Experimental for now, please make sure to direct any suggests towards the github. | ||||||
|  |  */ | ||||||
|  | @ApiStatus.Experimental | ||||||
|  | public final class RunConfigSettings implements Named { | ||||||
|  | 	/** | ||||||
|  | 	 * Arguments for the JVM, such as system properties. | ||||||
|  | 	 */ | ||||||
|  | 	private final List<String> vmArgs = new ArrayList<>(); | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Arguments for the program's main class. | ||||||
|  | 	 */ | ||||||
|  | 	private final List<String> programArgs = new ArrayList<>(); | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * The mode to run, which is the name of the run config in {@code fabric_installer.[method].json}. | ||||||
|  | 	 */ | ||||||
|  | 	private String mode; | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * The full name of the run configuration, i.e. 'Minecraft Client'. | ||||||
|  | 	 * | ||||||
|  | 	 * <p>By default this is determined from the base name. | ||||||
|  | 	 */ | ||||||
|  | 	private String name; | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * The default main class of the run configuration. | ||||||
|  | 	 * | ||||||
|  | 	 * <p>This can be overwritten in {@code fabric_installer.[method].json}. Note that this <em>doesn't</em> take | ||||||
|  | 	 * priority over the main class specified in the Fabric installer configuration. | ||||||
|  | 	 */ | ||||||
|  | 	private String defaultMainClass; | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * The source set getter, which obtains the source set from the given project. | ||||||
|  | 	 */ | ||||||
|  | 	private Function<Project, SourceSet> source; | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * The run directory for this configuration, relative to the root project directory. | ||||||
|  | 	 */ | ||||||
|  | 	private String runDir; | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * The base name of the run configuration, which is the name it is created with, i.e. 'client' | ||||||
|  | 	 */ | ||||||
|  | 	private final String baseName; | ||||||
|  | 
 | ||||||
|  | 	private final Project project; | ||||||
|  | 	private final LoomGradleExtension extension; | ||||||
|  | 
 | ||||||
|  | 	public RunConfigSettings(Project project, String baseName) { | ||||||
|  | 		this.baseName = baseName; | ||||||
|  | 		this.project = project; | ||||||
|  | 		this.extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
|  | 
 | ||||||
|  | 		mode(baseName); | ||||||
|  | 		source("main"); | ||||||
|  | 		runDir("run"); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public Project getProject() { | ||||||
|  | 		return project; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public LoomGradleExtension getExtension() { | ||||||
|  | 		return extension; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public String getName() { | ||||||
|  | 		return baseName; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public List<String> getVmArgs() { | ||||||
|  | 		return vmArgs; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public List<String> getProgramArgs() { | ||||||
|  | 		return programArgs; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public String getMode() { | ||||||
|  | 		return mode; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void setMode(String mode) { | ||||||
|  | 		this.mode = mode; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public String getConfigName() { | ||||||
|  | 		return name; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void setConfigName(String name) { | ||||||
|  | 		this.name = name; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public String getDefaultMainClass() { | ||||||
|  | 		return defaultMainClass; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void setDefaultMainClass(String defaultMainClass) { | ||||||
|  | 		this.defaultMainClass = defaultMainClass; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public String getRunDir() { | ||||||
|  | 		return runDir; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void setRunDir(String runDir) { | ||||||
|  | 		this.runDir = runDir; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public SourceSet getSource(Project proj) { | ||||||
|  | 		return source.apply(proj); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void setSource(SourceSet source) { | ||||||
|  | 		this.source = proj -> source; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void setSource(Function<Project, SourceSet> sourceFn) { | ||||||
|  | 		this.source = sourceFn; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void mode(String mode) { | ||||||
|  | 		setMode(mode); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void name(String name) { | ||||||
|  | 		setConfigName(name); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void defaultMainClass(String cls) { | ||||||
|  | 		setDefaultMainClass(cls); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void runDir(String dir) { | ||||||
|  | 		setRunDir(dir); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void vmArg(String arg) { | ||||||
|  | 		vmArgs.add(arg); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void vmArgs(String... args) { | ||||||
|  | 		vmArgs.addAll(Arrays.asList(args)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void vmArgs(Collection<String> args) { | ||||||
|  | 		vmArgs.addAll(args); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void property(String name, String value) { | ||||||
|  | 		vmArg("-D" + name + "=" + value); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void property(String name) { | ||||||
|  | 		vmArg("-D" + name); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void properties(Map<String, String> props) { | ||||||
|  | 		props.forEach(this::property); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void programArg(String arg) { | ||||||
|  | 		programArgs.add(arg); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void programArgs(String... args) { | ||||||
|  | 		programArgs.addAll(Arrays.asList(args)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void programArgs(Collection<String> args) { | ||||||
|  | 		programArgs.addAll(args); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void source(SourceSet source) { | ||||||
|  | 		setSource(source); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void source(String source) { | ||||||
|  | 		setSource(proj -> { | ||||||
|  | 			JavaPluginConvention conv = proj.getConvention().getPlugin(JavaPluginConvention.class); | ||||||
|  | 			return conv.getSourceSets().getByName(source); | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Add the {@code -XstartOnFirstThread} JVM argument when on OSX. | ||||||
|  | 	 */ | ||||||
|  | 	public void startFirstThread() { | ||||||
|  | 		if (OperatingSystem.getOS().equalsIgnoreCase("osx")) { | ||||||
|  | 			vmArg("-XstartOnFirstThread"); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Removes the {@code nogui} argument for the server configuration. By default {@code nogui} is specified, this is | ||||||
|  | 	 * a convenient way to remove it if wanted. | ||||||
|  | 	 */ | ||||||
|  | 	public void serverWithGui() { | ||||||
|  | 		programArgs.removeIf("nogui"::equals); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Configure run config with the default client options. | ||||||
|  | 	 */ | ||||||
|  | 	public void client() { | ||||||
|  | 		startFirstThread(); | ||||||
|  | 		mode("client"); | ||||||
|  | 		defaultMainClass(Constants.Knot.KNOT_CLIENT); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Configure run config with the default server options. | ||||||
|  | 	 */ | ||||||
|  | 	public void server() { | ||||||
|  | 		programArg("nogui"); | ||||||
|  | 		mode("server"); | ||||||
|  | 		defaultMainClass(Constants.Knot.KNOT_SERVER); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Copies settings from another run configuration. | ||||||
|  | 	 */ | ||||||
|  | 	public void inherit(RunConfigSettings parent) { | ||||||
|  | 		vmArgs.addAll(0, parent.vmArgs); | ||||||
|  | 		programArgs.addAll(0, parent.programArgs); | ||||||
|  | 
 | ||||||
|  | 		mode = parent.mode; | ||||||
|  | 		name = parent.name; | ||||||
|  | 		defaultMainClass = parent.defaultMainClass; | ||||||
|  | 		source = parent.source; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public void makeRunDir() { | ||||||
|  | 		File file = new File(getProject().getRootDir(), runDir); | ||||||
|  | 
 | ||||||
|  | 		if (!file.exists()) { | ||||||
|  | 			file.mkdir(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -50,12 +50,6 @@ public class SetupIntelijRunConfigs { | ||||||
| 		} catch (IOException e) { | 		} catch (IOException e) { | ||||||
| 			throw new RuntimeException("Failed to generate run configs", e); | 			throw new RuntimeException("Failed to generate run configs", e); | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 		File runDir = new File(project.getRootDir(), extension.runDir); |  | ||||||
| 
 |  | ||||||
| 		if (!runDir.exists()) { |  | ||||||
| 			runDir.mkdirs(); |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private static void generate(Project project) throws IOException { | 	private static void generate(Project project) throws IOException { | ||||||
|  | @ -72,22 +66,23 @@ public class SetupIntelijRunConfigs { | ||||||
| 
 | 
 | ||||||
| 		File projectDir = rootProject.file(".idea"); | 		File projectDir = rootProject.file(".idea"); | ||||||
| 		File runConfigsDir = new File(projectDir, "runConfigurations"); | 		File runConfigsDir = new File(projectDir, "runConfigurations"); | ||||||
| 		File clientRunConfigs = new File(runConfigsDir, "Minecraft_Client" + projectPath + ".xml"); |  | ||||||
| 		File serverRunConfigs = new File(runConfigsDir, "Minecraft_Server" + projectPath + ".xml"); |  | ||||||
| 
 | 
 | ||||||
| 		if (!runConfigsDir.exists()) { | 		if (!runConfigsDir.exists()) { | ||||||
| 			runConfigsDir.mkdirs(); | 			runConfigsDir.mkdirs(); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		String clientRunConfig = RunConfig.clientRunConfig(project).fromDummy("idea_run_config_template.xml"); | 		for (RunConfigSettings settings : extension.getRuns()) { | ||||||
| 		String serverRunConfig = RunConfig.serverRunConfig(project).fromDummy("idea_run_config_template.xml"); | 			RunConfig config = RunConfig.runConfig(project, settings); | ||||||
|  | 			String name = config.configName.replaceAll("[^a-zA-Z0-9$_]", "_"); | ||||||
| 
 | 
 | ||||||
| 		if (!clientRunConfigs.exists() || RunConfig.needsUpgrade(clientRunConfigs)) { | 			File runConfigs = new File(runConfigsDir, name + projectPath + ".xml"); | ||||||
| 			FileUtils.writeStringToFile(clientRunConfigs, clientRunConfig, StandardCharsets.UTF_8); | 			String runConfigXml = config.fromDummy("idea_run_config_template.xml"); | ||||||
| 		} |  | ||||||
| 
 | 
 | ||||||
| 		if (!serverRunConfigs.exists() || RunConfig.needsUpgrade(serverRunConfigs)) { | 			if (!runConfigs.exists()) { | ||||||
| 			FileUtils.writeStringToFile(serverRunConfigs, serverRunConfig, StandardCharsets.UTF_8); | 				FileUtils.writeStringToFile(runConfigs, runConfigXml, StandardCharsets.UTF_8); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			settings.makeRunDir(); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -85,8 +85,7 @@ public abstract class AbstractRunTask extends JavaExec { | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		args(argsSplit); | 		args(argsSplit); | ||||||
| 		LoomGradleExtension extension = this.getProject().getExtensions().getByType(LoomGradleExtension.class); | 		setWorkingDir(new File(getProject().getRootDir(), config.runDir)); | ||||||
| 		setWorkingDir(new File(getProject().getRootDir(), extension.runDir)); |  | ||||||
| 
 | 
 | ||||||
| 		super.exec(); | 		super.exec(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -32,30 +32,28 @@ import org.apache.commons.io.FileUtils; | ||||||
| import org.gradle.api.tasks.TaskAction; | import org.gradle.api.tasks.TaskAction; | ||||||
| import org.gradle.plugins.ide.eclipse.model.EclipseModel; | import org.gradle.plugins.ide.eclipse.model.EclipseModel; | ||||||
| 
 | 
 | ||||||
|  | import net.fabricmc.loom.LoomGradleExtension; | ||||||
| import net.fabricmc.loom.configuration.ide.RunConfig; | import net.fabricmc.loom.configuration.ide.RunConfig; | ||||||
|  | import net.fabricmc.loom.configuration.ide.RunConfigSettings; | ||||||
| 
 | 
 | ||||||
| public class GenEclipseRunsTask extends AbstractLoomTask { | public class GenEclipseRunsTask extends AbstractLoomTask { | ||||||
| 	@TaskAction | 	@TaskAction | ||||||
| 	public void genRuns() throws IOException { | 	public void genRuns() throws IOException { | ||||||
| 		EclipseModel eclipseModel = getProject().getExtensions().getByType(EclipseModel.class); | 		EclipseModel eclipseModel = getProject().getExtensions().getByType(EclipseModel.class); | ||||||
| 		File clientRunConfigs = new File(getProject().getRootDir(), eclipseModel.getProject().getName() + "_client.launch"); | 		LoomGradleExtension extension = getExtension(); | ||||||
| 		File serverRunConfigs = new File(getProject().getRootDir(), eclipseModel.getProject().getName() + "_server.launch"); |  | ||||||
| 
 | 
 | ||||||
| 		String clientRunConfig = RunConfig.clientRunConfig(getProject()).fromDummy("eclipse_run_config_template.xml"); | 		for (RunConfigSettings settings : extension.getRuns()) { | ||||||
| 		String serverRunConfig = RunConfig.serverRunConfig(getProject()).fromDummy("eclipse_run_config_template.xml"); | 			String name = settings.getName(); | ||||||
| 
 | 
 | ||||||
| 		if (!clientRunConfigs.exists() || RunConfig.needsUpgrade(clientRunConfigs)) { | 			File configs = new File(getProject().getRootDir(), eclipseModel.getProject().getName() + "_" + name + ".launch"); | ||||||
| 			FileUtils.writeStringToFile(clientRunConfigs, clientRunConfig, StandardCharsets.UTF_8); | 			RunConfig configInst = RunConfig.runConfig(getProject(), settings); | ||||||
| 		} | 			String config = configInst.fromDummy("eclipse_run_config_template.xml"); | ||||||
| 
 | 
 | ||||||
| 		if (!serverRunConfigs.exists() || RunConfig.needsUpgrade(serverRunConfigs)) { | 			if (!configs.exists()) { | ||||||
| 			FileUtils.writeStringToFile(serverRunConfigs, serverRunConfig, StandardCharsets.UTF_8); | 				FileUtils.writeStringToFile(configs, config, StandardCharsets.UTF_8); | ||||||
| 		} | 			} | ||||||
| 
 | 
 | ||||||
| 		File runDir = new File(getProject().getRootDir(), getExtension().runDir); | 			settings.makeRunDir(); | ||||||
| 
 |  | ||||||
| 		if (!runDir.exists()) { |  | ||||||
| 			runDir.mkdirs(); |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -46,6 +46,7 @@ import org.xml.sax.SAXException; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.LoomGradleExtension; | import net.fabricmc.loom.LoomGradleExtension; | ||||||
| import net.fabricmc.loom.configuration.ide.RunConfig; | import net.fabricmc.loom.configuration.ide.RunConfig; | ||||||
|  | import net.fabricmc.loom.configuration.ide.RunConfigSettings; | ||||||
| 
 | 
 | ||||||
| public class GenIdeaProjectTask extends AbstractLoomTask { | public class GenIdeaProjectTask extends AbstractLoomTask { | ||||||
| 	@TaskAction | 	@TaskAction | ||||||
|  | @ -82,8 +83,10 @@ public class GenIdeaProjectTask extends AbstractLoomTask { | ||||||
| 			throw new RuntimeException("Failed to generate IntelliJ run configurations (runManager was not found)"); | 			throw new RuntimeException("Failed to generate IntelliJ run configurations (runManager was not found)"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		runManager.appendChild(RunConfig.clientRunConfig(project).genRuns(runManager)); | 		for (RunConfigSettings settings : getExtension().getRuns()) { | ||||||
| 		runManager.appendChild(RunConfig.serverRunConfig(project).genRuns(runManager)); | 			runManager.appendChild(RunConfig.runConfig(project, settings).genRuns(runManager)); | ||||||
|  | 			settings.makeRunDir(); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		TransformerFactory transformerFactory = TransformerFactory.newInstance(); | 		TransformerFactory transformerFactory = TransformerFactory.newInstance(); | ||||||
| 		Transformer transformer = transformerFactory.newTransformer(); | 		Transformer transformer = transformerFactory.newTransformer(); | ||||||
|  | @ -92,11 +95,5 @@ public class GenIdeaProjectTask extends AbstractLoomTask { | ||||||
| 		transformer.setOutputProperty(OutputKeys.INDENT, "yes"); | 		transformer.setOutputProperty(OutputKeys.INDENT, "yes"); | ||||||
| 		transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); | 		transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); | ||||||
| 		transformer.transform(source, result); | 		transformer.transform(source, result); | ||||||
| 
 |  | ||||||
| 		File runDir = new File(getProject().getRootDir(), extension.runDir); |  | ||||||
| 
 |  | ||||||
| 		if (!runDir.exists()) { |  | ||||||
| 			runDir.mkdirs(); |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -38,6 +38,7 @@ import org.gradle.api.tasks.TaskAction; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.LoomGradleExtension; | import net.fabricmc.loom.LoomGradleExtension; | ||||||
| import net.fabricmc.loom.configuration.ide.RunConfig; | import net.fabricmc.loom.configuration.ide.RunConfig; | ||||||
|  | import net.fabricmc.loom.configuration.ide.RunConfigSettings; | ||||||
| 
 | 
 | ||||||
| // Recommended vscode plugins: | // Recommended vscode plugins: | ||||||
| // https://marketplace.visualstudio.com/items?itemName=redhat.java | // https://marketplace.visualstudio.com/items?itemName=redhat.java | ||||||
|  | @ -61,8 +62,11 @@ public class GenVsCodeProjectTask extends AbstractLoomTask { | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		VsCodeLaunch launch = new VsCodeLaunch(); | 		VsCodeLaunch launch = new VsCodeLaunch(); | ||||||
| 		launch.add(RunConfig.clientRunConfig(project)); | 
 | ||||||
| 		launch.add(RunConfig.serverRunConfig(project)); | 		for (RunConfigSettings settings : getExtension().getRuns()) { | ||||||
|  | 			launch.add(RunConfig.runConfig(project, settings)); | ||||||
|  | 			settings.makeRunDir(); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		Gson gson = new GsonBuilder().setPrettyPrinting().create(); | 		Gson gson = new GsonBuilder().setPrettyPrinting().create(); | ||||||
| 		String json = gson.toJson(launch); | 		String json = gson.toJson(launch); | ||||||
|  | @ -72,12 +76,6 @@ public class GenVsCodeProjectTask extends AbstractLoomTask { | ||||||
| 		} catch (IOException e) { | 		} catch (IOException e) { | ||||||
| 			throw new RuntimeException("Failed to write launch.json", e); | 			throw new RuntimeException("Failed to write launch.json", e); | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 		File runDir = new File(project.getRootDir(), extension.runDir); |  | ||||||
| 
 |  | ||||||
| 		if (!runDir.exists()) { |  | ||||||
| 			runDir.mkdirs(); |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private static class VsCodeLaunch { | 	private static class VsCodeLaunch { | ||||||
|  | @ -94,7 +92,7 @@ public class GenVsCodeProjectTask extends AbstractLoomTask { | ||||||
| 		public String type = "java"; | 		public String type = "java"; | ||||||
| 		public String name; | 		public String name; | ||||||
| 		public String request = "launch"; | 		public String request = "launch"; | ||||||
| 		public String cwd = "${workspaceFolder}/run"; | 		public String cwd; | ||||||
| 		public String console = "internalConsole"; | 		public String console = "internalConsole"; | ||||||
| 		public boolean stopOnEntry = false; | 		public boolean stopOnEntry = false; | ||||||
| 		public String mainClass; | 		public String mainClass; | ||||||
|  | @ -106,6 +104,7 @@ public class GenVsCodeProjectTask extends AbstractLoomTask { | ||||||
| 			this.mainClass = runConfig.mainClass; | 			this.mainClass = runConfig.mainClass; | ||||||
| 			this.vmArgs = runConfig.vmArgs; | 			this.vmArgs = runConfig.vmArgs; | ||||||
| 			this.args = runConfig.programArgs; | 			this.args = runConfig.programArgs; | ||||||
|  | 			this.cwd = "${workspaceFolder}/" + runConfig.runDir; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -29,6 +29,7 @@ import org.gradle.api.tasks.TaskContainer; | ||||||
| 
 | 
 | ||||||
| import net.fabricmc.loom.LoomGradleExtension; | import net.fabricmc.loom.LoomGradleExtension; | ||||||
| import net.fabricmc.loom.api.decompilers.LoomDecompiler; | import net.fabricmc.loom.api.decompilers.LoomDecompiler; | ||||||
|  | import net.fabricmc.loom.configuration.ide.RunConfigSettings; | ||||||
| import net.fabricmc.loom.decompilers.fernflower.FabricFernFlowerDecompiler; | import net.fabricmc.loom.decompilers.fernflower.FabricFernFlowerDecompiler; | ||||||
| 
 | 
 | ||||||
| public final class LoomTasks { | public final class LoomTasks { | ||||||
|  | @ -40,7 +41,7 @@ public final class LoomTasks { | ||||||
| 
 | 
 | ||||||
| 		tasks.register("migrateMappings", MigrateMappingsTask.class, t -> { | 		tasks.register("migrateMappings", MigrateMappingsTask.class, t -> { | ||||||
| 			t.setDescription("Migrates mappings to a new version."); | 			t.setDescription("Migrates mappings to a new version."); | ||||||
| 			t.getOutputs().upToDateWhen((o) -> false); | 			t.getOutputs().upToDateWhen(o -> false); | ||||||
| 		}); | 		}); | ||||||
| 
 | 
 | ||||||
| 		tasks.register("remapJar", RemapJarTask.class, t -> { | 		tasks.register("remapJar", RemapJarTask.class, t -> { | ||||||
|  | @ -52,7 +53,7 @@ public final class LoomTasks { | ||||||
| 		tasks.register("remapSourcesJar", RemapSourcesJarTask.class, t -> t.setDescription("Remaps the project sources jar to intermediary names.")); | 		tasks.register("remapSourcesJar", RemapSourcesJarTask.class, t -> t.setDescription("Remaps the project sources jar to intermediary names.")); | ||||||
| 
 | 
 | ||||||
| 		registerIDETasks(tasks); | 		registerIDETasks(tasks); | ||||||
| 		registerRunTasks(tasks); | 		registerRunTasks(tasks, project); | ||||||
| 		registerDecompileTasks(tasks, project); | 		registerDecompileTasks(tasks, project); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -81,25 +82,31 @@ public final class LoomTasks { | ||||||
| 		}); | 		}); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private static void registerRunTasks(TaskContainer tasks) { | 	private static void registerRunTasks(TaskContainer tasks, Project project) { | ||||||
| 		tasks.register("runClient", RunClientTask.class, t -> { | 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
| 			t.setDescription("Starts a development version of the Minecraft client."); |  | ||||||
| 			t.dependsOn("downloadAssets"); |  | ||||||
| 			t.setGroup("fabric"); |  | ||||||
| 		}); |  | ||||||
| 
 | 
 | ||||||
| 		tasks.register("runServer", RunServerTask.class, t -> { | 		extension.getRuns().create("client", RunConfigSettings::client); | ||||||
| 			t.setDescription("Starts a development version of the Minecraft server."); | 		extension.getRuns().create("server", RunConfigSettings::server); | ||||||
| 			t.setGroup("fabric"); | 
 | ||||||
|  | 		project.afterEvaluate(p -> { | ||||||
|  | 			for (RunConfigSettings config : extension.getRuns()) { | ||||||
|  | 				String configName = config.getName(); | ||||||
|  | 				String taskName = "run" + configName.substring(0, 1).toUpperCase() + configName.substring(1); | ||||||
|  | 
 | ||||||
|  | 				tasks.register(taskName, RunGameTask.class, config).configure(t -> { | ||||||
|  | 					t.setDescription("Starts the '" + config.getConfigName() + "' run configuration"); | ||||||
|  | 					t.setGroup("fabric"); | ||||||
|  | 				}); | ||||||
|  | 			} | ||||||
| 		}); | 		}); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private static void registerDecompileTasks(TaskContainer tasks, Project project) { | 	private static void registerDecompileTasks(TaskContainer tasks, Project project) { | ||||||
| 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | 		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
| 
 | 
 | ||||||
| 		project.afterEvaluate((p) -> { | 		project.afterEvaluate(p -> { | ||||||
| 			for (LoomDecompiler decompiler : extension.getDecompilers()) { | 			for (LoomDecompiler decompiler : extension.getDecompilers()) { | ||||||
| 				String taskName = (decompiler instanceof FabricFernFlowerDecompiler) ? "genSources" : "genSourcesWith" + decompiler.name(); | 				String taskName = decompiler instanceof FabricFernFlowerDecompiler ? "genSources" : "genSourcesWith" + decompiler.name(); | ||||||
| 				// decompiler will be passed to the constructor of GenerateSourcesTask | 				// decompiler will be passed to the constructor of GenerateSourcesTask | ||||||
| 				tasks.register(taskName, GenerateSourcesTask.class, decompiler); | 				tasks.register(taskName, GenerateSourcesTask.class, decompiler); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | @ -24,10 +24,15 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.task; | package net.fabricmc.loom.task; | ||||||
| 
 | 
 | ||||||
|  | import net.fabricmc.loom.LoomGradleExtension; | ||||||
| import net.fabricmc.loom.configuration.ide.RunConfig; | import net.fabricmc.loom.configuration.ide.RunConfig; | ||||||
| 
 | 
 | ||||||
|  | @Deprecated // Replaced by RunGameTask | ||||||
| public class RunClientTask extends AbstractRunTask { | public class RunClientTask extends AbstractRunTask { | ||||||
| 	public RunClientTask() { | 	public RunClientTask() { | ||||||
| 		super(RunConfig::clientRunConfig); | 		super(project -> { | ||||||
|  | 			LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
|  | 			return RunConfig.runConfig(project, extension.getRuns().getByName("client")); | ||||||
|  | 		}); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										37
									
								
								src/main/java/net/fabricmc/loom/task/RunGameTask.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/main/java/net/fabricmc/loom/task/RunGameTask.java
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | ||||||
|  | /* | ||||||
|  |  * This file is part of fabric-loom, licensed under the MIT License (MIT). | ||||||
|  |  * | ||||||
|  |  * Copyright (c) 2016, 2017, 2018 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.task; | ||||||
|  | 
 | ||||||
|  | import javax.inject.Inject; | ||||||
|  | 
 | ||||||
|  | import net.fabricmc.loom.configuration.ide.RunConfig; | ||||||
|  | import net.fabricmc.loom.configuration.ide.RunConfigSettings; | ||||||
|  | 
 | ||||||
|  | public class RunGameTask extends AbstractRunTask { | ||||||
|  | 	@Inject | ||||||
|  | 	public RunGameTask(RunConfigSettings settings) { | ||||||
|  | 		super(proj -> RunConfig.runConfig(proj, settings)); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -24,10 +24,15 @@ | ||||||
| 
 | 
 | ||||||
| package net.fabricmc.loom.task; | package net.fabricmc.loom.task; | ||||||
| 
 | 
 | ||||||
|  | import net.fabricmc.loom.LoomGradleExtension; | ||||||
| import net.fabricmc.loom.configuration.ide.RunConfig; | import net.fabricmc.loom.configuration.ide.RunConfig; | ||||||
| 
 | 
 | ||||||
|  | @Deprecated // Replaced by RunGameTask | ||||||
| public class RunServerTask extends AbstractRunTask { | public class RunServerTask extends AbstractRunTask { | ||||||
| 	public RunServerTask() { | 	public RunServerTask() { | ||||||
| 		super(RunConfig::serverRunConfig); | 		super(project -> { | ||||||
|  | 			LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); | ||||||
|  | 			return RunConfig.runConfig(project, extension.getRuns().getByName("client")); | ||||||
|  | 		}); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -126,4 +126,12 @@ public class Constants { | ||||||
| 		private LaunchWrapper() { | 		private LaunchWrapper() { | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	public static final class Knot { | ||||||
|  | 		public static final String KNOT_CLIENT = "net.fabricmc.loader.launch.knot.KnotClient"; | ||||||
|  | 		public static final String KNOT_SERVER = "net.fabricmc.loader.launch.knot.KnotServer"; | ||||||
|  | 
 | ||||||
|  | 		private Knot() { | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -12,5 +12,5 @@ | ||||||
|     <stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="%PROGRAM_ARGS%"/> |     <stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="%PROGRAM_ARGS%"/> | ||||||
|     <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="%ECLIPSE_PROJECT%"/> |     <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="%ECLIPSE_PROJECT%"/> | ||||||
|     <stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="%VM_ARGS%"/> |     <stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="%VM_ARGS%"/> | ||||||
|     <stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${workspace_loc:%ECLIPSE_PROJECT%}/run"/> |     <stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${workspace_loc:%ECLIPSE_PROJECT%}/%RUN_DIRECTORY%"/> | ||||||
| </launchConfiguration> | </launchConfiguration> | ||||||
|  |  | ||||||
|  | @ -4,9 +4,9 @@ | ||||||
|     <module name="%IDEA_MODULE%" /> |     <module name="%IDEA_MODULE%" /> | ||||||
|     <option name="PROGRAM_PARAMETERS" value="%PROGRAM_ARGS%" /> |     <option name="PROGRAM_PARAMETERS" value="%PROGRAM_ARGS%" /> | ||||||
|     <option name="VM_PARAMETERS" value="%VM_ARGS%" /> |     <option name="VM_PARAMETERS" value="%VM_ARGS%" /> | ||||||
|     <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/run/" /> |     <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/%RUN_DIRECTORY%/" /> | ||||||
|     <method v="2"> |     <method v="2"> | ||||||
|       <option name="Make" enabled="true" /> |       <option name="Make" enabled="true" /> | ||||||
|     </method> |     </method> | ||||||
|   </configuration> |   </configuration> | ||||||
| </component> | </component> | ||||||
|  |  | ||||||
|  | @ -54,7 +54,7 @@ class MixinBuildFunctionalTest extends Specification { | ||||||
| 		when: | 		when: | ||||||
| 		def result = GradleRunner.create() | 		def result = GradleRunner.create() | ||||||
| 				.withProjectDir(testProjectDir.root) | 				.withProjectDir(testProjectDir.root) | ||||||
| 				.withArguments('build') | 				.withArguments('build','--stacktrace') | ||||||
| 				.withPluginClasspath() | 				.withPluginClasspath() | ||||||
| 				.forwardOutput() | 				.forwardOutput() | ||||||
| 				.build() | 				.build() | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue