mirror of
https://github.com/GravitLauncher/Launcher
synced 2025-04-01 22:14:01 +03:00
Merge branch 'master' into fixesWriter1
This commit is contained in:
commit
43d6d40d94
15 changed files with 160 additions and 39 deletions
|
@ -32,6 +32,7 @@
|
|||
import java.util.zip.CRC32;
|
||||
|
||||
import ru.gravit.launcher.Launcher;
|
||||
import ru.gravit.launcher.LauncherConfig;
|
||||
import ru.gravit.launcher.hasher.HashedDir;
|
||||
import ru.gravit.launcher.managers.GarbageManager;
|
||||
import ru.gravit.launcher.profiles.ClientProfile;
|
||||
|
@ -48,10 +49,7 @@
|
|||
import ru.gravit.launchserver.auth.handler.AuthHandler;
|
||||
import ru.gravit.launchserver.auth.hwid.HWIDHandler;
|
||||
import ru.gravit.launchserver.auth.provider.AuthProvider;
|
||||
import ru.gravit.launchserver.binary.EXEL4JLauncherBinary;
|
||||
import ru.gravit.launchserver.binary.EXELauncherBinary;
|
||||
import ru.gravit.launchserver.binary.JARLauncherBinary;
|
||||
import ru.gravit.launchserver.binary.LauncherBinary;
|
||||
import ru.gravit.launchserver.binary.*;
|
||||
import ru.gravit.launchserver.command.handler.CommandHandler;
|
||||
import ru.gravit.launchserver.command.handler.JLineCommandHandler;
|
||||
import ru.gravit.launchserver.command.handler.StdCommandHandler;
|
||||
|
@ -112,6 +110,7 @@ public static final class Config extends ConfigObject {
|
|||
public final String binaryName;
|
||||
private final StringConfigEntry address;
|
||||
private final String bindAddress;
|
||||
public final LauncherConfig.LauncherEnvironment env;
|
||||
|
||||
private Config(BlockConfigEntry block, Path coredir, LaunchServer server) {
|
||||
super(block);
|
||||
|
@ -157,6 +156,7 @@ private Config(BlockConfigEntry block, Path coredir, LaunchServer server) {
|
|||
|
||||
isUsingWrapper = block.getEntryValue("isUsingWrapper", BooleanConfigEntry.class);
|
||||
isDownloadJava = block.getEntryValue("isDownloadJava", BooleanConfigEntry.class);
|
||||
env = LauncherConfig.LauncherEnvironment.STD;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -105,19 +105,13 @@ public synchronized Connection getConnection() throws SQLException {
|
|||
Class.forName("com.zaxxer.hikari.HikariDataSource");
|
||||
hikari = true; // Used for shutdown. Not instanceof because of possible classpath error
|
||||
HikariConfig cfg = new HikariConfig();
|
||||
cfg.setUsername(username);
|
||||
cfg.setPassword(password);
|
||||
cfg.setDataSource(mysqlSource);
|
||||
cfg.setPoolName(poolName);
|
||||
cfg.setMinimumIdle(0);
|
||||
cfg.setMaximumPoolSize(MAX_POOL_SIZE);
|
||||
cfg.setIdleTimeout(TIMEOUT * 1000L);
|
||||
// Set HikariCP pool
|
||||
HikariDataSource hikariSource = new HikariDataSource(cfg);
|
||||
// Replace source with hds
|
||||
source = hikariSource;
|
||||
source = new HikariDataSource(cfg);
|
||||
LogHelper.info("HikariCP pooling enabled for '%s'", poolName);
|
||||
return hikariSource.getConnection();
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
LogHelper.warning("HikariCP isn't in classpath for '%s'", poolName);
|
||||
}
|
||||
|
|
|
@ -8,8 +8,9 @@
|
|||
import javassist.CtConstructor;
|
||||
import javassist.CtMethod;
|
||||
import javassist.NotFoundException;
|
||||
import ru.gravit.launcher.LauncherConfig;
|
||||
|
||||
public class JAConfigurator implements AutoCloseable {
|
||||
public class JAConfigurator implements AutoCloseable {
|
||||
public ClassPool pool;
|
||||
public CtClass ctClass;
|
||||
public CtConstructor ctConstructor;
|
||||
|
@ -92,6 +93,28 @@ public void setPort(int port) {
|
|||
body.append(port);
|
||||
body.append(";");
|
||||
}
|
||||
public void setEnv(LauncherConfig.LauncherEnvironment env) {
|
||||
int i = 2;
|
||||
switch(env)
|
||||
{
|
||||
|
||||
case DEV:
|
||||
i = 0;
|
||||
break;
|
||||
case DEBUG:
|
||||
i = 1;
|
||||
break;
|
||||
case STD:
|
||||
i = 2;
|
||||
break;
|
||||
case PROD:
|
||||
i = 3;
|
||||
break;
|
||||
}
|
||||
body.append("this.env = ");
|
||||
body.append(i);
|
||||
body.append(";");
|
||||
}
|
||||
|
||||
public void setClientPort(int port) {
|
||||
body.append("this.clientPort = ");
|
||||
|
|
|
@ -216,6 +216,7 @@ private void stdBuild() throws IOException {
|
|||
jaConfigurator.setClientPort(32148 + SecurityHelper.newRandom().nextInt(512));
|
||||
jaConfigurator.setUsingWrapper(server.config.isUsingWrapper);
|
||||
jaConfigurator.setDownloadJava(server.config.isDownloadJava);
|
||||
jaConfigurator.setEnv(server.config.env);
|
||||
server.buildHookManager.registerAllClientModuleClass(jaConfigurator);
|
||||
try (ZipInputStream input = new ZipInputStream(IOHelper.newInput(cleanJar))) {
|
||||
ZipEntry e = input.getNextEntry();
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
package ru.gravit.launcher.server;
|
||||
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.instrument.Instrumentation;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.Collections;
|
||||
|
@ -31,21 +35,42 @@ public static void addJVMClassPath(JarFile file) throws IOException {
|
|||
inst.appendToSystemClassLoaderSearch(file);
|
||||
}
|
||||
|
||||
public boolean isAgentStarted() {
|
||||
public static boolean isAgentStarted() {
|
||||
return isAgentStarted;
|
||||
}
|
||||
|
||||
public static long getObjSize(Object obj) {
|
||||
return inst.getObjectSize(obj);
|
||||
}
|
||||
|
||||
public static Boolean isAutoloadLibraries = Boolean.getBoolean(System.getProperty("serverwrapper,agentlibrariesload","false"));
|
||||
public static Boolean isAgentProxy = Boolean.getBoolean(System.getProperty("serverwrapper,agentproxy","false"));
|
||||
public static void premain(String agentArgument, Instrumentation instrumentation) {
|
||||
LogHelper.debug("Server Agent");
|
||||
inst = instrumentation;
|
||||
isAgentStarted = true;
|
||||
|
||||
if(isAutoloadLibraries)
|
||||
{
|
||||
Path libraries = Paths.get("libraries");
|
||||
if(IOHelper.exists(libraries)) loadLibraries(libraries);
|
||||
}
|
||||
if(isAgentProxy)
|
||||
{
|
||||
String proxyClassName = System.getProperty("serverwrapper,agentproxyclass");
|
||||
Class proxyClass;
|
||||
try {
|
||||
proxyClass = Class.forName(proxyClassName);
|
||||
MethodHandle mainMethod = MethodHandles.publicLookup().findStatic(proxyClass, "premain", MethodType.methodType(void.class, String.class, Instrumentation.class));
|
||||
Object[] args = {agentArgument,instrumentation};
|
||||
mainMethod.invoke(args);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void loadLibraries(Path dir)
|
||||
{
|
||||
try {
|
||||
Files.walkFileTree(Paths.get("libraries"), Collections.singleton(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE, new StarterVisitor());
|
||||
Files.walkFileTree(dir, Collections.singleton(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE, new StarterVisitor());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
|
|
|
@ -7,8 +7,10 @@
|
|||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
||||
import ru.gravit.launcher.Launcher;
|
||||
|
@ -21,6 +23,7 @@
|
|||
import ru.gravit.launcher.serialize.config.entry.BooleanConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.IntegerConfigEntry;
|
||||
import ru.gravit.launcher.serialize.config.entry.StringConfigEntry;
|
||||
import ru.gravit.utils.PublicURLClassLoader;
|
||||
import ru.gravit.utils.helper.CommonHelper;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
@ -31,8 +34,13 @@
|
|||
|
||||
public class ServerWrapper {
|
||||
public static ModulesManager modulesManager;
|
||||
public static Path configFile;
|
||||
public static Config config;
|
||||
public static PublicURLClassLoader ucp;
|
||||
public static ClassLoader loader;
|
||||
|
||||
public static Path modulesDir = Paths.get(System.getProperty("serverwrapper.modulesDir","modules"));
|
||||
public static Path configFile = Paths.get(System.getProperty("serverwrapper.configFile","ServerWrapper.cfg"));
|
||||
public static Path publicKeyFile = Paths.get(System.getProperty("serverwrapper.publicKeyFile","public.key"));
|
||||
|
||||
public static boolean auth(ServerWrapper wrapper) {
|
||||
try {
|
||||
|
@ -79,15 +87,14 @@ public static void main(String[] args) throws Throwable {
|
|||
LogHelper.printVersion("ServerWrapper");
|
||||
LogHelper.printLicense("ServerWrapper");
|
||||
modulesManager = new ModulesManager(wrapper);
|
||||
modulesManager.autoload(Paths.get("srv_modules")); //BungeeCord using modules dir
|
||||
modulesManager.autoload(modulesDir);
|
||||
Launcher.modulesManager = modulesManager;
|
||||
configFile = Paths.get("ServerWrapper.cfg");
|
||||
modulesManager.preInitModules();
|
||||
generateConfigIfNotExists();
|
||||
try (BufferedReader reader = IOHelper.newReader(configFile)) {
|
||||
config = new Config(TextConfigReader.read(reader, true));
|
||||
}
|
||||
LauncherConfig cfg = new LauncherConfig(config.address, config.port, SecurityHelper.toPublicRSAKey(IOHelper.read(Paths.get("public.key"))), new HashMap<>(), config.projectname);
|
||||
LauncherConfig cfg = new LauncherConfig(config.address, config.port, SecurityHelper.toPublicRSAKey(IOHelper.read(publicKeyFile)), new HashMap<>(), config.projectname);
|
||||
Launcher.setConfig(cfg);
|
||||
if (config.syncAuth) auth(wrapper);
|
||||
else
|
||||
|
@ -99,19 +106,43 @@ public static void main(String[] args) throws Throwable {
|
|||
LogHelper.error("MainClass not found. Please set MainClass for ServerWrapper.cfg or first commandline argument");
|
||||
}
|
||||
Class<?> mainClass;
|
||||
if (config.customClassLoader) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<ClassLoader> classloader_class = (Class<ClassLoader>) Class.forName(config.classloader);
|
||||
ClassLoader loader = classloader_class.getConstructor(ClassLoader.class).newInstance(ClassLoader.getSystemClassLoader());
|
||||
Thread.currentThread().setContextClassLoader(loader);
|
||||
mainClass = Class.forName(classname, false, loader);
|
||||
} else mainClass = Class.forName(classname);
|
||||
if(config.customClassPath)
|
||||
{
|
||||
String[] cp = config.classpath.split(":");
|
||||
if(!ServerAgent.isAgentStarted())
|
||||
{
|
||||
LogHelper.warning("JavaAgent not found. Using URLClassLoader");
|
||||
URL[] urls = Arrays.stream(cp).map(Paths::get).map(IOHelper::toURL).toArray(URL[]::new);
|
||||
ucp = new PublicURLClassLoader(urls);
|
||||
Thread.currentThread().setContextClassLoader(ucp);
|
||||
loader = ucp;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogHelper.info("Found %d custom classpath elements",cp.length);
|
||||
for(String c : cp)
|
||||
ServerAgent.addJVMClassPath(c);
|
||||
}
|
||||
}
|
||||
if(config.autoloadLibraries)
|
||||
{
|
||||
if(!ServerAgent.isAgentStarted())
|
||||
{
|
||||
throw new UnsupportedOperationException("JavaAgent not found, autoloadLibraries not available");
|
||||
}
|
||||
Path librariesDir = Paths.get(config.librariesDir);
|
||||
LogHelper.info("Load libraries");
|
||||
ServerAgent.loadLibraries(librariesDir);
|
||||
}
|
||||
if(loader != null) mainClass = Class.forName(classname,true, loader);
|
||||
else mainClass = Class.forName(classname);
|
||||
MethodHandle mainMethod = MethodHandles.publicLookup().findStatic(mainClass, "main", MethodType.methodType(void.class, String[].class));
|
||||
String[] real_args = new String[args.length - 1];
|
||||
System.arraycopy(args, 1, real_args, 0, args.length - 1);
|
||||
modulesManager.postInitModules();
|
||||
LogHelper.info("ServerWrapper: Project %s, LaunchServer address: %s port %d. Title: %s",config.projectname,config.address,config.port,config.title);
|
||||
LogHelper.info("Minecraft Version (for profile): %s",wrapper.profile.getVersion().name);
|
||||
LogHelper.info("Start Minecraft Server");
|
||||
LogHelper.debug("Invoke main method %s", mainClass.getName());
|
||||
mainMethod.invoke(real_args);
|
||||
}
|
||||
|
@ -143,9 +174,11 @@ public static final class Config extends ConfigObject {
|
|||
public int port;
|
||||
public int reconnectCount;
|
||||
public int reconnectSleep;
|
||||
public boolean customClassLoader;
|
||||
public boolean customClassPath;
|
||||
public boolean autoloadLibraries;
|
||||
public boolean syncAuth;
|
||||
public String classloader;
|
||||
public String classpath;
|
||||
public String librariesDir;
|
||||
public String mainclass;
|
||||
public String login;
|
||||
public String password;
|
||||
|
@ -158,9 +191,12 @@ protected Config(BlockConfigEntry block) {
|
|||
login = block.getEntryValue("login", StringConfigEntry.class);
|
||||
password = block.getEntryValue("password", StringConfigEntry.class);
|
||||
port = block.getEntryValue("port", IntegerConfigEntry.class);
|
||||
customClassLoader = block.getEntryValue("customClassLoader", BooleanConfigEntry.class);
|
||||
if (customClassLoader)
|
||||
classloader = block.getEntryValue("classloader", StringConfigEntry.class);
|
||||
customClassPath = block.getEntryValue("customClassPath", BooleanConfigEntry.class);
|
||||
autoloadLibraries = block.getEntryValue("autoloadLibraries", BooleanConfigEntry.class);
|
||||
if (customClassPath)
|
||||
classpath = block.getEntryValue("classpath", StringConfigEntry.class);
|
||||
if (autoloadLibraries)
|
||||
librariesDir = block.getEntryValue("librariesDir", StringConfigEntry.class);
|
||||
mainclass = block.getEntryValue("MainClass", StringConfigEntry.class);
|
||||
reconnectCount = block.hasEntry("reconnectCount") ? block.getEntryValue("reconnectCount", IntegerConfigEntry.class) : 1;
|
||||
reconnectSleep = block.hasEntry("reconnectSleep") ? block.getEntryValue("reconnectSleep", IntegerConfigEntry.class) : 30000;
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
title: "xxxx";
|
||||
customClassLoader: false;
|
||||
classloader: "ru.gravit.utils.PublicURLClassLoader";
|
||||
|
||||
autoloadLibraries: false;
|
||||
librariesDir: "libraries";
|
||||
|
||||
customClassPath: false;
|
||||
classpath: "server.jar";
|
||||
|
||||
MainClass: "";
|
||||
address: "localhost";
|
||||
port: 7240;
|
||||
|
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,5 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.0-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
2
gradlew
vendored
2
gradlew
vendored
|
@ -28,7 +28,7 @@ APP_NAME="Gradle"
|
|||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
|
2
gradlew.bat
vendored
2
gradlew.bat
vendored
|
@ -14,7 +14,7 @@ set APP_BASE_NAME=%~n0
|
|||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
|
|
@ -9,6 +9,11 @@ public class AutogenConfig {
|
|||
public boolean isUsingWrapper;
|
||||
public boolean isDownloadJava; //Выставление этого флага требует модификации runtime части
|
||||
public String secretKeyClient;
|
||||
public int env;
|
||||
// 0 - Dev (дебаг включен по умолчанию, все сообщения)
|
||||
// 1 - Debug (дебаг включен по умолчанию, основные сообщения)
|
||||
// 2 - Std (дебаг выключен по умолчанию, основные сообщения)
|
||||
// 3 - Production (дебаг выключен, минимальный объем сообщений, stacktrace не выводится)
|
||||
|
||||
AutogenConfig() {
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ public final class Launcher {
|
|||
public static int MAJOR = 4;
|
||||
public static int MINOR = 1;
|
||||
public static int PATCH = 0;
|
||||
public static int BUILD = 1;
|
||||
public static int BUILD = 3;
|
||||
public static Version.Type RELEASE = Version.Type.DEV;
|
||||
|
||||
@LauncherAPI
|
||||
|
|
|
@ -56,6 +56,20 @@ public LauncherConfig(HInput input) throws IOException, InvalidKeySpecException
|
|||
secretKeyClient = config.secretKeyClient;
|
||||
isDownloadJava = config.isDownloadJava;
|
||||
isUsingWrapper = config.isUsingWrapper;
|
||||
LauncherEnvironment env;
|
||||
if(config.env == 0) env = LauncherEnvironment.DEV;
|
||||
else if(config.env == 1) env = LauncherEnvironment.DEBUG;
|
||||
else if(config.env == 2) env = LauncherEnvironment.STD;
|
||||
else if(config.env == 3) env = LauncherEnvironment.PROD;
|
||||
else env = LauncherEnvironment.STD;
|
||||
if(env == LauncherEnvironment.PROD) {
|
||||
LogHelper.setStacktraceEnabled(false);
|
||||
LogHelper.setDebugEnabled(false);
|
||||
}
|
||||
if(env == LauncherEnvironment.DEV || env == LauncherEnvironment.DEBUG)
|
||||
{
|
||||
LogHelper.setDebugEnabled(true);
|
||||
}
|
||||
// Read signed runtime
|
||||
int count = input.readLength(0);
|
||||
Map<String, byte[]> localResources = new HashMap<>(count);
|
||||
|
@ -108,4 +122,9 @@ public void write(HOutput output) throws IOException {
|
|||
output.writeByteArray(entry.getValue(), SecurityHelper.CRYPTO_MAX_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
public enum LauncherEnvironment
|
||||
{
|
||||
DEV,DEBUG,STD,PROD
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,8 @@ public final class LogHelper {
|
|||
@LauncherAPI
|
||||
public static final String DEBUG_PROPERTY = "launcher.debug";
|
||||
@LauncherAPI
|
||||
public static final String STACKTRACE_PROPERTY = "launcher.stacktrace";
|
||||
@LauncherAPI
|
||||
public static final String NO_JANSI_PROPERTY = "launcher.noJAnsi";
|
||||
@LauncherAPI
|
||||
public static final boolean JANSI;
|
||||
|
@ -34,6 +36,7 @@ public final class LogHelper {
|
|||
// Output settings
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss", Locale.US);
|
||||
private static final AtomicBoolean DEBUG_ENABLED = new AtomicBoolean(Boolean.getBoolean(DEBUG_PROPERTY));
|
||||
private static final AtomicBoolean STACKTRACE_ENABLED = new AtomicBoolean(Boolean.getBoolean(STACKTRACE_PROPERTY));
|
||||
private static final Set<Output> OUTPUTS = Collections.newSetFromMap(new ConcurrentHashMap<>(2));
|
||||
private static final Output STD_OUTPUT;
|
||||
|
||||
|
@ -73,7 +76,7 @@ public static void debug(String format, Object... args) {
|
|||
|
||||
@LauncherAPI
|
||||
public static void error(Throwable exc) {
|
||||
error(isDebugEnabled() ? toString(exc) : exc.toString());
|
||||
error(isStacktraceEnabled() ? toString(exc) : exc.toString());
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
|
@ -106,6 +109,16 @@ public static void setDebugEnabled(boolean debugEnabled) {
|
|||
DEBUG_ENABLED.set(debugEnabled);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public static boolean isStacktraceEnabled() {
|
||||
return STACKTRACE_ENABLED.get();
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public static void setStacktraceEnabled(boolean stacktraceEnabled) {
|
||||
STACKTRACE_ENABLED.set(stacktraceEnabled);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public static void log(Level level, String message, boolean sub) {
|
||||
String dateTime = DATE_TIME_FORMATTER.format(LocalDateTime.now());
|
||||
|
|
Loading…
Reference in a new issue