diff --git a/build.gradle b/build.gradle index 0f5bbc7290..812681ade1 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 5f82867563..7868b34898 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 11ea803edb..a047c88d04 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 744c350e5b..9ae15f211c 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 8241c10701..0000000000 --- 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 aafe557165..0000000000 --- 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 2fd8e9ddde..a9478233c0 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 27cd438b6a..adbf80324b 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 0000000000..c544075475 --- /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 0000000000..38a3a509ce --- /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 5d296ffee6..a46497090f 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 2aa792b341..dfe3812f30 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 5d085b44de..37b3f21cbf 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 0000000000..a87263397b --- /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 6afc266975..0000000000 --- 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 3c70f3f7ee..c24a0021a1 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 0000000000..077df5309f --- /dev/null +++ b/src/userdev/resources/META-INF/services/net.minecraftforge.fml.loading.moddiscovery.IModLocator @@ -0,0 +1 @@ +net.minecraftforge.userdev.ClasspathLocator