diff options
Diffstat (limited to 'src/main')
21 files changed, 556 insertions, 217 deletions
| diff --git a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java index f26decb3..8d7b1a6c 100644 --- a/src/main/java/net/fabricmc/loom/LoomGradleExtension.java +++ b/src/main/java/net/fabricmc/loom/LoomGradleExtension.java @@ -44,17 +44,20 @@ import com.google.gson.JsonObject;  import org.cadixdev.lorenz.MappingSet;  import org.cadixdev.mercury.Mercury;  import org.gradle.api.Action; +import org.gradle.api.NamedDomainObjectContainer;  import org.gradle.api.Project;  import org.gradle.api.artifacts.Configuration;  import org.gradle.api.artifacts.Dependency;  import org.gradle.api.file.ConfigurableFileCollection;  import org.gradle.api.plugins.BasePluginConvention; +import org.jetbrains.annotations.ApiStatus;  import org.gradle.api.plugins.JavaPluginConvention;  import org.gradle.api.tasks.SourceSet;  import org.jetbrains.annotations.Nullable;  import net.fabricmc.loom.api.decompilers.LoomDecompiler;  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.JarProcessorManager;  import net.fabricmc.loom.configuration.providers.MinecraftProvider; @@ -72,7 +75,6 @@ import net.fabricmc.loom.util.function.LazyBool;  public class LoomGradleExtension {  	private static final String FORGE_PROPERTY = "loom.forge"; -	public String runDir = "run";  	public String refmapName;  	public String loaderLaunchMethod;  	public boolean remapMod = true; @@ -111,6 +113,8 @@ public class LoomGradleExtension {  		}  	}))); +	private NamedDomainObjectContainer<RunConfigSettings> runs; +  	/**  	 * Loom will generate a new genSources task (with a new name, based off of {@link LoomDecompiler#name()})  	 * that uses the specified decompiler instead. @@ -209,6 +213,8 @@ public class LoomGradleExtension {  		this.autoGenIDERuns = isRootProject();  		this.unmappedMods = project.files();  		this.forge = new LazyBool(() -> Boolean.parseBoolean(Objects.toString(project.findProperty(FORGE_PROPERTY)))); +		this.runs = project.container(RunConfigSettings.class, +				baseName -> new RunConfigSettings(project, baseName));  	}  	/** @@ -384,7 +390,7 @@ public class LoomGradleExtension {  	@Nullable  	private Dependency getMixinDependency() { -		return recurseProjects((p) -> { +		return recurseProjects(p -> {  			Set<Configuration> configs = new LinkedHashSet<>();  			// check compile classpath first  			Configuration possibleCompileClasspath = p.getConfigurations().findByName("compileClasspath"); @@ -401,11 +407,7 @@ public class LoomGradleExtension {  					return true;  				} -				if (name.equalsIgnoreCase("sponge-mixin") && group.equalsIgnoreCase("net.fabricmc")) { -					return true; -				} - -				return false; +				return name.equalsIgnoreCase("sponge-mixin") && group.equalsIgnoreCase("net.fabricmc");  			});  		});  	} @@ -561,4 +563,14 @@ public class LoomGradleExtension {  	public List<LoomDecompiler> getDecompilers() {  		return decompilers;  	} + +	@ApiStatus.Experimental +	public void runs(Action<NamedDomainObjectContainer<RunConfigSettings>> action) { +		action.execute(runs); +	} + +	@ApiStatus.Experimental +	public NamedDomainObjectContainer<RunConfigSettings> getRuns() { +		return runs; +	}  } diff --git a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java index cb7be779..d315f75c 100644 --- a/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java +++ b/src/main/java/net/fabricmc/loom/configuration/CompileConfiguration.java @@ -74,21 +74,6 @@ public final class CompileConfiguration {  	}  	public static void setupConfigurations(Project project) { -		// Force add Mojang and Forge repositories -		addMavenRepo(project, "Mojang", "https://libraries.minecraft.net/"); -		addMavenRepo(project, "Forge", "https://files.minecraftforge.net/maven/", repo -> { -			repo.metadataSources(sources -> { -				sources.mavenPom(); - -				try { -					MavenArtifactRepository.MetadataSources.class.getDeclaredMethod("ignoreGradleMetadataRedirection") -							.invoke(sources); -				} catch (Throwable ignored) { -					// Method not available -				} -			}); -		}); -  		Configuration modCompileClasspathConfig = project.getConfigurations().maybeCreate(Constants.Configurations.MOD_COMPILE_CLASSPATH);  		modCompileClasspathConfig.setTransitive(true);  		Configuration modCompileClasspathMappedConfig = project.getConfigurations().maybeCreate(Constants.Configurations.MOD_COMPILE_CLASSPATH_MAPPED); @@ -219,6 +204,17 @@ public final class CompileConfiguration {  			project1.getRepositories().maven(mavenArtifactRepository -> {  				mavenArtifactRepository.setName("Forge");  				mavenArtifactRepository.setUrl("https://files.minecraftforge.net/maven/"); + +				mavenArtifactRepository.metadataSources(sources -> { +					sources.mavenPom(); + +					try { +						MavenArtifactRepository.MetadataSources.class.getDeclaredMethod("ignoreGradleMetadataRedirection") +								.invoke(sources); +					} catch (Throwable ignored) { +						// Method not available +					} +				});  			});  			project1.getRepositories().mavenCentral(); diff --git a/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerJarProcessor.java b/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerJarProcessor.java index 91c4ee9d..ae73c145 100644 --- a/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerJarProcessor.java +++ b/src/main/java/net/fabricmc/loom/configuration/accesswidener/AccessWidenerJarProcessor.java @@ -32,6 +32,7 @@ import java.io.StringWriter;  import java.nio.charset.StandardCharsets;  import java.nio.file.Path;  import java.util.Arrays; +import java.util.List;  import java.util.Set;  import java.util.zip.ZipEntry; @@ -88,6 +89,12 @@ public class AccessWidenerJarProcessor implements JarProcessor {  		//Remap accessWidener if its not named, allows for AE's to be written in intermediary  		if (!accessWidener.getNamespace().equals("named")) {  			try { +				List<String> validNamespaces = loomGradleExtension.getMappingsProvider().getMappings().getMetadata().getNamespaces(); + +				if (!validNamespaces.contains(accessWidener.getNamespace())) { +					throw new UnsupportedOperationException(String.format("Access Widener namespace '%s' is not a valid namespace, it must be one of: '%s'", accessWidener.getNamespace(), String.join(", ", validNamespaces))); +				} +  				TinyRemapper tinyRemapper = loomGradleExtension.getMinecraftMappedProvider().getTinyRemapper(null, "official", "named");  				loomGradleExtension.getMinecraftMappedProvider();  				tinyRemapper.readClassPath(MinecraftMappedProvider.getRemapClasspath(project)); diff --git a/src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java index 1e75b56b..eb85934a 100644 --- a/src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java +++ b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java @@ -31,7 +31,6 @@ import java.nio.charset.StandardCharsets;  import java.util.ArrayList;  import java.util.HashMap;  import java.util.List; -import java.util.Locale;  import java.util.Map;  import java.util.UUID;  import java.util.function.Supplier; @@ -44,7 +43,6 @@ import com.google.common.collect.ImmutableList;  import com.google.common.collect.ImmutableMap;  import com.google.gson.JsonElement;  import com.google.gson.JsonObject; -import org.apache.commons.io.FileUtils;  import org.apache.commons.io.IOUtils;  import org.gradle.api.Project;  import org.gradle.api.tasks.SourceSet; @@ -63,6 +61,7 @@ public class RunConfig {  	public String ideaModuleName;  	public String vscodeProjectName;  	public String mainClass; +	public String runDirIdeaUrl;  	public String runDir;  	public String vmArgs;  	public String programArgs; @@ -75,7 +74,7 @@ public class RunConfig {  		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", "WORKING_DIRECTORY", "value", runDir)); +		this.addXml(root, "option", ImmutableMap.of("name", "WORKING_DIRECTORY", "value", runDirIdeaUrl));  		if (!Strings.isNullOrEmpty(vmArgs)) {  			this.addXml(root, "option", ImmutableMap.of("name", "VM_PARAMETERS", "value", vmArgs)); @@ -113,8 +112,8 @@ public class RunConfig {  		return e;  	} -	private static String getIdeaModuleName(Project project) { -		String module = project.getName() + ".main"; +	private static String getIdeaModuleName(Project project, SourceSet srcs) { +		String module = project.getName() + "." + srcs.getName();  		while ((project = project.getParent()) != null) {  			module = project.getName() + "." + module; @@ -126,13 +125,12 @@ public class RunConfig {  	private static void populate(Project project, LoomGradleExtension extension, RunConfig runConfig, String mode) {  		runConfig.configName += extension.isRootProject() ? "" : " (" + project.getPath() + ")";  		runConfig.eclipseProjectName = project.getExtensions().getByType(EclipseModel.class).getProject().getName(); -		runConfig.ideaModuleName = getIdeaModuleName(project);  		runConfig.vscodeProjectName = extension.isRootProject() ? "" : project.getPath(); -		runConfig.runDir = "file://$PROJECT_DIR$/" + extension.runDir;  		runConfig.vmArgs = ""; +		runConfig.programArgs = "";  		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);  		} else {  			runConfig.mainClass = "net.fabricmc.devlaunchinjector.Main"; @@ -186,50 +184,74 @@ public class RunConfig {  		}  	} -	public static RunConfig clientRunConfig(Project project) { -		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); - -		RunConfig ideaClient = new RunConfig(); -		ideaClient.configName = "Minecraft Client"; -		ideaClient.programArgs = ""; -		populate(project, extension, ideaClient, "client"); -		ideaClient.vmArgs += getOSClientJVMArgs(); -		ideaClient.vmArgs += " -Dfabric.dli.main=" + getMainClass("client", extension); -		ideaClient.vscodeBeforeRun = new ArrayList<>(extension.getTasksBeforeRun()); +	// Turns camelCase/PascalCase into Capital Case +	// caseConversionExample -> Case Conversion Example +	private static String capitalizeCamelCaseName(String name) { +		if (name.length() == 0) { +			return ""; +		} -		return ideaClient; +		return name.substring(0, 1).toUpperCase() + name.substring(1).replaceAll("([^A-Z])([A-Z])", "$1 $2");  	} -	public static RunConfig serverRunConfig(Project project) { +	public static RunConfig runConfig(Project project, RunConfigSettings settings) {  		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); +		String name = settings.getName(); -		RunConfig ideaServer = new RunConfig(); -		ideaServer.configName = "Minecraft Server"; -		ideaServer.programArgs = "nogui "; -		populate(project, extension, ideaServer, "server"); -		ideaServer.vmArgs += " -Dfabric.dli.main=" + getMainClass("server", extension); -		ideaServer.vscodeBeforeRun = new ArrayList<>(extension.getTasksBeforeRun()); +		String configName = settings.getConfigName(); +		String mode = settings.getMode(); +		SourceSet sourceSet = settings.getSource(project); -		return ideaServer; -	} +		String defaultMain = settings.getDefaultMainClass(); -	public static RunConfig dataRunConfig(Project project) { -		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); +		if (defaultMain == null) { +			throw new IllegalArgumentException("Run configuration '" + name + "' must specify 'defaultMainClass'"); +		} -		RunConfig ideaServer = new RunConfig(); -		ideaServer.configName = "Generate Data"; -		ideaServer.programArgs = ""; -		populate(project, extension, ideaServer, "data"); -		ideaServer.vmArgs += " -Dfabric.dli.main=" + getMainClass("data", extension); -		ideaServer.vscodeBeforeRun = new ArrayList<>(extension.getTasksBeforeRun()); +		if (configName == null) { +			configName = ""; +			String srcName = sourceSet.getName(); -		return ideaServer; -	} +			if (!srcName.equals(SourceSet.MAIN_SOURCE_SET_NAME)) { +				configName += capitalizeCamelCaseName(srcName) + " "; +			} + +			configName += "Minecraft " + capitalizeCamelCaseName(name); +		} + +		if (mode == null) { +			mode = name; +		} + +		String runDir = settings.getRunDir(); -	// This can be removed at somepoint, its not ideal but its the best solution I could thing of -	public static boolean needsUpgrade(File file) throws IOException { -		String contents = FileUtils.readFileToString(file, StandardCharsets.UTF_8); -		return !(contents.contains("net.fabricmc.devlaunchinjector.Main")); +		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 { @@ -243,6 +265,7 @@ public class RunConfig {  		dummyConfig = dummyConfig.replace("%MAIN_CLASS%", mainClass);  		dummyConfig = dummyConfig.replace("%ECLIPSE_PROJECT%", eclipseProjectName);  		dummyConfig = dummyConfig.replace("%IDEA_MODULE%", ideaModuleName); +		dummyConfig = dummyConfig.replace("%RUN_DIRECTORY%", runDir);  		dummyConfig = dummyConfig.replace("%PROGRAM_ARGS%", programArgs.replaceAll("\"", """));  		dummyConfig = dummyConfig.replace("%VM_ARGS%", vmArgs.replaceAll("\"", """)); @@ -276,11 +299,7 @@ public class RunConfig {  		return "";  	} -	private static String getMainClass(String side, LoomGradleExtension extension) { -		if (extension.isForge()) { -			return "net.minecraftforge.userdev.LaunchTesting"; -		} - +	private static String getMainClass(String side, LoomGradleExtension extension, String defaultMainClass) {  		JsonObject installerJson = extension.getInstallerJson();  		if (installerJson != null && installerJson.has("mainClass")) { @@ -306,7 +325,7 @@ public class RunConfig {  			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) { diff --git a/src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java new file mode 100644 index 00000000..1a3ff178 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java @@ -0,0 +1,299 @@ +/* + * 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(getExtension().isForge() ? Constants.ForgeUserDev.LAUNCH_TESTING : Constants.Knot.KNOT_CLIENT); +	} + +	/** +	 * Configure run config with the default server options. +	 */ +	public void server() { +		programArg("nogui"); +		mode("server"); +		defaultMainClass(getExtension().isForge() ? Constants.ForgeUserDev.LAUNCH_TESTING : Constants.Knot.KNOT_SERVER); +	} + +	/** +	 * Configure run config with the default server options. +	 */ +	public void data() { +		mode("data"); +		defaultMainClass(getExtension().isForge() ? Constants.ForgeUserDev.LAUNCH_TESTING : 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(); +		} +	} +} diff --git a/src/main/java/net/fabricmc/loom/configuration/ide/SetupIntelijRunConfigs.java b/src/main/java/net/fabricmc/loom/configuration/ide/SetupIntelijRunConfigs.java index 5cf04f9b..c531cee8 100644 --- a/src/main/java/net/fabricmc/loom/configuration/ide/SetupIntelijRunConfigs.java +++ b/src/main/java/net/fabricmc/loom/configuration/ide/SetupIntelijRunConfigs.java @@ -50,12 +50,6 @@ public class SetupIntelijRunConfigs {  		} catch (IOException 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 { @@ -72,31 +66,23 @@ public class SetupIntelijRunConfigs {  		File projectDir = rootProject.file(".idea");  		File runConfigsDir = new File(projectDir, "runConfigurations"); -		File clientRunConfigs = new File(runConfigsDir, "Minecraft_Client" + projectPath + ".xml"); -		File serverRunConfigs = new File(runConfigsDir, "Minecraft_Server" + projectPath + ".xml"); -		File dataRunConfigs = new File(runConfigsDir, "Minecraft_Data" + projectPath + ".xml");  		if (!runConfigsDir.exists()) {  			runConfigsDir.mkdirs();  		} -		String clientRunConfig = RunConfig.clientRunConfig(project).fromDummy("idea_run_config_template.xml"); -		String serverRunConfig = RunConfig.serverRunConfig(project).fromDummy("idea_run_config_template.xml"); - -		if (!clientRunConfigs.exists() || RunConfig.needsUpgrade(clientRunConfigs)) { -			FileUtils.writeStringToFile(clientRunConfigs, clientRunConfig, StandardCharsets.UTF_8); -		} - -		if (!serverRunConfigs.exists() || RunConfig.needsUpgrade(serverRunConfigs)) { -			FileUtils.writeStringToFile(serverRunConfigs, serverRunConfig, StandardCharsets.UTF_8); -		} +		for (RunConfigSettings settings : extension.getRuns()) { +			RunConfig config = RunConfig.runConfig(project, settings); +			String name = config.configName.replaceAll("[^a-zA-Z0-9$_]", "_"); -		if (extension.isDataGenEnabled()) { -			String dataRunConfig = RunConfig.dataRunConfig(project).fromDummy("idea_run_config_template.xml"); +			File runConfigs = new File(runConfigsDir, name + projectPath + ".xml"); +			String runConfigXml = config.fromDummy("idea_run_config_template.xml"); -			if (!dataRunConfigs.exists() || RunConfig.needsUpgrade(dataRunConfigs)) { -				FileUtils.writeStringToFile(dataRunConfigs, dataRunConfig, StandardCharsets.UTF_8); +			if (!runConfigs.exists()) { +				FileUtils.writeStringToFile(runConfigs, runConfigXml, StandardCharsets.UTF_8);  			} + +			settings.makeRunDir();  		}  	}  } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/MinecraftProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/MinecraftProvider.java index a36e7355..8d0a8d5e 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/MinecraftProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/MinecraftProvider.java @@ -31,8 +31,6 @@ import java.net.URL;  import java.nio.charset.StandardCharsets;  import java.util.Optional;  import java.util.function.Consumer; -import java.util.regex.Matcher; -import java.util.regex.Pattern;  import java.util.zip.ZipError;  import com.google.common.io.Files; @@ -178,13 +176,11 @@ public class MinecraftProvider extends DependencyProvider {  			} else {  				getProject().getLogger().debug("Downloading Minecraft {} manifest", minecraftVersion); -				String url = optionalVersion.get().url; -				// Find the sha1 of the json from the url, return true if it matches the local json -				Pattern sha1Pattern = Pattern.compile("\\b[0-9a-f]{5,40}\\b"); -				Matcher matcher = sha1Pattern.matcher(url); +				ManifestVersion.Versions version = optionalVersion.get(); +				String url = version.url; -				if (matcher.find()) { -					HashedDownloadUtil.downloadIfInvalid(new URL(url), minecraftJson, matcher.group(), getProject().getLogger(), true); +				if (version.sha1 != null) { +					HashedDownloadUtil.downloadIfInvalid(new URL(url), minecraftJson, version.sha1, getProject().getLogger(), true);  				} else {  					// Use the etag if no hash found from url  					DownloadUtil.downloadIfChanged(new URL(url), minecraftJson, getProject().getLogger()); diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/ManifestVersion.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/ManifestVersion.java index 4cc2e33e..8ab01007 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/ManifestVersion.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/ManifestVersion.java @@ -31,6 +31,6 @@ public class ManifestVersion {  	public List<Versions> versions = new ArrayList<>();  	public static class Versions { -		public String id, url; +		public String id, url, sha1;  	}  } diff --git a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/assets/MinecraftAssetsProvider.java b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/assets/MinecraftAssetsProvider.java index ee4d9448..b1913436 100644 --- a/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/assets/MinecraftAssetsProvider.java +++ b/src/main/java/net/fabricmc/loom/configuration/providers/minecraft/assets/MinecraftAssetsProvider.java @@ -30,23 +30,23 @@ import java.io.FileWriter;  import java.io.IOException;  import java.net.URL;  import java.util.Deque; +import java.util.HashMap;  import java.util.Map; -import java.util.concurrent.ConcurrentHashMap;  import java.util.concurrent.ConcurrentLinkedDeque;  import java.util.concurrent.ExecutorService;  import java.util.concurrent.Executors;  import java.util.concurrent.TimeUnit; -import au.com.bytecode.opencsv.CSVReader; -import au.com.bytecode.opencsv.CSVWriter;  import com.google.common.base.Stopwatch;  import com.google.common.hash.Hashing;  import com.google.common.io.Files;  import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken;  import org.gradle.api.GradleException;  import org.gradle.api.Project;  import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.LoomGradlePlugin;  import net.fabricmc.loom.configuration.providers.MinecraftProvider;  import net.fabricmc.loom.configuration.providers.minecraft.MinecraftVersionInfo;  import net.fabricmc.loom.util.Checksum; @@ -70,7 +70,7 @@ public class MinecraftAssetsProvider {  		}  		File assetsInfo = new File(assets, "indexes" + File.separator + assetIndex.getFabricId(minecraftProvider.getMinecraftVersion()) + ".json"); -		File checksumInfo = new File(assets, "checksum" + File.separator + minecraftProvider.getMinecraftVersion() + ".csv"); +		File checksumInfo = new File(assets, "checksum" + File.separator + minecraftProvider.getMinecraftVersion() + ".json");  		if (!assetsInfo.exists() || !Checksum.equals(assetsInfo, assetIndex.sha1)) {  			project.getLogger().lifecycle(":downloading asset index"); @@ -88,50 +88,46 @@ public class MinecraftAssetsProvider {  			}  		} -		Map<String, AssetChecksumInfo> checksumInfos = new ConcurrentHashMap<>(); +		Gson gson = new Gson(); +		Map<String, String> checksumInfos = new HashMap<>();  		if (checksumInfo.exists()) { -			try (CSVReader reader = new CSVReader(new FileReader(checksumInfo))) { -				String[] strings; - -				while ((strings = reader.readNext()) != null) { -					checksumInfos.put(strings[0], new AssetChecksumInfo(strings[1], Long.parseLong(strings[2]))); -				} +			try (FileReader reader = new FileReader(checksumInfo)) { +				checksumInfos.putAll(gson.fromJson(reader, new TypeToken<Map<String, String>>() { +				}.getType()));  			}  		} -		project.getLogger().lifecycle(":downloading assets..."); -  		Deque<ProgressLogger> loggers = new ConcurrentLinkedDeque<>();  		ExecutorService executor = Executors.newFixedThreadPool(Math.min(10, Math.max(Runtime.getRuntime().availableProcessors() / 2, 1))); +		int toDownload = 0;  		AssetIndex index;  		try (FileReader fileReader = new FileReader(assetsInfo)) { -			index = new Gson().fromJson(fileReader, AssetIndex.class); +			index = gson.fromJson(fileReader, AssetIndex.class);  		}  		Stopwatch stopwatch = Stopwatch.createStarted();  		Map<String, AssetObject> parent = index.getFileMap(); -		parent.entrySet().parallelStream().forEach(entry -> { +		for (Map.Entry<String, AssetObject> entry : parent.entrySet()) {  			AssetObject object = entry.getValue();  			String sha1 = object.getHash();  			String filename = "objects" + File.separator + sha1.substring(0, 2) + File.separator + sha1;  			File file = new File(assets, filename); -			long localFileLength = !file.exists() ? -1L : file.length(); -			AssetChecksumInfo localFileChecksum = localFileLength == -1L ? null : checksumInfos.computeIfAbsent(entry.getKey(), path -> { +			String localFileChecksum = !file.exists() ? null : checksumInfos.computeIfAbsent(entry.getKey(), path -> {  				try { -					return new AssetChecksumInfo(Files.asByteSource(file).hash(Hashing.sha1()).toString(), localFileLength); +					return Files.asByteSource(file).hash(Hashing.sha1()).toString();  				} catch (IOException e) {  					e.printStackTrace();  					return null;  				}  			}); -			if (localFileChecksum == null || localFileChecksum.length != localFileLength || !localFileChecksum.sha1.equals(sha1)) { +			if (LoomGradlePlugin.refreshDeps || localFileChecksum == null || !localFileChecksum.equals(sha1)) {  				if (offline) {  					if (file.exists()) {  						project.getLogger().warn("Outdated asset " + entry.getKey()); @@ -139,6 +135,7 @@ public class MinecraftAssetsProvider {  						throw new GradleException("Asset " + entry.getKey() + " not found at " + file.getAbsolutePath());  					}  				} else { +					toDownload++;  					executor.execute(() -> {  						ProgressLogger progressLogger; @@ -167,12 +164,8 @@ public class MinecraftAssetsProvider {  							throw new RuntimeException("Failed to download: " + assetName, e);  						} -						try { -							if (localFileChecksum == null) { -								checksumInfos.put(entry.getKey(), new AssetChecksumInfo(Files.asByteSource(file).hash(Hashing.sha1()).toString(), file.length())); -							} -						} catch (IOException e) { -							throw new RuntimeException("Failed to save checksum: " + assetName, e); +						if (localFileChecksum == null) { +							checksumInfos.put(entry.getKey(), sha1);  						}  						//Give this logger back @@ -180,22 +173,18 @@ public class MinecraftAssetsProvider {  					});  				}  			} -		}); +		}  		project.getLogger().info("Took " + stopwatch.stop() + " to iterate " + parent.size() + " asset index."); -		{ -			checksumInfo.getParentFile().mkdirs(); +		if (toDownload > 0) { +			project.getLogger().lifecycle(":downloading " + toDownload + " asset" + (toDownload == 1 ? "" : "s") + "..."); +		} + +		checksumInfo.getParentFile().mkdirs(); -			try (CSVWriter writer = new CSVWriter(new FileWriter(checksumInfo))) { -				checksumInfos.forEach((path, info) -> { -					writer.writeNext(new String[] { -							path, -							info.sha1, -							String.valueOf(info.length) -					}); -				}); -			} +		try (FileWriter writer = new FileWriter(checksumInfo)) { +			gson.toJson(checksumInfos, writer);  		}  		//Wait for the assets to all download @@ -211,14 +200,4 @@ public class MinecraftAssetsProvider {  		loggers.forEach(ProgressLogger::completed);  	} - -	private static class AssetChecksumInfo { -		public final String sha1; -		public long length; - -		AssetChecksumInfo(String sha1, long length) { -			this.sha1 = sha1; -			this.length = length; -		} -	}  } diff --git a/src/main/java/net/fabricmc/loom/task/AbstractRunTask.java b/src/main/java/net/fabricmc/loom/task/AbstractRunTask.java index 551bd58a..5f47cc17 100644 --- a/src/main/java/net/fabricmc/loom/task/AbstractRunTask.java +++ b/src/main/java/net/fabricmc/loom/task/AbstractRunTask.java @@ -45,6 +45,9 @@ public abstract class AbstractRunTask extends JavaExec {  		super();  		setGroup("fabric");  		this.configProvider = config; + +		classpath(getProject().getConfigurations().getByName("runtimeClasspath")); +		classpath(this.getProject().getExtensions().getByType(LoomGradleExtension.class).getUnmappedModCollection());  	}  	@Override @@ -53,9 +56,6 @@ public abstract class AbstractRunTask extends JavaExec {  			config = configProvider.apply(getProject());  		} -		classpath(getProject().getConfigurations().getByName("runtimeClasspath")); -		classpath(this.getProject().getExtensions().getByType(LoomGradleExtension.class).getUnmappedModCollection()); -  		List<String> argsSplit = new ArrayList<>();  		String[] args = config.programArgs.split(" ");  		int partPos = -1; @@ -85,8 +85,7 @@ public abstract class AbstractRunTask extends JavaExec {  		}  		args(argsSplit); -		LoomGradleExtension extension = this.getProject().getExtensions().getByType(LoomGradleExtension.class); -		setWorkingDir(new File(getProject().getRootDir(), extension.runDir)); +		setWorkingDir(new File(getProject().getRootDir(), config.runDir));  		environment(config.envVariables);  		super.exec(); diff --git a/src/main/java/net/fabricmc/loom/task/GenEclipseRunsTask.java b/src/main/java/net/fabricmc/loom/task/GenEclipseRunsTask.java index 0896c4bf..1f93ef0b 100644 --- a/src/main/java/net/fabricmc/loom/task/GenEclipseRunsTask.java +++ b/src/main/java/net/fabricmc/loom/task/GenEclipseRunsTask.java @@ -32,39 +32,29 @@ import org.apache.commons.io.FileUtils;  import org.gradle.api.tasks.TaskAction;  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.RunConfigSettings;  public class GenEclipseRunsTask extends AbstractLoomTask {  	@TaskAction  	public void genRuns() throws IOException {  		EclipseModel eclipseModel = getProject().getExtensions().getByType(EclipseModel.class); -		File clientRunConfigs = new File(getProject().getRootDir(), eclipseModel.getProject().getName() + "_client.launch"); -		File serverRunConfigs = new File(getProject().getRootDir(), eclipseModel.getProject().getName() + "_server.launch"); +		LoomGradleExtension extension = getExtension();  		File dataRunConfigs = new File(getProject().getRootDir(), eclipseModel.getProject().getName() + "_data.launch"); -		String clientRunConfig = RunConfig.clientRunConfig(getProject()).fromDummy("eclipse_run_config_template.xml"); -		String serverRunConfig = RunConfig.serverRunConfig(getProject()).fromDummy("eclipse_run_config_template.xml"); +		for (RunConfigSettings settings : extension.getRuns()) { +			String name = settings.getName(); -		if (!clientRunConfigs.exists() || RunConfig.needsUpgrade(clientRunConfigs)) { -			FileUtils.writeStringToFile(clientRunConfigs, clientRunConfig, StandardCharsets.UTF_8); -		} - -		if (!serverRunConfigs.exists() || RunConfig.needsUpgrade(serverRunConfigs)) { -			FileUtils.writeStringToFile(serverRunConfigs, serverRunConfig, StandardCharsets.UTF_8); -		} +			File configs = new File(getProject().getRootDir(), eclipseModel.getProject().getName() + "_" + name + ".launch"); +			RunConfig configInst = RunConfig.runConfig(getProject(), settings); +			String config = configInst.fromDummy("eclipse_run_config_template.xml"); -		if (getExtension().isDataGenEnabled()) { -			String dataRunConfig = RunConfig.dataRunConfig(getProject()).fromDummy("eclipse_run_config_template.xml"); - -			if (!dataRunConfigs.exists() || RunConfig.needsUpgrade(dataRunConfigs)) { -				FileUtils.writeStringToFile(dataRunConfigs, dataRunConfig, StandardCharsets.UTF_8); +			if (!configs.exists()) { +				FileUtils.writeStringToFile(configs, config, StandardCharsets.UTF_8);  			} -		} - -		File runDir = new File(getProject().getRootDir(), getExtension().runDir); -		if (!runDir.exists()) { -			runDir.mkdirs(); +			settings.makeRunDir();  		}  	}  } diff --git a/src/main/java/net/fabricmc/loom/task/GenIdeaProjectTask.java b/src/main/java/net/fabricmc/loom/task/GenIdeaProjectTask.java index cd5fbe52..8ad3586b 100644 --- a/src/main/java/net/fabricmc/loom/task/GenIdeaProjectTask.java +++ b/src/main/java/net/fabricmc/loom/task/GenIdeaProjectTask.java @@ -46,6 +46,7 @@ import org.xml.sax.SAXException;  import net.fabricmc.loom.LoomGradleExtension;  import net.fabricmc.loom.configuration.ide.RunConfig; +import net.fabricmc.loom.configuration.ide.RunConfigSettings;  public class GenIdeaProjectTask extends AbstractLoomTask {  	@TaskAction @@ -82,11 +83,9 @@ public class GenIdeaProjectTask extends AbstractLoomTask {  			throw new RuntimeException("Failed to generate IntelliJ run configurations (runManager was not found)");  		} -		runManager.appendChild(RunConfig.clientRunConfig(project).genRuns(runManager)); -		runManager.appendChild(RunConfig.serverRunConfig(project).genRuns(runManager)); - -		if (extension.isDataGenEnabled()) { -			runManager.appendChild(RunConfig.dataRunConfig(project).genRuns(runManager)); +		for (RunConfigSettings settings : getExtension().getRuns()) { +			runManager.appendChild(RunConfig.runConfig(project, settings).genRuns(runManager)); +			settings.makeRunDir();  		}  		TransformerFactory transformerFactory = TransformerFactory.newInstance(); @@ -96,11 +95,5 @@ public class GenIdeaProjectTask extends AbstractLoomTask {  		transformer.setOutputProperty(OutputKeys.INDENT, "yes");  		transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");  		transformer.transform(source, result); - -		File runDir = new File(getProject().getRootDir(), extension.runDir); - -		if (!runDir.exists()) { -			runDir.mkdirs(); -		}  	}  } diff --git a/src/main/java/net/fabricmc/loom/task/GenVsCodeProjectTask.java b/src/main/java/net/fabricmc/loom/task/GenVsCodeProjectTask.java index d1fe52b9..e6ea643f 100644 --- a/src/main/java/net/fabricmc/loom/task/GenVsCodeProjectTask.java +++ b/src/main/java/net/fabricmc/loom/task/GenVsCodeProjectTask.java @@ -43,6 +43,7 @@ import org.gradle.api.tasks.TaskAction;  import net.fabricmc.loom.LoomGradleExtension;  import net.fabricmc.loom.configuration.ide.RunConfig; +import net.fabricmc.loom.configuration.ide.RunConfigSettings;  // Recommended vscode plugins:  // https://marketplace.visualstudio.com/items?itemName=redhat.java @@ -94,11 +95,9 @@ public class GenVsCodeProjectTask extends AbstractLoomTask {  			launch = new VsCodeLaunch();  		} -		launch.add(RunConfig.clientRunConfig(project)); -		launch.add(RunConfig.serverRunConfig(project)); - -		if (extension.isDataGenEnabled()) { -			launch.add(RunConfig.dataRunConfig(project)); +		for (RunConfigSettings settings : extension.getRuns()) { +			launch.add(RunConfig.runConfig(project, settings)); +			settings.makeRunDir();  		}  		String json = gson.toJson(launch); @@ -109,12 +108,6 @@ public class GenVsCodeProjectTask extends AbstractLoomTask {  			throw new RuntimeException("Failed to write launch.json", e);  		} -		File runDir = new File(project.getRootDir(), extension.runDir); - -		if (!runDir.exists()) { -			runDir.mkdirs(); -		} -  		VsCodeTasks tasks;  		if (tasksJson.exists()) { @@ -181,7 +174,7 @@ public class GenVsCodeProjectTask extends AbstractLoomTask {  		public String type = "java";  		public String name;  		public String request = "launch"; -		public String cwd = "${workspaceFolder}/run"; +		public String cwd;  		public String console = "internalConsole";  		public boolean stopOnEntry = false;  		public String mainClass; @@ -197,6 +190,7 @@ public class GenVsCodeProjectTask extends AbstractLoomTask {  			this.mainClass = runConfig.mainClass;  			this.vmArgs = runConfig.vmArgs;  			this.args = runConfig.programArgs; +			this.cwd = "${workspaceFolder}/" + runConfig.runDir;  			this.projectName = runConfig.vscodeProjectName;  			this.env.putAll(runConfig.envVariables);  			this.tasksBeforeRun.addAll(runConfig.vscodeBeforeRun); diff --git a/src/main/java/net/fabricmc/loom/task/LoomTasks.java b/src/main/java/net/fabricmc/loom/task/LoomTasks.java index e17ad8e6..0fdd28cd 100644 --- a/src/main/java/net/fabricmc/loom/task/LoomTasks.java +++ b/src/main/java/net/fabricmc/loom/task/LoomTasks.java @@ -29,6 +29,7 @@ import org.gradle.api.tasks.TaskContainer;  import net.fabricmc.loom.LoomGradleExtension;  import net.fabricmc.loom.api.decompilers.LoomDecompiler; +import net.fabricmc.loom.configuration.ide.RunConfigSettings;  import net.fabricmc.loom.decompilers.fernflower.FabricFernFlowerDecompiler;  public final class LoomTasks { @@ -40,7 +41,7 @@ public final class LoomTasks {  		tasks.register("migrateMappings", MigrateMappingsTask.class, t -> {  			t.setDescription("Migrates mappings to a new version."); -			t.getOutputs().upToDateWhen((o) -> false); +			t.getOutputs().upToDateWhen(o -> false);  		});  		tasks.register("remapJar", RemapJarTask.class, t -> { @@ -84,21 +85,22 @@ public final class LoomTasks {  	private static void registerRunTasks(TaskContainer tasks, Project project) {  		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); -		tasks.register("runClient", RunClientTask.class, t -> { -			t.setDescription("Starts a development version of the Minecraft client."); -			t.dependsOn("downloadAssets"); -			t.setGroup("fabric"); -		}); +		extension.getRuns().create("client", RunConfigSettings::client); +		extension.getRuns().create("server", RunConfigSettings::server); -		tasks.register("runServer", RunServerTask.class, t -> { -			t.setDescription("Starts a development version of the Minecraft server."); -			t.setGroup("fabric"); +		project.afterEvaluate(p -> { +			if (extension.isDataGenEnabled()) { +				extension.getRuns().create("data", RunConfigSettings::data); +			}  		});  		project.afterEvaluate(p -> { -			if (extension.isDataGenEnabled()) { -				tasks.register("runData", RunDataTask.class, t -> { -					t.setDescription("Starts a development version of the Minecraft data."); +			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");  				});  			} @@ -108,9 +110,9 @@ public final class LoomTasks {  	private static void registerDecompileTasks(TaskContainer tasks, Project project) {  		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); -		project.afterEvaluate((p) -> { +		project.afterEvaluate(p -> {  			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  				tasks.register(taskName, GenerateSourcesTask.class, decompiler);  			} diff --git a/src/main/java/net/fabricmc/loom/task/RunClientTask.java b/src/main/java/net/fabricmc/loom/task/RunClientTask.java index de0cc377..0bfaca0c 100644 --- a/src/main/java/net/fabricmc/loom/task/RunClientTask.java +++ b/src/main/java/net/fabricmc/loom/task/RunClientTask.java @@ -24,10 +24,15 @@  package net.fabricmc.loom.task; +import net.fabricmc.loom.LoomGradleExtension;  import net.fabricmc.loom.configuration.ide.RunConfig; +@Deprecated // Replaced by RunGameTask  public class RunClientTask extends AbstractRunTask {  	public RunClientTask() { -		super(RunConfig::clientRunConfig); +		super(project -> { +			LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); +			return RunConfig.runConfig(project, extension.getRuns().getByName("client")); +		});  	}  } diff --git a/src/main/java/net/fabricmc/loom/task/RunDataTask.java b/src/main/java/net/fabricmc/loom/task/RunDataTask.java index 01f62884..fbb80951 100644 --- a/src/main/java/net/fabricmc/loom/task/RunDataTask.java +++ b/src/main/java/net/fabricmc/loom/task/RunDataTask.java @@ -24,10 +24,15 @@  package net.fabricmc.loom.task; +import net.fabricmc.loom.LoomGradleExtension;  import net.fabricmc.loom.configuration.ide.RunConfig; +@Deprecated // Replaced by RunGameTask  public class RunDataTask extends AbstractRunTask {  	public RunDataTask() { -		super(RunConfig::dataRunConfig); +		super(project -> { +			LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); +			return RunConfig.runConfig(project, extension.getRuns().getByName("data")); +		});  	}  } diff --git a/src/main/java/net/fabricmc/loom/task/RunGameTask.java b/src/main/java/net/fabricmc/loom/task/RunGameTask.java new file mode 100644 index 00000000..f82352a0 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/task/RunGameTask.java @@ -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)); +	} +} diff --git a/src/main/java/net/fabricmc/loom/task/RunServerTask.java b/src/main/java/net/fabricmc/loom/task/RunServerTask.java index 977b65c7..aa9fc94a 100644 --- a/src/main/java/net/fabricmc/loom/task/RunServerTask.java +++ b/src/main/java/net/fabricmc/loom/task/RunServerTask.java @@ -24,10 +24,15 @@  package net.fabricmc.loom.task; +import net.fabricmc.loom.LoomGradleExtension;  import net.fabricmc.loom.configuration.ide.RunConfig; +@Deprecated // Replaced by RunGameTask  public class RunServerTask extends AbstractRunTask {  	public RunServerTask() { -		super(RunConfig::serverRunConfig); +		super(project -> { +			LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); +			return RunConfig.runConfig(project, extension.getRuns().getByName("client")); +		});  	}  } diff --git a/src/main/java/net/fabricmc/loom/util/Constants.java b/src/main/java/net/fabricmc/loom/util/Constants.java index eb37930e..0ff48728 100644 --- a/src/main/java/net/fabricmc/loom/util/Constants.java +++ b/src/main/java/net/fabricmc/loom/util/Constants.java @@ -136,4 +136,19 @@ public class Constants {  		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() { +		} +	} +	 +	public static final class ForgeUserDev { +		public static final String LAUNCH_TESTING = "net.minecraftforge.userdev.LaunchTesting"; + +		private ForgeUserDev() { +		} +	}  } diff --git a/src/main/resources/eclipse_run_config_template.xml b/src/main/resources/eclipse_run_config_template.xml index c8697299..cff2835c 100644 --- a/src/main/resources/eclipse_run_config_template.xml +++ b/src/main/resources/eclipse_run_config_template.xml @@ -12,5 +12,5 @@      <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.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> diff --git a/src/main/resources/idea_run_config_template.xml b/src/main/resources/idea_run_config_template.xml index f462051d..6b71bd71 100644 --- a/src/main/resources/idea_run_config_template.xml +++ b/src/main/resources/idea_run_config_template.xml @@ -5,7 +5,7 @@      <module name="%IDEA_MODULE%" />      <option name="PROGRAM_PARAMETERS" value="%PROGRAM_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">        <option name="Make" enabled="true" />      </method> | 
