diff options
Diffstat (limited to 'src/main/java/net/fabricmc/loom/configuration')
3 files changed, 372 insertions, 48 deletions
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 4b68da53..5acf4e78 100644 --- a/src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java +++ b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java @@ -24,12 +24,10 @@ package net.fabricmc.loom.configuration.ide; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.List; -import java.util.Locale; import java.util.Map; 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.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; import org.gradle.plugins.ide.eclipse.model.EclipseModel; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -54,6 +52,7 @@ public class RunConfig { public String eclipseProjectName; public String ideaModuleName; public String mainClass; + public String runDirIdeaUrl; public String runDir; public String vmArgs; public String programArgs; @@ -64,7 +63,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)); @@ -94,8 +93,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; @@ -107,12 +106,11 @@ 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.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"; @@ -149,35 +147,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); + // 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); + String configName = settings.getConfigName(); + String mode = settings.getMode(); + SourceSet sourceSet = settings.getSource(project); - return ideaServer; - } + String defaultMain = settings.getDefaultMainClass(); + + if (defaultMain == null) { + throw new IllegalArgumentException("Run configuration '" + name + "' must specify 'defaultMainClass'"); + } + + 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(); - // 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")); + return runConfig; } public String fromDummy(String dummy) throws IOException { @@ -191,6 +228,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("\"", """)); @@ -205,7 +243,7 @@ public class RunConfig { return ""; } - private static String getMainClass(String side, LoomGradleExtension extension) { + private static String getMainClass(String side, LoomGradleExtension extension, String defaultMainClass) { JsonObject installerJson = extension.getInstallerJson(); if (installerJson != null && installerJson.has("mainClass")) { @@ -231,7 +269,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..e28c4e62 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfigSettings.java @@ -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(); + } + } +} 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 d2413f0d..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,22 +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"); 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"); + for (RunConfigSettings settings : extension.getRuns()) { + RunConfig config = RunConfig.runConfig(project, settings); + String name = config.configName.replaceAll("[^a-zA-Z0-9$_]", "_"); - if (!clientRunConfigs.exists() || RunConfig.needsUpgrade(clientRunConfigs)) { - FileUtils.writeStringToFile(clientRunConfigs, clientRunConfig, StandardCharsets.UTF_8); - } + File runConfigs = new File(runConfigsDir, name + projectPath + ".xml"); + String runConfigXml = config.fromDummy("idea_run_config_template.xml"); + + if (!runConfigs.exists()) { + FileUtils.writeStringToFile(runConfigs, runConfigXml, StandardCharsets.UTF_8); + } - if (!serverRunConfigs.exists() || RunConfig.needsUpgrade(serverRunConfigs)) { - FileUtils.writeStringToFile(serverRunConfigs, serverRunConfig, StandardCharsets.UTF_8); + settings.makeRunDir(); } } } |
