diff options
Diffstat (limited to 'src/main/java/net/fabricmc/loom/configuration/ide')
3 files changed, 387 insertions, 0 deletions
| diff --git a/src/main/java/net/fabricmc/loom/configuration/ide/IdeConfiguration.java b/src/main/java/net/fabricmc/loom/configuration/ide/IdeConfiguration.java new file mode 100644 index 00000000..364981c1 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/ide/IdeConfiguration.java @@ -0,0 +1,42 @@ +/* + * 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 org.gradle.api.Project; +import org.gradle.plugins.ide.idea.model.IdeaModel; + +public final class IdeConfiguration { +	private IdeConfiguration() { +	} + +	public static void setup(Project project) { +		IdeaModel ideaModel = (IdeaModel) project.getExtensions().getByName("idea"); + +		ideaModel.getModule().getExcludeDirs().addAll(project.files(".gradle", "build", ".idea", "out").getFiles()); +		ideaModel.getModule().setDownloadJavadoc(true); +		ideaModel.getModule().setDownloadSources(true); +		ideaModel.getModule().setInheritOutputDirs(true); +	} +} diff --git a/src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java new file mode 100644 index 00000000..4b68da53 --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/ide/RunConfig.java @@ -0,0 +1,252 @@ +/* + * 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.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; +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.plugins.ide.eclipse.model.EclipseModel; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.util.Constants; +import net.fabricmc.loom.util.OperatingSystem; + +public class RunConfig { +	public String configName; +	public String eclipseProjectName; +	public String ideaModuleName; +	public String mainClass; +	public String runDir; +	public String vmArgs; +	public String programArgs; + +	public Element genRuns(Element doc) { +		Element root = this.addXml(doc, "component", ImmutableMap.of("name", "ProjectRunConfigurationManager")); +		root = addXml(root, "configuration", ImmutableMap.of("default", "false", "name", configName, "type", "Application", "factoryName", "Application")); + +		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)); + +		if (!Strings.isNullOrEmpty(vmArgs)) { +			this.addXml(root, "option", ImmutableMap.of("name", "VM_PARAMETERS", "value", vmArgs)); +		} + +		if (!Strings.isNullOrEmpty(programArgs)) { +			this.addXml(root, "option", ImmutableMap.of("name", "PROGRAM_PARAMETERS", "value", programArgs)); +		} + +		return root; +	} + +	public Element addXml(Node parent, String name, Map<String, String> values) { +		Document doc = parent.getOwnerDocument(); + +		if (doc == null) { +			doc = (Document) parent; +		} + +		Element e = doc.createElement(name); + +		for (Map.Entry<String, String> entry : values.entrySet()) { +			e.setAttribute(entry.getKey(), entry.getValue()); +		} + +		parent.appendChild(e); +		return e; +	} + +	private static String getIdeaModuleName(Project project) { +		String module = project.getName() + ".main"; + +		while ((project = project.getParent()) != null) { +			module = project.getName() + "." + module; +		} + +		return module; +	} + +	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 = ""; + +		if ("launchwrapper".equals(extension.getLoaderLaunchMethod())) { +			runConfig.mainClass = "net.minecraft.launchwrapper.Launch"; +			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"; +			runConfig.vmArgs = "-Dfabric.dli.config=" + encodeEscaped(extension.getDevLauncherConfig().getAbsolutePath()) + " -Dfabric.dli.env=" + mode.toLowerCase(); +		} + +		if (extension.getLoaderLaunchMethod().equals("launchwrapper")) { +			// if installer.json found... +			JsonObject installerJson = extension.getInstallerJson(); + +			if (installerJson != null) { +				List<String> sideKeys = ImmutableList.of(mode, "common"); + +				// copy launchwrapper tweakers +				if (installerJson.has("launchwrapper")) { +					JsonObject launchwrapperJson = installerJson.getAsJsonObject("launchwrapper"); + +					if (launchwrapperJson.has("tweakers")) { +						JsonObject tweakersJson = launchwrapperJson.getAsJsonObject("tweakers"); +						StringBuilder builder = new StringBuilder(); + +						for (String s : sideKeys) { +							if (tweakersJson.has(s)) { +								for (JsonElement element : tweakersJson.getAsJsonArray(s)) { +									builder.append(" --tweakClass ").append(element.getAsString()); +								} +							} +						} + +						runConfig.programArgs += builder.toString(); +					} +				} +			} +		} +	} + +	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); + +		return ideaClient; +	} + +	public static RunConfig serverRunConfig(Project project) { +		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); + +		RunConfig ideaServer = new RunConfig(); +		ideaServer.configName = "Minecraft Server"; +		ideaServer.programArgs = "nogui "; +		populate(project, extension, ideaServer, "server"); +		ideaServer.vmArgs += " -Dfabric.dli.main=" + getMainClass("server", extension); + +		return ideaServer; +	} + +	// 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")); +	} + +	public String fromDummy(String dummy) throws IOException { +		String dummyConfig; + +		try (InputStream input = SetupIntelijRunConfigs.class.getClassLoader().getResourceAsStream(dummy)) { +			dummyConfig = IOUtils.toString(input, StandardCharsets.UTF_8); +		} + +		dummyConfig = dummyConfig.replace("%NAME%", configName); +		dummyConfig = dummyConfig.replace("%MAIN_CLASS%", mainClass); +		dummyConfig = dummyConfig.replace("%ECLIPSE_PROJECT%", eclipseProjectName); +		dummyConfig = dummyConfig.replace("%IDEA_MODULE%", ideaModuleName); +		dummyConfig = dummyConfig.replace("%PROGRAM_ARGS%", programArgs.replaceAll("\"", """)); +		dummyConfig = dummyConfig.replace("%VM_ARGS%", vmArgs.replaceAll("\"", """)); + +		return dummyConfig; +	} + +	public static String getOSClientJVMArgs() { +		if (OperatingSystem.getOS().equalsIgnoreCase("osx")) { +			return " -XstartOnFirstThread"; +		} + +		return ""; +	} + +	private static String getMainClass(String side, LoomGradleExtension extension) { +		JsonObject installerJson = extension.getInstallerJson(); + +		if (installerJson != null && installerJson.has("mainClass")) { +			JsonElement mainClassJson = installerJson.get("mainClass"); + +			String mainClassName = ""; + +			if (mainClassJson.isJsonObject()) { +				JsonObject mainClassesJson = mainClassJson.getAsJsonObject(); + +				if (mainClassesJson.has(side)) { +					mainClassName = mainClassesJson.get(side).getAsString(); +				} +			} else { +				mainClassName = mainClassJson.getAsString(); +			} + +			return mainClassName; +		} + +		// Fallback to default class names, happens when in a loader dev env +		if ("launchwrapper".equals(extension.getLoaderLaunchMethod())) { +			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); +	} + +	private static String encodeEscaped(String s) { +		StringBuilder ret = new StringBuilder(); + +		for (int i = 0; i < s.length(); i++) { +			char c = s.charAt(i); + +			if (c == '@' && i > 0 && s.charAt(i - 1) == '@' || c == ' ') { +				ret.append(String.format("@@%04x", (int) c)); +			} else { +				ret.append(c); +			} +		} + +		return ret.toString(); +	} +} diff --git a/src/main/java/net/fabricmc/loom/configuration/ide/SetupIntelijRunConfigs.java b/src/main/java/net/fabricmc/loom/configuration/ide/SetupIntelijRunConfigs.java new file mode 100644 index 00000000..d2413f0d --- /dev/null +++ b/src/main/java/net/fabricmc/loom/configuration/ide/SetupIntelijRunConfigs.java @@ -0,0 +1,93 @@ +/* + * 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.io.IOException; +import java.nio.charset.StandardCharsets; + +import org.apache.commons.io.FileUtils; +import org.gradle.api.Project; + +import net.fabricmc.loom.LoomGradleExtension; +import net.fabricmc.loom.configuration.providers.minecraft.MinecraftNativesProvider; +import net.fabricmc.loom.configuration.providers.minecraft.assets.MinecraftAssetsProvider; + +public class SetupIntelijRunConfigs { +	public static void setup(Project project) { +		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); + +		File projectDir = project.getRootProject().file(".idea"); + +		if (!projectDir.exists()) { +			return; +		} + +		try { +			generate(project); +		} 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 { +		Project rootProject = project.getRootProject(); +		LoomGradleExtension extension = project.getExtensions().getByType(LoomGradleExtension.class); + +		if (extension.ideSync()) { +			//Ensures the assets are downloaded when idea is syncing a project +			MinecraftAssetsProvider.provide(extension.getMinecraftProvider(), project); +			MinecraftNativesProvider.provide(extension.getMinecraftProvider(), project); +		} + +		String projectPath = project == rootProject ? "" : project.getPath().replace(':', '_'); + +		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"); + +		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); +		} +	} +} | 
