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.
This commit is contained in:
LexManos 2019-03-06 20:59:32 -08:00
parent 7bd7b059c4
commit 3003e33074
17 changed files with 440 additions and 335 deletions

View File

@ -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'

View File

@ -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);

View File

@ -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;

View File

@ -1,4 +1,2 @@
net.minecraftforge.fml.loading.FMLClientLaunchProvider
net.minecraftforge.fml.loading.FMLServerLaunchProvider
net.minecraftforge.fml.loading.FMLDevClientLaunchProvider
net.minecraftforge.fml.loading.FMLDevServerLaunchProvider

View File

@ -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) {}
}
}

View File

@ -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<String, String> 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());
}
}

View File

@ -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
}

View File

@ -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;

View File

@ -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<Supplier<String[]>> entries = new ArrayList<>();
private Map<String, EntryValue> 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<String[]> {
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());
}
}
}

View File

@ -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<Path> modCoords;
@Override
public List<ModFile> 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<String, ?> arguments) {
try {
modCoords = new ArrayList<>();
final Enumeration<URL> 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);
}
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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<String, ?> 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<String> mavenRoots = new ArrayList<>((List<String>) arguments.get("mavenRoots"));
final List<String> mods = new ArrayList<>((List<String>) 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<URL> resources = ClassLoader.getSystemClassLoader().getResources("META-INF/mods.toml");
final ArrayList<URL> 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<String, List<Pair<Path, List<Path>>>>) arguments);
// generics are gross yea?
((Map)arguments).put("mavenRoots", mavenRoots);
((Map)arguments).put("mods", mods);
}
@Override

View File

@ -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;
}
}

View File

@ -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) {}
}
}

View File

@ -1,2 +1,4 @@
net.minecraftforge.userdev.FMLUserdevClientLaunchProvider
net.minecraftforge.userdev.FMLUserdevServerLaunchProvider
net.minecraftforge.userdev.FMLUserdevServerLaunchProvider
net.minecraftforge.userdev.FMLDevClientLaunchProvider
net.minecraftforge.userdev.FMLDevServerLaunchProvider

View File

@ -0,0 +1 @@
net.minecraftforge.userdev.ClasspathLocator