ForgePatch/src/userdev/java/net/minecraftforge/userdev/LaunchTesting.java

171 lines
7.0 KiB
Java

/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* 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.gson.Gson;
import com.google.gson.GsonBuilder;
import com.mojang.authlib.Agent;
import com.mojang.authlib.UserAuthentication;
import com.mojang.authlib.exceptions.AuthenticationException;
import com.mojang.authlib.properties.PropertyMap;
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
import cpw.mods.modlauncher.Launcher;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.Proxy;
import java.util.Arrays;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.logging.log4j.LogManager;
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"));
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)) {
String username = lst.get("username");
if (username != null) { // Replace '#' placeholders with random numbers
Matcher m = Pattern.compile("#+").matcher(username);
StringBuffer replaced = new StringBuffer();
while (m.find()) {
m.appendReplacement(replaced, getRandomNumbers(m.group().length()));
}
m.appendTail(replaced);
lst.put("username", replaced.toString());
} else {
lst.putLazy("username", "Dev");
}
lst.put("accessToken", "DONT_CRASH");
lst.put("userProperties", "{}");
}
}
}
if (Arrays.asList(
"fmldevclient", "fmldevserver", "fmldevdata",
"fmluserdevclient", "fmluserdevserver", "fmluserdevdata"
).contains(target)) {
//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 // because there's daemon threads that should cleanly exit -cpw 04/10/20
}
private static String getRandomNumbers(int length)
{ // Generate a time-based random number, to mimic how n.m.client.Main works
return Long.toString(System.nanoTime() % (int) Math.pow(10, length));
}
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 Method initializePathMethod = ClassLoader.class.getDeclaredMethod("initializePath", String.class);
initializePathMethod.setAccessible(true);
final Object usrPathsValue = initializePathMethod.invoke(null, "java.library.path");
final Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths");
usrPathsField.setAccessible(true);
usrPathsField.set(null, usrPathsValue);
}
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) {
LogManager.getLogger().error("Login failed!", e);
throw new RuntimeException(e); // don't set other variables
}
Gson gson = (new GsonBuilder()).registerTypeAdapter(PropertyMap.class, new PropertyMap.Serializer()).create();
args.put("username", auth.getSelectedProfile().getName());
args.put("uuid", auth.getSelectedProfile().getId().toString().replace("-", ""));
args.put("accessToken", auth.getAuthenticatedToken());
args.put("userProperties", gson.toJson(auth.getUserProperties()));
return true;
}
}