From 3003e3307425ade9dc4dbebe2069b2534c7e5157 Mon Sep 17 00:00:00 2001 From: LexManos Date: Wed, 6 Mar 2019 20:59:32 -0800 Subject: [PATCH] Refactor Userdev and Forgedev launching. Locating mods on the classpath in dev should solve linked MC sources when debugging. As well as loading deobfed mods. Rewrote how arguments are handled in dev, so users can overwrite any defaults we provide. Added basic Yggdrasil auth support. Passing in --username and --password arguments. ONLY USE IF NECESSARY. Forge is NOT responsible for your login information. --- build.gradle | 32 ++-- .../fml/loading/LauncherVersion.java | 2 +- .../fml/loading/LibraryFinder.java | 2 - ...mods.modlauncher.api.ILaunchHandlerService | 2 - .../net/minecraftforge/fml/LaunchTesting.java | 99 ---------- .../fml/common/launcher/Yggdrasil.java | 60 ------ .../versions/forge/ForgeVersion.java | 8 +- .../versions/mcp/MCPVersion.java | 4 +- .../minecraftforge/userdev/ArgumentList.java | 175 ++++++++++++++++++ .../userdev/ClasspathLocator.java | 77 ++++++++ .../userdev}/FMLDevClientLaunchProvider.java | 5 +- .../userdev}/FMLDevServerLaunchProvider.java | 6 +- .../userdev/FMLUserdevLaunchProvider.java | 46 ++--- .../minecraftforge/userdev/LaunchTesting.java | 143 ++++++++++++++ .../userdev/UserdevLauncher.java | 109 ----------- ...mods.modlauncher.api.ILaunchHandlerService | 4 +- ...forge.fml.loading.moddiscovery.IModLocator | 1 + 17 files changed, 440 insertions(+), 335 deletions(-) delete mode 100644 src/main/java/net/minecraftforge/fml/LaunchTesting.java delete mode 100644 src/main/java/net/minecraftforge/fml/common/launcher/Yggdrasil.java create mode 100644 src/userdev/java/net/minecraftforge/userdev/ArgumentList.java create mode 100644 src/userdev/java/net/minecraftforge/userdev/ClasspathLocator.java rename src/{fmllauncher/java/net/minecraftforge/fml/loading => userdev/java/net/minecraftforge/userdev}/FMLDevClientLaunchProvider.java (96%) rename src/{fmllauncher/java/net/minecraftforge/fml/loading => userdev/java/net/minecraftforge/userdev}/FMLDevServerLaunchProvider.java (95%) create mode 100644 src/userdev/java/net/minecraftforge/userdev/LaunchTesting.java delete mode 100644 src/userdev/java/net/minecraftforge/userdev/UserdevLauncher.java create mode 100644 src/userdev/resources/META-INF/services/net.minecraftforge.fml.loading.moddiscovery.IModLocator diff --git a/build.gradle b/build.gradle index 0f5bbc729..812681ade 100644 --- a/build.gradle +++ b/build.gradle @@ -192,7 +192,7 @@ project(':forge') { forge_client { taskName 'forge_client' - main 'net.minecraftforge.fml.LaunchTesting' + main 'net.minecraftforge.userdev.LaunchTesting' workingDirectory project.file('run') environment 'target', 'fmldevclient' @@ -200,30 +200,30 @@ project(':forge') { environment 'assetDirectory', downloadAssets.output environment 'nativesDirectory', extractNatives.output - property 'mc.version', MC_VERSION - property 'forge.spec', SPEC_VERSION - property 'mcp.version', MCP_VERSION - property 'forge.group', project.group - property 'forge.version', project.version.substring(MC_VERSION.length() + 1).toString() + environment 'MC_VERSION', MC_VERSION + environment 'MCP_VERSION', MCP_VERSION + environment 'FORGE_GROUP', project.group + environment 'FORGE_SPEC', SPEC_VERSION + environment 'FORGE_VERSION', project.version.substring(MC_VERSION.length() + 1).toString() + environment 'LAUNCHER_VERSION', SPEC_VERSION property 'terminal.ansi', 'true' - property 'fmllauncher.version', SPEC_VERSION property 'org.lwjgl.system.SharedLibraryExtractDirectory', 'lwjgl_dll' } forge_server { taskName 'forge_server' - main 'net.minecraftforge.fml.LaunchTesting' + main 'net.minecraftforge.userdev.LaunchTesting' workingDirectory project.file('run') environment 'target', 'fmldevserver' - property 'mc.version', MC_VERSION - property 'forge.spec', SPEC_VERSION - property 'mcp.version', MCP_VERSION - property 'forge.group', project.group - property 'forge.version', project.version.substring(MC_VERSION.length() + 1).toString() - property 'fmllauncher.version', SPEC_VERSION + environment 'MC_VERSION', MC_VERSION + environment 'MCP_VERSION', MCP_VERSION + environment 'FORGE_GROUP', project.group + environment 'FORGE_SPEC', SPEC_VERSION + environment 'FORGE_VERSION', project.version.substring(MC_VERSION.length() + 1).toString() + environment 'LAUNCHER_VERSION', SPEC_VERSION } } } @@ -793,7 +793,7 @@ project(':forge') { addLibrary("${project.group}:${project.name}:${project.version}:launcher") runs { client { - main 'net.minecraftforge.userdev.UserdevLauncher' + main 'net.minecraftforge.userdev.LaunchTesting' environment 'target', 'fmluserdevclient' environment 'assetIndex', '{asset_index}' @@ -809,7 +809,7 @@ project(':forge') { } server { - main 'net.minecraftforge.userdev.UserdevLauncher' + main 'net.minecraftforge.userdev.LaunchTesting' environment 'target', 'fmluserdevserver' diff --git a/src/fmllauncher/java/net/minecraftforge/fml/loading/LauncherVersion.java b/src/fmllauncher/java/net/minecraftforge/fml/loading/LauncherVersion.java index 5f8286756..7868b3489 100644 --- a/src/fmllauncher/java/net/minecraftforge/fml/loading/LauncherVersion.java +++ b/src/fmllauncher/java/net/minecraftforge/fml/loading/LauncherVersion.java @@ -29,7 +29,7 @@ public class LauncherVersion { private static final String launcherVersion; static { - String vers = JarVersionLookupHandler.getImplementationVersion(LauncherVersion.class).orElse(System.getProperty("fmllauncher.version")); + String vers = JarVersionLookupHandler.getImplementationVersion(LauncherVersion.class).orElse(System.getenv("LAUNCHER_VERSION")); if (vers == null) throw new RuntimeException("Missing FMLLauncher version, cannot continue"); launcherVersion = vers; LOGGER.debug(CORE, "Found FMLLauncher version {}", launcherVersion); diff --git a/src/fmllauncher/java/net/minecraftforge/fml/loading/LibraryFinder.java b/src/fmllauncher/java/net/minecraftforge/fml/loading/LibraryFinder.java index 11ea803ed..a047c88d0 100644 --- a/src/fmllauncher/java/net/minecraftforge/fml/loading/LibraryFinder.java +++ b/src/fmllauncher/java/net/minecraftforge/fml/loading/LibraryFinder.java @@ -19,11 +19,9 @@ package net.minecraftforge.fml.loading; -import com.google.common.collect.ObjectArrays; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import java.io.File; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; diff --git a/src/fmllauncher/resources/META-INF/services/cpw.mods.modlauncher.api.ILaunchHandlerService b/src/fmllauncher/resources/META-INF/services/cpw.mods.modlauncher.api.ILaunchHandlerService index 744c350e5..9ae15f211 100644 --- a/src/fmllauncher/resources/META-INF/services/cpw.mods.modlauncher.api.ILaunchHandlerService +++ b/src/fmllauncher/resources/META-INF/services/cpw.mods.modlauncher.api.ILaunchHandlerService @@ -1,4 +1,2 @@ net.minecraftforge.fml.loading.FMLClientLaunchProvider net.minecraftforge.fml.loading.FMLServerLaunchProvider -net.minecraftforge.fml.loading.FMLDevClientLaunchProvider -net.minecraftforge.fml.loading.FMLDevServerLaunchProvider \ No newline at end of file diff --git a/src/main/java/net/minecraftforge/fml/LaunchTesting.java b/src/main/java/net/minecraftforge/fml/LaunchTesting.java deleted file mode 100644 index 8241c1070..000000000 --- a/src/main/java/net/minecraftforge/fml/LaunchTesting.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Minecraft Forge - * Copyright (c) 2016-2019. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.minecraftforge.fml; - -import com.google.common.base.Strings; -import com.google.common.collect.ObjectArrays; -import cpw.mods.modlauncher.Launcher; -import net.minecraftforge.fml.loading.StringUtils; -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.core.Filter; -import org.apache.logging.log4j.core.LoggerContext; -import org.apache.logging.log4j.core.config.Configurator; -import org.apache.logging.log4j.core.filter.MarkerFilter; - -import java.io.File; -import java.lang.reflect.Field; -import java.util.Arrays; -import java.util.Locale; -import java.util.Objects; - -public class LaunchTesting -{ - public static void main(String... args) throws InterruptedException - { - final String markerselection = System.getProperty("forge.logging.markers", ""); - Arrays.stream(markerselection.split(",")).forEach(marker-> System.setProperty("forge.logging.marker."+ marker.toLowerCase(Locale.ROOT), "ACCEPT")); - - String assets = System.getenv().getOrDefault("assetDirectory", "assets"); - String target = System.getenv().get("target"); - String[] launchArgs = new String[]{ - "--gameDir", ".", - "--launchTarget", target, - "--fml.forgeVersion", System.getProperty("forge.version"), - "--fml.mcpVersion", System.getProperty("mcp.version"), - "--fml.mcVersion", System.getProperty("mc.version"), - "--fml.forgeGroup", System.getProperty("forge.group") - }; - - - if (target == null) { - throw new IllegalArgumentException("Environment variable target must be set."); - } - - if (Objects.equals(target,"fmldevclient")) { - hackNatives(); - launchArgs = ObjectArrays.concat(launchArgs, new String[] { - "--accessToken", "blah", - "--version", "FMLDev", - "--assetIndex", System.getenv("assetIndex"), - "--assetsDir", assets, - "--userProperties", "{}" - }, String.class); - } else { - launchArgs = ObjectArrays.concat(launchArgs, args, String.class); - } - Launcher.main(launchArgs); - Thread.sleep(10000); - } - - private static void hackNatives() - { - String paths = System.getProperty("java.library.path"); - String nativesDir = System.getenv().get("nativesDirectory"); - - if (Strings.isNullOrEmpty(paths)) - paths = nativesDir; - else - paths += File.pathSeparator + nativesDir; - - System.setProperty("java.library.path", paths); - - // hack the classloader now. - try - { - final Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths"); - sysPathsField.setAccessible(true); - sysPathsField.set(null, null); - } - catch(Throwable t) {} - } - -} diff --git a/src/main/java/net/minecraftforge/fml/common/launcher/Yggdrasil.java b/src/main/java/net/minecraftforge/fml/common/launcher/Yggdrasil.java deleted file mode 100644 index aafe55716..000000000 --- a/src/main/java/net/minecraftforge/fml/common/launcher/Yggdrasil.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Minecraft Forge - * Copyright (c) 2016-2019. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.minecraftforge.fml.common.launcher; - -import java.net.Proxy; -import java.util.Map; - -import org.apache.logging.log4j.LogManager; - -import com.mojang.authlib.Agent; -import com.mojang.authlib.exceptions.AuthenticationException; -import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; -import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication; - -/** - * Basic implementation of Mojang's 'Yggdrasil' login system, purely intended as a dev time bare bones login. - * Login errors are not handled. - */ -public class Yggdrasil -{ - public static void login(Map args) - { - if (!args.containsKey("--username") || !args.containsKey("--password")) return; - YggdrasilUserAuthentication auth = (YggdrasilUserAuthentication) new YggdrasilAuthenticationService(Proxy.NO_PROXY, "1").createUserAuthentication(Agent.MINECRAFT); - auth.setUsername(args.get("--username")); - auth.setPassword(args.remove("--password")); - - try - { - auth.logIn(); - } - catch (AuthenticationException e) - { - LogManager.getLogger("FML.TWEAK").error("-- Login failed!", e); - throw new RuntimeException(e); // don't set other variables - } - - args.put("--username", auth.getSelectedProfile().getName()); - args.put("--uuid", auth.getSelectedProfile().getId().toString().replace("-", "")); - args.put("--accessToken", auth.getAuthenticatedToken()); - args.put("--userProperties", auth.getUserProperties().toString()); - } -} diff --git a/src/main/java/net/minecraftforge/versions/forge/ForgeVersion.java b/src/main/java/net/minecraftforge/versions/forge/ForgeVersion.java index 2fd8e9ddd..a9478233c 100644 --- a/src/main/java/net/minecraftforge/versions/forge/ForgeVersion.java +++ b/src/main/java/net/minecraftforge/versions/forge/ForgeVersion.java @@ -24,8 +24,6 @@ import net.minecraftforge.fml.VersionChecker; import net.minecraftforge.fml.loading.JarVersionLookupHandler; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.apache.maven.artifact.versioning.ArtifactVersion; -import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import javax.annotation.Nullable; @@ -43,11 +41,11 @@ public class ForgeVersion static { LOGGER.debug(CORE, "Forge Version package {} from {}", ForgeVersion.class.getPackage(), ForgeVersion.class.getClassLoader()); - String vers = JarVersionLookupHandler.getImplementationVersion(ForgeVersion.class).orElse(System.getProperty("forge.version")); + String vers = JarVersionLookupHandler.getImplementationVersion(ForgeVersion.class).orElse(System.getenv("FORGE_VERSION")); if (vers == null) throw new RuntimeException("Missing forge version, cannot continue"); - String spec = JarVersionLookupHandler.getSpecificationVersion(ForgeVersion.class).orElse(System.getProperty("forge.spec")); + String spec = JarVersionLookupHandler.getSpecificationVersion(ForgeVersion.class).orElse(System.getenv("FORGE_SPEC")); if (spec == null) throw new RuntimeException("Missing forge spec, cannot continue"); - String group = JarVersionLookupHandler.getImplementationTitle(ForgeVersion.class).orElse(System.getProperty("forge.group")); + String group = JarVersionLookupHandler.getImplementationTitle(ForgeVersion.class).orElse(System.getenv("FORGE_GROUP")); if (group == null) { group = "net.minecraftforge"; // If all else fails, Our normal group } diff --git a/src/main/java/net/minecraftforge/versions/mcp/MCPVersion.java b/src/main/java/net/minecraftforge/versions/mcp/MCPVersion.java index 27cd438b6..adbf80324 100644 --- a/src/main/java/net/minecraftforge/versions/mcp/MCPVersion.java +++ b/src/main/java/net/minecraftforge/versions/mcp/MCPVersion.java @@ -31,14 +31,14 @@ public class MCPVersion { static { String vers = MCPVersion.class.getPackage().getSpecificationVersion(); if (vers == null) { - vers = System.getProperty("mc.version"); + vers = System.getenv("MC_VERSION"); } if (vers == null) throw new RuntimeException("Missing MC version, cannot continue"); mcVersion = vers; vers = MCPVersion.class.getPackage().getImplementationVersion(); if (vers == null) { - vers = System.getProperty("mcp.version"); + vers = System.getenv("MCP_VERSION"); } if (vers == null) throw new RuntimeException("Missing MCP version, cannot continue"); mcpVersion = vers; diff --git a/src/userdev/java/net/minecraftforge/userdev/ArgumentList.java b/src/userdev/java/net/minecraftforge/userdev/ArgumentList.java new file mode 100644 index 000000000..c54407547 --- /dev/null +++ b/src/userdev/java/net/minecraftforge/userdev/ArgumentList.java @@ -0,0 +1,175 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2019. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.userdev; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +/* + * A class that attempts to parse command line arguments into key value pairs to allow addition and editing. + * Can not use JOptSimple as that doesn't parse out the values for keys unless the spec says it has a value. + */ +class ArgumentList { + private static final Logger LOGGER = LogManager.getLogger(); + private List> entries = new ArrayList<>(); + private Map values = new HashMap<>(); + + public static ArgumentList from(String... args) { + ArgumentList ret = new ArgumentList(); + + boolean ended = false; + for (int x = 0; x < args.length; x++) { + if (!ended) { + if ("--".equals(args[x])) { // '--' by itself means there are no more arguments + ended = true; + } else if ("-".equals(args[x])) { + ret.addRaw(args[x]); + } else if (args[x].startsWith("-")) { + int idx = args[x].indexOf('='); + String key = idx == -1 ? args[x] : args[x].substring(0, idx); + String value = idx == -1 ? null : idx == args[x].length() - 1 ? "" : args[x].substring(idx + 1); + + if (idx == -1 && x + 1 < args.length && !args[x+1].startsWith("-")) { //Not in --key=value, so try and grab the next argument. + ret.addArg(true, key, args[x+1]); //Assume that if the next value is a "argument" then don't use it as a value. + x++; // This isn't perfect, but the best we can do without knowing all of the spec. + } else { + ret.addArg(false, key, value); + } + } else { + ret.addRaw(args[x]); + } + } else { + ret.addRaw(args[x]); + } + } + return ret; + } + + public void addRaw(final String arg) { + entries.add(() -> new String[] { arg }); + } + + public void addArg(boolean split, String raw, String value) { + int idx = raw.startsWith("--") ? 2 : 1; + String prefix = raw.substring(0, idx); + String key = raw.substring(idx); + EntryValue entry = new EntryValue(split, prefix, key, value); + if (values.containsKey(key)) { + LOGGER.info("Duplicate entries for " + key + " Unindexable"); + } else { + values.put(key, entry); + } + entries.add(entry); + } + + public String[] getArguments() { + return entries.stream() + .flatMap(e -> Arrays.asList(e.get()).stream()) + .toArray(size -> new String[size]); + } + + public boolean hasValue(String key) { + return getOrDefault(key, null) != null; + } + + public String get(String key) { + EntryValue ent = values.get(key); + return ent == null ? null : ent.getValue(); + } + + public String getOrDefault(String key, String value) { + EntryValue ent = values.get(key); + return ent == null ? value : ent.getValue() == null ? value : ent.getValue(); + } + + public void put(String key, String value) { + EntryValue entry = values.get(key); + if (entry == null) { + entry = new EntryValue(true, "--", key, value); + values.put(key, entry); + entries.add(entry); + } else { + entry.setValue(value); + } + } + + public void putLazy(String key, String value) { + EntryValue ent = values.get(key); + if (ent == null) + addArg(true, "--" + key, value); + else if (ent.getValue() == null) + ent.setValue(value); + } + + public String remove(String key) { + EntryValue ent = values.remove(key); + if (ent == null) + return null; + entries.remove(ent); + return ent.getValue(); + } + + private class EntryValue implements Supplier { + private final String prefix; + private final String key; + private final boolean split; + private String value; + + public EntryValue(boolean split, String prefix, String key, String value) { + this.split = split; + this.prefix = prefix; + this.key = key; + this.value = value; + } + + public String getKey() { + return this.key; + } + + public String getValue() { + return this.value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public String[] get() { + if (getValue() == null) + return new String[] { prefix + getKey() }; + if (split) + return new String[] { prefix + getKey(), getValue() }; + return new String[] { prefix + getKey() + '=' + getValue() }; + } + + @Override + public String toString() { + return String.join(", ", get()); + } + } +} diff --git a/src/userdev/java/net/minecraftforge/userdev/ClasspathLocator.java b/src/userdev/java/net/minecraftforge/userdev/ClasspathLocator.java new file mode 100644 index 000000000..38a3a509c --- /dev/null +++ b/src/userdev/java/net/minecraftforge/userdev/ClasspathLocator.java @@ -0,0 +1,77 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2019. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.userdev; + +import static net.minecraftforge.fml.loading.LogMarkers.CORE; + +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import net.minecraftforge.fml.loading.LibraryFinder; +import net.minecraftforge.fml.loading.moddiscovery.AbstractJarFileLocator; +import net.minecraftforge.fml.loading.moddiscovery.ModFile; + +public class ClasspathLocator extends AbstractJarFileLocator { + private static final Logger LOGGER = LogManager.getLogger(); + private static final String MODS_TOML = "META-INF/mods.toml"; + private List modCoords; + + @Override + public List scanMods() { + return modCoords.stream(). + map(mc -> new ModFile(mc, this)). + peek(f->modJars.compute(f, (mf, fs)->createFileSystem(mf))). + collect(Collectors.toList()); + } + + @Override + public String name() { + return "userdev classpath"; + } + + @Override + public void initArguments(Map arguments) { + try { + modCoords = new ArrayList<>(); + final Enumeration resources = ClassLoader.getSystemClassLoader().getResources(MODS_TOML); + while (resources.hasMoreElements()) { + URL url = resources.nextElement(); + Path path = LibraryFinder.findJarPathFor(MODS_TOML, "classpath_mod", url); + if (Files.isDirectory(path)) + continue; + + this.modCoords.add(path); + } + } catch (IOException e) { + LOGGER.fatal(CORE,"Error trying to find resources", e); + throw new RuntimeException("wha?", e); + } + } +} diff --git a/src/fmllauncher/java/net/minecraftforge/fml/loading/FMLDevClientLaunchProvider.java b/src/userdev/java/net/minecraftforge/userdev/FMLDevClientLaunchProvider.java similarity index 96% rename from src/fmllauncher/java/net/minecraftforge/fml/loading/FMLDevClientLaunchProvider.java rename to src/userdev/java/net/minecraftforge/userdev/FMLDevClientLaunchProvider.java index 5d296ffee..a46497090 100644 --- a/src/fmllauncher/java/net/minecraftforge/fml/loading/FMLDevClientLaunchProvider.java +++ b/src/userdev/java/net/minecraftforge/userdev/FMLDevClientLaunchProvider.java @@ -17,13 +17,16 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package net.minecraftforge.fml.loading; +package net.minecraftforge.userdev; import cpw.mods.modlauncher.api.IEnvironment; import cpw.mods.modlauncher.api.ILaunchHandlerService; import cpw.mods.modlauncher.api.ITransformingClassLoader; import cpw.mods.modlauncher.api.ITransformingClassLoaderBuilder; import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.loading.FMLCommonLaunchHandler; +import net.minecraftforge.fml.loading.LibraryFinder; + import org.apache.commons.lang3.tuple.Pair; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/src/fmllauncher/java/net/minecraftforge/fml/loading/FMLDevServerLaunchProvider.java b/src/userdev/java/net/minecraftforge/userdev/FMLDevServerLaunchProvider.java similarity index 95% rename from src/fmllauncher/java/net/minecraftforge/fml/loading/FMLDevServerLaunchProvider.java rename to src/userdev/java/net/minecraftforge/userdev/FMLDevServerLaunchProvider.java index 2aa792b34..dfe3812f3 100644 --- a/src/fmllauncher/java/net/minecraftforge/fml/loading/FMLDevServerLaunchProvider.java +++ b/src/userdev/java/net/minecraftforge/userdev/FMLDevServerLaunchProvider.java @@ -17,13 +17,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -package net.minecraftforge.fml.loading; +package net.minecraftforge.userdev; -import com.google.common.collect.ObjectArrays; import cpw.mods.modlauncher.api.IEnvironment; import cpw.mods.modlauncher.api.ILaunchHandlerService; import cpw.mods.modlauncher.api.ITransformingClassLoader; import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.loading.FMLCommonLaunchHandler; +import net.minecraftforge.fml.loading.LibraryFinder; + import org.apache.commons.lang3.tuple.Pair; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/src/userdev/java/net/minecraftforge/userdev/FMLUserdevLaunchProvider.java b/src/userdev/java/net/minecraftforge/userdev/FMLUserdevLaunchProvider.java index 5d085b44d..37b3f21cb 100644 --- a/src/userdev/java/net/minecraftforge/userdev/FMLUserdevLaunchProvider.java +++ b/src/userdev/java/net/minecraftforge/userdev/FMLUserdevLaunchProvider.java @@ -26,76 +26,52 @@ import org.apache.commons.lang3.tuple.Pair; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import java.io.File; -import java.io.IOException; import java.net.URL; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.*; -import java.util.stream.Collectors; - import static net.minecraftforge.fml.loading.LogMarkers.CORE; public abstract class FMLUserdevLaunchProvider extends FMLCommonLaunchHandler { private static final Logger LOGGER = LogManager.getLogger(); private Path forgeJar; private Path mcJars; + private static final String FORGE_VERSION_CLASS = "net/minecraftforge/versions/forge/ForgeVersion.class"; @Override public Path getForgePath(final String mcVersion, final String forgeVersion, final String forgeGroup) { - final URL forgePath = getClass().getClassLoader().getResource("net/minecraftforge/versions/forge/ForgeVersion.class"); + final URL forgePath = getClass().getClassLoader().getResource(FORGE_VERSION_CLASS); if (forgePath == null) { LOGGER.fatal(CORE, "Unable to locate forge on the classpath"); throw new RuntimeException("Unable to locate forge on the classpath"); } - forgeJar = LibraryFinder.findJarPathFor("ForgeVersion.class", "forge", forgePath); + forgeJar = LibraryFinder.findJarPathFor(FORGE_VERSION_CLASS, "forge", forgePath); return forgeJar; } - @SuppressWarnings("unchecked") + @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public void setup(final IEnvironment environment, final Map arguments) { + if (!forgeJar.getFileName().toString().endsWith(".jar")) { + LOGGER.fatal(CORE, "Userdev Launcher attempted to be used with non-jar version of Forge: {}" + forgeJar); + throw new RuntimeException("Userdev Launcher can only be used with dev-jar version of Forge"); + } + final List mavenRoots = new ArrayList<>((List) arguments.get("mavenRoots")); - final List mods = new ArrayList<>((List) arguments.get("mods")); - final String forgeVersion = (String) arguments.get("forgeVersion"); - final String mcVersion = (String) arguments.get("mcVersion"); - final String mcpVersion = (String) arguments.get("mcpVersion"); - final String mcpMappings = (String) arguments.get("mcpMappings"); final String forgeGroup = (String) arguments.get("forgeGroup"); - final String userdevVersion = mcVersion + "-" + forgeVersion + "_mapped_" + mcpMappings; int dirs = forgeGroup.split("\\.").length + 2; + Path fjroot = forgeJar; do { fjroot = fjroot.getParent(); } while (dirs-- > 0); final String fjpath = fjroot.toString(); - LOGGER.debug(CORE, "Injecting forge as mod {} from maven path {}", userdevVersion, fjpath); mavenRoots.add(fjpath); - - String classifier = ""; - if (forgeJar.getFileName().endsWith(".jar")) { - if (!("forge-" + userdevVersion + ".jar").equals(forgeJar.getFileName().toString())) { - String suffix = forgeJar.getFileName().toString().substring(userdevVersion.length() + 7); //"forge-" + version + "-" - suffix = suffix.substring(0, suffix.length() - 4); // Remove ".jar" - } - } - mods.add(forgeGroup+":forge:"+userdevVersion + classifier); - - try { - final Enumeration resources = ClassLoader.getSystemClassLoader().getResources("META-INF/mods.toml"); - final ArrayList modstoml = Collections.list(resources); - modstoml.stream().filter(u-> !u.getPath().contains("!")); - - } catch (IOException e) { - LOGGER.fatal(CORE,"Error trying to find resources", e); - throw new RuntimeException("wha?", e); - } + LOGGER.debug(CORE, "Injecting maven path {}", fjpath); processModClassesEnvironmentVariable((Map>>>) arguments); // generics are gross yea? ((Map)arguments).put("mavenRoots", mavenRoots); - ((Map)arguments).put("mods", mods); } @Override diff --git a/src/userdev/java/net/minecraftforge/userdev/LaunchTesting.java b/src/userdev/java/net/minecraftforge/userdev/LaunchTesting.java new file mode 100644 index 000000000..a87263397 --- /dev/null +++ b/src/userdev/java/net/minecraftforge/userdev/LaunchTesting.java @@ -0,0 +1,143 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2019. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.userdev; + +import com.google.common.base.Strings; +import com.mojang.authlib.Agent; +import com.mojang.authlib.UserAuthentication; +import com.mojang.authlib.exceptions.AuthenticationException; +import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; +import cpw.mods.modlauncher.Launcher; + +import java.io.File; +import java.lang.reflect.Field; +import java.net.Proxy; +import java.util.Arrays; +import java.util.Locale; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class LaunchTesting +{ + private static final Logger LOGGER = LogManager.getLogger(); + + public static void main(String... args) throws InterruptedException + { + final String markerselection = System.getProperty("forge.logging.markers", ""); + Arrays.stream(markerselection.split(",")).forEach(marker-> System.setProperty("forge.logging.marker."+ marker.toLowerCase(Locale.ROOT), "ACCEPT")); + + ArgumentList lst = ArgumentList.from(args); + + String target = lst.getOrDefault("launchTarget", System.getenv().get("target")); + + if (target == null) { + throw new IllegalArgumentException("Environment variable target must be set."); + } + + lst.putLazy("gameDir", "."); + lst.putLazy("launchTarget", target); + lst.putLazy("fml.mcpVersion", System.getenv("MCP_VERSION")); + lst.putLazy("fml.mcVersion", System.getenv("MC_VERSION")); + lst.putLazy("fml.forgeGroup", System.getenv("FORGE_GROUP")); + lst.putLazy("fml.forgeVersion", System.getenv("FORGE_VERSION")); + + if (target.contains("client")) { + hackNatives(); + lst.putLazy("version", "MOD_DEV"); + lst.putLazy("assetIndex", System.getenv("assetIndex")); + lst.putLazy("assetsDir", System.getenv().getOrDefault("assetDirectory", "assets")); + + String assets = lst.get("assetsDir"); + if (assets == null || !new File(assets).exists()) { + throw new IllegalArgumentException("Environment variable 'assetDirectory' must be set to a valid path."); + } + + if (!lst.hasValue("accessToken")) { + if (!login(lst)) { + lst.putLazy("username", "Test"); + lst.put("accessToken", "DONT_CRASH"); + lst.put("userProperties", "{}"); + } + } + } + + if (target.equals("fmldevclient") || target.equals("fmldevserver") || target.equals("fmluserdevclient") || target.equals("fmluserdevserver")) { + //nop + } else { + throw new IllegalArgumentException("Unknown value for 'target' property: " + target); + } + + Launcher.main(lst.getArguments()); + Thread.sleep(10000);// Why do we have this? -Lex 03/06/19 + } + + private static void hackNatives() + { + String paths = System.getProperty("java.library.path"); + String nativesDir = System.getenv().get("nativesDirectory"); + + if (Strings.isNullOrEmpty(paths)) + paths = nativesDir; + else + paths += File.pathSeparator + nativesDir; + + System.setProperty("java.library.path", paths); + + // hack the classloader now. + try + { + final Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths"); + sysPathsField.setAccessible(true); + sysPathsField.set(null, null); + } + catch(Throwable t) {} + } + + /** + * Basic implementation of Mojang's 'Yggdrasil' login system, purely intended as a dev time bare bones login. + * Login errors are not handled. + * Do not use this unless you know what you are doing and must use it to debug things REQUIRING authentication. + * Forge is not responsible for any auth information passed in, saved to logs, run configs, etc... + * BE CAREFUL WITH YOUR LOGIN INFO + */ + private static boolean login(ArgumentList args) { + if (!args.hasValue("username") || !args.hasValue("password")) { + args.remove("password"); //Just in case, so it shouldn't show up anywhere. + return false; + } + + UserAuthentication auth = new YggdrasilAuthenticationService(Proxy.NO_PROXY, "1").createUserAuthentication(Agent.MINECRAFT); + auth.setUsername(args.get("username")); + auth.setPassword(args.remove("password")); + + try { + auth.logIn(); + } catch (AuthenticationException e) { + LOGGER.error("Login failed!", e); + throw new RuntimeException(e); // don't set other variables + } + + args.put("username", auth.getSelectedProfile().getName()); + args.put("uuid", auth.getSelectedProfile().getId().toString().replace("-", "")); + args.put("accessToken", auth.getAuthenticatedToken()); + args.put("userProperties", auth.getUserProperties().toString()); + return true; + } +} diff --git a/src/userdev/java/net/minecraftforge/userdev/UserdevLauncher.java b/src/userdev/java/net/minecraftforge/userdev/UserdevLauncher.java deleted file mode 100644 index 6afc26697..000000000 --- a/src/userdev/java/net/minecraftforge/userdev/UserdevLauncher.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Minecraft Forge - * Copyright (c) 2016-2019. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.minecraftforge.userdev; - -import com.google.common.base.Strings; -import com.google.common.collect.ObjectArrays; -import cpw.mods.modlauncher.Launcher; -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.MarkerManager; -import org.apache.logging.log4j.core.Filter; -import org.apache.logging.log4j.core.LoggerContext; -import org.apache.logging.log4j.core.config.Configurator; -import org.apache.logging.log4j.core.filter.MarkerFilter; - -import java.io.File; -import java.lang.reflect.Field; -import java.util.*; - -public class UserdevLauncher -{ - public static void main(String... args) throws InterruptedException - { - final String markerselection = System.getProperty("forge.logging.markers", ""); - Arrays.stream(markerselection.split(",")).forEach(marker-> { - System.setProperty("forge.logging.marker." + marker.toLowerCase(Locale.ROOT), "ACCEPT"); - MarkerManager.getMarker(marker.toUpperCase(Locale.ROOT)); - }); - - String assets = System.getenv().getOrDefault("assetDirectory", "assets"); - String target = System.getenv().get("target"); - - if (target == null) { - throw new IllegalArgumentException("Environment variable 'target' must be set to 'fmluserdevclient' or 'fmluserdevserver'."); - } - - String[] launchArgs = new String[]{ - "--gameDir", ".", - "--launchTarget", target, - "--fml.forgeVersion", System.getenv("FORGE_VERSION"), - "--fml.mcpVersion", System.getenv("MCP_VERSION"), - "--fml.mcpMappings", System.getenv("MCP_MAPPINGS"), - "--fml.mcVersion", System.getenv("MC_VERSION"), - "--fml.forgeGroup", System.getenv("FORGE_GROUP") - }; - - if (Objects.equals(target,"fmluserdevclient")) { - if (assets == null || !new File(assets).exists()) { - throw new IllegalArgumentException("Environment variable 'assetDirectory' must be set to a valid path."); - } - - hackNatives(); - launchArgs = ObjectArrays.concat(launchArgs, new String[] { - "--accessToken", "blah", - "--version", "FMLDev", - "--assetIndex", System.getenv("assetIndex"), - "--assetsDir", assets, - "--userProperties", "{}" - }, String.class); - } else if (Objects.equals(target, "fmluserdevserver")) { - // we're good - } else { - throw new IllegalArgumentException("Unknown value for 'target' property: " + target); - } - Launcher.main(launchArgs); - Thread.sleep(10000); - } - - private static void hackNatives() - { - String paths = System.getProperty("java.library.path"); - String nativesDir = System.getenv().get("nativesDirectory"); - - if (Strings.isNullOrEmpty(paths)) - paths = nativesDir; - else - paths += File.pathSeparator + nativesDir; - - System.setProperty("java.library.path", paths); - - // hack the classloader now. - try - { - final Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths"); - sysPathsField.setAccessible(true); - sysPathsField.set(null, null); - } - catch(Throwable t) {} - } - - - -} diff --git a/src/userdev/resources/META-INF/services/cpw.mods.modlauncher.api.ILaunchHandlerService b/src/userdev/resources/META-INF/services/cpw.mods.modlauncher.api.ILaunchHandlerService index 3c70f3f7e..c24a0021a 100644 --- a/src/userdev/resources/META-INF/services/cpw.mods.modlauncher.api.ILaunchHandlerService +++ b/src/userdev/resources/META-INF/services/cpw.mods.modlauncher.api.ILaunchHandlerService @@ -1,2 +1,4 @@ net.minecraftforge.userdev.FMLUserdevClientLaunchProvider -net.minecraftforge.userdev.FMLUserdevServerLaunchProvider \ No newline at end of file +net.minecraftforge.userdev.FMLUserdevServerLaunchProvider +net.minecraftforge.userdev.FMLDevClientLaunchProvider +net.minecraftforge.userdev.FMLDevServerLaunchProvider diff --git a/src/userdev/resources/META-INF/services/net.minecraftforge.fml.loading.moddiscovery.IModLocator b/src/userdev/resources/META-INF/services/net.minecraftforge.fml.loading.moddiscovery.IModLocator new file mode 100644 index 000000000..077df5309 --- /dev/null +++ b/src/userdev/resources/META-INF/services/net.minecraftforge.fml.loading.moddiscovery.IModLocator @@ -0,0 +1 @@ +net.minecraftforge.userdev.ClasspathLocator