Merge branch 'release/5.0.6'
3
.gitmodules
vendored
|
@ -1,6 +1,3 @@
|
||||||
[submodule "modules"]
|
[submodule "modules"]
|
||||||
path = modules
|
path = modules
|
||||||
url = git@github.com:GravitLauncher/LauncherModules.git
|
url = git@github.com:GravitLauncher/LauncherModules.git
|
||||||
[submodule "Radon"]
|
|
||||||
path = Radon
|
|
||||||
url = git@github.com:GravitLauncher/Radon.git
|
|
||||||
|
|
|
@ -40,10 +40,24 @@
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
task cleanjar(type: Jar, dependsOn: jar) {
|
||||||
|
classifier = 'clean'
|
||||||
|
manifest.attributes("Main-Class": mainClassName,
|
||||||
|
"Premain-Class": mainAgentName,
|
||||||
|
"Can-Redefine-Classes": "true",
|
||||||
|
"Can-Retransform-Classes": "true",
|
||||||
|
"Can-Set-Native-Method-Prefix": "true"
|
||||||
|
)
|
||||||
|
from sourceSets.main.output
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
pack project(':LauncherAPI')
|
pack project(':LauncherAPI')
|
||||||
bundle project(':Radon')
|
bundle 'org.ow2.asm:asm-commons:7.1'
|
||||||
bundle 'mysql:mysql-connector-java:8.0.16'
|
bundle 'mysql:mysql-connector-java:8.0.16'
|
||||||
|
bundle 'org.postgresql:postgresql:42.2.6'
|
||||||
bundle 'org.jline:jline:3.11.0'
|
bundle 'org.jline:jline:3.11.0'
|
||||||
bundle 'org.jline:jline-reader:3.11.0'
|
bundle 'org.jline:jline-reader:3.11.0'
|
||||||
bundle 'org.jline:jline-terminal:3.11.0'
|
bundle 'org.jline:jline-terminal:3.11.0'
|
||||||
|
@ -53,7 +67,7 @@ bundle project(':Radon')
|
||||||
bundle 'commons-codec:commons-codec:1.12'
|
bundle 'commons-codec:commons-codec:1.12'
|
||||||
bundle 'org.javassist:javassist:3.25.0-GA'
|
bundle 'org.javassist:javassist:3.25.0-GA'
|
||||||
bundle 'io.netty:netty-all:4.1.36.Final'
|
bundle 'io.netty:netty-all:4.1.36.Final'
|
||||||
bundle 'org.hibernate:hibernate-core:5.4.3.Final'
|
bundle 'org.hibernate:hibernate-core:5.4.4.Final'
|
||||||
bundle 'org.bouncycastle:bcpkix-jdk15on:1.61'
|
bundle 'org.bouncycastle:bcpkix-jdk15on:1.61'
|
||||||
|
|
||||||
bundle 'org.slf4j:slf4j-simple:1.7.25'
|
bundle 'org.slf4j:slf4j-simple:1.7.25'
|
||||||
|
@ -146,4 +160,35 @@ task dumpClientLibs(type: Copy) {
|
||||||
from parent.childProjects.Launcher.tasks.dumpLibs.destinationDir
|
from parent.childProjects.Launcher.tasks.dumpLibs.destinationDir
|
||||||
}
|
}
|
||||||
|
|
||||||
build.dependsOn tasks.dumpLibs, tasks.dumpCompileOnlyLibs, tasks.dumpClientLibs, tasks.bundle
|
build.dependsOn tasks.dumpLibs, tasks.dumpCompileOnlyLibs, tasks.dumpClientLibs, tasks.bundle, tasks.cleanjar
|
||||||
|
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
launchserverapi(MavenPublication) {
|
||||||
|
artifactId = 'launchserver-api'
|
||||||
|
artifact cleanjar
|
||||||
|
pom {
|
||||||
|
name = 'GravitLauncher LaunchServer API'
|
||||||
|
description = 'GravitLauncher LaunchServer Module API'
|
||||||
|
url = 'https://launcher.gravit.pro'
|
||||||
|
licenses {
|
||||||
|
license {
|
||||||
|
name = 'GNU General Public License, Version 3.0'
|
||||||
|
url = 'https://www.gnu.org/licenses/gpl-3.0.html'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scm {
|
||||||
|
connection = 'scm:git:https://github.com/GravitLauncher/Launcher.git'
|
||||||
|
developerConnection = 'scm:git:ssh://git@github.com:GravitLauncher/Launcher.git'
|
||||||
|
url = 'https://launcher.gravit.pro/'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
signing {
|
||||||
|
sign publishing.publications.launchserverapi
|
||||||
|
}
|
||||||
|
|
|
@ -13,11 +13,12 @@
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.SimpleFileVisitor;
|
import java.nio.file.SimpleFileVisitor;
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.interfaces.RSAPrivateKey;
|
import java.security.interfaces.RSAPrivateKey;
|
||||||
import java.security.interfaces.RSAPublicKey;
|
import java.security.interfaces.RSAPublicKey;
|
||||||
import java.security.spec.InvalidKeySpecException;
|
import java.security.spec.InvalidKeySpecException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -32,6 +33,10 @@
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.zip.CRC32;
|
import java.util.zip.CRC32;
|
||||||
|
|
||||||
|
import io.netty.channel.epoll.Epoll;
|
||||||
|
import org.bouncycastle.crypto.util.PrivateKeyFactory;
|
||||||
|
import org.bouncycastle.operator.OperatorCreationException;
|
||||||
|
|
||||||
import io.netty.handler.logging.LogLevel;
|
import io.netty.handler.logging.LogLevel;
|
||||||
import pro.gravit.launcher.Launcher;
|
import pro.gravit.launcher.Launcher;
|
||||||
import pro.gravit.launcher.LauncherConfig;
|
import pro.gravit.launcher.LauncherConfig;
|
||||||
|
@ -41,7 +46,6 @@
|
||||||
import pro.gravit.launcher.managers.ConfigManager;
|
import pro.gravit.launcher.managers.ConfigManager;
|
||||||
import pro.gravit.launcher.managers.GarbageManager;
|
import pro.gravit.launcher.managers.GarbageManager;
|
||||||
import pro.gravit.launcher.profiles.ClientProfile;
|
import pro.gravit.launcher.profiles.ClientProfile;
|
||||||
import pro.gravit.launcher.serialize.signed.SignedObjectHolder;
|
|
||||||
import pro.gravit.launchserver.auth.AuthProviderPair;
|
import pro.gravit.launchserver.auth.AuthProviderPair;
|
||||||
import pro.gravit.launchserver.auth.handler.AuthHandler;
|
import pro.gravit.launchserver.auth.handler.AuthHandler;
|
||||||
import pro.gravit.launchserver.auth.handler.MemoryAuthHandler;
|
import pro.gravit.launchserver.auth.handler.MemoryAuthHandler;
|
||||||
|
@ -61,13 +65,19 @@
|
||||||
import pro.gravit.launchserver.binary.JARLauncherBinary;
|
import pro.gravit.launchserver.binary.JARLauncherBinary;
|
||||||
import pro.gravit.launchserver.binary.LauncherBinary;
|
import pro.gravit.launchserver.binary.LauncherBinary;
|
||||||
import pro.gravit.launchserver.binary.ProguardConf;
|
import pro.gravit.launchserver.binary.ProguardConf;
|
||||||
|
import pro.gravit.launchserver.binary.SimpleEXELauncherBinary;
|
||||||
import pro.gravit.launchserver.components.AuthLimiterComponent;
|
import pro.gravit.launchserver.components.AuthLimiterComponent;
|
||||||
import pro.gravit.launchserver.components.Component;
|
import pro.gravit.launchserver.components.Component;
|
||||||
import pro.gravit.launchserver.components.RegLimiterComponent;
|
import pro.gravit.launchserver.components.RegLimiterComponent;
|
||||||
import pro.gravit.launchserver.config.LaunchServerRuntimeConfig;
|
import pro.gravit.launchserver.config.LaunchServerRuntimeConfig;
|
||||||
import pro.gravit.launchserver.dao.UserService;
|
|
||||||
import pro.gravit.launchserver.dao.provider.DaoProvider;
|
import pro.gravit.launchserver.dao.provider.DaoProvider;
|
||||||
import pro.gravit.launchserver.manangers.*;
|
import pro.gravit.launchserver.manangers.CertificateManager;
|
||||||
|
import pro.gravit.launchserver.manangers.LaunchServerGsonManager;
|
||||||
|
import pro.gravit.launchserver.manangers.MirrorManager;
|
||||||
|
import pro.gravit.launchserver.manangers.ModulesManager;
|
||||||
|
import pro.gravit.launchserver.manangers.ReconfigurableManager;
|
||||||
|
import pro.gravit.launchserver.manangers.ReloadManager;
|
||||||
|
import pro.gravit.launchserver.manangers.SessionManager;
|
||||||
import pro.gravit.launchserver.manangers.hook.AuthHookManager;
|
import pro.gravit.launchserver.manangers.hook.AuthHookManager;
|
||||||
import pro.gravit.launchserver.manangers.hook.BuildHookManager;
|
import pro.gravit.launchserver.manangers.hook.BuildHookManager;
|
||||||
import pro.gravit.launchserver.socket.WebSocketService;
|
import pro.gravit.launchserver.socket.WebSocketService;
|
||||||
|
@ -147,15 +157,8 @@ public AuthProviderPair getAuthProviderPair() {
|
||||||
public GuardLicenseConf guardLicense;
|
public GuardLicenseConf guardLicense;
|
||||||
|
|
||||||
public String whitelistRejectString;
|
public String whitelistRejectString;
|
||||||
|
|
||||||
public boolean genMappings;
|
|
||||||
public LauncherConf launcher;
|
public LauncherConf launcher;
|
||||||
|
public CertificateConf certificate;
|
||||||
public boolean isWarningMissArchJava;
|
|
||||||
public boolean enabledProGuard;
|
|
||||||
public boolean enabledRadon;
|
|
||||||
public boolean stripLineNumbers;
|
|
||||||
public boolean deleteTempFiles;
|
|
||||||
|
|
||||||
public String startScript;
|
public String startScript;
|
||||||
|
|
||||||
|
@ -253,6 +256,7 @@ public void close() {
|
||||||
|
|
||||||
public static class ExeConf {
|
public static class ExeConf {
|
||||||
public boolean enabled;
|
public boolean enabled;
|
||||||
|
public String alternative;
|
||||||
public boolean setMaxVersion;
|
public boolean setMaxVersion;
|
||||||
public String maxVersion;
|
public String maxVersion;
|
||||||
public String productName;
|
public String productName;
|
||||||
|
@ -267,6 +271,11 @@ public static class ExeConf {
|
||||||
public String txtProductVersion;
|
public String txtProductVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class CertificateConf
|
||||||
|
{
|
||||||
|
public boolean enabled;
|
||||||
|
}
|
||||||
|
|
||||||
public static class NettyUpdatesBind {
|
public static class NettyUpdatesBind {
|
||||||
public String url;
|
public String url;
|
||||||
public boolean zip;
|
public boolean zip;
|
||||||
|
@ -275,6 +284,12 @@ public static class NettyUpdatesBind {
|
||||||
public class LauncherConf {
|
public class LauncherConf {
|
||||||
public String guardType;
|
public String guardType;
|
||||||
public boolean attachLibraryBeforeProGuard;
|
public boolean attachLibraryBeforeProGuard;
|
||||||
|
public boolean compress;
|
||||||
|
public boolean warningMissArchJava;
|
||||||
|
public boolean enabledProGuard;
|
||||||
|
public boolean stripLineNumbers;
|
||||||
|
public boolean deleteTempFiles;
|
||||||
|
public boolean proguardGenMappings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NettyConfig {
|
public class NettyConfig {
|
||||||
|
@ -289,7 +304,6 @@ public class NettyConfig {
|
||||||
public NettyPerformanceConfig performance;
|
public NettyPerformanceConfig performance;
|
||||||
public NettyBindAddress[] binds;
|
public NettyBindAddress[] binds;
|
||||||
public LogLevel logLevel = LogLevel.DEBUG;
|
public LogLevel logLevel = LogLevel.DEBUG;
|
||||||
public NettyProxyConfig proxy = new NettyProxyConfig();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NettyPerformanceConfig {
|
public class NettyPerformanceConfig {
|
||||||
|
@ -298,15 +312,6 @@ public class NettyPerformanceConfig {
|
||||||
public int workerThread;
|
public int workerThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NettyProxyConfig {
|
|
||||||
public boolean enabled;
|
|
||||||
public String address = "ws://localhost:9275/api";
|
|
||||||
public String login = "login";
|
|
||||||
public String password = "password";
|
|
||||||
public String auth_id = "std";
|
|
||||||
public ArrayList<String> requests = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class NettyBindAddress {
|
public class NettyBindAddress {
|
||||||
public String address;
|
public String address;
|
||||||
public int port;
|
public int port;
|
||||||
|
@ -355,7 +360,7 @@ public static void main(String... args) throws Throwable {
|
||||||
LogHelper.printLicense("LaunchServer");
|
LogHelper.printLicense("LaunchServer");
|
||||||
if (!StarterAgent.isAgentStarted()) {
|
if (!StarterAgent.isAgentStarted()) {
|
||||||
LogHelper.error("StarterAgent is not started!");
|
LogHelper.error("StarterAgent is not started!");
|
||||||
LogHelper.error("Your should add to JVM options this option: `-javaagent:LaunchServer.jar`");
|
LogHelper.error("You should add to JVM options this option: `-javaagent:LaunchServer.jar`");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start LaunchServer
|
// Start LaunchServer
|
||||||
|
@ -394,6 +399,14 @@ public static void main(String... args) throws Throwable {
|
||||||
|
|
||||||
public final Path privateKeyFile;
|
public final Path privateKeyFile;
|
||||||
|
|
||||||
|
public final Path caCertFile;
|
||||||
|
|
||||||
|
public final Path caKeyFile;
|
||||||
|
|
||||||
|
public final Path serverCertFile;
|
||||||
|
|
||||||
|
public final Path serverKeyFile;
|
||||||
|
|
||||||
public final Path updatesDir;
|
public final Path updatesDir;
|
||||||
|
|
||||||
//public static LaunchServer server = null;
|
//public static LaunchServer server = null;
|
||||||
|
@ -448,7 +461,7 @@ public static void main(String... args) throws Throwable {
|
||||||
|
|
||||||
// Updates and profiles
|
// Updates and profiles
|
||||||
private volatile List<ClientProfile> profilesList;
|
private volatile List<ClientProfile> profilesList;
|
||||||
public volatile Map<String, SignedObjectHolder<HashedDir>> updatesDirMap;
|
public volatile Map<String, HashedDir> updatesDirMap;
|
||||||
|
|
||||||
public final Timer taskPool;
|
public final Timer taskPool;
|
||||||
|
|
||||||
|
@ -482,6 +495,12 @@ public LaunchServer(Path dir, boolean testEnv, String[] args) throws IOException
|
||||||
updatesDir = dir.resolve("updates");
|
updatesDir = dir.resolve("updates");
|
||||||
profilesDir = dir.resolve("profiles");
|
profilesDir = dir.resolve("profiles");
|
||||||
|
|
||||||
|
caCertFile = dir.resolve("ca.crt");
|
||||||
|
caKeyFile = dir.resolve("ca.key");
|
||||||
|
|
||||||
|
serverCertFile = dir.resolve("server.crt");
|
||||||
|
serverKeyFile = dir.resolve("server.key");
|
||||||
|
|
||||||
//Registration handlers and providers
|
//Registration handlers and providers
|
||||||
AuthHandler.registerHandlers();
|
AuthHandler.registerHandlers();
|
||||||
AuthProvider.registerProviders();
|
AuthProvider.registerProviders();
|
||||||
|
@ -594,6 +613,43 @@ public LaunchServer(Path dir, boolean testEnv, String[] args) throws IOException
|
||||||
authHookManager = new AuthHookManager();
|
authHookManager = new AuthHookManager();
|
||||||
configManager = new ConfigManager();
|
configManager = new ConfigManager();
|
||||||
certificateManager = new CertificateManager();
|
certificateManager = new CertificateManager();
|
||||||
|
//Generate or set new Certificate API
|
||||||
|
certificateManager.orgName = config.projectName;
|
||||||
|
if(config.certificate != null && config.certificate.enabled)
|
||||||
|
{
|
||||||
|
if(IOHelper.isFile(caCertFile) && IOHelper.isFile(caKeyFile))
|
||||||
|
{
|
||||||
|
certificateManager.ca = certificateManager.readCertificate(caCertFile);
|
||||||
|
certificateManager.caKey = certificateManager.readPrivateKey(caKeyFile);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
certificateManager.generateCA();
|
||||||
|
certificateManager.writeCertificate(caCertFile, certificateManager.ca);
|
||||||
|
certificateManager.writePrivateKey(caKeyFile, certificateManager.caKey);
|
||||||
|
} catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException | OperatorCreationException e) {
|
||||||
|
LogHelper.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(IOHelper.isFile(serverCertFile) && IOHelper.isFile(serverKeyFile))
|
||||||
|
{
|
||||||
|
certificateManager.server = certificateManager.readCertificate(serverCertFile);
|
||||||
|
certificateManager.serverKey = certificateManager.readPrivateKey(serverKeyFile);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
KeyPair pair = certificateManager.generateKeyPair();
|
||||||
|
certificateManager.server = certificateManager.generateCertificate(config.projectName.concat(" Server"), pair.getPublic());
|
||||||
|
certificateManager.serverKey = PrivateKeyFactory.createKey(pair.getPrivate().getEncoded());
|
||||||
|
certificateManager.writePrivateKey(serverKeyFile, pair.getPrivate());
|
||||||
|
certificateManager.writeCertificate(serverCertFile, certificateManager.server);
|
||||||
|
} catch (InvalidAlgorithmParameterException | NoSuchAlgorithmException | OperatorCreationException e) {
|
||||||
|
LogHelper.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
GarbageManager.registerNeedGC(sessionManager);
|
GarbageManager.registerNeedGC(sessionManager);
|
||||||
reloadManager.registerReloadable("launchServer", this);
|
reloadManager.registerReloadable("launchServer", this);
|
||||||
registerObject("permissionsHandler", config.permissionsHandler);
|
registerObject("permissionsHandler", config.permissionsHandler);
|
||||||
|
@ -669,6 +725,19 @@ private LauncherBinary binary() {
|
||||||
LogHelper.error(e);
|
LogHelper.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(config.launch4j.alternative != null)
|
||||||
|
{
|
||||||
|
switch (config.launch4j.alternative) {
|
||||||
|
case "simple":
|
||||||
|
return new SimpleEXELauncherBinary(this);
|
||||||
|
case "no":
|
||||||
|
//None
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LogHelper.warning("Alternative %s not found", config.launch4j.alternative);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
Class.forName("net.sf.launch4j.Builder");
|
Class.forName("net.sf.launch4j.Builder");
|
||||||
if (config.launch4j.enabled) return new EXEL4JLauncherBinary(this);
|
if (config.launch4j.enabled) return new EXEL4JLauncherBinary(this);
|
||||||
|
@ -714,6 +783,7 @@ private void generateConfigIfNotExists(boolean testEnv) throws IOException {
|
||||||
newConfig.launch4j = new ExeConf();
|
newConfig.launch4j = new ExeConf();
|
||||||
newConfig.launch4j.enabled = true;
|
newConfig.launch4j.enabled = true;
|
||||||
newConfig.launch4j.copyright = "© GravitLauncher Team";
|
newConfig.launch4j.copyright = "© GravitLauncher Team";
|
||||||
|
newConfig.launch4j.alternative = "no";
|
||||||
newConfig.launch4j.fileDesc = "GravitLauncher ".concat(Version.getVersion().getVersionString());
|
newConfig.launch4j.fileDesc = "GravitLauncher ".concat(Version.getVersion().getVersionString());
|
||||||
newConfig.launch4j.fileVer = Version.getVersion().getVersionString().concat(".").concat(String.valueOf(Version.getVersion().patch));
|
newConfig.launch4j.fileVer = Version.getVersion().getVersionString().concat(".").concat(String.valueOf(Version.getVersion().patch));
|
||||||
newConfig.launch4j.internalName = "Launcher";
|
newConfig.launch4j.internalName = "Launcher";
|
||||||
|
@ -741,19 +811,22 @@ private void generateConfigIfNotExists(boolean testEnv) throws IOException {
|
||||||
newConfig.netty.fileServerEnabled = true;
|
newConfig.netty.fileServerEnabled = true;
|
||||||
newConfig.netty.binds = new NettyBindAddress[]{new NettyBindAddress("0.0.0.0", 9274)};
|
newConfig.netty.binds = new NettyBindAddress[]{new NettyBindAddress("0.0.0.0", 9274)};
|
||||||
newConfig.netty.performance = new NettyPerformanceConfig();
|
newConfig.netty.performance = new NettyPerformanceConfig();
|
||||||
newConfig.netty.performance.usingEpoll = JVMHelper.OS_TYPE == JVMHelper.OS.LINUX; //Only linux
|
newConfig.netty.performance.usingEpoll = Epoll.isAvailable();
|
||||||
newConfig.netty.performance.bossThread = 2;
|
newConfig.netty.performance.bossThread = 2;
|
||||||
newConfig.netty.performance.workerThread = 8;
|
newConfig.netty.performance.workerThread = 8;
|
||||||
|
|
||||||
newConfig.launcher = new LauncherConf();
|
newConfig.launcher = new LauncherConf();
|
||||||
newConfig.launcher.guardType = "no";
|
newConfig.launcher.guardType = "no";
|
||||||
|
newConfig.launcher.compress = true;
|
||||||
|
newConfig.launcher.warningMissArchJava = true;
|
||||||
|
newConfig.launcher.attachLibraryBeforeProGuard = false;
|
||||||
|
newConfig.launcher.deleteTempFiles = true;
|
||||||
|
newConfig.launcher.enabledProGuard = true;
|
||||||
|
newConfig.launcher.stripLineNumbers = true;
|
||||||
|
newConfig.launcher.proguardGenMappings = true;
|
||||||
|
|
||||||
newConfig.enabledRadon = true;
|
newConfig.certificate = new CertificateConf();
|
||||||
newConfig.genMappings = true;
|
newConfig.certificate.enabled = false;
|
||||||
newConfig.enabledProGuard = true;
|
|
||||||
newConfig.stripLineNumbers = true;
|
|
||||||
newConfig.deleteTempFiles = true;
|
|
||||||
newConfig.isWarningMissArchJava = true;
|
|
||||||
|
|
||||||
newConfig.components = new HashMap<>();
|
newConfig.components = new HashMap<>();
|
||||||
AuthLimiterComponent authLimiterComponent = new AuthLimiterComponent();
|
AuthLimiterComponent authLimiterComponent = new AuthLimiterComponent();
|
||||||
|
@ -808,12 +881,12 @@ public void setProfiles(List<ClientProfile> profilesList) {
|
||||||
this.profilesList = Collections.unmodifiableList(profilesList);
|
this.profilesList = Collections.unmodifiableList(profilesList);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SignedObjectHolder<HashedDir> getUpdateDir(String name) {
|
public HashedDir getUpdateDir(String name) {
|
||||||
return updatesDirMap.get(name);
|
return updatesDirMap.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Set<Entry<String, SignedObjectHolder<HashedDir>>> getUpdateDirs() {
|
public Set<Entry<String, HashedDir>> getUpdateDirs() {
|
||||||
return updatesDirMap.entrySet();
|
return updatesDirMap.entrySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -866,7 +939,7 @@ public void syncProfilesDir() throws IOException {
|
||||||
|
|
||||||
public void syncUpdatesDir(Collection<String> dirs) throws IOException {
|
public void syncUpdatesDir(Collection<String> dirs) throws IOException {
|
||||||
LogHelper.info("Syncing updates dir");
|
LogHelper.info("Syncing updates dir");
|
||||||
Map<String, SignedObjectHolder<HashedDir>> newUpdatesDirMap = new HashMap<>(16);
|
Map<String, HashedDir> newUpdatesDirMap = new HashMap<>(16);
|
||||||
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(updatesDir)) {
|
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(updatesDir)) {
|
||||||
for (final Path updateDir : dirStream) {
|
for (final Path updateDir : dirStream) {
|
||||||
if (Files.isHidden(updateDir))
|
if (Files.isHidden(updateDir))
|
||||||
|
@ -882,7 +955,7 @@ public void syncUpdatesDir(Collection<String> dirs) throws IOException {
|
||||||
|
|
||||||
// Add from previous map (it's guaranteed to be non-null)
|
// Add from previous map (it's guaranteed to be non-null)
|
||||||
if (dirs != null && !dirs.contains(name)) {
|
if (dirs != null && !dirs.contains(name)) {
|
||||||
SignedObjectHolder<HashedDir> hdir = updatesDirMap.get(name);
|
HashedDir hdir = updatesDirMap.get(name);
|
||||||
if (hdir != null) {
|
if (hdir != null) {
|
||||||
newUpdatesDirMap.put(name, hdir);
|
newUpdatesDirMap.put(name, hdir);
|
||||||
continue;
|
continue;
|
||||||
|
@ -892,7 +965,7 @@ public void syncUpdatesDir(Collection<String> dirs) throws IOException {
|
||||||
// Sync and sign update dir
|
// Sync and sign update dir
|
||||||
LogHelper.info("Syncing '%s' update dir", name);
|
LogHelper.info("Syncing '%s' update dir", name);
|
||||||
HashedDir updateHDir = new HashedDir(updateDir, null, true, true);
|
HashedDir updateHDir = new HashedDir(updateDir, null, true, true);
|
||||||
newUpdatesDirMap.put(name, new SignedObjectHolder<>(updateHDir, privateKey));
|
newUpdatesDirMap.put(name, updateHDir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updatesDirMap = Collections.unmodifiableMap(newUpdatesDirMap);
|
updatesDirMap = Collections.unmodifiableMap(newUpdatesDirMap);
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
package pro.gravit.launchserver.auth;
|
||||||
|
|
||||||
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
|
|
||||||
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
import pro.gravit.utils.helper.VerifyHelper;
|
||||||
|
|
||||||
|
import org.postgresql.ds.PGSimpleDataSource;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
public final class PostgreSQLSourceConfig implements AutoCloseable {
|
||||||
|
public static final int TIMEOUT = VerifyHelper.verifyInt(
|
||||||
|
Integer.parseUnsignedInt(System.getProperty("launcher.postgresql.idleTimeout", Integer.toString(5000))),
|
||||||
|
VerifyHelper.POSITIVE, "launcher.postgresql.idleTimeout can't be <= 5000");
|
||||||
|
private static final int MAX_POOL_SIZE = VerifyHelper.verifyInt(
|
||||||
|
Integer.parseUnsignedInt(System.getProperty("launcher.postgresql.maxPoolSize", Integer.toString(3))),
|
||||||
|
VerifyHelper.POSITIVE, "launcher.postgresql.maxPoolSize can't be <= 0");
|
||||||
|
|
||||||
|
// Instance
|
||||||
|
private String poolName;
|
||||||
|
|
||||||
|
// Config
|
||||||
|
private String address;
|
||||||
|
private int port;
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
private String database;
|
||||||
|
|
||||||
|
// Cache
|
||||||
|
private DataSource source;
|
||||||
|
private boolean hikari;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void close() {
|
||||||
|
if (hikari) { // Shutdown hikari pool
|
||||||
|
((HikariDataSource) source).close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized Connection getConnection() throws SQLException {
|
||||||
|
if (source == null) { // New data source
|
||||||
|
PGSimpleDataSource postgresqlSource = new PGSimpleDataSource();
|
||||||
|
|
||||||
|
// Set credentials
|
||||||
|
postgresqlSource.setServerName(address);
|
||||||
|
postgresqlSource.setPortNumber(port);
|
||||||
|
postgresqlSource.setUser(username);
|
||||||
|
postgresqlSource.setPassword(password);
|
||||||
|
postgresqlSource.setDatabaseName(database);
|
||||||
|
|
||||||
|
// Try using HikariCP
|
||||||
|
source = postgresqlSource;
|
||||||
|
|
||||||
|
//noinspection Duplicates
|
||||||
|
try {
|
||||||
|
Class.forName("com.zaxxer.hikari.HikariDataSource");
|
||||||
|
hikari = true; // Used for shutdown. Not instanceof because of possible classpath error
|
||||||
|
|
||||||
|
// Set HikariCP pool
|
||||||
|
HikariDataSource hikariSource = new HikariDataSource();
|
||||||
|
hikariSource.setDataSource(source);
|
||||||
|
|
||||||
|
// Set pool settings
|
||||||
|
hikariSource.setPoolName(poolName);
|
||||||
|
hikariSource.setMinimumIdle(0);
|
||||||
|
hikariSource.setMaximumPoolSize(MAX_POOL_SIZE);
|
||||||
|
hikariSource.setIdleTimeout(TIMEOUT * 1000L);
|
||||||
|
|
||||||
|
// Replace source with hds
|
||||||
|
source = hikariSource;
|
||||||
|
LogHelper.info("HikariCP pooling enabled for '%s'", poolName);
|
||||||
|
} catch (ClassNotFoundException ignored) {
|
||||||
|
LogHelper.warning("HikariCP isn't in classpath for '%s'", poolName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return source.getConnection();
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,6 +24,7 @@ public static void registerHandlers() {
|
||||||
providers.register("json", JsonAuthHandler.class);
|
providers.register("json", JsonAuthHandler.class);
|
||||||
providers.register("memory", MemoryAuthHandler.class);
|
providers.register("memory", MemoryAuthHandler.class);
|
||||||
providers.register("mysql", MySQLAuthHandler.class);
|
providers.register("mysql", MySQLAuthHandler.class);
|
||||||
|
providers.register("postgresql", PostgreSQLAuthHandler.class);
|
||||||
providers.register("request", RequestAuthHandler.class);
|
providers.register("request", RequestAuthHandler.class);
|
||||||
providers.register("hibernate", HibernateAuthHandler.class);
|
providers.register("hibernate", HibernateAuthHandler.class);
|
||||||
registredHandl = true;
|
registredHandl = true;
|
||||||
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
package pro.gravit.launchserver.auth.handler;
|
||||||
|
|
||||||
|
import org.postgresql.util.PGobject;
|
||||||
|
|
||||||
|
import pro.gravit.launchserver.auth.PostgreSQLSourceConfig;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.sql.*;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public final class PostgreSQLAuthHandler extends CachedAuthHandler {
|
||||||
|
private PostgreSQLSourceConfig postgreSQLHolder;
|
||||||
|
private String uuidColumn;
|
||||||
|
private String usernameColumn;
|
||||||
|
private String accessTokenColumn;
|
||||||
|
private String serverIDColumn;
|
||||||
|
|
||||||
|
|
||||||
|
private String queryByUUIDSQL;
|
||||||
|
private String queryByUsernameSQL;
|
||||||
|
private String updateAuthSQL;
|
||||||
|
private String updateServerIDSQL;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
postgreSQLHolder.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Entry constructEntry(ResultSet set) throws SQLException {
|
||||||
|
return set.next() ? new Entry(UUID.fromString(set.getString(uuidColumn)),
|
||||||
|
set.getString(usernameColumn), set.getString(accessTokenColumn), set.getString(serverIDColumn)) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Entry fetchEntry(String username) throws IOException {
|
||||||
|
return query(queryByUsernameSQL, username);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Entry fetchEntry(UUID uuid) throws IOException {
|
||||||
|
return query(queryByUUIDSQL, uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean updateAuth(UUID uuid, String username, String accessToken) throws IOException {
|
||||||
|
try (Connection c = postgreSQLHolder.getConnection();
|
||||||
|
PreparedStatement s = c.prepareStatement(updateAuthSQL)) {
|
||||||
|
s.setString(1, username); // Username case
|
||||||
|
s.setString(2, accessToken);
|
||||||
|
|
||||||
|
PGobject uuidObject = new PGobject();
|
||||||
|
uuidObject.setType("uuid");
|
||||||
|
uuidObject.setValue(uuid.toString());
|
||||||
|
s.setObject(3, uuidObject);
|
||||||
|
|
||||||
|
// Execute update
|
||||||
|
s.setQueryTimeout(PostgreSQLSourceConfig.TIMEOUT);
|
||||||
|
return s.executeUpdate() > 0;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new IOException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean updateServerID(UUID uuid, String serverID) throws IOException {
|
||||||
|
try (Connection c = postgreSQLHolder.getConnection();
|
||||||
|
PreparedStatement s = c.prepareStatement(updateServerIDSQL)) {
|
||||||
|
s.setString(1, serverID);
|
||||||
|
|
||||||
|
PGobject uuidObject = new PGobject();
|
||||||
|
uuidObject.setType("uuid");
|
||||||
|
uuidObject.setValue(uuid.toString());
|
||||||
|
s.setObject(2, uuidObject);
|
||||||
|
|
||||||
|
// Execute update
|
||||||
|
s.setQueryTimeout(PostgreSQLSourceConfig.TIMEOUT);
|
||||||
|
return s.executeUpdate() > 0;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new IOException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Entry query(String sql, String value) throws IOException {
|
||||||
|
try (Connection c = postgreSQLHolder.getConnection();
|
||||||
|
PreparedStatement s = c.prepareStatement(sql)) {
|
||||||
|
s.setString(1, value);
|
||||||
|
|
||||||
|
// Execute query
|
||||||
|
s.setQueryTimeout(PostgreSQLSourceConfig.TIMEOUT);
|
||||||
|
try (ResultSet set = s.executeQuery()) {
|
||||||
|
return constructEntry(set);
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new IOException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Entry query(String sql, UUID value) throws IOException {
|
||||||
|
try (Connection c = postgreSQLHolder.getConnection();
|
||||||
|
PreparedStatement s = c.prepareStatement(sql)) {
|
||||||
|
PGobject uuidObject = new PGobject();
|
||||||
|
uuidObject.setType("uuid");
|
||||||
|
uuidObject.setValue(value.toString());
|
||||||
|
|
||||||
|
s.setObject(1, uuidObject);
|
||||||
|
|
||||||
|
// Execute query
|
||||||
|
s.setQueryTimeout(PostgreSQLSourceConfig.TIMEOUT);
|
||||||
|
try (ResultSet set = s.executeQuery()) {
|
||||||
|
return constructEntry(set);
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new IOException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -153,13 +153,17 @@ public void onCheckInfo(OshiHWID hwid, String username, Connection c) throws HWI
|
||||||
db_hwid.HWDiskSerial = set.getString(hwidFieldHWDiskSerial);
|
db_hwid.HWDiskSerial = set.getString(hwidFieldHWDiskSerial);
|
||||||
db_hwid.totalMemory = Long.valueOf(set.getString(hwidFieldTotalMemory));
|
db_hwid.totalMemory = Long.valueOf(set.getString(hwidFieldTotalMemory));
|
||||||
db_hwid.macAddr = set.getString(hwidFieldMAC);
|
db_hwid.macAddr = set.getString(hwidFieldMAC);
|
||||||
|
if (LogHelper.isDevEnabled()) {
|
||||||
LogHelper.dev("Compare HWID: %s vs %s", hwid.getSerializeString(), db_hwid.getSerializeString());
|
LogHelper.dev("Compare HWID: %s vs %s", hwid.getSerializeString(), db_hwid.getSerializeString());
|
||||||
|
}
|
||||||
int compare_point = hwid.compare(db_hwid);
|
int compare_point = hwid.compare(db_hwid);
|
||||||
if (compare_point < compare) continue;
|
if (compare_point < compare) continue;
|
||||||
else {
|
else {
|
||||||
|
if (LogHelper.isDevEnabled()) {
|
||||||
LogHelper.debug("User %s hwid check: found compare %d in %d", username, compare_point, set.getInt("id"));
|
LogHelper.debug("User %s hwid check: found compare %d in %d", username, compare_point, set.getInt("id"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (oneCompareMode) isOne = true;
|
if (oneCompareMode) isOne = true;
|
||||||
boolean isBanned = set.getBoolean(hwidFieldBanned);
|
boolean isBanned = set.getBoolean(hwidFieldBanned);
|
||||||
if (isBanned) {
|
if (isBanned) {
|
||||||
|
@ -175,7 +179,9 @@ public void onCheckInfo(OshiHWID hwid, String username, Connection c) throws HWI
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIsBanned(HWID hwid, boolean isBanned) {
|
public void setIsBanned(HWID hwid, boolean isBanned) {
|
||||||
|
if (LogHelper.isDebugEnabled()) {
|
||||||
LogHelper.debug("%s Request HWID: %s", isBanned ? "Ban" : "UnBan", hwid.toString());
|
LogHelper.debug("%s Request HWID: %s", isBanned ? "Ban" : "UnBan", hwid.toString());
|
||||||
|
}
|
||||||
if (hwid instanceof OshiHWID) {
|
if (hwid instanceof OshiHWID) {
|
||||||
OshiHWID oshiHWID = (OshiHWID) hwid;
|
OshiHWID oshiHWID = (OshiHWID) hwid;
|
||||||
try (Connection c = mySQLHolder.getConnection()) {
|
try (Connection c = mySQLHolder.getConnection()) {
|
||||||
|
@ -214,7 +220,9 @@ public void unban(List<HWID> list) {
|
||||||
public List<HWID> getHwid(String username) {
|
public List<HWID> getHwid(String username) {
|
||||||
ArrayList<HWID> list = new ArrayList<>();
|
ArrayList<HWID> list = new ArrayList<>();
|
||||||
try (Connection c = mySQLHolder.getConnection()) {
|
try (Connection c = mySQLHolder.getConnection()) {
|
||||||
|
if (LogHelper.isDebugEnabled()) {
|
||||||
LogHelper.debug("Try find HWID from username %s", username);
|
LogHelper.debug("Try find HWID from username %s", username);
|
||||||
|
}
|
||||||
PreparedStatement s = c.prepareStatement(String.format("SELECT %s, %s FROM `%s` WHERE `%s` = ? LIMIT 1", userFieldHwid, userFieldLogin, tableUsers, userFieldLogin));
|
PreparedStatement s = c.prepareStatement(String.format("SELECT %s, %s FROM `%s` WHERE `%s` = ? LIMIT 1", userFieldHwid, userFieldLogin, tableUsers, userFieldLogin));
|
||||||
s.setString(1, username);
|
s.setString(1, username);
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ public static void registerProviders() {
|
||||||
providers.register("accept", AcceptAuthProvider.class);
|
providers.register("accept", AcceptAuthProvider.class);
|
||||||
providers.register("reject", RejectAuthProvider.class);
|
providers.register("reject", RejectAuthProvider.class);
|
||||||
providers.register("mysql", MySQLAuthProvider.class);
|
providers.register("mysql", MySQLAuthProvider.class);
|
||||||
|
providers.register("postgresql", PostgreSQLAuthProvider.class);
|
||||||
providers.register("request", RequestAuthProvider.class);
|
providers.register("request", RequestAuthProvider.class);
|
||||||
providers.register("json", JsonAuthProvider.class);
|
providers.register("json", JsonAuthProvider.class);
|
||||||
providers.register("hibernate", HibernateAuthProvider.class);
|
providers.register("hibernate", HibernateAuthProvider.class);
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
package pro.gravit.launchserver.auth.provider;
|
||||||
|
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.ClientPermissions;
|
||||||
|
import pro.gravit.launchserver.auth.AuthException;
|
||||||
|
import pro.gravit.launchserver.auth.PostgreSQLSourceConfig;
|
||||||
|
import pro.gravit.utils.helper.CommonHelper;
|
||||||
|
import pro.gravit.utils.helper.SecurityHelper;
|
||||||
|
|
||||||
|
public final class PostgreSQLAuthProvider extends AuthProvider {
|
||||||
|
private PostgreSQLSourceConfig postgreSQLHolder;
|
||||||
|
private String query;
|
||||||
|
private String message;
|
||||||
|
private String[] queryParams;
|
||||||
|
private boolean usePermission;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthProviderResult auth(String login, String password, String ip) throws SQLException, AuthException {
|
||||||
|
try (Connection c = postgreSQLHolder.getConnection(); PreparedStatement s = c.prepareStatement(query)) {
|
||||||
|
String[] replaceParams = {"login", login, "password", password, "ip", ip};
|
||||||
|
for (int i = 0; i < queryParams.length; i++) {
|
||||||
|
s.setString(i + 1, CommonHelper.replace(queryParams[i], replaceParams));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute SQL query
|
||||||
|
s.setQueryTimeout(PostgreSQLSourceConfig.TIMEOUT);
|
||||||
|
try (ResultSet set = s.executeQuery()) {
|
||||||
|
return set.next() ? new AuthProviderResult(set.getString(1), SecurityHelper.randomStringToken(), usePermission ? new ClientPermissions(set.getLong(2)) : srv.config.permissionsHandler.getPermissions(set.getString(1))) : authError(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
postgreSQLHolder.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,7 +20,9 @@ public RequestTextureProvider(String skinURL, String cloakURL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Texture getTexture(String url, boolean cloak) throws IOException {
|
private static Texture getTexture(String url, boolean cloak) throws IOException {
|
||||||
|
if (LogHelper.isDebugEnabled()) {
|
||||||
LogHelper.debug("Getting texture: '%s'", url);
|
LogHelper.debug("Getting texture: '%s'", url);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
return new Texture(url, cloak);
|
return new Texture(url, cloak);
|
||||||
} catch (FileNotFoundException ignored) {
|
} catch (FileNotFoundException ignored) {
|
||||||
|
|
|
@ -1,109 +1,100 @@
|
||||||
package pro.gravit.launchserver.binary;
|
package pro.gravit.launchserver.binary;
|
||||||
|
|
||||||
import java.io.IOException;
|
import org.objectweb.asm.ClassWriter;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
import org.objectweb.asm.tree.FieldInsnNode;
|
||||||
|
import org.objectweb.asm.tree.InsnList;
|
||||||
|
import org.objectweb.asm.tree.InsnNode;
|
||||||
|
import org.objectweb.asm.tree.IntInsnNode;
|
||||||
|
import org.objectweb.asm.tree.LdcInsnNode;
|
||||||
|
import org.objectweb.asm.tree.MethodInsnNode;
|
||||||
|
import org.objectweb.asm.tree.MethodNode;
|
||||||
|
import org.objectweb.asm.tree.TypeInsnNode;
|
||||||
|
|
||||||
import javassist.CannotCompileException;
|
import org.objectweb.asm.Type;
|
||||||
import javassist.ClassPool;
|
|
||||||
import javassist.CtClass;
|
import pro.gravit.launcher.AutogenConfig;
|
||||||
import javassist.CtConstructor;
|
|
||||||
import javassist.CtMethod;
|
|
||||||
import javassist.NotFoundException;
|
|
||||||
import pro.gravit.launcher.LauncherConfig;
|
import pro.gravit.launcher.LauncherConfig;
|
||||||
import pro.gravit.launchserver.binary.tasks.MainBuildTask;
|
import pro.gravit.launcher.modules.Module;
|
||||||
|
import pro.gravit.launcher.modules.ModulesManager;
|
||||||
|
import pro.gravit.launchserver.asm.ClassMetadataReader;
|
||||||
|
import pro.gravit.launchserver.asm.SafeClassWriter;
|
||||||
|
|
||||||
public class JAConfigurator implements AutoCloseable {
|
public class JAConfigurator {
|
||||||
public ClassPool pool;
|
private static final String modulesManagerName = Type.getInternalName(ModulesManager.class);
|
||||||
public CtClass ctClass;
|
private static final String registerModDesc = Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Module.class));
|
||||||
public CtConstructor ctConstructor;
|
private static final String autoGenConfigName = Type.getInternalName(AutogenConfig.class);
|
||||||
public CtMethod initModuleMethod;
|
private static final String stringName = Type.getInternalName(String.class);
|
||||||
String classname;
|
private final ClassNode configclass;
|
||||||
StringBuilder body;
|
private final MethodNode constructor;
|
||||||
StringBuilder moduleBody;
|
private final MethodNode initModuleMethod;
|
||||||
int autoincrement;
|
|
||||||
|
|
||||||
public JAConfigurator(String configclass, MainBuildTask jarLauncherBinary) throws NotFoundException {
|
public JAConfigurator(ClassNode configclass) {
|
||||||
pool = new ClassPool(false);
|
this.configclass = configclass;
|
||||||
pool.appendSystemPath();
|
constructor = configclass.methods.stream().filter(e -> "<init>".equals(e.name)).findFirst().get();
|
||||||
classname = configclass;
|
constructor.instructions = new InsnList();
|
||||||
ctClass = pool.get(classname);
|
initModuleMethod = configclass.methods.stream().filter(e -> "initModules".equals(e.name)).findFirst().get();
|
||||||
ctConstructor = ctClass.getDeclaredConstructor(null);
|
initModuleMethod.instructions = new InsnList();
|
||||||
initModuleMethod = ctClass.getDeclaredMethod("initModules");
|
|
||||||
body = new StringBuilder("{ isInitModules = false; ");
|
|
||||||
moduleBody = new StringBuilder("{ isInitModules = true; ");
|
|
||||||
autoincrement = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addModuleClass(String fullName) {
|
public void addModuleClass(String fullName) {
|
||||||
moduleBody.append("pro.gravit.launcher.modules.Module mod");
|
initModuleMethod.instructions.insert(new MethodInsnNode(Opcodes.INVOKEINTERFACE, modulesManagerName, "registerModule", registerModDesc));
|
||||||
moduleBody.append(autoincrement);
|
initModuleMethod.instructions.insert(new MethodInsnNode(Opcodes.INVOKESPECIAL, fullName.replace('.', '/'), "<init>", "()V"));
|
||||||
moduleBody.append(" = new ");
|
initModuleMethod.instructions.insert(new TypeInsnNode(Opcodes.NEW, fullName.replace('.', '/')));
|
||||||
moduleBody.append(fullName);
|
|
||||||
moduleBody.append("();");
|
|
||||||
moduleBody.append("pro.gravit.launcher.Launcher.modulesManager.registerModule( mod");
|
|
||||||
moduleBody.append(autoincrement);
|
|
||||||
moduleBody.append(");");
|
|
||||||
autoincrement++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public byte[] getBytecode(ClassMetadataReader reader) {
|
||||||
public void close() {
|
ClassWriter cw = new SafeClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
|
||||||
ctClass.defrost();
|
configclass.accept(cw);
|
||||||
}
|
return cw.toByteArray();
|
||||||
|
|
||||||
public CtClass getCtClass() {
|
|
||||||
return ctClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getBytecode() throws IOException, CannotCompileException {
|
|
||||||
return ctClass.toBytecode();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void compile() throws CannotCompileException {
|
|
||||||
body.append("}");
|
|
||||||
moduleBody.append("}");
|
|
||||||
ctConstructor.setBody(body.toString());
|
|
||||||
initModuleMethod.insertAfter(moduleBody.toString());
|
|
||||||
if (ctClass.isFrozen()) ctClass.defrost();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getZipEntryPath() {
|
public String getZipEntryPath() {
|
||||||
return classname.replace('.', '/').concat(".class");
|
return configclass.name.concat(".class");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAddress(String address) {
|
public void setAddress(String address) {
|
||||||
body.append("this.address = \"");
|
constructor.instructions.add(new LdcInsnNode(address));
|
||||||
body.append(address);
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "address", stringName));
|
||||||
body.append("\";");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setProjectName(String name) {
|
public void setProjectName(String name) {
|
||||||
body.append("this.projectname = \"");
|
constructor.instructions.add(new LdcInsnNode(name));
|
||||||
body.append(name);
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "projectname", stringName));
|
||||||
body.append("\";");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSecretKey(String key) {
|
public void setSecretKey(String key) {
|
||||||
body.append("this.secretKeyClient = \"");
|
constructor.instructions.add(new LdcInsnNode(key));
|
||||||
body.append(key);
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "secretKeyClient", stringName));
|
||||||
body.append("\";");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOemUnlockKey(String key) {
|
public void setOemUnlockKey(String key) {
|
||||||
body.append("this.oemUnlockKey = \"");
|
constructor.instructions.add(new LdcInsnNode(key));
|
||||||
body.append(key);
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "oemUnlockKey", stringName));
|
||||||
body.append("\";");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGuardType(String key) {
|
public void setGuardType(String key) {
|
||||||
body.append("this.guardType = \"");
|
constructor.instructions.add(new LdcInsnNode(key));
|
||||||
body.append(key);
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "guardType", stringName));
|
||||||
body.append("\";");
|
}
|
||||||
|
|
||||||
|
public void push(final int value) {
|
||||||
|
if (value >= -1 && value <= 5)
|
||||||
|
constructor.instructions.add(new InsnNode(Opcodes.ICONST_0 + value));
|
||||||
|
else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE)
|
||||||
|
constructor.instructions.add(new IntInsnNode(Opcodes.BIPUSH, value));
|
||||||
|
else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE)
|
||||||
|
constructor.instructions.add(new IntInsnNode(Opcodes.SIPUSH, value));
|
||||||
|
else
|
||||||
|
constructor.instructions.add(new LdcInsnNode(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEnv(LauncherConfig.LauncherEnvironment env) {
|
public void setEnv(LauncherConfig.LauncherEnvironment env) {
|
||||||
int i = 2;
|
int i = 2;
|
||||||
switch (env) {
|
|
||||||
|
|
||||||
|
switch (env) {
|
||||||
case DEV:
|
case DEV:
|
||||||
i = 0;
|
i = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -117,36 +108,35 @@ public void setEnv(LauncherConfig.LauncherEnvironment env) {
|
||||||
i = 3;
|
i = 3;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
body.append("this.env = ");
|
push(i);
|
||||||
body.append(i);
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "env", Type.INT_TYPE.getInternalName()));
|
||||||
body.append(";");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setClientPort(int port) {
|
public void setClientPort(int port) {
|
||||||
body.append("this.clientPort = ");
|
push(port);
|
||||||
body.append(port);
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "clientPort", Type.INT_TYPE.getInternalName()));
|
||||||
body.append(";");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setWarningMissArchJava(boolean b) {
|
public void setWarningMissArchJava(boolean b) {
|
||||||
body.append("this.isWarningMissArchJava = ");
|
constructor.instructions.add(new InsnNode(b ? Opcodes.ICONST_1 : Opcodes.ICONST_0));
|
||||||
body.append(b ? "true" : "false");
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "isWarningMissArchJava", Type.BOOLEAN_TYPE.getInternalName()));
|
||||||
body.append(";");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGuardLicense(String name, String key, String encryptKey) {
|
public void setGuardLicense(String name, String key, String encryptKey) {
|
||||||
body.append("this.guardLicenseName = \"");
|
constructor.instructions.add(new LdcInsnNode(name));
|
||||||
body.append(name);
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "guardLicenseName", stringName));
|
||||||
body.append("\";");
|
constructor.instructions.add(new LdcInsnNode(key));
|
||||||
body.append("this.guardLicenseKey = \"");
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "guardLicenseKey", stringName));
|
||||||
body.append(key);
|
constructor.instructions.add(new LdcInsnNode(encryptKey));
|
||||||
body.append("\";");
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "guardLicenseEncryptKey", stringName));
|
||||||
body.append("this.guardLicenseEncryptKey = \"");
|
|
||||||
body.append(encryptKey);
|
|
||||||
body.append("\";");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClassPool getPool() {
|
public void nullGuardLicense() {
|
||||||
return pool;
|
constructor.instructions.add(new InsnNode(Opcodes.ACONST_NULL));
|
||||||
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "guardLicenseName", stringName));
|
||||||
|
constructor.instructions.add(new InsnNode(Opcodes.ACONST_NULL));
|
||||||
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "guardLicenseKey", stringName));
|
||||||
|
constructor.instructions.add(new InsnNode(Opcodes.ACONST_NULL));
|
||||||
|
constructor.instructions.add(new FieldInsnNode(Opcodes.PUTFIELD, autoGenConfigName, "guardLicenseEncryptKey", stringName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,13 +9,7 @@
|
||||||
|
|
||||||
import pro.gravit.launcher.Launcher;
|
import pro.gravit.launcher.Launcher;
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
import pro.gravit.launchserver.binary.tasks.AdditionalFixesApplyTask;
|
import pro.gravit.launchserver.binary.tasks.*;
|
||||||
import pro.gravit.launchserver.binary.tasks.AttachJarsTask;
|
|
||||||
import pro.gravit.launchserver.binary.tasks.LauncherBuildTask;
|
|
||||||
import pro.gravit.launchserver.binary.tasks.MainBuildTask;
|
|
||||||
import pro.gravit.launchserver.binary.tasks.PrepareBuildTask;
|
|
||||||
import pro.gravit.launchserver.binary.tasks.ProGuardBuildTask;
|
|
||||||
import pro.gravit.launchserver.binary.tasks.RadonBuildTask;
|
|
||||||
import pro.gravit.utils.helper.CommonHelper;
|
import pro.gravit.utils.helper.CommonHelper;
|
||||||
import pro.gravit.utils.helper.IOHelper;
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
@ -51,8 +45,8 @@ public void init() {
|
||||||
if (server.config.launcher.attachLibraryBeforeProGuard) tasks.add(new AttachJarsTask(server));
|
if (server.config.launcher.attachLibraryBeforeProGuard) tasks.add(new AttachJarsTask(server));
|
||||||
tasks.add(new ProGuardBuildTask(server));
|
tasks.add(new ProGuardBuildTask(server));
|
||||||
tasks.add(new AdditionalFixesApplyTask(server));
|
tasks.add(new AdditionalFixesApplyTask(server));
|
||||||
tasks.add(new RadonBuildTask(server));
|
|
||||||
if (!server.config.launcher.attachLibraryBeforeProGuard) tasks.add(new AttachJarsTask(server));
|
if (!server.config.launcher.attachLibraryBeforeProGuard) tasks.add(new AttachJarsTask(server));
|
||||||
|
if(server.config.launcher.compress) tasks.add(new CompressBuildTask(server));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -70,12 +64,12 @@ public void build() throws IOException {
|
||||||
long time_task_end = System.currentTimeMillis();
|
long time_task_end = System.currentTimeMillis();
|
||||||
long time_task = time_task_end - time_this;
|
long time_task = time_task_end - time_this;
|
||||||
time_this = time_task_end;
|
time_this = time_task_end;
|
||||||
if (isNeedDelete && server.config.deleteTempFiles) Files.deleteIfExists(oldPath);
|
if (isNeedDelete && server.config.launcher.deleteTempFiles) Files.deleteIfExists(oldPath);
|
||||||
isNeedDelete = task.allowDelete();
|
isNeedDelete = task.allowDelete();
|
||||||
LogHelper.subInfo("Task %s processed from %d millis", task.getName(), time_task);
|
LogHelper.subInfo("Task %s processed from %d millis", task.getName(), time_task);
|
||||||
}
|
}
|
||||||
long time_end = System.currentTimeMillis();
|
long time_end = System.currentTimeMillis();
|
||||||
if (isNeedDelete && server.config.deleteTempFiles) IOHelper.move(thisPath, syncBinaryFile);
|
if (isNeedDelete && server.config.launcher.deleteTempFiles) IOHelper.move(thisPath, syncBinaryFile);
|
||||||
else IOHelper.copy(thisPath, syncBinaryFile);
|
else IOHelper.copy(thisPath, syncBinaryFile);
|
||||||
LogHelper.info("Build successful from %d millis", time_end - time_start);
|
LogHelper.info("Build successful from %d millis", time_end - time_start);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
||||||
import pro.gravit.launcher.serialize.signed.DigestBytesHolder;
|
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
import pro.gravit.utils.helper.IOHelper;
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
import pro.gravit.utils.helper.SecurityHelper;
|
import pro.gravit.utils.helper.SecurityHelper;
|
||||||
|
@ -11,7 +10,7 @@
|
||||||
public abstract class LauncherBinary {
|
public abstract class LauncherBinary {
|
||||||
public final LaunchServer server;
|
public final LaunchServer server;
|
||||||
public final Path syncBinaryFile;
|
public final Path syncBinaryFile;
|
||||||
private volatile DigestBytesHolder binary;
|
private volatile byte[] digest;
|
||||||
private volatile byte[] sign;
|
private volatile byte[] sign;
|
||||||
|
|
||||||
protected LauncherBinary(LaunchServer server, Path binaryFile) {
|
protected LauncherBinary(LaunchServer server, Path binaryFile) {
|
||||||
|
@ -27,8 +26,8 @@ public final boolean exists() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public final DigestBytesHolder getBytes() {
|
public final byte[] getDigest() {
|
||||||
return binary;
|
return digest;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final byte[] getSign() {
|
public final byte[] getSign() {
|
||||||
|
@ -40,7 +39,7 @@ public void init() {
|
||||||
|
|
||||||
public final boolean sync() throws IOException {
|
public final boolean sync() throws IOException {
|
||||||
boolean exists = exists();
|
boolean exists = exists();
|
||||||
binary = exists ? new DigestBytesHolder(IOHelper.read(syncBinaryFile), SecurityHelper.DigestAlgorithm.SHA512) : null;
|
digest = exists ? SecurityHelper.digest(SecurityHelper.DigestAlgorithm.SHA512, IOHelper.read(syncBinaryFile)) : null;
|
||||||
sign = exists ? SecurityHelper.sign(IOHelper.read(syncBinaryFile), server.privateKey) : null;
|
sign = exists ? SecurityHelper.sign(IOHelper.read(syncBinaryFile), server.privateKey) : null;
|
||||||
|
|
||||||
return exists;
|
return exists;
|
||||||
|
|
|
@ -44,7 +44,7 @@ public ProguardConf(LaunchServer srv) {
|
||||||
public String[] buildConfig(Path inputJar, Path outputJar) {
|
public String[] buildConfig(Path inputJar, Path outputJar) {
|
||||||
List<String> confStrs = new ArrayList<>();
|
List<String> confStrs = new ArrayList<>();
|
||||||
prepare(false);
|
prepare(false);
|
||||||
if (srv.config.genMappings) confStrs.add("-printmapping \'" + mappings.toFile().getName() + "\'");
|
if (srv.config.launcher.proguardGenMappings) confStrs.add("-printmapping \'" + mappings.toFile().getName() + "\'");
|
||||||
confStrs.add("-obfuscationdictionary \'" + words.toFile().getName() + "\'");
|
confStrs.add("-obfuscationdictionary \'" + words.toFile().getName() + "\'");
|
||||||
confStrs.add("-injar \'" + inputJar.toAbsolutePath() + "\'");
|
confStrs.add("-injar \'" + inputJar.toAbsolutePath() + "\'");
|
||||||
confStrs.add("-outjar \'" + outputJar.toAbsolutePath() + "\'");
|
confStrs.add("-outjar \'" + outputJar.toAbsolutePath() + "\'");
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package pro.gravit.launchserver.binary;
|
||||||
|
|
||||||
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public class SimpleEXELauncherBinary extends LauncherBinary {
|
||||||
|
public Path exeTemplate;
|
||||||
|
public SimpleEXELauncherBinary(LaunchServer server) {
|
||||||
|
super(server, LauncherBinary.resolve(server, ".exe"));
|
||||||
|
exeTemplate = server.dir.resolve("SimpleTemplate.exe");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void build() throws IOException {
|
||||||
|
if(!IOHelper.isFile(exeTemplate))
|
||||||
|
{
|
||||||
|
LogHelper.warning("[SimpleEXEBinary] File %s not found. %s not created", exeTemplate.toString(), syncBinaryFile.toString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try(OutputStream output = IOHelper.newOutput(syncBinaryFile))
|
||||||
|
{
|
||||||
|
IOHelper.transfer(exeTemplate, output);
|
||||||
|
IOHelper.transfer(server.launcherBinary.syncBinaryFile, output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,7 @@
|
||||||
import pro.gravit.launchserver.asm.ClassMetadataReader;
|
import pro.gravit.launchserver.asm.ClassMetadataReader;
|
||||||
import pro.gravit.launchserver.asm.SafeClassWriter;
|
import pro.gravit.launchserver.asm.SafeClassWriter;
|
||||||
import pro.gravit.utils.helper.IOHelper;
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
public class AdditionalFixesApplyTask implements LauncherBuildTask {
|
public class AdditionalFixesApplyTask implements LauncherBuildTask {
|
||||||
private final LaunchServer server;
|
private final LaunchServer server;
|
||||||
|
@ -73,7 +74,12 @@ public static void apply(Path inputFile, Path addFile, ZipOutputStream output, L
|
||||||
IOHelper.transfer(input, outputStream);
|
IOHelper.transfer(input, outputStream);
|
||||||
bytes = outputStream.toByteArray();
|
bytes = outputStream.toByteArray();
|
||||||
}
|
}
|
||||||
output.write(classFix(bytes, reader, srv.config.stripLineNumbers));
|
try {
|
||||||
|
bytes = classFix(bytes, reader, srv.config.launcher.stripLineNumbers);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
LogHelper.subWarning("Error on fixing class: " + t);
|
||||||
|
}
|
||||||
|
output.write(bytes);
|
||||||
} else
|
} else
|
||||||
IOHelper.transfer(input, output);
|
IOHelper.transfer(input, output);
|
||||||
e = input.getNextEntry();
|
e = input.getNextEntry();
|
||||||
|
@ -86,7 +92,6 @@ private static byte[] classFix(byte[] bytes, ClassMetadataReader reader, boolean
|
||||||
ClassReader cr = new ClassReader(bytes);
|
ClassReader cr = new ClassReader(bytes);
|
||||||
ClassNode cn = new ClassNode();
|
ClassNode cn = new ClassNode();
|
||||||
cr.accept(cn, stripNumbers ? (ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES) : ClassReader.SKIP_FRAMES);
|
cr.accept(cn, stripNumbers ? (ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES) : ClassReader.SKIP_FRAMES);
|
||||||
|
|
||||||
ClassWriter cw = new SafeClassWriter(reader, ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
|
ClassWriter cw = new SafeClassWriter(reader, ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
|
||||||
cn.accept(cw);
|
cn.accept(cw);
|
||||||
return cw.toByteArray();
|
return cw.toByteArray();
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
package pro.gravit.launchserver.binary.tasks;
|
||||||
|
|
||||||
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.zip.Deflater;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipInputStream;
|
||||||
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
|
public class CompressBuildTask implements LauncherBuildTask {
|
||||||
|
public transient final LaunchServer server;
|
||||||
|
|
||||||
|
public CompressBuildTask(LaunchServer server) {
|
||||||
|
this.server = server;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "compress";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Path process(Path inputFile) throws IOException {
|
||||||
|
Path output = server.launcherBinary.nextPath(this);
|
||||||
|
try(ZipOutputStream outputStream = new ZipOutputStream(IOHelper.newOutput(output)))
|
||||||
|
{
|
||||||
|
outputStream.setMethod(ZipOutputStream.DEFLATED);
|
||||||
|
outputStream.setLevel(Deflater.BEST_COMPRESSION);
|
||||||
|
try(ZipInputStream input = IOHelper.newZipInput(inputFile))
|
||||||
|
{
|
||||||
|
ZipEntry e = input.getNextEntry();
|
||||||
|
while (e != null) {
|
||||||
|
if (e.isDirectory()) {
|
||||||
|
e = input.getNextEntry();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
outputStream.putNextEntry(IOHelper.newZipEntry(e));
|
||||||
|
IOHelper.transfer(input, outputStream);
|
||||||
|
e = input.getNextEntry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean allowDelete() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,8 +16,9 @@
|
||||||
import java.util.zip.ZipInputStream;
|
import java.util.zip.ZipInputStream;
|
||||||
import java.util.zip.ZipOutputStream;
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
import javassist.CannotCompileException;
|
import org.objectweb.asm.ClassReader;
|
||||||
import javassist.NotFoundException;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
|
||||||
import pro.gravit.launcher.AutogenConfig;
|
import pro.gravit.launcher.AutogenConfig;
|
||||||
import pro.gravit.launcher.Launcher;
|
import pro.gravit.launcher.Launcher;
|
||||||
import pro.gravit.launcher.LauncherConfig;
|
import pro.gravit.launcher.LauncherConfig;
|
||||||
|
@ -115,27 +116,22 @@ public String getName() {
|
||||||
@Override
|
@Override
|
||||||
public Path process(Path inputJar) throws IOException {
|
public Path process(Path inputJar) throws IOException {
|
||||||
Path outputJar = server.launcherBinary.nextPath("main");
|
Path outputJar = server.launcherBinary.nextPath("main");
|
||||||
try (ZipOutputStream output = new ZipOutputStream(IOHelper.newOutput(outputJar));
|
try (ZipOutputStream output = new ZipOutputStream(IOHelper.newOutput(outputJar))) {
|
||||||
JAConfigurator jaConfigurator = new JAConfigurator(AutogenConfig.class.getName(), this)) {
|
ClassNode cn = new ClassNode();
|
||||||
jaConfigurator.pool.insertClassPath(inputJar.toFile().getAbsolutePath());
|
new ClassReader(IOHelper.getResourceBytes(AutogenConfig.class.getName().replace('.', '/').concat(".class"))).accept(cn, 0);
|
||||||
server.launcherBinary.coreLibs.stream().map(e -> e.toFile().getAbsolutePath())
|
JAConfigurator jaConfigurator = new JAConfigurator(cn);
|
||||||
.forEach(t -> {
|
|
||||||
try {
|
|
||||||
jaConfigurator.pool.appendClassPath(t);
|
|
||||||
} catch (NotFoundException e2) {
|
|
||||||
LogHelper.error(e2);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
BuildContext context = new BuildContext(output, jaConfigurator, this);
|
BuildContext context = new BuildContext(output, jaConfigurator, this);
|
||||||
server.buildHookManager.hook(context);
|
server.buildHookManager.hook(context);
|
||||||
jaConfigurator.setAddress(server.config.netty.address);
|
jaConfigurator.setAddress(server.config.netty.address);
|
||||||
if (server.config.guardLicense != null)
|
if (server.config.guardLicense != null)
|
||||||
jaConfigurator.setGuardLicense(server.config.guardLicense.name, server.config.guardLicense.key, server.config.guardLicense.encryptKey);
|
jaConfigurator.setGuardLicense(server.config.guardLicense.name, server.config.guardLicense.key, server.config.guardLicense.encryptKey);
|
||||||
|
else
|
||||||
|
jaConfigurator.nullGuardLicense();
|
||||||
jaConfigurator.setProjectName(server.config.projectName);
|
jaConfigurator.setProjectName(server.config.projectName);
|
||||||
jaConfigurator.setSecretKey(SecurityHelper.randomStringAESKey());
|
jaConfigurator.setSecretKey(SecurityHelper.randomStringAESKey());
|
||||||
jaConfigurator.setClientPort(32148 + SecurityHelper.newRandom().nextInt(512));
|
jaConfigurator.setClientPort(32148 + SecurityHelper.newRandom().nextInt(512));
|
||||||
jaConfigurator.setGuardType(server.config.launcher.guardType);
|
jaConfigurator.setGuardType(server.config.launcher.guardType);
|
||||||
jaConfigurator.setWarningMissArchJava(server.config.isWarningMissArchJava);
|
jaConfigurator.setWarningMissArchJava(server.config.launcher.warningMissArchJava);
|
||||||
jaConfigurator.setEnv(server.config.env);
|
jaConfigurator.setEnv(server.config.env);
|
||||||
if (server.runtime.oemUnlockKey == null) server.runtime.oemUnlockKey = SecurityHelper.randomStringToken();
|
if (server.runtime.oemUnlockKey == null) server.runtime.oemUnlockKey = SecurityHelper.randomStringToken();
|
||||||
jaConfigurator.setOemUnlockKey(server.runtime.oemUnlockKey);
|
jaConfigurator.setOemUnlockKey(server.runtime.oemUnlockKey);
|
||||||
|
@ -148,11 +144,12 @@ public Path process(Path inputJar) throws IOException {
|
||||||
LogHelper.error(e1);
|
LogHelper.error(e1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
String zPath = jaConfigurator.getZipEntryPath();
|
||||||
try (ZipInputStream input = new ZipInputStream(IOHelper.newInput(inputJar))) {
|
try (ZipInputStream input = new ZipInputStream(IOHelper.newInput(inputJar))) {
|
||||||
ZipEntry e = input.getNextEntry();
|
ZipEntry e = input.getNextEntry();
|
||||||
while (e != null) {
|
while (e != null) {
|
||||||
String filename = e.getName();
|
String filename = e.getName();
|
||||||
if (server.buildHookManager.isContainsBlacklist(filename) || e.isDirectory()) {
|
if (server.buildHookManager.isContainsBlacklist(filename) || e.isDirectory() || zPath.equals(filename)) {
|
||||||
e = input.getNextEntry();
|
e = input.getNextEntry();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -204,12 +201,9 @@ public Path process(Path inputJar) throws IOException {
|
||||||
// Write launcher config file
|
// Write launcher config file
|
||||||
output.putNextEntry(newZipEntry(Launcher.CONFIG_FILE));
|
output.putNextEntry(newZipEntry(Launcher.CONFIG_FILE));
|
||||||
output.write(launcherConfigBytes);
|
output.write(launcherConfigBytes);
|
||||||
ZipEntry e = newZipEntry(jaConfigurator.getZipEntryPath());
|
ZipEntry e = newZipEntry(zPath);
|
||||||
output.putNextEntry(e);
|
output.putNextEntry(e);
|
||||||
jaConfigurator.compile();
|
output.write(jaConfigurator.getBytecode(reader));
|
||||||
output.write(jaConfigurator.getBytecode());
|
|
||||||
} catch (CannotCompileException | NotFoundException e) {
|
|
||||||
throw new IOException(e);
|
|
||||||
}
|
}
|
||||||
reader.close();
|
reader.close();
|
||||||
return outputJar;
|
return outputJar;
|
||||||
|
|
|
@ -26,7 +26,7 @@ public String getName() {
|
||||||
@Override
|
@Override
|
||||||
public Path process(Path inputFile) throws IOException {
|
public Path process(Path inputFile) throws IOException {
|
||||||
Path outputJar = server.launcherBinary.nextLowerPath(this);
|
Path outputJar = server.launcherBinary.nextLowerPath(this);
|
||||||
if (server.config.enabledProGuard) {
|
if (server.config.launcher.enabledProGuard) {
|
||||||
Configuration proguard_cfg = new Configuration();
|
Configuration proguard_cfg = new Configuration();
|
||||||
ConfigurationParser parser = new ConfigurationParser(server.proguardConf.buildConfig(inputFile, outputJar),
|
ConfigurationParser parser = new ConfigurationParser(server.proguardConf.buildConfig(inputFile, outputJar),
|
||||||
server.proguardConf.proguard.toFile(), System.getProperties());
|
server.proguardConf.proguard.toFile(), System.getProperties());
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
package pro.gravit.launchserver.binary.tasks;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import me.itzsomebody.radon.Radon;
|
|
||||||
import me.itzsomebody.radon.SessionInfo;
|
|
||||||
import me.itzsomebody.radon.config.ConfigurationParser;
|
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
|
||||||
import pro.gravit.utils.helper.IOHelper;
|
|
||||||
import pro.gravit.utils.helper.UnpackHelper;
|
|
||||||
|
|
||||||
public class RadonBuildTask implements LauncherBuildTask {
|
|
||||||
private final LaunchServer srv;
|
|
||||||
public final Path config;
|
|
||||||
|
|
||||||
public RadonBuildTask(LaunchServer srv) {
|
|
||||||
this.srv = srv;
|
|
||||||
config = this.srv.dir.resolve("radon.yml");
|
|
||||||
System.setProperty("radon.useJVMCP", "true");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "Radon";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Path process(Path inputFile) throws IOException {
|
|
||||||
Path outputFile = srv.launcherBinary.nextLowerPath(this);
|
|
||||||
Files.deleteIfExists(outputFile);
|
|
||||||
if (srv.config.enabledRadon) {
|
|
||||||
if (!IOHelper.isFile(config))
|
|
||||||
UnpackHelper.unpack(IOHelper.getResourceURL("pro/gravit/launchserver/defaults/radon.cfg"), config);
|
|
||||||
ConfigurationParser p = new ConfigurationParser(IOHelper.newInput(config));
|
|
||||||
SessionInfo info = p.createSessionFromConfig();
|
|
||||||
info.setInput(inputFile.toFile());
|
|
||||||
info.setOutput(outputFile.toFile());
|
|
||||||
List<File> libs = srv.launcherBinary.coreLibs.stream().map(Path::toFile).collect(Collectors.toList());
|
|
||||||
libs.addAll(srv.launcherBinary.addonLibs.stream().map(Path::toFile).collect(Collectors.toList()));
|
|
||||||
info.setLibraries(libs);
|
|
||||||
Radon r = new Radon(info);
|
|
||||||
r.run();
|
|
||||||
} else
|
|
||||||
IOHelper.copy(inputFile, outputFile);
|
|
||||||
return outputFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean allowDelete() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,16 +1,15 @@
|
||||||
package pro.gravit.launchserver.command.basic;
|
package pro.gravit.launchserver.command.basic;
|
||||||
|
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.security.KeyPair;
|
||||||
|
|
||||||
import org.bouncycastle.cert.X509CertificateHolder;
|
import org.bouncycastle.cert.X509CertificateHolder;
|
||||||
import pro.gravit.launcher.events.PingEvent;
|
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
import pro.gravit.launchserver.command.Command;
|
import pro.gravit.launchserver.command.Command;
|
||||||
import pro.gravit.launchserver.socket.handlers.NettyServerSocketHandler;
|
import pro.gravit.launchserver.socket.handlers.NettyServerSocketHandler;
|
||||||
import pro.gravit.utils.helper.CommonHelper;
|
import pro.gravit.utils.helper.CommonHelper;
|
||||||
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.security.KeyPair;
|
|
||||||
import java.security.KeyPairGenerator;
|
|
||||||
|
|
||||||
public class TestCommand extends Command {
|
public class TestCommand extends Command {
|
||||||
public TestCommand(LaunchServer server) {
|
public TestCommand(LaunchServer server) {
|
||||||
super(server);
|
super(server);
|
||||||
|
@ -44,6 +43,10 @@ public void invoke(String... args) throws Exception {
|
||||||
server.certificateManager.writePrivateKey(Paths.get("ca.key"), server.certificateManager.caKey);
|
server.certificateManager.writePrivateKey(Paths.get("ca.key"), server.certificateManager.caKey);
|
||||||
server.certificateManager.writeCertificate(Paths.get("ca.crt"), server.certificateManager.ca);
|
server.certificateManager.writeCertificate(Paths.get("ca.crt"), server.certificateManager.ca);
|
||||||
}
|
}
|
||||||
|
if(args[0].equals("readCA")) {
|
||||||
|
server.certificateManager.ca = server.certificateManager.readCertificate(Paths.get("ca.crt"));
|
||||||
|
server.certificateManager.caKey = server.certificateManager.readPrivateKey(Paths.get("ca.key"));
|
||||||
|
}
|
||||||
if(args[0].equals("genCert")) {
|
if(args[0].equals("genCert")) {
|
||||||
verifyArgs(args, 2);
|
verifyArgs(args, 2);
|
||||||
String name = args[1];
|
String name = args[1];
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ public void invoke(String... args) throws Exception {
|
||||||
public void invoke(String... args) throws Exception {
|
public void invoke(String... args) throws Exception {
|
||||||
verifyArgs(args, 1);
|
verifyArgs(args, 1);
|
||||||
LogHelper.info("Sessions write to %s", args[0]);
|
LogHelper.info("Sessions write to %s", args[0]);
|
||||||
Set<Client> clientSet = server.sessionManager.getSessions();
|
Collection<Client> clientSet = server.sessionManager.getSessions();
|
||||||
try (Writer writer = IOHelper.newWriter(Paths.get(args[0]))) {
|
try (Writer writer = IOHelper.newWriter(Paths.get(args[0]))) {
|
||||||
Launcher.gsonManager.configGson.toJson(clientSet, writer);
|
Launcher.gsonManager.configGson.toJson(clientSet, writer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
import pro.gravit.launchserver.command.Command;
|
import pro.gravit.launchserver.command.Command;
|
||||||
import pro.gravit.launchserver.manangers.ReconfigurableManager;
|
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
|
||||||
|
|
||||||
public class ConfigCommand extends Command {
|
public class ConfigCommand extends Command {
|
||||||
public ConfigCommand(LaunchServer server) {
|
public ConfigCommand(LaunchServer server) {
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
package pro.gravit.launchserver.components;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.NeedGarbageCollection;
|
||||||
|
|
||||||
|
public class AbstractLimiter<T> implements NeedGarbageCollection {
|
||||||
|
public final int maxTrys;
|
||||||
|
public final int banMillis;
|
||||||
|
|
||||||
|
public AbstractLimiter(int maxTrys, int banMillis) {
|
||||||
|
this.maxTrys = maxTrys;
|
||||||
|
this.banMillis = banMillis;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void garbageCollection() {
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
|
map.entrySet().removeIf((e) -> e.getValue().time + banMillis < time);
|
||||||
|
}
|
||||||
|
|
||||||
|
class LimitEntry
|
||||||
|
{
|
||||||
|
long time;
|
||||||
|
int trys;
|
||||||
|
|
||||||
|
public LimitEntry(long time, int trys) {
|
||||||
|
this.time = time;
|
||||||
|
this.trys = trys;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LimitEntry() {
|
||||||
|
time = System.currentTimeMillis();
|
||||||
|
trys = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected Map<T, LimitEntry> map = new HashMap<>();
|
||||||
|
public boolean check(T address)
|
||||||
|
{
|
||||||
|
LimitEntry entry = map.get(address);
|
||||||
|
if(entry == null)
|
||||||
|
{
|
||||||
|
map.put(address, new LimitEntry());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
|
if(entry.trys < maxTrys)
|
||||||
|
{
|
||||||
|
entry.trys++;
|
||||||
|
entry.time = time;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(entry.time + banMillis < time)
|
||||||
|
{
|
||||||
|
entry.trys = 1;
|
||||||
|
entry.time = time;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,18 +1,17 @@
|
||||||
package pro.gravit.launchserver.components;
|
package pro.gravit.launchserver.components;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import pro.gravit.launcher.NeedGarbageCollection;
|
import pro.gravit.launcher.NeedGarbageCollection;
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
import pro.gravit.launchserver.socket.Client;
|
import pro.gravit.launchserver.socket.Client;
|
||||||
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
|
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
|
||||||
import pro.gravit.utils.BiHookSet.Hook;
|
|
||||||
import pro.gravit.utils.HookException;
|
import pro.gravit.utils.HookException;
|
||||||
|
|
||||||
public class AuthLimiterComponent extends Component implements NeedGarbageCollection, AutoCloseable {
|
public class AuthLimiterComponent extends Component implements NeedGarbageCollection, AutoCloseable {
|
||||||
private transient final Hook<AuthResponse.AuthContext, Client> prA = this::preAuthHook;
|
|
||||||
|
private transient AbstractLimiter<String> limiter;
|
||||||
private transient LaunchServer srv;
|
private transient LaunchServer srv;
|
||||||
@Override
|
@Override
|
||||||
public void preInit(LaunchServer launchServer) {
|
public void preInit(LaunchServer launchServer) {
|
||||||
|
@ -21,7 +20,8 @@ public void preInit(LaunchServer launchServer) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(LaunchServer launchServer) {
|
public void init(LaunchServer launchServer) {
|
||||||
launchServer.authHookManager.preHook.registerHook(prA);
|
limiter = new AbstractLimiter<>(rateLimit, rateLimitMilis);
|
||||||
|
launchServer.authHookManager.preHook.registerHook(this::preAuthHook);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -30,88 +30,25 @@ public void postInit(LaunchServer launchServer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean preAuthHook(AuthResponse.AuthContext context, Client client) {
|
public boolean preAuthHook(AuthResponse.AuthContext context, Client client) {
|
||||||
if (isLimit(context.ip)) {
|
if (!excludeIps.contains(context.ip) && !limiter.check(context.ip)) {
|
||||||
throw new HookException(message);
|
throw new HookException(message);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static class AuthEntry {
|
|
||||||
public int value;
|
|
||||||
|
|
||||||
public long ts;
|
|
||||||
|
|
||||||
public AuthEntry(int i, long l) {
|
|
||||||
value = i;
|
|
||||||
ts = l;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj)
|
|
||||||
return true;
|
|
||||||
if (obj == null)
|
|
||||||
return false;
|
|
||||||
if (!(obj instanceof AuthEntry))
|
|
||||||
return false;
|
|
||||||
AuthEntry other = (AuthEntry) obj;
|
|
||||||
if (ts != other.ts)
|
|
||||||
return false;
|
|
||||||
return value == other.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
final int prime = 31;
|
|
||||||
int result = 1;
|
|
||||||
result = prime * result + (int) (ts ^ ts >>> 32);
|
|
||||||
result = prime * result + value;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("AuthEntry {value=%s, ts=%s}", value, ts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static final long TIMEOUT = 10 * 60 * 1000; //10 минут
|
|
||||||
public int rateLimit;
|
public int rateLimit;
|
||||||
public int rateLimitMilis;
|
public int rateLimitMilis;
|
||||||
public String message;
|
public String message;
|
||||||
|
|
||||||
public transient HashMap<String, AuthEntry> map = new HashMap<>();
|
|
||||||
public List<String> excludeIps = new ArrayList<>();
|
public List<String> excludeIps = new ArrayList<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void garbageCollection() {
|
public void garbageCollection() {
|
||||||
long time = System.currentTimeMillis();
|
if(limiter != null)
|
||||||
long max_timeout = Math.max(rateLimitMilis, TIMEOUT);
|
limiter.garbageCollection();
|
||||||
map.entrySet().removeIf(e -> e.getValue().ts + max_timeout < time);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLimit(String ip) {
|
|
||||||
if (excludeIps.contains(ip)) return false;
|
|
||||||
if (map.containsKey(ip)) {
|
|
||||||
AuthEntry rate = map.get(ip);
|
|
||||||
long currenttime = System.currentTimeMillis();
|
|
||||||
if (rate.ts + rateLimitMilis < currenttime) rate.value = 0;
|
|
||||||
if (rate.value >= rateLimit && rateLimit > 0) {
|
|
||||||
rate.value++;
|
|
||||||
rate.ts = currenttime;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
rate.value++;
|
|
||||||
rate.ts = currenttime;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
map.put(ip, new AuthEntry(1, System.currentTimeMillis()));
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws Exception {
|
public void close() throws Exception {
|
||||||
srv.authHookManager.preHook.unregisterHook(prA);
|
srv.authHookManager.preHook.unregisterHook(this::preAuthHook);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +1,26 @@
|
||||||
package pro.gravit.launchserver.components;
|
package pro.gravit.launchserver.components;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import pro.gravit.launcher.NeedGarbageCollection;
|
import pro.gravit.launcher.NeedGarbageCollection;
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
import pro.gravit.launchserver.manangers.hook.AuthHookManager;
|
import pro.gravit.launchserver.manangers.hook.AuthHookManager;
|
||||||
import pro.gravit.utils.HookException;
|
import pro.gravit.utils.HookException;
|
||||||
import pro.gravit.utils.HookSet;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class RegLimiterComponent extends Component implements NeedGarbageCollection, AutoCloseable {
|
public class RegLimiterComponent extends Component implements NeedGarbageCollection, AutoCloseable {
|
||||||
|
|
||||||
public static final long TIMEOUT = 12 * 60 * 60 * 1000; //12 часов
|
private transient AbstractLimiter<String> limiter;
|
||||||
public transient LaunchServer launchServer;
|
public transient LaunchServer launchServer;
|
||||||
public int rateLimit;
|
public int rateLimit;
|
||||||
public int rateLimitMilis;
|
public int rateLimitMilis;
|
||||||
public String message;
|
public String message;
|
||||||
public transient HookSet.Hook<AuthHookManager.RegContext> hook;
|
|
||||||
|
|
||||||
public transient HashMap<String, AuthLimiterComponent.AuthEntry> map = new HashMap<>();
|
|
||||||
public List<String> excludeIps = new ArrayList<>();
|
public List<String> excludeIps = new ArrayList<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void preInit(LaunchServer launchServer) {
|
public void preInit(LaunchServer launchServer) {
|
||||||
|
limiter = new AbstractLimiter<>(rateLimit, rateLimitMilis);
|
||||||
this.launchServer = launchServer;
|
this.launchServer = launchServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,43 +31,24 @@ public void init(LaunchServer launchServer) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postInit(LaunchServer launchServer) {
|
public void postInit(LaunchServer launchServer) {
|
||||||
launchServer.authHookManager.registraion.registerHook(context -> {
|
launchServer.authHookManager.registraion.registerHook(this::registerHook);
|
||||||
if (isLimit(context.ip)) {
|
}
|
||||||
|
|
||||||
|
public boolean registerHook(AuthHookManager.RegContext context)
|
||||||
|
{
|
||||||
|
if (!limiter.check(context.ip)) {
|
||||||
throw new HookException(message);
|
throw new HookException(message);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void garbageCollection() {
|
public void garbageCollection() {
|
||||||
long time = System.currentTimeMillis();
|
if(limiter != null)
|
||||||
long max_timeout = Math.max(rateLimitMilis, TIMEOUT);
|
limiter.garbageCollection();
|
||||||
map.entrySet().removeIf(e -> e.getValue().ts + max_timeout < time);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLimit(String ip) {
|
|
||||||
if (excludeIps.contains(ip)) return false;
|
|
||||||
if (map.containsKey(ip)) {
|
|
||||||
AuthLimiterComponent.AuthEntry rate = map.get(ip);
|
|
||||||
long currenttime = System.currentTimeMillis();
|
|
||||||
if (rate.ts + rateLimitMilis < currenttime) rate.value = 0;
|
|
||||||
if (rate.value >= rateLimit && rateLimit > 0) {
|
|
||||||
rate.value++;
|
|
||||||
rate.ts = currenttime;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
rate.value++;
|
|
||||||
rate.ts = currenttime;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
map.put(ip, new AuthLimiterComponent.AuthEntry(1, System.currentTimeMillis()));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws Exception {
|
public void close() throws Exception {
|
||||||
if(hook != null)
|
launchServer.authHookManager.registraion.unregisterHook(this::registerHook);
|
||||||
launchServer.authHookManager.registraion.unregisterHook(hook);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,16 @@
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
import pro.gravit.launcher.ClientPermissions;
|
import pro.gravit.launcher.ClientPermissions;
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package pro.gravit.launchserver.dao;
|
package pro.gravit.launchserver.dao;
|
||||||
|
|
||||||
import pro.gravit.launcher.hwid.OshiHWID;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.hwid.OshiHWID;
|
||||||
|
|
||||||
public interface UserDAO {
|
public interface UserDAO {
|
||||||
User findById(int id);
|
User findById(int id);
|
||||||
User findByUsername(String username);
|
User findByUsername(String username);
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
package pro.gravit.launchserver.dao;
|
package pro.gravit.launchserver.dao;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
import pro.gravit.launcher.hwid.HWID;
|
import pro.gravit.launcher.hwid.HWID;
|
||||||
import pro.gravit.launcher.hwid.OshiHWID;
|
import pro.gravit.launcher.hwid.OshiHWID;
|
||||||
|
|
||||||
import javax.persistence.*;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "users_hwids")
|
@Table(name = "users_hwids")
|
||||||
public class UserHWID implements HWID {
|
public class UserHWID implements HWID {
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
|
||||||
|
|
||||||
public class UserService {
|
public class UserService {
|
||||||
|
|
||||||
private final UserDAO usersDao;
|
private final UserDAO usersDao;
|
||||||
|
|
|
@ -1,38 +1,18 @@
|
||||||
package pro.gravit.launchserver.manangers;
|
package pro.gravit.launchserver.manangers;
|
||||||
|
|
||||||
|
|
||||||
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
|
import java.io.ByteArrayInputStream;
|
||||||
import org.bouncycastle.asn1.x500.X500Name;
|
|
||||||
import org.bouncycastle.asn1.x500.X500NameBuilder;
|
|
||||||
import org.bouncycastle.asn1.x500.style.BCStyle;
|
|
||||||
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
|
|
||||||
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
|
|
||||||
import org.bouncycastle.cert.CertIOException;
|
|
||||||
import org.bouncycastle.cert.X509CertificateHolder;
|
|
||||||
import org.bouncycastle.cert.X509v3CertificateBuilder;
|
|
||||||
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
|
|
||||||
import org.bouncycastle.crypto.params.ECKeyParameters;
|
|
||||||
import org.bouncycastle.crypto.util.PrivateKeyFactory;
|
|
||||||
import org.bouncycastle.crypto.util.PrivateKeyInfoFactory;
|
|
||||||
import org.bouncycastle.jce.ECNamedCurveTable;
|
|
||||||
import org.bouncycastle.jce.spec.ECParameterSpec;
|
|
||||||
import org.bouncycastle.openssl.PEMWriter;
|
|
||||||
import org.bouncycastle.operator.ContentSigner;
|
|
||||||
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
|
|
||||||
import org.bouncycastle.operator.OperatorCreationException;
|
|
||||||
import org.bouncycastle.operator.bc.BcECContentSignerBuilder;
|
|
||||||
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
|
|
||||||
import org.bouncycastle.util.io.pem.PemObject;
|
|
||||||
import org.bouncycastle.util.io.pem.PemWriter;
|
|
||||||
import pro.gravit.utils.helper.IOHelper;
|
|
||||||
import pro.gravit.utils.helper.SecurityHelper;
|
|
||||||
|
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.io.Writer;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.security.*;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.KeyPair;
|
||||||
|
import java.security.KeyPairGenerator;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.PublicKey;
|
||||||
import java.security.spec.ECGenParameterSpec;
|
import java.security.spec.ECGenParameterSpec;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
@ -41,16 +21,45 @@
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
|
||||||
|
import org.bouncycastle.asn1.x500.X500Name;
|
||||||
|
import org.bouncycastle.asn1.x500.X500NameBuilder;
|
||||||
|
import org.bouncycastle.asn1.x500.style.BCStyle;
|
||||||
|
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
|
||||||
|
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
|
||||||
|
import org.bouncycastle.cert.X509CertificateHolder;
|
||||||
|
import org.bouncycastle.cert.X509v3CertificateBuilder;
|
||||||
|
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
|
||||||
|
import org.bouncycastle.crypto.util.PrivateKeyFactory;
|
||||||
|
import org.bouncycastle.crypto.util.PrivateKeyInfoFactory;
|
||||||
|
import org.bouncycastle.operator.ContentSigner;
|
||||||
|
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
|
||||||
|
import org.bouncycastle.operator.OperatorCreationException;
|
||||||
|
import org.bouncycastle.operator.bc.BcECContentSignerBuilder;
|
||||||
|
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
|
||||||
|
import org.bouncycastle.util.io.pem.PemObject;
|
||||||
|
import org.bouncycastle.util.io.pem.PemReader;
|
||||||
|
import org.bouncycastle.util.io.pem.PemWriter;
|
||||||
|
|
||||||
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
|
import pro.gravit.utils.helper.SecurityHelper;
|
||||||
|
|
||||||
public class CertificateManager {
|
public class CertificateManager {
|
||||||
public X509CertificateHolder ca;
|
public X509CertificateHolder ca;
|
||||||
public AsymmetricKeyParameter caKey;
|
public AsymmetricKeyParameter caKey;
|
||||||
|
|
||||||
|
public X509CertificateHolder server;
|
||||||
|
public AsymmetricKeyParameter serverKey;
|
||||||
|
|
||||||
|
|
||||||
//public X509CertificateHolder server;
|
//public X509CertificateHolder server;
|
||||||
//public AsymmetricKeyParameter serverKey;
|
//public AsymmetricKeyParameter serverKey;
|
||||||
|
|
||||||
public int validDays = 60;
|
public int validDays = 60;
|
||||||
public int minusHours = 6;
|
public int minusHours = 6;
|
||||||
|
|
||||||
|
public String orgName;
|
||||||
|
|
||||||
public X509CertificateHolder generateCertificate(String subjectName, PublicKey subjectPublicKey) throws OperatorCreationException {
|
public X509CertificateHolder generateCertificate(String subjectName, PublicKey subjectPublicKey) throws OperatorCreationException {
|
||||||
SubjectPublicKeyInfo subjectPubKeyInfo = SubjectPublicKeyInfo.getInstance(subjectPublicKey.getEncoded());
|
SubjectPublicKeyInfo subjectPubKeyInfo = SubjectPublicKeyInfo.getInstance(subjectPublicKey.getEncoded());
|
||||||
BigInteger serial = BigInteger.valueOf(SecurityHelper.newRandom().nextLong());
|
BigInteger serial = BigInteger.valueOf(SecurityHelper.newRandom().nextLong());
|
||||||
|
@ -59,6 +68,7 @@ public X509CertificateHolder generateCertificate(String subjectName, PublicKey s
|
||||||
|
|
||||||
X500NameBuilder subject = new X500NameBuilder();
|
X500NameBuilder subject = new X500NameBuilder();
|
||||||
subject.addRDN(BCStyle.CN, subjectName);
|
subject.addRDN(BCStyle.CN, subjectName);
|
||||||
|
subject.addRDN(BCStyle.O, orgName);
|
||||||
X509v3CertificateBuilder v3CertGen = new X509v3CertificateBuilder(ca.getSubject(), serial,
|
X509v3CertificateBuilder v3CertGen = new X509v3CertificateBuilder(ca.getSubject(), serial,
|
||||||
startDate, endDate, subject.build(), subjectPubKeyInfo);
|
startDate, endDate, subject.build(), subjectPubKeyInfo);
|
||||||
|
|
||||||
|
@ -76,8 +86,12 @@ public void generateCA() throws NoSuchAlgorithmException, IOException, OperatorC
|
||||||
KeyPair pair = generator.generateKeyPair();
|
KeyPair pair = generator.generateKeyPair();
|
||||||
LocalDateTime startDate = LocalDate.now().atStartOfDay();
|
LocalDateTime startDate = LocalDate.now().atStartOfDay();
|
||||||
|
|
||||||
|
X500NameBuilder subject = new X500NameBuilder();
|
||||||
|
subject.addRDN(BCStyle.CN, orgName.concat(" CA"));
|
||||||
|
subject.addRDN(BCStyle.O, orgName);
|
||||||
|
|
||||||
X509v3CertificateBuilder builder= new X509v3CertificateBuilder(
|
X509v3CertificateBuilder builder= new X509v3CertificateBuilder(
|
||||||
new X500Name("CN=ca"),
|
subject.build(),
|
||||||
new BigInteger("0"),
|
new BigInteger("0"),
|
||||||
Date.from(startDate.atZone(ZoneId.systemDefault()).toInstant()),
|
Date.from(startDate.atZone(ZoneId.systemDefault()).toInstant()),
|
||||||
Date.from(startDate.plusDays(3650).atZone(ZoneId.systemDefault()).toInstant()),
|
Date.from(startDate.plusDays(3650).atZone(ZoneId.systemDefault()).toInstant()),
|
||||||
|
@ -97,21 +111,65 @@ public KeyPair generateKeyPair() throws InvalidAlgorithmParameterException, NoSu
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writePrivateKey(Path file, PrivateKey privateKey) throws IOException {
|
public void writePrivateKey(Path file, PrivateKey privateKey) throws IOException {
|
||||||
try (PemWriter writer = new PemWriter(IOHelper.newWriter(file))) {
|
writePrivateKey(IOHelper.newWriter(file), privateKey);
|
||||||
writer.writeObject(new PemObject("PRIVATE KEY", privateKey.getEncoded()));
|
}
|
||||||
|
|
||||||
|
public void writePrivateKey(Writer writer, PrivateKey privateKey) throws IOException {
|
||||||
|
try (PemWriter writer1 = new PemWriter(writer)) {
|
||||||
|
writer1.writeObject(new PemObject("PRIVATE KEY", privateKey.getEncoded()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writePrivateKey(Path file, AsymmetricKeyParameter key) throws IOException {
|
public void writePrivateKey(Path file, AsymmetricKeyParameter key) throws IOException {
|
||||||
|
writePrivateKey(IOHelper.newWriter(file), key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writePrivateKey(Writer writer, AsymmetricKeyParameter key) throws IOException {
|
||||||
PrivateKeyInfo info = PrivateKeyInfoFactory.createPrivateKeyInfo(key);
|
PrivateKeyInfo info = PrivateKeyInfoFactory.createPrivateKeyInfo(key);
|
||||||
try (PemWriter writer = new PemWriter(IOHelper.newWriter(file))) {
|
try (PemWriter writer1 = new PemWriter(writer)) {
|
||||||
writer.writeObject(new PemObject("PRIVATE KEY", info.getEncoded()));
|
writer1.writeObject(new PemObject("PRIVATE KEY", info.getEncoded()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeCertificate(Path file, X509CertificateHolder holder) throws IOException {
|
public void writeCertificate(Path file, X509CertificateHolder holder) throws IOException {
|
||||||
try (PemWriter writer = new PemWriter(IOHelper.newWriter(file))) {
|
writeCertificate(IOHelper.newWriter(file), holder);
|
||||||
writer.writeObject(new PemObject("CERTIFICATE", holder.toASN1Structure().getEncoded()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void writeCertificate(Writer writer, X509CertificateHolder holder) throws IOException {
|
||||||
|
try (PemWriter writer1 = new PemWriter(writer)) {
|
||||||
|
writer1.writeObject(new PemObject("CERTIFICATE", holder.toASN1Structure().getEncoded()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsymmetricKeyParameter readPrivateKey(Path file) throws IOException {
|
||||||
|
return readPrivateKey(IOHelper.newReader(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsymmetricKeyParameter readPrivateKey(Reader reader) throws IOException {
|
||||||
|
AsymmetricKeyParameter ret;
|
||||||
|
try(PemReader reader1 = new PemReader(reader))
|
||||||
|
{
|
||||||
|
byte[] bytes = reader1.readPemObject().getContent();
|
||||||
|
try(ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes))
|
||||||
|
{
|
||||||
|
|
||||||
|
ret = PrivateKeyFactory.createKey(inputStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public X509CertificateHolder readCertificate(Path file) throws IOException {
|
||||||
|
return readCertificate(IOHelper.newReader(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
public X509CertificateHolder readCertificate(Reader reader) throws IOException {
|
||||||
|
X509CertificateHolder ret;
|
||||||
|
try(PemReader reader1 = new PemReader(reader))
|
||||||
|
{
|
||||||
|
byte[] bytes = reader1.readPemObject().getContent();
|
||||||
|
ret = new X509CertificateHolder(bytes);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,14 +2,11 @@
|
||||||
|
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
|
|
||||||
import pro.gravit.launcher.hasher.HashedEntry;
|
|
||||||
import pro.gravit.launcher.hasher.HashedEntryAdapter;
|
|
||||||
import pro.gravit.launcher.hwid.HWID;
|
import pro.gravit.launcher.hwid.HWID;
|
||||||
import pro.gravit.launcher.hwid.HWIDProvider;
|
import pro.gravit.launcher.hwid.HWIDProvider;
|
||||||
import pro.gravit.launcher.managers.GsonManager;
|
import pro.gravit.launcher.managers.GsonManager;
|
||||||
import pro.gravit.launcher.request.JsonResultSerializeAdapter;
|
import pro.gravit.launcher.request.JsonResultSerializeAdapter;
|
||||||
import pro.gravit.launcher.request.WebSocketEvent;
|
import pro.gravit.launcher.request.WebSocketEvent;
|
||||||
import pro.gravit.launcher.request.websockets.ClientWebSocketService;
|
|
||||||
import pro.gravit.launchserver.auth.handler.AuthHandler;
|
import pro.gravit.launchserver.auth.handler.AuthHandler;
|
||||||
import pro.gravit.launchserver.auth.hwid.HWIDHandler;
|
import pro.gravit.launchserver.auth.hwid.HWIDHandler;
|
||||||
import pro.gravit.launchserver.auth.permissions.PermissionsHandler;
|
import pro.gravit.launchserver.auth.permissions.PermissionsHandler;
|
||||||
|
|
|
@ -2,13 +2,11 @@
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import pro.gravit.launchserver.Reconfigurable;
|
import pro.gravit.launchserver.Reconfigurable;
|
||||||
import pro.gravit.utils.command.Command;
|
import pro.gravit.utils.command.Command;
|
||||||
import pro.gravit.utils.command.CommandException;
|
import pro.gravit.utils.command.CommandException;
|
||||||
import pro.gravit.utils.command.basic.HelpCommand;
|
import pro.gravit.utils.command.basic.HelpCommand;
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
|
||||||
import pro.gravit.utils.helper.VerifyHelper;
|
import pro.gravit.utils.helper.VerifyHelper;
|
||||||
|
|
||||||
public class ReconfigurableManager {
|
public class ReconfigurableManager {
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
package pro.gravit.launchserver.manangers;
|
package pro.gravit.launchserver.manangers;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import pro.gravit.launcher.NeedGarbageCollection;
|
import pro.gravit.launcher.NeedGarbageCollection;
|
||||||
import pro.gravit.launchserver.socket.Client;
|
import pro.gravit.launchserver.socket.Client;
|
||||||
|
@ -10,53 +14,50 @@ public class SessionManager implements NeedGarbageCollection {
|
||||||
|
|
||||||
public static final long SESSION_TIMEOUT = 3 * 60 * 60 * 1000; // 3 часа
|
public static final long SESSION_TIMEOUT = 3 * 60 * 60 * 1000; // 3 часа
|
||||||
public static final boolean GARBAGE_SERVER = Boolean.parseBoolean(System.getProperty("launcher.garbageSessionsServer", "false"));
|
public static final boolean GARBAGE_SERVER = Boolean.parseBoolean(System.getProperty("launcher.garbageSessionsServer", "false"));
|
||||||
private HashSet<Client> clientSet = new HashSet<>(128);
|
private Map<Long, Client> clientSet = new HashMap<>(128);
|
||||||
|
|
||||||
|
|
||||||
public boolean addClient(Client client) {
|
public boolean addClient(Client client) {
|
||||||
clientSet.add(client);
|
clientSet.put(client.session, client);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void garbageCollection() {
|
public void garbageCollection() {
|
||||||
long time = System.currentTimeMillis();
|
long time = System.currentTimeMillis();
|
||||||
clientSet.removeIf(c -> (c.timestamp + SESSION_TIMEOUT < time) && ((c.type == Client.Type.USER) || ((c.type == Client.Type.SERVER) && GARBAGE_SERVER)));
|
clientSet.entrySet().removeIf(entry -> {
|
||||||
|
Client c = entry.getValue();
|
||||||
|
return (c.timestamp + SESSION_TIMEOUT < time) && ((c.type == Client.Type.USER) || ((c.type == Client.Type.SERVER) && GARBAGE_SERVER));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Client getClient(long session) {
|
public Client getClient(long session) {
|
||||||
for (Client c : clientSet)
|
return clientSet.get(session);
|
||||||
if (c.session == session) return c;
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Client getOrNewClient(long session) {
|
public Client getOrNewClient(long session) {
|
||||||
for (Client c : clientSet)
|
return clientSet.computeIfAbsent(session, Client::new);
|
||||||
if (c.session == session) return c;
|
|
||||||
Client newClient = new Client(session);
|
|
||||||
clientSet.add(newClient);
|
|
||||||
return newClient;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void updateClient(long session) {
|
public void updateClient(long session) {
|
||||||
for (Client c : clientSet) {
|
Client c = clientSet.get(session);
|
||||||
if (c.session == session) {
|
if (c != null) {
|
||||||
c.up();
|
c.up();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Client newClient = new Client(session);
|
Client newClient = new Client(session);
|
||||||
clientSet.add(newClient);
|
clientSet.put(session, newClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Client> getSessions() {
|
public Set<Client> getSessions() {
|
||||||
return clientSet;
|
// TODO: removeme
|
||||||
|
return new HashSet<>(clientSet.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadSessions(Set<Client> set) {
|
public void loadSessions(Set<Client> set) {
|
||||||
clientSet.addAll(set);
|
clientSet.putAll(set.stream().collect(Collectors.toMap(c -> c.session, Function.identity())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,6 +87,14 @@ public void registerClientModuleClass(String clazz) {
|
||||||
MODULE_CLASS.add(clazz);
|
MODULE_CLASS.add(clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void unregisterClientModuleClass(String clazz) {
|
||||||
|
MODULE_CLASS.remove(clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearClientModuleClassList() {
|
||||||
|
MODULE_CLASS.clear();
|
||||||
|
}
|
||||||
|
|
||||||
public void registerIgnoredClass(String clazz) {
|
public void registerIgnoredClass(String clazz) {
|
||||||
CLASS_BLACKLIST.add(clazz);
|
CLASS_BLACKLIST.add(clazz);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
|
|
||||||
public class Client {
|
public class Client {
|
||||||
public long session;
|
public long session;
|
||||||
public boolean proxy;
|
|
||||||
public String auth_id;
|
public String auth_id;
|
||||||
public long timestamp;
|
public long timestamp;
|
||||||
public Type type;
|
public Type type;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
import io.netty.channel.ChannelInitializer;
|
import io.netty.channel.ChannelInitializer;
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelPipeline;
|
||||||
import io.netty.channel.EventLoopGroup;
|
import io.netty.channel.EventLoopGroup;
|
||||||
|
import io.netty.channel.epoll.Epoll;
|
||||||
import io.netty.channel.group.DefaultChannelGroup;
|
import io.netty.channel.group.DefaultChannelGroup;
|
||||||
import io.netty.channel.socket.SocketChannel;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import io.netty.handler.codec.http.HttpObjectAggregator;
|
import io.netty.handler.codec.http.HttpObjectAggregator;
|
||||||
|
@ -15,14 +16,11 @@
|
||||||
import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler;
|
import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler;
|
||||||
import io.netty.handler.logging.LoggingHandler;
|
import io.netty.handler.logging.LoggingHandler;
|
||||||
import io.netty.util.concurrent.GlobalEventExecutor;
|
import io.netty.util.concurrent.GlobalEventExecutor;
|
||||||
import pro.gravit.launcher.request.Request;
|
|
||||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
|
||||||
import pro.gravit.launcher.request.websockets.StandartClientWebSocketService;
|
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
import pro.gravit.launchserver.socket.handlers.NettyIpForwardHandler;
|
import pro.gravit.launchserver.socket.handlers.NettyIpForwardHandler;
|
||||||
import pro.gravit.launchserver.socket.handlers.WebSocketFrameHandler;
|
import pro.gravit.launchserver.socket.handlers.WebSocketFrameHandler;
|
||||||
import pro.gravit.launchserver.socket.handlers.fileserver.FileServerHandler;
|
import pro.gravit.launchserver.socket.handlers.fileserver.FileServerHandler;
|
||||||
import pro.gravit.utils.helper.JVMHelper;
|
import pro.gravit.utils.BiHookSet;
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
public class LauncherNettyServer implements AutoCloseable {
|
public class LauncherNettyServer implements AutoCloseable {
|
||||||
|
@ -30,6 +28,7 @@ public class LauncherNettyServer implements AutoCloseable {
|
||||||
public final EventLoopGroup bossGroup;
|
public final EventLoopGroup bossGroup;
|
||||||
public final EventLoopGroup workerGroup;
|
public final EventLoopGroup workerGroup;
|
||||||
public final WebSocketService service;
|
public final WebSocketService service;
|
||||||
|
public final BiHookSet<NettyConnectContext,SocketChannel> pipelineHook = new BiHookSet<>();
|
||||||
private static final String WEBSOCKET_PATH = "/api";
|
private static final String WEBSOCKET_PATH = "/api";
|
||||||
|
|
||||||
public LauncherNettyServer(LaunchServer server) {
|
public LauncherNettyServer(LaunchServer server) {
|
||||||
|
@ -39,16 +38,16 @@ public LauncherNettyServer(LaunchServer server) {
|
||||||
{
|
{
|
||||||
LogHelper.debug("Netty: Epoll enabled");
|
LogHelper.debug("Netty: Epoll enabled");
|
||||||
}
|
}
|
||||||
if(config.performance.usingEpoll && JVMHelper.OS_TYPE != JVMHelper.OS.LINUX)
|
if(config.performance.usingEpoll && !Epoll.isAvailable())
|
||||||
{
|
{
|
||||||
LogHelper.error("netty,perfomance.usingEpoll work only Linux systems");
|
LogHelper.error("Epoll is not available: (netty,perfomance.usingEpoll configured wrongly)", Epoll.unavailabilityCause());
|
||||||
}
|
}
|
||||||
bossGroup = NettyObjectFactory.newEventLoopGroup(config.performance.bossThread);
|
bossGroup = NettyObjectFactory.newEventLoopGroup(config.performance.bossThread);
|
||||||
workerGroup = NettyObjectFactory.newEventLoopGroup(config.performance.workerThread);
|
workerGroup = NettyObjectFactory.newEventLoopGroup(config.performance.workerThread);
|
||||||
serverBootstrap = new ServerBootstrap();
|
serverBootstrap = new ServerBootstrap();
|
||||||
service = new WebSocketService(new DefaultChannelGroup(GlobalEventExecutor.INSTANCE), server);
|
service = new WebSocketService(new DefaultChannelGroup(GlobalEventExecutor.INSTANCE), server);
|
||||||
serverBootstrap.group(bossGroup, workerGroup)
|
serverBootstrap.group(bossGroup, workerGroup)
|
||||||
.channel(NettyObjectFactory.getServerSocketChannelClass())
|
.channelFactory(NettyObjectFactory.getServerSocketChannelFactory())
|
||||||
.handler(new LoggingHandler(config.logLevel))
|
.handler(new LoggingHandler(config.logLevel))
|
||||||
.childHandler(new ChannelInitializer<SocketChannel>() {
|
.childHandler(new ChannelInitializer<SocketChannel>() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -65,19 +64,9 @@ public void initChannel(SocketChannel ch) {
|
||||||
if (server.config.netty.fileServerEnabled)
|
if (server.config.netty.fileServerEnabled)
|
||||||
pipeline.addLast(new FileServerHandler(server.updatesDir, true));
|
pipeline.addLast(new FileServerHandler(server.updatesDir, true));
|
||||||
pipeline.addLast(new WebSocketFrameHandler(context, server, service));
|
pipeline.addLast(new WebSocketFrameHandler(context, server, service));
|
||||||
|
pipelineHook.hook(context, ch);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (config.proxy != null && config.proxy.enabled) {
|
|
||||||
LogHelper.info("Connect to main server %s");
|
|
||||||
Request.service = StandartClientWebSocketService.initWebSockets(config.proxy.address, false);
|
|
||||||
AuthRequest authRequest = new AuthRequest(config.proxy.login, config.proxy.password, config.proxy.auth_id, AuthRequest.ConnectTypes.PROXY);
|
|
||||||
authRequest.initProxy = true;
|
|
||||||
try {
|
|
||||||
authRequest.request();
|
|
||||||
} catch (Exception e) {
|
|
||||||
LogHelper.error(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChannelFuture bind(InetSocketAddress address) {
|
public ChannelFuture bind(InetSocketAddress address) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package pro.gravit.launchserver.socket;
|
package pro.gravit.launchserver.socket;
|
||||||
|
|
||||||
|
import io.netty.channel.ChannelFactory;
|
||||||
import io.netty.channel.EventLoopGroup;
|
import io.netty.channel.EventLoopGroup;
|
||||||
import io.netty.channel.ServerChannel;
|
import io.netty.channel.ServerChannel;
|
||||||
import io.netty.channel.epoll.EpollEventLoopGroup;
|
import io.netty.channel.epoll.EpollEventLoopGroup;
|
||||||
|
@ -20,12 +21,12 @@ public static EventLoopGroup newEventLoopGroup(int threads)
|
||||||
else
|
else
|
||||||
return new NioEventLoopGroup(threads);
|
return new NioEventLoopGroup(threads);
|
||||||
}
|
}
|
||||||
public static Class<? extends ServerChannel> getServerSocketChannelClass()
|
public static ChannelFactory<? extends ServerChannel> getServerSocketChannelFactory()
|
||||||
{
|
{
|
||||||
if(epoll)
|
if(epoll)
|
||||||
return EpollServerSocketChannel.class;
|
return EpollServerSocketChannel::new;
|
||||||
else
|
else
|
||||||
return NioServerSocketChannel.class;
|
return NioServerSocketChannel::new;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Random;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
|
@ -11,23 +9,26 @@
|
||||||
import io.netty.channel.ChannelFutureListener;
|
import io.netty.channel.ChannelFutureListener;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.group.ChannelGroup;
|
import io.netty.channel.group.ChannelGroup;
|
||||||
|
import io.netty.channel.group.ChannelMatchers;
|
||||||
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
|
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
|
||||||
import pro.gravit.launcher.Launcher;
|
import pro.gravit.launcher.Launcher;
|
||||||
import pro.gravit.launcher.events.ExceptionEvent;
|
import pro.gravit.launcher.events.ExceptionEvent;
|
||||||
import pro.gravit.launcher.events.RequestEvent;
|
import pro.gravit.launcher.events.RequestEvent;
|
||||||
import pro.gravit.launcher.events.request.AuthRequestEvent;
|
|
||||||
import pro.gravit.launcher.events.request.ErrorRequestEvent;
|
import pro.gravit.launcher.events.request.ErrorRequestEvent;
|
||||||
import pro.gravit.launcher.request.Request;
|
|
||||||
import pro.gravit.launcher.request.RequestException;
|
|
||||||
import pro.gravit.launcher.request.WebSocketEvent;
|
import pro.gravit.launcher.request.WebSocketEvent;
|
||||||
import pro.gravit.launcher.request.admin.ProxyRequest;
|
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
import pro.gravit.launchserver.socket.response.WebSocketServerResponse;
|
|
||||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||||
|
import pro.gravit.launchserver.socket.response.WebSocketServerResponse;
|
||||||
import pro.gravit.launchserver.socket.response.admin.AddLogListenerResponse;
|
import pro.gravit.launchserver.socket.response.admin.AddLogListenerResponse;
|
||||||
import pro.gravit.launchserver.socket.response.admin.ExecCommandResponse;
|
import pro.gravit.launchserver.socket.response.admin.ExecCommandResponse;
|
||||||
import pro.gravit.launchserver.socket.response.admin.ProxyCommandResponse;
|
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
|
||||||
import pro.gravit.launchserver.socket.response.auth.*;
|
import pro.gravit.launchserver.socket.response.auth.CheckServerResponse;
|
||||||
|
import pro.gravit.launchserver.socket.response.auth.GetAvailabilityAuthResponse;
|
||||||
|
import pro.gravit.launchserver.socket.response.auth.JoinServerResponse;
|
||||||
|
import pro.gravit.launchserver.socket.response.auth.ProfilesResponse;
|
||||||
|
import pro.gravit.launchserver.socket.response.auth.RegisterResponse;
|
||||||
|
import pro.gravit.launchserver.socket.response.auth.RestoreSessionResponse;
|
||||||
|
import pro.gravit.launchserver.socket.response.auth.SetProfileResponse;
|
||||||
import pro.gravit.launchserver.socket.response.profile.BatchProfileByUsername;
|
import pro.gravit.launchserver.socket.response.profile.BatchProfileByUsername;
|
||||||
import pro.gravit.launchserver.socket.response.profile.ProfileByUUIDResponse;
|
import pro.gravit.launchserver.socket.response.profile.ProfileByUUIDResponse;
|
||||||
import pro.gravit.launchserver.socket.response.profile.ProfileByUsername;
|
import pro.gravit.launchserver.socket.response.profile.ProfileByUsername;
|
||||||
|
@ -36,6 +37,7 @@
|
||||||
import pro.gravit.launchserver.socket.response.update.LauncherResponse;
|
import pro.gravit.launchserver.socket.response.update.LauncherResponse;
|
||||||
import pro.gravit.launchserver.socket.response.update.UpdateListResponse;
|
import pro.gravit.launchserver.socket.response.update.UpdateListResponse;
|
||||||
import pro.gravit.launchserver.socket.response.update.UpdateResponse;
|
import pro.gravit.launchserver.socket.response.update.UpdateResponse;
|
||||||
|
import pro.gravit.utils.BiHookSet;
|
||||||
import pro.gravit.utils.ProviderMap;
|
import pro.gravit.utils.ProviderMap;
|
||||||
import pro.gravit.utils.helper.IOHelper;
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
@ -44,6 +46,19 @@
|
||||||
public class WebSocketService {
|
public class WebSocketService {
|
||||||
public final ChannelGroup channels;
|
public final ChannelGroup channels;
|
||||||
public static ProviderMap<WebSocketServerResponse> providers = new ProviderMap<>();
|
public static ProviderMap<WebSocketServerResponse> providers = new ProviderMap<>();
|
||||||
|
public static class WebSocketRequestContext
|
||||||
|
{
|
||||||
|
public WebSocketServerResponse response;
|
||||||
|
public Client client;
|
||||||
|
public String ip;
|
||||||
|
|
||||||
|
public WebSocketRequestContext(WebSocketServerResponse response, Client client, String ip) {
|
||||||
|
this.response = response;
|
||||||
|
this.client = client;
|
||||||
|
this.ip = ip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public final BiHookSet<WebSocketRequestContext, ChannelHandlerContext> hook = new BiHookSet<>();
|
||||||
|
|
||||||
public WebSocketService(ChannelGroup channels, LaunchServer server) {
|
public WebSocketService(ChannelGroup channels, LaunchServer server) {
|
||||||
this.channels = channels;
|
this.channels = channels;
|
||||||
|
@ -55,68 +70,20 @@ public WebSocketService(ChannelGroup channels, LaunchServer server) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private final LaunchServer server;
|
private final LaunchServer server;
|
||||||
private static final HashMap<String, Class> responses = new HashMap<>();
|
|
||||||
private final Gson gson;
|
private final Gson gson;
|
||||||
|
|
||||||
public void process(ChannelHandlerContext ctx, TextWebSocketFrame frame, Client client, String ip) {
|
public void process(ChannelHandlerContext ctx, TextWebSocketFrame frame, Client client, String ip) {
|
||||||
String request = frame.text();
|
String request = frame.text();
|
||||||
WebSocketServerResponse response = gson.fromJson(request, WebSocketServerResponse.class);
|
WebSocketServerResponse response = gson.fromJson(request, WebSocketServerResponse.class);
|
||||||
if (server.config.netty.proxy.enabled) {
|
|
||||||
if (server.config.netty.proxy.requests.contains(response.getType())) {
|
|
||||||
|
|
||||||
UUID origRequestUUID = null;
|
|
||||||
if (response instanceof SimpleResponse) {
|
|
||||||
SimpleResponse simpleResponse = (SimpleResponse) response;
|
|
||||||
simpleResponse.server = server;
|
|
||||||
simpleResponse.service = this;
|
|
||||||
simpleResponse.ctx = ctx;
|
|
||||||
if (ip != null) simpleResponse.ip = ip;
|
|
||||||
else simpleResponse.ip = IOHelper.getIP(ctx.channel().remoteAddress());
|
|
||||||
origRequestUUID = simpleResponse.requestUUID;
|
|
||||||
}
|
|
||||||
LogHelper.debug("Proxy %s request", response.getType());
|
|
||||||
if (client.session == 0) client.session = new Random().nextLong();
|
|
||||||
ProxyRequest proxyRequest = new ProxyRequest(response, client.session);
|
|
||||||
if (response instanceof SimpleResponse) {
|
|
||||||
((SimpleResponse) response).requestUUID = proxyRequest.requestUUID;
|
|
||||||
}
|
|
||||||
proxyRequest.isCheckSign = client.checkSign;
|
|
||||||
try {
|
|
||||||
WebSocketEvent result = proxyRequest.request();
|
|
||||||
if (result instanceof AuthRequestEvent) {
|
|
||||||
LogHelper.debug("Client auth params get successful");
|
|
||||||
AuthRequestEvent authRequestEvent = (AuthRequestEvent) result;
|
|
||||||
client.isAuth = true;
|
|
||||||
client.session = authRequestEvent.session;
|
|
||||||
if (authRequestEvent.playerProfile != null)
|
|
||||||
client.username = authRequestEvent.playerProfile.username;
|
|
||||||
}
|
|
||||||
if (result instanceof Request && response instanceof SimpleResponse) {
|
|
||||||
((Request) result).requestUUID = origRequestUUID;
|
|
||||||
}
|
|
||||||
sendObject(ctx, result);
|
|
||||||
} catch (RequestException e) {
|
|
||||||
sendObject(ctx, new ErrorRequestEvent(e.getMessage()));
|
|
||||||
} catch (Exception e) {
|
|
||||||
LogHelper.error(e);
|
|
||||||
RequestEvent event;
|
|
||||||
if (server.config.netty.sendExceptionEnabled) {
|
|
||||||
event = new ExceptionEvent(e);
|
|
||||||
} else {
|
|
||||||
event = new ErrorRequestEvent("Fatal server error. Contact administrator");
|
|
||||||
}
|
|
||||||
if (response instanceof SimpleResponse) {
|
|
||||||
event.requestUUID = ((SimpleResponse) response).requestUUID;
|
|
||||||
}
|
|
||||||
sendObject(ctx, event);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
process(ctx, response, client, ip);
|
process(ctx, response, client, ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
void process(ChannelHandlerContext ctx, WebSocketServerResponse response, Client client, String ip) {
|
void process(ChannelHandlerContext ctx, WebSocketServerResponse response, Client client, String ip) {
|
||||||
|
WebSocketRequestContext context = new WebSocketRequestContext(response, client, ip);
|
||||||
|
if(hook.hook(context, ctx))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (response instanceof SimpleResponse) {
|
if (response instanceof SimpleResponse) {
|
||||||
SimpleResponse simpleResponse = (SimpleResponse) response;
|
SimpleResponse simpleResponse = (SimpleResponse) response;
|
||||||
simpleResponse.server = server;
|
simpleResponse.server = server;
|
||||||
|
@ -142,10 +109,6 @@ void process(ChannelHandlerContext ctx, WebSocketServerResponse response, Client
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class getResponseClass(String type) {
|
|
||||||
return responses.get(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void registerClient(Channel channel) {
|
public void registerClient(Channel channel) {
|
||||||
channels.add(channel);
|
channels.add(channel);
|
||||||
}
|
}
|
||||||
|
@ -168,27 +131,26 @@ public static void registerResponses() {
|
||||||
providers.register("getSecureToken", GetSecureTokenResponse.class);
|
providers.register("getSecureToken", GetSecureTokenResponse.class);
|
||||||
providers.register("verifySecureToken", VerifySecureTokenResponse.class);
|
providers.register("verifySecureToken", VerifySecureTokenResponse.class);
|
||||||
providers.register("getAvailabilityAuth", GetAvailabilityAuthResponse.class);
|
providers.register("getAvailabilityAuth", GetAvailabilityAuthResponse.class);
|
||||||
providers.register("proxy", ProxyCommandResponse.class);
|
|
||||||
providers.register("register", RegisterResponse.class);
|
providers.register("register", RegisterResponse.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendObject(ChannelHandlerContext ctx, Object obj) {
|
public void sendObject(ChannelHandlerContext ctx, Object obj) {
|
||||||
ctx.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, WebSocketEvent.class)));
|
ctx.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, WebSocketEvent.class)), ctx.voidPromise());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendObject(ChannelHandlerContext ctx, Object obj, Type type) {
|
public void sendObject(ChannelHandlerContext ctx, Object obj, Type type) {
|
||||||
ctx.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, type)));
|
ctx.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, type)), ctx.voidPromise());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendObjectAll(Object obj) {
|
public void sendObjectAll(Object obj) {
|
||||||
for (Channel ch : channels) {
|
for (Channel ch : channels) {
|
||||||
ch.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, WebSocketEvent.class)));
|
ch.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, WebSocketEvent.class)), ch.voidPromise());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendObjectAll(Object obj, Type type) {
|
public void sendObjectAll(Object obj, Type type) {
|
||||||
for (Channel ch : channels) {
|
for (Channel ch : channels) {
|
||||||
ch.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, type)));
|
ch.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, type)), ch.voidPromise());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,7 +163,7 @@ public void sendObjectAndClose(ChannelHandlerContext ctx, Object obj, Type type)
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendEvent(EventResult obj) {
|
public void sendEvent(EventResult obj) {
|
||||||
channels.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj)));
|
channels.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj)), ChannelMatchers.all(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class EventResult implements WebSocketEvent {
|
public static class EventResult implements WebSocketEvent {
|
||||||
|
|
|
@ -36,7 +36,9 @@ protected void decode(ChannelHandlerContext ctx, HttpRequest msg, List<Object> o
|
||||||
realIP = headers.get("X-Real-IP");
|
realIP = headers.get("X-Real-IP");
|
||||||
}
|
}
|
||||||
if (realIP != null) {
|
if (realIP != null) {
|
||||||
|
if (LogHelper.isDevEnabled()) {
|
||||||
LogHelper.dev("Real IP address %s", realIP);
|
LogHelper.dev("Real IP address %s", realIP);
|
||||||
|
}
|
||||||
context.ip = realIP;
|
context.ip = realIP;
|
||||||
} else LogHelper.error("IpForwarding error. Headers not found");
|
} else LogHelper.error("IpForwarding error. Headers not found");
|
||||||
out.add(msg);
|
out.add(msg);
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
import pro.gravit.launchserver.socket.LauncherNettyServer;
|
import pro.gravit.launchserver.socket.LauncherNettyServer;
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
@SuppressWarnings({"unused", "rawtypes"})
|
@SuppressWarnings("unused")
|
||||||
public final class NettyServerSocketHandler implements Runnable, AutoCloseable {
|
public final class NettyServerSocketHandler implements Runnable, AutoCloseable {
|
||||||
private SSLServerSocketFactory ssf;
|
private SSLServerSocketFactory ssf;
|
||||||
|
|
||||||
|
|
|
@ -2,22 +2,18 @@
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import com.google.gson.GsonBuilder;
|
import io.netty.channel.Channel;
|
||||||
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.SimpleChannelInboundHandler;
|
import io.netty.channel.SimpleChannelInboundHandler;
|
||||||
import io.netty.channel.group.DefaultChannelGroup;
|
|
||||||
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
|
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
|
||||||
import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
|
import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
|
||||||
import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
|
import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
|
||||||
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
|
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
|
||||||
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
|
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
|
||||||
import io.netty.util.concurrent.GlobalEventExecutor;
|
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
import pro.gravit.launchserver.socket.Client;
|
import pro.gravit.launchserver.socket.Client;
|
||||||
import pro.gravit.launchserver.socket.NettyConnectContext;
|
import pro.gravit.launchserver.socket.NettyConnectContext;
|
||||||
import pro.gravit.launchserver.socket.WebSocketService;
|
import pro.gravit.launchserver.socket.WebSocketService;
|
||||||
import pro.gravit.utils.helper.CommonHelper;
|
|
||||||
import pro.gravit.utils.helper.IOHelper;
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
|
@ -45,11 +41,14 @@ public void setClient(Client client) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void channelActive(ChannelHandlerContext ctx) {
|
public void channelActive(ChannelHandlerContext ctx) {
|
||||||
|
if (LogHelper.isDevEnabled()) {
|
||||||
LogHelper.dev("New client %s", IOHelper.getIP(ctx.channel().remoteAddress()));
|
LogHelper.dev("New client %s", IOHelper.getIP(ctx.channel().remoteAddress()));
|
||||||
|
}
|
||||||
client = new Client(0);
|
client = new Client(0);
|
||||||
service.registerClient(ctx.channel());
|
Channel ch = ctx.channel();
|
||||||
|
service.registerClient(ch);
|
||||||
ctx.executor().schedule(() -> {
|
ctx.executor().schedule(() -> {
|
||||||
ctx.channel().writeAndFlush(new PingWebSocketFrame());
|
ch.writeAndFlush(new PingWebSocketFrame(), ch.voidPromise());
|
||||||
}, 30L, TimeUnit.SECONDS);
|
}, 30L, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.RandomAccessFile;
|
import java.io.RandomAccessFile;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.net.URI;
|
||||||
import java.net.URLDecoder;
|
import java.net.URISyntaxException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
@ -77,7 +77,15 @@ public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) thr
|
||||||
}
|
}
|
||||||
|
|
||||||
final String uri = request.uri();
|
final String uri = request.uri();
|
||||||
final String path = sanitizeUri(uri);
|
final String path;
|
||||||
|
|
||||||
|
try {
|
||||||
|
path = Paths.get(new URI(uri).getPath()).normalize().toString().substring(1);
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
sendError(ctx, BAD_REQUEST);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (path == null) {
|
if (path == null) {
|
||||||
sendError(ctx, FORBIDDEN);
|
sendError(ctx, FORBIDDEN);
|
||||||
return;
|
return;
|
||||||
|
@ -172,26 +180,6 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Pattern INSECURE_URI = Pattern.compile(".*[<>&\"].*");
|
|
||||||
|
|
||||||
private static String sanitizeUri(String uri) {
|
|
||||||
// Decode the path.
|
|
||||||
try {
|
|
||||||
uri = URLDecoder.decode(uri, "UTF-8");
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
throw new Error(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uri.isEmpty() || uri.charAt(0) != '/') {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert file separators.
|
|
||||||
uri = uri.replace(File.separatorChar, '/');
|
|
||||||
|
|
||||||
return Paths.get(uri).normalize().toString().substring(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Pattern ALLOWED_FILE_NAME = Pattern.compile("[^-\\._]?[^<>&\\\"]*");
|
private static final Pattern ALLOWED_FILE_NAME = Pattern.compile("[^-\\._]?[^<>&\\\"]*");
|
||||||
|
|
||||||
private static void sendListing(ChannelHandlerContext ctx, File dir, String dirPath) {
|
private static void sendListing(ChannelHandlerContext ctx, File dir, String dirPath) {
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
package pro.gravit.launchserver.socket.response.admin;
|
|
||||||
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import pro.gravit.launchserver.socket.Client;
|
|
||||||
import pro.gravit.launchserver.socket.response.WebSocketServerResponse;
|
|
||||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
|
||||||
|
|
||||||
public class ProxyCommandResponse extends SimpleResponse {
|
|
||||||
public WebSocketServerResponse response;
|
|
||||||
public long session;
|
|
||||||
public boolean isCheckSign;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
|
||||||
if (!client.proxy) {
|
|
||||||
sendError("Proxy server error");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Client real_client = server.sessionManager.getOrNewClient(session);
|
|
||||||
real_client.checkSign = isCheckSign;
|
|
||||||
response.execute(ctx, real_client);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getType() {
|
|
||||||
return "proxy";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -45,12 +45,11 @@ public AuthResponse(String login, String password, String auth_id, OshiHWID hwid
|
||||||
}
|
}
|
||||||
|
|
||||||
public String auth_id;
|
public String auth_id;
|
||||||
public boolean initProxy;
|
|
||||||
public ConnectTypes authType;
|
public ConnectTypes authType;
|
||||||
public HWID hwid;
|
public HWID hwid;
|
||||||
|
|
||||||
public enum ConnectTypes {
|
public enum ConnectTypes {
|
||||||
SERVER, CLIENT, BOT
|
SERVER, CLIENT, API
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -111,11 +110,9 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti
|
||||||
clientData.username = login;
|
clientData.username = login;
|
||||||
result.accessToken = aresult.accessToken;
|
result.accessToken = aresult.accessToken;
|
||||||
result.permissions = clientData.permissions;
|
result.permissions = clientData.permissions;
|
||||||
if (authType == ConnectTypes.BOT && !clientData.permissions.canBot) {
|
|
||||||
AuthProvider.authError("authType: BOT not allowed for this account");
|
|
||||||
}
|
|
||||||
if (authType == ConnectTypes.SERVER && !clientData.permissions.canServer) {
|
if (authType == ConnectTypes.SERVER && !clientData.permissions.canServer) {
|
||||||
AuthProvider.authError("authType: SERVER not allowed for this account");
|
AuthProvider.authError("authType: SERVER not allowed for this account");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (getSession) {
|
if (getSession) {
|
||||||
if (clientData.session == 0) {
|
if (clientData.session == 0) {
|
||||||
|
@ -124,15 +121,13 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti
|
||||||
}
|
}
|
||||||
result.session = clientData.session;
|
result.session = clientData.session;
|
||||||
}
|
}
|
||||||
if (initProxy) {
|
if (authType != ConnectTypes.API && server.config.protectHandler.allowGetAccessToken(context)) {
|
||||||
if (!clientData.permissions.canProxy) throw new AuthException("initProxy not allow");
|
|
||||||
clientData.proxy = true;
|
|
||||||
}
|
|
||||||
if (server.config.protectHandler.allowGetAccessToken(context)) {
|
|
||||||
UUID uuid = pair.handler.auth(aresult);
|
UUID uuid = pair.handler.auth(aresult);
|
||||||
result.playerProfile = ProfileByUUIDResponse.getProfile(server, uuid, aresult.username, client, clientData.auth.textureProvider);
|
result.playerProfile = ProfileByUUIDResponse.getProfile(uuid, aresult.username, client, clientData.auth.textureProvider);
|
||||||
|
if (LogHelper.isDebugEnabled()) {
|
||||||
LogHelper.debug("Auth: %s accessToken %s uuid: %s", login, result.accessToken, uuid.toString());
|
LogHelper.debug("Auth: %s accessToken %s uuid: %s", login, result.accessToken, uuid.toString());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
sendResult(result);
|
sendResult(result);
|
||||||
} catch (AuthException | HWIDException | HookException e) {
|
} catch (AuthException | HWIDException | HookException e) {
|
||||||
sendError(e.getMessage());
|
sendError(e.getMessage());
|
||||||
|
@ -140,10 +135,10 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class AuthContext {
|
public static class AuthContext {
|
||||||
public AuthContext(long session, String login, int password_lenght, String customText, String client, String hwid, String ip, ConnectTypes authType) {
|
public AuthContext(long session, String login, int password_length, String customText, String client, String hwid, String ip, ConnectTypes authType) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.login = login;
|
this.login = login;
|
||||||
this.password_lenght = password_lenght;
|
this.password_length = password_length;
|
||||||
this.customText = customText;
|
this.customText = customText;
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.hwid = hwid;
|
this.hwid = hwid;
|
||||||
|
@ -153,7 +148,7 @@ public AuthContext(long session, String login, int password_lenght, String custo
|
||||||
|
|
||||||
public long session;
|
public long session;
|
||||||
public String login;
|
public String login;
|
||||||
public int password_lenght; //Use AuthProvider for get password
|
public int password_length; //Use AuthProvider for get password
|
||||||
public String client;
|
public String client;
|
||||||
public String hwid;
|
public String hwid;
|
||||||
public String customText;
|
public String customText;
|
||||||
|
|
|
@ -26,8 +26,10 @@ public void execute(ChannelHandlerContext ctx, Client pClient) {
|
||||||
server.authHookManager.checkServerHook.hook(this, pClient);
|
server.authHookManager.checkServerHook.hook(this, pClient);
|
||||||
result.uuid = pClient.auth.handler.checkServer(username, serverID);
|
result.uuid = pClient.auth.handler.checkServer(username, serverID);
|
||||||
if (result.uuid != null)
|
if (result.uuid != null)
|
||||||
result.playerProfile = ProfileByUUIDResponse.getProfile(server, result.uuid, username, client, pClient.auth.textureProvider);
|
result.playerProfile = ProfileByUUIDResponse.getProfile(result.uuid, username, client, pClient.auth.textureProvider);
|
||||||
|
if (LogHelper.isDebugEnabled()) {
|
||||||
LogHelper.debug("checkServer: %s uuid: %s serverID: %s", result.playerProfile.username, result.uuid.toString(), serverID);
|
LogHelper.debug("checkServer: %s uuid: %s serverID: %s", result.playerProfile.username, result.uuid.toString(), serverID);
|
||||||
|
}
|
||||||
} catch (AuthException | HookException e) {
|
} catch (AuthException | HookException e) {
|
||||||
sendError(e.getMessage());
|
sendError(e.getMessage());
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -27,7 +27,9 @@ public void execute(ChannelHandlerContext ctx, Client client) {
|
||||||
LogHelper.warning("Client auth is null. Using default.");
|
LogHelper.warning("Client auth is null. Using default.");
|
||||||
success = server.config.getAuthProviderPair().handler.joinServer(username, accessToken, serverID);
|
success = server.config.getAuthProviderPair().handler.joinServer(username, accessToken, serverID);
|
||||||
} else success = client.auth.handler.joinServer(username, accessToken, serverID);
|
} else success = client.auth.handler.joinServer(username, accessToken, serverID);
|
||||||
|
if (LogHelper.isDebugEnabled()) {
|
||||||
LogHelper.debug("joinServer: %s accessToken: %s serverID: %s", username, accessToken, serverID);
|
LogHelper.debug("joinServer: %s accessToken: %s serverID: %s", username, accessToken, serverID);
|
||||||
|
}
|
||||||
} catch (AuthException | HookException e) {
|
} catch (AuthException | HookException e) {
|
||||||
sendError(e.getMessage());
|
sendError(e.getMessage());
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -32,7 +32,7 @@ public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||||
LogHelper.warning("Client auth is null. Using default.");
|
LogHelper.warning("Client auth is null. Using default.");
|
||||||
uuid = server.config.getAuthProviderPair().handler.usernameToUUID(list[i].username);
|
uuid = server.config.getAuthProviderPair().handler.usernameToUUID(list[i].username);
|
||||||
} else uuid = client.auth.handler.usernameToUUID(list[i].username);
|
} else uuid = client.auth.handler.usernameToUUID(list[i].username);
|
||||||
result.playerProfiles[i] = ProfileByUUIDResponse.getProfile(server, uuid, list[i].username, list[i].client, client.auth.textureProvider);
|
result.playerProfiles[i] = ProfileByUUIDResponse.getProfile(uuid, list[i].username, list[i].client, client.auth.textureProvider);
|
||||||
}
|
}
|
||||||
sendResult(result);
|
sendResult(result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
import pro.gravit.launcher.events.request.ProfileByUUIDRequestEvent;
|
import pro.gravit.launcher.events.request.ProfileByUUIDRequestEvent;
|
||||||
import pro.gravit.launcher.profiles.PlayerProfile;
|
import pro.gravit.launcher.profiles.PlayerProfile;
|
||||||
import pro.gravit.launcher.profiles.Texture;
|
import pro.gravit.launcher.profiles.Texture;
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.auth.AuthProviderPair;
|
||||||
import pro.gravit.launchserver.auth.texture.TextureProvider;
|
import pro.gravit.launchserver.auth.texture.TextureProvider;
|
||||||
import pro.gravit.launchserver.socket.Client;
|
import pro.gravit.launchserver.socket.Client;
|
||||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||||
|
@ -17,7 +17,7 @@ public class ProfileByUUIDResponse extends SimpleResponse {
|
||||||
public UUID uuid;
|
public UUID uuid;
|
||||||
public String client;
|
public String client;
|
||||||
|
|
||||||
public static PlayerProfile getProfile(LaunchServer server, UUID uuid, String username, String client, TextureProvider textureProvider) {
|
public static PlayerProfile getProfile(UUID uuid, String username, String client, TextureProvider textureProvider) {
|
||||||
// Get skin texture
|
// Get skin texture
|
||||||
Texture skin;
|
Texture skin;
|
||||||
try {
|
try {
|
||||||
|
@ -48,10 +48,19 @@ public String getType() {
|
||||||
@Override
|
@Override
|
||||||
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||||
String username;
|
String username;
|
||||||
|
AuthProviderPair pair;
|
||||||
if (client.auth == null) {
|
if (client.auth == null) {
|
||||||
LogHelper.warning("Client auth is null. Using default.");
|
LogHelper.warning("Client auth is null. Using default.");
|
||||||
username = server.config.getAuthProviderPair().handler.uuidToUsername(uuid);
|
pair = server.config.getAuthProviderPair();
|
||||||
} else username = client.auth.handler.uuidToUsername(uuid);
|
} else {
|
||||||
sendResult(new ProfileByUUIDRequestEvent(getProfile(server, uuid, username, this.client, client.auth.textureProvider)));
|
pair = client.auth;
|
||||||
|
}
|
||||||
|
if(pair == null)
|
||||||
|
{
|
||||||
|
sendError("ProfileByUUIDResponse: AuthProviderPair is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
username = pair.handler.uuidToUsername(uuid);
|
||||||
|
sendResult(new ProfileByUUIDRequestEvent(getProfile(uuid, username, this.client, client.auth.textureProvider)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,6 @@ public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||||
LogHelper.warning("Client auth is null. Using default.");
|
LogHelper.warning("Client auth is null. Using default.");
|
||||||
uuid = server.config.getAuthProviderPair().handler.usernameToUUID(username);
|
uuid = server.config.getAuthProviderPair().handler.usernameToUUID(username);
|
||||||
} else uuid = client.auth.handler.usernameToUUID(username);
|
} else uuid = client.auth.handler.usernameToUUID(username);
|
||||||
sendResult(new ProfileByUsernameRequestEvent(ProfileByUUIDResponse.getProfile(server, uuid, username, this.client, client.auth.textureProvider)));
|
sendResult(new ProfileByUsernameRequestEvent(ProfileByUUIDResponse.getProfile(uuid, username, this.client, client.auth.textureProvider)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ public void execute(ChannelHandlerContext ctx, Client client) {
|
||||||
bytes = digest;
|
bytes = digest;
|
||||||
if (launcher_type == 1) // JAR
|
if (launcher_type == 1) // JAR
|
||||||
{
|
{
|
||||||
byte[] hash = server.launcherBinary.getBytes().getDigest();
|
byte[] hash = server.launcherBinary.getDigest();
|
||||||
if (hash == null) service.sendObjectAndClose(ctx, new LauncherRequestEvent(true, server.config.netty.launcherURL));
|
if (hash == null) service.sendObjectAndClose(ctx, new LauncherRequestEvent(true, server.config.netty.launcherURL));
|
||||||
if (Arrays.equals(bytes, hash)) {
|
if (Arrays.equals(bytes, hash)) {
|
||||||
client.checkSign = true;
|
client.checkSign = true;
|
||||||
|
@ -39,7 +39,7 @@ public void execute(ChannelHandlerContext ctx, Client client) {
|
||||||
}
|
}
|
||||||
} else if (launcher_type == 2) //EXE
|
} else if (launcher_type == 2) //EXE
|
||||||
{
|
{
|
||||||
byte[] hash = server.launcherEXEBinary.getBytes().getDigest();
|
byte[] hash = server.launcherEXEBinary.getDigest();
|
||||||
if (hash == null) sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherEXEURL));
|
if (hash == null) sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherEXEURL));
|
||||||
if (Arrays.equals(bytes, hash)) {
|
if (Arrays.equals(bytes, hash)) {
|
||||||
client.checkSign = true;
|
client.checkSign = true;
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import pro.gravit.launcher.events.request.UpdateListRequestEvent;
|
import pro.gravit.launcher.events.request.UpdateListRequestEvent;
|
||||||
import pro.gravit.launcher.hasher.HashedDir;
|
import pro.gravit.launcher.hasher.HashedDir;
|
||||||
import pro.gravit.launcher.serialize.signed.SignedObjectHolder;
|
|
||||||
import pro.gravit.launchserver.socket.Client;
|
import pro.gravit.launchserver.socket.Client;
|
||||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||||
|
|
||||||
|
@ -24,7 +23,7 @@ public void execute(ChannelHandlerContext ctx, Client client) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HashSet<String> set = new HashSet<>();
|
HashSet<String> set = new HashSet<>();
|
||||||
for (Map.Entry<String, SignedObjectHolder<HashedDir>> entry : server.updatesDirMap.entrySet())
|
for (Map.Entry<String, HashedDir> entry : server.updatesDirMap.entrySet())
|
||||||
set.add(entry.getKey());
|
set.add(entry.getKey());
|
||||||
sendResult(new UpdateListRequestEvent(set));
|
sendResult(new UpdateListRequestEvent(set));
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
import pro.gravit.launcher.events.request.UpdateRequestEvent;
|
import pro.gravit.launcher.events.request.UpdateRequestEvent;
|
||||||
import pro.gravit.launcher.hasher.HashedDir;
|
import pro.gravit.launcher.hasher.HashedDir;
|
||||||
import pro.gravit.launcher.profiles.ClientProfile;
|
import pro.gravit.launcher.profiles.ClientProfile;
|
||||||
import pro.gravit.launcher.serialize.signed.SignedObjectHolder;
|
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
import pro.gravit.launchserver.socket.Client;
|
import pro.gravit.launchserver.socket.Client;
|
||||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||||
|
@ -34,7 +33,7 @@ public void execute(ChannelHandlerContext ctx, Client client) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SignedObjectHolder<HashedDir> dir = server.updatesDirMap.get(dirName);
|
HashedDir dir = server.updatesDirMap.get(dirName);
|
||||||
if (dir == null) {
|
if (dir == null) {
|
||||||
service.sendObject(ctx, new ErrorRequestEvent(String.format("Directory %s not found", dirName)));
|
service.sendObject(ctx, new ErrorRequestEvent(String.format("Directory %s not found", dirName)));
|
||||||
return;
|
return;
|
||||||
|
@ -46,6 +45,6 @@ public void execute(ChannelHandlerContext ctx, Client client) {
|
||||||
url = bind.url;
|
url = bind.url;
|
||||||
zip = bind.zip;
|
zip = bind.zip;
|
||||||
}
|
}
|
||||||
service.sendObject(ctx, new UpdateRequestEvent(dir.object, url, zip));
|
service.sendObject(ctx, new UpdateRequestEvent(dir, url, zip));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
{
|
|
||||||
"port": 7240,
|
|
||||||
"address": "xx.xx",
|
|
||||||
"bindAddress": "0.0.0.0",
|
|
||||||
"projectName": "XXX",
|
|
||||||
"mirrors": [
|
|
||||||
"http://mirror.gravitlauncher.ml/"
|
|
||||||
],
|
|
||||||
"binaryName": "Launcher",
|
|
||||||
"env": "STD",
|
|
||||||
"authProvider": [
|
|
||||||
{
|
|
||||||
"message": "Настройте authProvider",
|
|
||||||
"type": "reject"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"authHandler": {
|
|
||||||
"type": "memory"
|
|
||||||
},
|
|
||||||
"permissionsHandler": {
|
|
||||||
"filename": "permissions.json",
|
|
||||||
"type": "json"
|
|
||||||
},
|
|
||||||
"textureProvider": {
|
|
||||||
"skinURL": "http://example.com/skins/%username%.png",
|
|
||||||
"cloakURL": "http://example.com/cloaks/%username%.png",
|
|
||||||
"type": "request"
|
|
||||||
},
|
|
||||||
"hwidHandler": {
|
|
||||||
"type": "accept"
|
|
||||||
},
|
|
||||||
"threadCount": 2,
|
|
||||||
"threadCoreCount": 0,
|
|
||||||
"launch4j": {
|
|
||||||
"enabled": false,
|
|
||||||
"productName": "GravitLauncher",
|
|
||||||
"productVer": "4.2.0.0",
|
|
||||||
"fileDesc": "GravitLauncher 4.2.0",
|
|
||||||
"fileVer": "4.2.0.0",
|
|
||||||
"internalName": "Launcher",
|
|
||||||
"copyright": "© GravitLauncher Team",
|
|
||||||
"trademarks": "This product is licensed under GPLv3",
|
|
||||||
"txtFileVersion": "%s, build %d",
|
|
||||||
"txtProductVersion": "%s, build %d"
|
|
||||||
},
|
|
||||||
"buildPostTransform": {
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
"compress": false,
|
|
||||||
"authRateLimit": 0,
|
|
||||||
"authRateLimitMilis": 0,
|
|
||||||
"authRejectString": "Превышен лимит авторизаций",
|
|
||||||
"whitelistRejectString": "Вас нет в белом списке",
|
|
||||||
"genMappings": true,
|
|
||||||
"isUsingWrapper": false,
|
|
||||||
"isDownloadJava": false,
|
|
||||||
"isWarningMissArchJava": true,
|
|
||||||
"enabledProGuard": true,
|
|
||||||
"updatesNotify": true,
|
|
||||||
"stripLineNumbers": true,
|
|
||||||
"deleteTempFiles": true,
|
|
||||||
"startScript": ".\\start.sh"
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
StringEncryption:
|
|
||||||
Enabled: true
|
|
||||||
Mode: Normal
|
|
||||||
StringPool: false
|
|
||||||
InvokeDynamic: None
|
|
||||||
NumberObfuscation: Normal
|
|
||||||
FlowObfuscation: Normal
|
|
||||||
HideCode: false
|
|
||||||
Shuffler: true
|
|
||||||
Crasher: false
|
|
||||||
Optimizer:
|
|
||||||
Enabled: true
|
|
||||||
InlineGotoGoto: true
|
|
||||||
InlineGotoReturn: true
|
|
||||||
RemoveNopInstructions: true
|
|
||||||
Watermarker:
|
|
||||||
Enabled: false
|
|
||||||
Message: "This copy belongs to GravitLauncher"
|
|
||||||
Key: "SuperSecureKey"
|
|
||||||
Dictionary: Spaces
|
|
||||||
TrashClasses: 500
|
|
|
@ -39,7 +39,6 @@
|
||||||
dependencies {
|
dependencies {
|
||||||
pack project(':LauncherAuthlib')
|
pack project(':LauncherAuthlib')
|
||||||
bundle 'com.github.oshi:oshi-core:3.13.0'
|
bundle 'com.github.oshi:oshi-core:3.13.0'
|
||||||
bundle 'de.jensd:fontawesomefx:8.9'
|
|
||||||
bundle 'org.apache.httpcomponents:httpclient:4.5.7'
|
bundle 'org.apache.httpcomponents:httpclient:4.5.7'
|
||||||
pack 'io.netty:netty-codec-http:4.1.36.Final'
|
pack 'io.netty:netty-codec-http:4.1.36.Final'
|
||||||
pack 'org.ow2.asm:asm-tree:7.1'
|
pack 'org.ow2.asm:asm-tree:7.1'
|
||||||
|
@ -58,3 +57,33 @@ task dumpLibs(type: Copy) {
|
||||||
|
|
||||||
|
|
||||||
build.dependsOn tasks.genRuntimeJS, tasks.dumpLibs, tasks.shadowJar
|
build.dependsOn tasks.genRuntimeJS, tasks.dumpLibs, tasks.shadowJar
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
launcherclientapi(MavenPublication) {
|
||||||
|
artifactId = 'launcher-client-api'
|
||||||
|
artifact jar
|
||||||
|
pom {
|
||||||
|
name = 'GravitLauncher Client API'
|
||||||
|
description = 'GravitLauncher Client Module API'
|
||||||
|
url = 'https://launcher.gravit.pro'
|
||||||
|
licenses {
|
||||||
|
license {
|
||||||
|
name = 'GNU General Public License, Version 3.0'
|
||||||
|
url = 'https://www.gnu.org/licenses/gpl-3.0.html'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scm {
|
||||||
|
connection = 'scm:git:https://github.com/GravitLauncher/Launcher.git'
|
||||||
|
developerConnection = 'scm:git:ssh://git@github.com:GravitLauncher/Launcher.git'
|
||||||
|
url = 'https://launcher.gravit.pro/'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
signing {
|
||||||
|
sign publishing.publications.launcherclientapi
|
||||||
|
}
|
||||||
|
|
|
@ -1,27 +1,31 @@
|
||||||
// ====== LAUNCHER CONFIG ====== //
|
|
||||||
var config = {
|
var config = {
|
||||||
dir: "GravitLauncher", // Launcher directory
|
//*** Настройки лаунчера ***//
|
||||||
title: "GravitLauncher", // Window title
|
dir: "GravitLauncher", // Название папки лаунчера
|
||||||
icons: [ "favicon.png" ], // Window icon paths
|
title: "GravitLauncher", // Заголовок окна
|
||||||
|
icons: ["favicon.png"], // Путь/Пути до иконки окна
|
||||||
|
|
||||||
// Auth config
|
//*** Меню авторизации ***//
|
||||||
linkText: "GravitLauncher", // Text for link under "Auth" button
|
linkText: "GravitLauncher", // Текст ссылки
|
||||||
linkURL: new java.net.URL("https://gravitlauncher.ml"), // URL for link under "Auth" button
|
linkURL: new java.net.URL("https://gravit.pro"), // Ссылка
|
||||||
|
|
||||||
// Menu config
|
//*** Меню выбора серверов ***//
|
||||||
discord: new java.net.URL("https://discord.gg/aJK6nMN"),
|
discord: new java.net.URL("https://discord.gg/aJK6nMN"), // Ссылка
|
||||||
|
|
||||||
// Settings defaults
|
//*** Стандартные настройки клиента ***//
|
||||||
settingsMagic: 0xC0DE5, // Magic, don't touch
|
autoEnterDefault: false, // Автоматический вход на выбранный сервер
|
||||||
autoEnterDefault: false, // Should autoEnter be enabled by default?
|
fullScreenDefault: false, // Клиент в полный экран
|
||||||
fullScreenDefault: false, // Should fullScreen be enabled by default?
|
featureStoreDefault: true, // Поиск файлов в других клиентах (Используется для экономии трафика и ускорения загрузки)
|
||||||
ramDefault: 1024, // Default RAM amount (0 for auto)
|
ramDefault: 1024, // Количество оперативной памяти выделенной по умолчанию (0 - Автоматически)
|
||||||
|
|
||||||
|
//*** Настройка загрузки JVM ***//
|
||||||
|
/* LaunchServer: guardtype = java */
|
||||||
jvm: {
|
jvm: {
|
||||||
enable: false,
|
enable: false, // Включение загрузки своей JVM
|
||||||
jvmMustdie32Dir: "jre-8u202-win32",
|
jvmMustdie32Dir: "jre-8u211-win32", // Название папки JVM для Windows x32
|
||||||
jvmMustdie64Dir: "jre-8u202-win64",
|
jvmMustdie64Dir: "jre-8u211-win64", // Название папки JVM для Windows x64
|
||||||
}
|
},
|
||||||
|
|
||||||
|
settingsMagic: 0xC0DE5, // Магия вне хогвартса
|
||||||
};
|
};
|
||||||
|
|
||||||
DirBridge.dir = DirBridge.getLauncherDir(config.dir);
|
DirBridge.dir = DirBridge.getLauncherDir(config.dir);
|
||||||
|
|
|
@ -24,9 +24,9 @@ function initLauncher() {
|
||||||
|
|
||||||
/* ======== init Login window======== */
|
/* ======== init Login window======== */
|
||||||
function initLoginScene() {
|
function initLoginScene() {
|
||||||
loginPane.setOnMousePressed(function(event){ movePoint = new javafx.geometry.Point2D(event.getSceneX(), event.getSceneY())});
|
loginPane.setOnMousePressed(function(event) { movePoint = new javafx.geometry.Point2D(event.getSceneX(), event.getSceneY()) });
|
||||||
loginPane.setOnMouseDragged(function(event) {
|
loginPane.setOnMouseDragged(function(event) {
|
||||||
if(movePoint === null) {
|
if (movePoint === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
stage.setX(event.getScreenX() - movePoint.getX());
|
stage.setX(event.getScreenX() - movePoint.getX());
|
||||||
|
@ -35,9 +35,9 @@ function initLoginScene() {
|
||||||
|
|
||||||
var pane = loginPane.lookup("#bar");
|
var pane = loginPane.lookup("#bar");
|
||||||
bar = pane;
|
bar = pane;
|
||||||
loginPane.lookup("#close").setOnAction(function(event){ javafx.application.Platform.exit()});
|
loginPane.lookup("#close").setOnAction(function(event) { javafx.application.Platform.exit() });
|
||||||
loginPane.lookup("#hide").setOnAction(function(event){ stage.setIconified(true)});
|
loginPane.lookup("#hide").setOnAction(function(event) { stage.setIconified(true) });
|
||||||
loginPane.lookup("#discord").setOnAction(function(){ openURL(config.discord); });
|
loginPane.lookup("#discord").setOnAction(function() { openURL(config.discord); });
|
||||||
|
|
||||||
var pane = loginPane.lookup("#authPane");
|
var pane = loginPane.lookup("#authPane");
|
||||||
authPane = pane;
|
authPane = pane;
|
||||||
|
@ -46,14 +46,14 @@ function initLoginScene() {
|
||||||
loginPaneLayout = loginLayout;
|
loginPaneLayout = loginLayout;
|
||||||
|
|
||||||
loginField = pane.lookup("#login");
|
loginField = pane.lookup("#login");
|
||||||
loginField.setOnMouseMoved(function(event){rootPane.fireEvent(event)});
|
loginField.setOnMouseMoved(function(event) { rootPane.fireEvent(event) });
|
||||||
loginField.setOnAction(goAuth);
|
loginField.setOnAction(goAuth);
|
||||||
if (settings.login !== null) {
|
if (settings.login !== null) {
|
||||||
loginField.setText(settings.login);
|
loginField.setText(settings.login);
|
||||||
}
|
}
|
||||||
|
|
||||||
passwordField = pane.lookup("#password");
|
passwordField = pane.lookup("#password");
|
||||||
passwordField.setOnMouseMoved(function(event){rootPane.fireEvent(event)});
|
passwordField.setOnMouseMoved(function(event) { rootPane.fireEvent(event) });
|
||||||
passwordField.setOnAction(goAuth);
|
passwordField.setOnAction(goAuth);
|
||||||
if (settings.rsaPassword !== null) {
|
if (settings.rsaPassword !== null) {
|
||||||
passwordField.getStyleClass().add("hasSaved");
|
passwordField.getStyleClass().add("hasSaved");
|
||||||
|
@ -74,9 +74,9 @@ function initLoginScene() {
|
||||||
|
|
||||||
/* ======== init Menu window======== */
|
/* ======== init Menu window======== */
|
||||||
function initMenuScene() {
|
function initMenuScene() {
|
||||||
menuPane.setOnMousePressed(function(event){ movePoint = new javafx.geometry.Point2D(event.getSceneX(), event.getSceneY())});
|
menuPane.setOnMousePressed(function(event) { movePoint = new javafx.geometry.Point2D(event.getSceneX(), event.getSceneY()) });
|
||||||
menuPane.setOnMouseDragged(function(event) {
|
menuPane.setOnMouseDragged(function(event) {
|
||||||
if(movePoint === null) {
|
if (movePoint === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,9 +86,9 @@ function initMenuScene() {
|
||||||
|
|
||||||
var pane = menuPane.lookup("#bar");
|
var pane = menuPane.lookup("#bar");
|
||||||
bar = pane;
|
bar = pane;
|
||||||
pane.lookup("#close").setOnAction(function(event){ javafx.application.Platform.exit()});
|
pane.lookup("#close").setOnAction(function(event) { javafx.application.Platform.exit() });
|
||||||
pane.lookup("#hide").setOnAction(function(event){ stage.setIconified(true)});
|
pane.lookup("#hide").setOnAction(function(event) { stage.setIconified(true) });
|
||||||
pane.lookup("#discord").setOnAction(function(){ openURL(config.discord); });
|
pane.lookup("#discord").setOnAction(function() { openURL(config.discord); });
|
||||||
pane.lookup("#settings").setOnAction(goSettings);
|
pane.lookup("#settings").setOnAction(goSettings);
|
||||||
pane.lookup("#goConsole").setOnAction(goConsole);
|
pane.lookup("#goConsole").setOnAction(goConsole);
|
||||||
|
|
||||||
|
@ -105,10 +105,10 @@ function initMenuScene() {
|
||||||
serverEntrance = pane.lookup("#serverentrance");
|
serverEntrance = pane.lookup("#serverentrance");
|
||||||
serverStatus = serverEntrance.lookup("#serverStatus");
|
serverStatus = serverEntrance.lookup("#serverStatus");
|
||||||
serverLabel = serverEntrance.lookup("#serverLabel");
|
serverLabel = serverEntrance.lookup("#serverLabel");
|
||||||
serverEntrance.lookup("#clientLaunch").setOnAction(function(){
|
serverEntrance.lookup("#clientLaunch").setOnAction(function() {
|
||||||
doUpdate(profilesList[serverHolder.old], loginData.pp, loginData.accessToken);
|
doUpdate(profilesList[serverHolder.old], loginData.pp, loginData.accessToken);
|
||||||
});
|
});
|
||||||
pane.lookup("#logout").setOnAction(function(){
|
pane.lookup("#logout").setOnAction(function() {
|
||||||
setCurrentScene(loginScene);
|
setCurrentScene(loginScene);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -116,9 +116,9 @@ function initMenuScene() {
|
||||||
|
|
||||||
/* ======== init Console window======== */
|
/* ======== init Console window======== */
|
||||||
function initConsoleScene() {
|
function initConsoleScene() {
|
||||||
consoleMenu.setOnMousePressed(function(event){ movePoint = new javafx.geometry.Point2D(event.getSceneX(), event.getSceneY())});
|
consoleMenu.setOnMousePressed(function(event) { movePoint = new javafx.geometry.Point2D(event.getSceneX(), event.getSceneY()) });
|
||||||
consoleMenu.setOnMouseDragged(function(event) {
|
consoleMenu.setOnMouseDragged(function(event) {
|
||||||
if(movePoint === null) {
|
if (movePoint === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,13 +128,13 @@ function initConsoleScene() {
|
||||||
|
|
||||||
var pane = consoleMenu.lookup("#bar");
|
var pane = consoleMenu.lookup("#bar");
|
||||||
consoleBar = pane;
|
consoleBar = pane;
|
||||||
pane.lookup("#close").setOnAction(function(){
|
pane.lookup("#close").setOnAction(function() {
|
||||||
consoleStage.hide();
|
consoleStage.hide();
|
||||||
});
|
});
|
||||||
var text = consoleMenu.lookup("#textField");
|
var text = consoleMenu.lookup("#textField");
|
||||||
var output = consoleMenu.lookup("#output");
|
var output = consoleMenu.lookup("#output");
|
||||||
var appendFunction = function(line) javafx.application.Platform.runLater(function() output.appendText(line));
|
var appendFunction = function(line) javafx.application.Platform.runLater(function() output.appendText(line));
|
||||||
consoleMenu.lookup("#send").setOnAction(function(){
|
consoleMenu.lookup("#send").setOnAction(function() {
|
||||||
execCommand(text.getText());
|
execCommand(text.getText());
|
||||||
if (text.getText() == "clear") {
|
if (text.getText() == "clear") {
|
||||||
output.setText("");
|
output.setText("");
|
||||||
|
@ -142,7 +142,7 @@ function initConsoleScene() {
|
||||||
text.setText("");
|
text.setText("");
|
||||||
});
|
});
|
||||||
FunctionalBridge.addPlainOutput(function(string) {
|
FunctionalBridge.addPlainOutput(function(string) {
|
||||||
appendFunction(string+"\n");
|
appendFunction(string + "\n");
|
||||||
})
|
})
|
||||||
pane.lookup("#hide").setOnAction(function(event) { consoleStage.setIconified(true) });
|
pane.lookup("#hide").setOnAction(function(event) { consoleStage.setIconified(true) });
|
||||||
|
|
||||||
|
@ -153,9 +153,9 @@ function initConsoleScene() {
|
||||||
|
|
||||||
/* ======== init Options window======== */
|
/* ======== init Options window======== */
|
||||||
function initOptionsScene() {
|
function initOptionsScene() {
|
||||||
optionsMenu.setOnMousePressed(function(event){ movePoint = new javafx.geometry.Point2D(event.getSceneX(), event.getSceneY())});
|
optionsMenu.setOnMousePressed(function(event) { movePoint = new javafx.geometry.Point2D(event.getSceneX(), event.getSceneY()) });
|
||||||
optionsMenu.setOnMouseDragged(function(event) {
|
optionsMenu.setOnMouseDragged(function(event) {
|
||||||
if(movePoint === null) {
|
if (movePoint === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,9 +165,9 @@ function initOptionsScene() {
|
||||||
|
|
||||||
var pane = optionsMenu.lookup("#bar");
|
var pane = optionsMenu.lookup("#bar");
|
||||||
bar = pane;
|
bar = pane;
|
||||||
pane.lookup("#close").setOnAction(function(event){ javafx.application.Platform.exit()});
|
pane.lookup("#close").setOnAction(function(event) { javafx.application.Platform.exit() });
|
||||||
pane.lookup("#hide").setOnAction(function(event){ stage.setIconified(true)});
|
pane.lookup("#hide").setOnAction(function(event) { stage.setIconified(true) });
|
||||||
pane.lookup("#back").setOnAction(function(){
|
pane.lookup("#back").setOnAction(function() {
|
||||||
setCurrentScene(menuScene);
|
setCurrentScene(menuScene);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -222,9 +222,9 @@ function goAuth(event) {
|
||||||
|
|
||||||
settings.login = login;
|
settings.login = login;
|
||||||
doAuth(login, rsaPassword, authTypes[auth]);
|
doAuth(login, rsaPassword, authTypes[auth]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ======== Console ======== */
|
/* ======== Console ======== */
|
||||||
function goConsole(event) {
|
function goConsole(event) {
|
||||||
setConsoleCurrentScene(consoleScene);
|
setConsoleCurrentScene(consoleScene);
|
||||||
}
|
}
|
||||||
|
@ -267,7 +267,7 @@ function verifyLauncher(e) {
|
||||||
authOptions.getSelectionModel().select(0);
|
authOptions.getSelectionModel().select(0);
|
||||||
var sm = authOptions.getSelectionModel().selectedIndexProperty();
|
var sm = authOptions.getSelectionModel().selectedIndexProperty();
|
||||||
sm.addListener(new javafx.beans.value.ChangeListener({
|
sm.addListener(new javafx.beans.value.ChangeListener({
|
||||||
changed: function (observableValue, oldSelection, newSelection) {
|
changed: function(observableValue, oldSelection, newSelection) {
|
||||||
settings.auth = authTypes[authOptions.getSelectionModel().getSelectedItem()];
|
settings.auth = authTypes[authOptions.getSelectionModel().getSelectedItem()];
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
@ -287,14 +287,18 @@ function verifyLauncher(e) {
|
||||||
|
|
||||||
function doAuth(login, rsaPassword, auth_type) {
|
function doAuth(login, rsaPassword, auth_type) {
|
||||||
processing.resetOverlay();
|
processing.resetOverlay();
|
||||||
overlay.show(processing.overlay, function (event) {
|
overlay.show(processing.overlay, function(event) {
|
||||||
FunctionalBridge.getHWID.join();
|
FunctionalBridge.getHWID.join();
|
||||||
makeAuthRequest(login, rsaPassword, auth_type, function (result) {
|
makeAuthRequest(login, rsaPassword, auth_type, function(result) {
|
||||||
FunctionalBridge.setAuthParams(result);
|
FunctionalBridge.setAuthParams(result);
|
||||||
loginData = { pp: result.playerProfile , accessToken: result.accessToken, permissions: result.permissions,
|
loginData = {
|
||||||
auth_type: settings.auth};
|
pp: result.playerProfile,
|
||||||
|
accessToken: result.accessToken,
|
||||||
|
permissions: result.permissions,
|
||||||
|
auth_type: settings.auth
|
||||||
|
};
|
||||||
|
|
||||||
overlay.hide(0, function () {
|
overlay.hide(0, function() {
|
||||||
setCurrentScene(menuScene);
|
setCurrentScene(menuScene);
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
|
@ -355,10 +359,8 @@ function doUpdate(profile, pp, accessToken) {
|
||||||
|
|
||||||
function doLaunchClient(assetDir, assetHDir, clientDir, clientHDir, profile, pp, accessToken) {
|
function doLaunchClient(assetDir, assetHDir, clientDir, clientHDir, profile, pp, accessToken) {
|
||||||
processing.resetOverlay();
|
processing.resetOverlay();
|
||||||
overlay.swap(0, processing.overlay, function(event)
|
overlay.swap(0, processing.overlay, function(event) launchClient(assetHDir, clientHDir, profile, new ClientLauncherParams(settings.lastDigest,
|
||||||
launchClient(assetHDir, clientHDir, profile, new ClientLauncherParams(settings.lastDigest,
|
assetDir, clientDir, pp, accessToken, settings.autoEnter, settings.fullScreen, settings.ram, 0, 0), doDebugClient));
|
||||||
assetDir, clientDir, pp, accessToken, settings.autoEnter, settings.fullScreen, settings.ram, 0, 0), doDebugClient)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function doDebugClient(process) {
|
function doDebugClient(process) {
|
||||||
|
@ -398,10 +400,10 @@ function updateProfilesList(profiles) {
|
||||||
if (profile.getOptional() != null) profile.updateOptionalGraph();
|
if (profile.getOptional() != null) profile.updateOptionalGraph();
|
||||||
index++;
|
index++;
|
||||||
});
|
});
|
||||||
LogHelper.debug("Load selected %d profile",settings.profile);
|
LogHelper.debug("Load selected %d profile", settings.profile);
|
||||||
if(profiles.length > 0) {
|
if (profiles.length > 0) {
|
||||||
if(settings.profile >= profiles.length)
|
if (settings.profile >= profiles.length)
|
||||||
settings.profile = profiles.length-1;
|
settings.profile = profiles.length - 1;
|
||||||
serverHolder.set(serverList.getChildren().get(settings.profile));
|
serverHolder.set(serverList.getChildren().get(settings.profile));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -412,11 +414,11 @@ function pingServer(btn) {
|
||||||
var task = newTask(function() pingers[profile].ping());
|
var task = newTask(function() pingers[profile].ping());
|
||||||
task.setOnSucceeded(function(event) {
|
task.setOnSucceeded(function(event) {
|
||||||
var result = task.getValue();
|
var result = task.getValue();
|
||||||
if(btn==serverHolder.old){
|
if (btn == serverHolder.old) {
|
||||||
setServerStatus(java.lang.String.format("%d из %d", result.onlinePlayers, result.maxPlayers));
|
setServerStatus(java.lang.String.format("%d из %d", result.onlinePlayers, result.maxPlayers));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
task.setOnFailed(function(event){ if(btn==serverHolder.old){setServerStatus("Недоступен")}});
|
task.setOnFailed(function(event) { if (btn == serverHolder.old) { setServerStatus("Недоступен") } });
|
||||||
startTask(task);
|
startTask(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -482,7 +484,7 @@ var overlay = {
|
||||||
fade(overlay.current, delay, 1.0, 0.0, function(event) {
|
fade(overlay.current, delay, 1.0, 0.0, function(event) {
|
||||||
dimPane.requestFocus();
|
dimPane.requestFocus();
|
||||||
|
|
||||||
if(overlay.current==null){
|
if (overlay.current == null) {
|
||||||
overlay.show(newOverlay, onFinished);
|
overlay.show(newOverlay, onFinished);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -504,13 +506,13 @@ var overlay = {
|
||||||
var serverHolder = {
|
var serverHolder = {
|
||||||
old: null,
|
old: null,
|
||||||
|
|
||||||
set: function(btn){
|
set: function(btn) {
|
||||||
pingServer(btn);
|
pingServer(btn);
|
||||||
serverLabel.setText(profilesList[btn]);
|
serverLabel.setText(profilesList[btn]);
|
||||||
serverDescription.setText(profilesList[btn].info);
|
serverDescription.setText(profilesList[btn].info);
|
||||||
btn.setSelected(true);
|
btn.setSelected(true);
|
||||||
btn.setDisable(true);
|
btn.setDisable(true);
|
||||||
if(serverHolder.old!=null){
|
if (serverHolder.old != null) {
|
||||||
serverHolder.old.setSelected(false);
|
serverHolder.old.setSelected(false);
|
||||||
serverHolder.old.setDisable(false);
|
serverHolder.old.setDisable(false);
|
||||||
}
|
}
|
||||||
|
|
BIN
Launcher/runtime/dialog/images/icons/back.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
Launcher/runtime/dialog/images/icons/close.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
Launcher/runtime/dialog/images/icons/console.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
Launcher/runtime/dialog/images/icons/discord.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
Launcher/runtime/dialog/images/icons/hide.png
Normal file
After Width: | Height: | Size: 2 KiB |
BIN
Launcher/runtime/dialog/images/icons/list.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
Launcher/runtime/dialog/images/icons/settings.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
|
@ -1,16 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8"/>
|
|
||||||
<title>Offline-режим</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body style="color:red">
|
|
||||||
<h2>Offline-режим</h2>
|
|
||||||
Лаунчер запущен в Offline-режиме. В этом режиме Вы можете запустить любой ранее загруженный клиент
|
|
||||||
с любым именем пользователя, при этом вход на серверы с авторизацией, а так же система скинов и плащей <b>может не
|
|
||||||
работать</b>.
|
|
||||||
Скорее всего, проблема вызвана сбоем на сервере или неполадками в интернет-подключении.
|
|
||||||
Проверьте состояние интернет-подключения или обратитесь к администратору сервера.
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -4,55 +4,54 @@ Button {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Outputs */
|
/* Outputs */
|
||||||
#overlay > #output,
|
#overlay>#output,
|
||||||
#background > #output {
|
#background>#output {
|
||||||
-fx-background-color: white;
|
-fx-background-color: white;
|
||||||
-fx-background-radius: 0;
|
-fx-background-radius: 0;
|
||||||
-fx-font-family: monospace;
|
-fx-font-family: monospace;
|
||||||
-fx-font-size: 8pt;
|
-fx-font-size: 8pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
#overlay > #output .content,
|
#overlay>#output .content,
|
||||||
#background > #output .content {
|
#background>#output .content {
|
||||||
-fx-background-color: white;
|
-fx-background-color: white;
|
||||||
-fx-background-radius: 0;
|
-fx-background-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Close button */
|
/* Close button */
|
||||||
#overlay > #copy,
|
#overlay>#copy,
|
||||||
#overlay > #action.close {
|
#overlay>#action.close {
|
||||||
-fx-background-radius: 0;
|
-fx-background-radius: 0;
|
||||||
-fx-text-fill: white;
|
-fx-text-fill: white;
|
||||||
-fx-background-position: center;
|
-fx-background-position: center;
|
||||||
-jfx-button-type: FLAT;
|
|
||||||
-fx-background-color: #2d83ce;
|
-fx-background-color: #2d83ce;
|
||||||
-fx-pref-width: 150px;
|
-fx-pref-width: 150px;
|
||||||
-fx-pref-height: 25px;
|
-fx-pref-height: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#overlay > #copy:hover,
|
#overlay>#copy:hover,
|
||||||
#overlay > #copy:focused,
|
#overlay>#copy:focused,
|
||||||
#overlay > #action.close:hover,
|
#overlay>#action.close:hover,
|
||||||
#overlay > #action.close:focused,
|
#overlay>#action.close:focused,
|
||||||
#overlay > #copy:pressed,
|
#overlay>#copy:pressed,
|
||||||
#overlay > #action.close:pressed {
|
#overlay>#action.close:pressed {
|
||||||
-fx-background-color: #1568ce;
|
-fx-background-color: #1568ce;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Kill button */
|
/* Kill button */
|
||||||
#overlay > #action.kill {
|
#overlay>#action.kill {
|
||||||
-fx-background-radius: 0;
|
-fx-background-radius: 0;
|
||||||
-fx-text-fill: white;
|
-fx-text-fill: white;
|
||||||
-fx-background-position: center;
|
-fx-background-position: center;
|
||||||
-jfx-button-type: FLAT;
|
|
||||||
-fx-background-color: #CE5757;
|
-fx-background-color: #CE5757;
|
||||||
-fx-pref-width: 150px;
|
-fx-pref-width: 150px;
|
||||||
-fx-pref-height: 25px;
|
-fx-pref-height: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#overlay > #action.kill:hover,
|
#overlay>#action.kill:hover,
|
||||||
#overlay > #action.kill:focused,
|
#overlay>#action.kill:focused,
|
||||||
#overlay > #action.kill:pressed {
|
#overlay>#action.kill:pressed {
|
||||||
-fx-background-color: #DB5252;
|
-fx-background-color: #DB5252;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-- DrLeonardo Design --*/
|
/*-- DrLeonardo Design --*/
|
|
@ -1,27 +1,28 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
<?import javafx.scene.control.Button?>
|
|
||||||
<?import javafx.scene.control.TextArea?>
|
|
||||||
<?import java.net.URL?>
|
<?import java.net.URL?>
|
||||||
<?import javafx.geometry.Insets?>
|
<?import javafx.geometry.Insets?>
|
||||||
|
<?import javafx.scene.control.Button?>
|
||||||
|
<?import javafx.scene.control.Label?>
|
||||||
|
<?import javafx.scene.control.TextArea?>
|
||||||
<?import javafx.scene.layout.Pane?>
|
<?import javafx.scene.layout.Pane?>
|
||||||
|
|
||||||
<!-- DrLeonardo Design -->
|
<!-- DrLeonardo Design -->
|
||||||
|
|
||||||
<Pane fx:id="overlay" prefHeight="450.0" prefWidth="693.0" xmlns="http://javafx.com/javafx/8.0.201"
|
<Pane fx:id="overlay" prefHeight="450.0" prefWidth="693.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
xmlns:fx="http://javafx.com/fxml/1">
|
|
||||||
<stylesheets>
|
<stylesheets>
|
||||||
<URL value="@debug.css"/>
|
<URL value="@debug.css" />
|
||||||
<URL value="@../../styles.css"/>
|
<URL value="@../../styles.css" />
|
||||||
</stylesheets>
|
</stylesheets>
|
||||||
|
|
||||||
<!-- Debug controls -->
|
<!-- Debug controls -->
|
||||||
<TextArea fx:id="output" prefHeight="450.0" prefWidth="693.0">
|
<TextArea fx:id="output" prefHeight="405.0" prefWidth="693.0">
|
||||||
<padding>
|
<padding>
|
||||||
<Insets left="10.0" right="10.0"/>
|
<Insets left="10.0" right="10.0" />
|
||||||
</padding>
|
</padding>
|
||||||
</TextArea>
|
</TextArea>
|
||||||
<Button fx:id="copy" defaultButton="true" layoutX="373.0" layoutY="415.0" prefHeight="30.0" prefWidth="100.0"
|
<Pane layoutY="405.0" prefHeight="45.0" prefWidth="693.0" style="-fx-background-color: #ffffff;" />
|
||||||
text="Копировать"/>
|
<Button fx:id="copy" defaultButton="true" layoutX="373.0" layoutY="415.0" prefHeight="30.0" prefWidth="100.0" text="Копировать" />
|
||||||
<Button fx:id="action" layoutX="533.0" layoutY="415.0" prefHeight="25.0" prefWidth="150.0" text="Убить"/>
|
<Button fx:id="action" layoutX="533.0" layoutY="415.0" prefHeight="25.0" prefWidth="150.0" text="Убить" />
|
||||||
|
<Label fx:id="version" layoutX="14.0" layoutY="419.0" text="GravitLauncher" />
|
||||||
</Pane>
|
</Pane>
|
||||||
|
|
|
@ -1,9 +1,21 @@
|
||||||
var debug = {
|
var debug = {
|
||||||
overlay: null, output: null, action: null, process: null,
|
overlay: null,
|
||||||
|
output: null,
|
||||||
|
action: null,
|
||||||
|
process: null,
|
||||||
|
|
||||||
initOverlay: function() {
|
initOverlay: function() {
|
||||||
debug.overlay = loadFXML("dialog/overlay/debug/debug.fxml");
|
debug.overlay = loadFXML("dialog/overlay/debug/debug.fxml");
|
||||||
|
|
||||||
|
debug.overlay.lookup("#version").setText(
|
||||||
|
java.lang.String.format(
|
||||||
|
"%s | Java %s x%s",
|
||||||
|
FunctionalBridge.getLauncherVersion(),
|
||||||
|
java.lang.System.getProperty("java.version"),
|
||||||
|
JVMHelper.JVM_BITS
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
debug.output = debug.overlay.lookup("#output");
|
debug.output = debug.overlay.lookup("#output");
|
||||||
debug.output.setEditable(false);
|
debug.output.setEditable(false);
|
||||||
|
|
||||||
|
@ -38,8 +50,7 @@ var debug = {
|
||||||
|
|
||||||
append: function(text) {
|
append: function(text) {
|
||||||
//Experimental Feature
|
//Experimental Feature
|
||||||
if(debug.output.getText().length() > 32000 /* Max length */)
|
if (debug.output.getText().length() > 32000 /* Max length */ ) {
|
||||||
{
|
|
||||||
debug.output.deleteText(0, text.length());
|
debug.output.deleteText(0, text.length());
|
||||||
}
|
}
|
||||||
debug.output.appendText(text);
|
debug.output.appendText(text);
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
/*-- DrLeonardo Design --*/
|
/*-- DrLeonardo Design --*/
|
||||||
#overlay > #description {
|
#overlay>#description {
|
||||||
-fx-font-size: 12pt;
|
-fx-font-size: 12pt;
|
||||||
-fx-text-fill: #fff;
|
-fx-text-fill: #fff;
|
||||||
-fx-wrap-text: true;
|
-fx-wrap-text: true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#overlay > #description.error {
|
#overlay>#description.error {
|
||||||
-fx-text-fill: red;
|
-fx-text-fill: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-- DrLeonardo Design --*/
|
/*-- DrLeonardo Design --*/
|
|
@ -1,6 +1,9 @@
|
||||||
var processing = {
|
var processing = {
|
||||||
overlay: null, spinner: null, description: null,
|
overlay: null,
|
||||||
processingImage: null, errorImage: null,
|
spinner: null,
|
||||||
|
description: null,
|
||||||
|
processingImage: null,
|
||||||
|
errorImage: null,
|
||||||
|
|
||||||
initOverlay: function() {
|
initOverlay: function() {
|
||||||
processing.overlay = loadFXML("dialog/overlay/processing/processing.fxml");
|
processing.overlay = loadFXML("dialog/overlay/processing/processing.fxml");
|
||||||
|
@ -69,6 +72,7 @@ function makeLauncherRequest(callback) {
|
||||||
task.updateMessage("Обновление лаунчера");
|
task.updateMessage("Обновление лаунчера");
|
||||||
startTask(task);
|
startTask(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeProfilesRequest(callback) {
|
function makeProfilesRequest(callback) {
|
||||||
var task = newRequestTask(new ProfilesRequest());
|
var task = newRequestTask(new ProfilesRequest());
|
||||||
|
|
||||||
|
@ -83,6 +87,7 @@ function makeProfilesRequest(callback) {
|
||||||
task.updateMessage("Обновление профилей");
|
task.updateMessage("Обновление профилей");
|
||||||
startTask(task);
|
startTask(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeAuthAvailabilityRequest(callback) {
|
function makeAuthAvailabilityRequest(callback) {
|
||||||
var task = newRequestTask(new GetAvailabilityAuthRequest());
|
var task = newRequestTask(new GetAvailabilityAuthRequest());
|
||||||
|
|
||||||
|
@ -98,6 +103,7 @@ function makeAuthAvailabilityRequest(callback) {
|
||||||
task.updateMessage("Обновление способов авторизации");
|
task.updateMessage("Обновление способов авторизации");
|
||||||
startTask(task);
|
startTask(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeSetProfileRequest(profile, callback) {
|
function makeSetProfileRequest(profile, callback) {
|
||||||
var task = newRequestTask(new SetProfileRequest(profile));
|
var task = newRequestTask(new SetProfileRequest(profile));
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,19 @@
|
||||||
/*-- DrLeonardo Design --*/
|
/*-- DrLeonardo Design --*/
|
||||||
|
|
||||||
#holder {
|
#holder {
|
||||||
-fx-background-color: #fff;
|
-fx-background-color: #fff;
|
||||||
}
|
}
|
||||||
#holder > #transferDialog {
|
|
||||||
|
#holder>#transferDialog {
|
||||||
-fx-background-color: rgba(0, 0, 0, 0.5);
|
-fx-background-color: rgba(0, 0, 0, 0.5);
|
||||||
-fx-pref-width: 694px;
|
-fx-pref-width: 694px;
|
||||||
-fx-pref-height: 425px;
|
-fx-pref-height: 425px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Labels */
|
/* Labels */
|
||||||
#holder > #settingsTitle {
|
|
||||||
|
#holder>#settingsTitle {
|
||||||
-fx-font-size: 14pt;
|
-fx-font-size: 14pt;
|
||||||
-fx-alignment: baseline-center;
|
-fx-alignment: baseline-center;
|
||||||
}
|
}
|
||||||
|
@ -19,66 +24,77 @@ #holder #dirChange {
|
||||||
-fx-font-weight: bold;
|
-fx-font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* RAM slider */
|
/* RAM slider */
|
||||||
#holder > #ramSlider > .track {
|
|
||||||
|
#holder>#ramSlider>.track {
|
||||||
-fx-background-color: #909090;
|
-fx-background-color: #909090;
|
||||||
}
|
}
|
||||||
|
|
||||||
#holder > #ramSlider > .thumb {
|
#holder>#ramSlider>.thumb {
|
||||||
-fx-background-color: #5fd97a;
|
-fx-background-color: #5fd97a;
|
||||||
}
|
}
|
||||||
|
|
||||||
#holder > #ramSlider > .colored-track {
|
#holder>#ramSlider>.colored-track {
|
||||||
-fx-background-color: #5fd97a;
|
-fx-background-color: #5fd97a;
|
||||||
}
|
}
|
||||||
|
|
||||||
#holder > #ramSlider > .animated-thumb {
|
#holder>#ramSlider>.animated-thumb {
|
||||||
-fx-background-color: #5fd97a;
|
-fx-background-color: #5fd97a;
|
||||||
}
|
}
|
||||||
|
|
||||||
#holder > #ramSlider > .slider-value {
|
#holder>#ramSlider>.slider-value {
|
||||||
-fx-fill: white;
|
-fx-fill: white;
|
||||||
-fx-stroke: white;
|
-fx-stroke: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Dir options */
|
/* Dir options */
|
||||||
#holder > #deleteDir, #cancelTransfer {
|
|
||||||
|
#holder>#deleteDir,
|
||||||
|
#cancelTransfer {
|
||||||
-fx-background-radius: 0;
|
-fx-background-radius: 0;
|
||||||
-fx-text-fill: white;
|
-fx-text-fill: white;
|
||||||
-fx-background-position: center;
|
-fx-background-position: center;
|
||||||
-jfx-button-type: FLAT;
|
|
||||||
-fx-background-color: #CE5757;
|
-fx-background-color: #CE5757;
|
||||||
-fx-pref-width: 150px;
|
-fx-pref-width: 150px;
|
||||||
-fx-pref-height: 25px;
|
-fx-pref-height: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#holder > #deleteDir:hover,#cancelTransfer:hover,
|
#holder>#deleteDir:hover,
|
||||||
#holder > #deleteDir:focused,#cancelTransfer:focused {
|
#cancelTransfer:hover,
|
||||||
|
#holder>#deleteDir:focused,
|
||||||
|
#cancelTransfer:focused {
|
||||||
-fx-background-color: #DB5252;
|
-fx-background-color: #DB5252;
|
||||||
}
|
}
|
||||||
|
|
||||||
#holder > #changeDir {
|
#holder>#changeDir {
|
||||||
-fx-background-color: transparent;
|
-fx-background-color: transparent;
|
||||||
-fx-text-fill: #909090;
|
-fx-text-fill: #909090;
|
||||||
-fx-background-radius: 0;
|
-fx-background-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#holder > #changeDir:focused,
|
#holder>#changeDir:focused,
|
||||||
#holder > #changeDir:pressed {
|
#holder>#changeDir:pressed {
|
||||||
-fx-font-weight: bold;
|
-fx-font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
#holder > #apply,#applyTransfer{
|
#holder>#apply,
|
||||||
|
#applyTransfer {
|
||||||
-fx-background-color: #5fd97a;
|
-fx-background-color: #5fd97a;
|
||||||
-fx-background-radius: 0;
|
-fx-background-radius: 0;
|
||||||
-fx-text-fill: white;
|
-fx-text-fill: white;
|
||||||
-fx-background-position: center;
|
-fx-background-position: center;
|
||||||
-jfx-button-type: FLAT;
|
|
||||||
-fx-pref-width: 150px;
|
-fx-pref-width: 150px;
|
||||||
-fx-pref-height: 25px;
|
-fx-pref-height: 25px;
|
||||||
}
|
}
|
||||||
#holder > #apply:hover,#applyTransfer:hover,
|
|
||||||
#holder > #apply:focused,#applyTransfer:focused{
|
#holder>#apply:hover,
|
||||||
|
#applyTransfer:hover,
|
||||||
|
#holder>#apply:focused,
|
||||||
|
#applyTransfer:focused {
|
||||||
-fx-background-color: #75e18c;
|
-fx-background-color: #75e18c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-- DrLeonardo Design --*/
|
/*-- DrLeonardo Design --*/
|
|
@ -1,10 +1,11 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import java.net.URL?>
|
||||||
<?import javafx.scene.control.Button?>
|
<?import javafx.scene.control.Button?>
|
||||||
<?import javafx.scene.control.CheckBox?>
|
<?import javafx.scene.control.CheckBox?>
|
||||||
<?import javafx.scene.control.Slider?>
|
|
||||||
<?import java.net.URL?>
|
|
||||||
<?import javafx.scene.control.Hyperlink?>
|
<?import javafx.scene.control.Hyperlink?>
|
||||||
|
<?import javafx.scene.control.Label?>
|
||||||
|
<?import javafx.scene.control.Slider?>
|
||||||
<?import javafx.scene.layout.Pane?>
|
<?import javafx.scene.layout.Pane?>
|
||||||
<?import javafx.scene.shape.Line?>
|
<?import javafx.scene.shape.Line?>
|
||||||
<?import javafx.scene.text.Font?>
|
<?import javafx.scene.text.Font?>
|
||||||
|
@ -13,16 +14,22 @@
|
||||||
|
|
||||||
<!-- DrLeonardo Design -->
|
<!-- DrLeonardo Design -->
|
||||||
|
|
||||||
<Pane fx:id="overlay" prefHeight="450.0" prefWidth="693.0" xmlns="http://javafx.com/javafx/8.0.201" xmlns:fx="http://javafx.com/fxml/1">
|
<Pane fx:id="overlay" prefHeight="450.0" prefWidth="693.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
<children>
|
<children>
|
||||||
<Pane id="holder" prefHeight="450.0" prefWidth="694.0">
|
<Pane id="holder" prefHeight="450.0" prefWidth="694.0">
|
||||||
<children>
|
<children>
|
||||||
<CheckBox fx:id="autoEnter" layoutX="14.0" layoutY="137.0" text="Автовход на сервер" />
|
<CheckBox fx:id="autoEnter" layoutX="28.0" layoutY="169.0" text="Автовход на сервер">
|
||||||
<Text fill="#8c8c8c" layoutX="40.0" layoutY="153.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Включение авто-входа означает что вы сразу после загрузки клиента попадете на сервер" wrappingWidth="636.9999872148037" y="15.0" />
|
<font>
|
||||||
<CheckBox fx:id="fullScreen" layoutX="13.0" layoutY="244.0" text="Клиент в полный экран" />
|
<Font size="13.0" />
|
||||||
<Text fill="#8c8c8c" layoutX="40.0" layoutY="261.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Включение данной функции позволяет запустить игру сразу в полноэкранном режиме" wrappingWidth="636.9999872148037" y="15.0" />
|
</font></CheckBox>
|
||||||
<CheckBox id="debug" layoutX="13.0" layoutY="183.0" text="Режим Отладки" />
|
<CheckBox fx:id="fullScreen" layoutX="28.0" layoutY="229.0" text="Клиент в полный экран">
|
||||||
<Text fill="#8c8c8c" layoutX="40.0" layoutY="198.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Режим отладки позволяет просмотреть лог запуска и работы программы в реальном времени прямо из лаунчера, что упрощает поиск нужной информации" wrappingWidth="637.0000016447157" y="15.0" />
|
<font>
|
||||||
|
<Font size="13.0" />
|
||||||
|
</font></CheckBox>
|
||||||
|
<CheckBox id="debug" layoutX="28.0" layoutY="199.0" text="Режим Отладки">
|
||||||
|
<font>
|
||||||
|
<Font size="13.0" />
|
||||||
|
</font></CheckBox>
|
||||||
<TextFlow layoutX="126.0" layoutY="15.0" prefHeight="16.0" prefWidth="112.0">
|
<TextFlow layoutX="126.0" layoutY="15.0" prefHeight="16.0" prefWidth="112.0">
|
||||||
<Text fx:id="ramLabel" />
|
<Text fx:id="ramLabel" />
|
||||||
</TextFlow>
|
</TextFlow>
|
||||||
|
@ -44,8 +51,20 @@
|
||||||
</children>
|
</children>
|
||||||
</Pane>
|
</Pane>
|
||||||
<Line endX="594.0" layoutX="100.0" layoutY="420.0" startX="-100.0" stroke="#5b3636" styleClass="lineHead" />
|
<Line endX="594.0" layoutX="100.0" layoutY="420.0" startX="-100.0" stroke="#5b3636" styleClass="lineHead" />
|
||||||
<CheckBox fx:id="featureStore" layoutX="13.0" layoutY="292.0" text="Поиск файлов в других клиентах" />
|
<CheckBox fx:id="featureStore" layoutX="28.0" layoutY="259.0" text="Поиск файлов в других клиентах">
|
||||||
<Text fill="#8c8c8c" layoutX="40.0" layoutY="309.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Используется для экономии вашего трафика, аналогичные файлы будут скопированы с других игровых клиентов" wrappingWidth="636.9999872148037" y="15.0" />
|
<font>
|
||||||
|
<Font size="13.0" />
|
||||||
|
</font></CheckBox>
|
||||||
|
<Text fx:id="description" layoutX="317.0" layoutY="208.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Режим отладки позволяет просмотреть лог запуска и работы программы в реальном времени прямо из лаунчера, что упрощает поиск нужной информации" wrappingWidth="260.888671875">
|
||||||
|
<font>
|
||||||
|
<Font size="13.0" />
|
||||||
|
</font>
|
||||||
|
</Text>
|
||||||
|
<Label fx:id="descLabel" layoutX="317.0" layoutY="169.0" text="Режим отладки">
|
||||||
|
<font>
|
||||||
|
<Font name="System Bold" size="14.0" />
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
</children>
|
</children>
|
||||||
</Pane>
|
</Pane>
|
||||||
</children>
|
</children>
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
var settingsOverlay = {
|
var settingsOverlay = {
|
||||||
/* ===================== OVERLAY ===================== */
|
/* ===================== OVERLAY ===================== */
|
||||||
overlay: null, ramLabel: null, dirLabel: null, transferDialog: null,
|
overlay: null,
|
||||||
deleteDirPressedAgain: false, count: 0,
|
ramLabel: null,
|
||||||
|
dirLabel: null,
|
||||||
|
transferDialog: null,
|
||||||
|
deleteDirPressedAgain: false,
|
||||||
|
count: 0,
|
||||||
|
descLabel: null,
|
||||||
|
description: null,
|
||||||
|
|
||||||
initOverlay: function() {
|
initOverlay: function() {
|
||||||
settingsOverlay.overlay = loadFXML("dialog/overlay/settings/settings.fxml");
|
settingsOverlay.overlay = loadFXML("dialog/overlay/settings/settings.fxml");
|
||||||
|
@ -12,10 +18,12 @@ var settingsOverlay = {
|
||||||
autoEnterBox.setSelected(settings.autoEnter);
|
autoEnterBox.setSelected(settings.autoEnter);
|
||||||
autoEnterBox.selectedProperty()["addListener(javafx.beans.value.ChangeListener)"](
|
autoEnterBox.selectedProperty()["addListener(javafx.beans.value.ChangeListener)"](
|
||||||
function(o, ov, nv) settings.autoEnter = nv);
|
function(o, ov, nv) settings.autoEnter = nv);
|
||||||
|
autoEnterBox.setOnMouseEntered(function() {
|
||||||
|
settingsOverlay.updateDesc(autoEnterBox.getText(), "Включение авто-входа означает что вы сразу после загрузки клиента попадете на сервер");
|
||||||
|
});
|
||||||
|
|
||||||
settingsOverlay.dirLabel = holder.lookup("#dirLabel");
|
settingsOverlay.dirLabel = holder.lookup("#dirLabel");
|
||||||
settingsOverlay.dirLabel.setOnAction(function(event)
|
settingsOverlay.dirLabel.setOnAction(function(event) app.getHostServices().showDocument(settings.updatesDir.toUri()));
|
||||||
app.getHostServices().showDocument(settings.updatesDir.toUri()));
|
|
||||||
settingsOverlay.updateDirLabel();
|
settingsOverlay.updateDirLabel();
|
||||||
|
|
||||||
settingsOverlay.transferDialog = holder.lookup("#transferDialog");
|
settingsOverlay.transferDialog = holder.lookup("#transferDialog");
|
||||||
|
@ -33,15 +41,24 @@ var settingsOverlay = {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.descLabel = holder.lookup("#descLabel");
|
||||||
|
this.description = holder.lookup("#description");
|
||||||
|
|
||||||
var featureStore = holder.lookup("#featureStore");
|
var featureStore = holder.lookup("#featureStore");
|
||||||
featureStore.setSelected(settings.featureStore);
|
featureStore.setSelected(settings.featureStore);
|
||||||
featureStore.selectedProperty()["addListener(javafx.beans.value.ChangeListener)"](
|
featureStore.selectedProperty()["addListener(javafx.beans.value.ChangeListener)"](
|
||||||
function(o, ov, nv) settings.featureStore = nv);
|
function(o, ov, nv) settings.featureStore = nv);
|
||||||
|
featureStore.setOnMouseEntered(function() {
|
||||||
|
settingsOverlay.updateDesc(featureStore.getText(), "Используется для экономии вашего трафика, аналогичные файлы будут скопированы с других игровых клиентов");
|
||||||
|
});
|
||||||
|
|
||||||
var fullScreenBox = holder.lookup("#fullScreen");
|
var fullScreenBox = holder.lookup("#fullScreen");
|
||||||
fullScreenBox.setSelected(settings.fullScreen);
|
fullScreenBox.setSelected(settings.fullScreen);
|
||||||
fullScreenBox.selectedProperty()["addListener(javafx.beans.value.ChangeListener)"](
|
fullScreenBox.selectedProperty()["addListener(javafx.beans.value.ChangeListener)"](
|
||||||
function(o, ov, nv) settings.fullScreen = nv);
|
function(o, ov, nv) settings.fullScreen = nv);
|
||||||
|
fullScreenBox.setOnMouseEntered(function() {
|
||||||
|
settingsOverlay.updateDesc(fullScreenBox.getText(), "Включение данной функции позволяет запустить игру сразу в полноэкранном режиме");
|
||||||
|
});
|
||||||
|
|
||||||
settingsOverlay.ramLabel = holder.lookup("#ramLabel");
|
settingsOverlay.ramLabel = holder.lookup("#ramLabel");
|
||||||
settingsOverlay.updateRAMLabel();
|
settingsOverlay.updateRAMLabel();
|
||||||
|
@ -70,16 +87,16 @@ var settingsOverlay = {
|
||||||
|
|
||||||
settingsOverlay.deleteUpdatesDir();
|
settingsOverlay.deleteUpdatesDir();
|
||||||
settingsOverlay.deleteDirPressedAgain = false;
|
settingsOverlay.deleteDirPressedAgain = false;
|
||||||
settingsOverlay.count = settingsOverlay.count+1;
|
settingsOverlay.count = settingsOverlay.count + 1;
|
||||||
if(settingsOverlay.count>9){
|
if (settingsOverlay.count > 9) {
|
||||||
javafx.application.Platform.exit();
|
javafx.application.Platform.exit();
|
||||||
}
|
}
|
||||||
deleteDirButton.setText(
|
deleteDirButton.setText(
|
||||||
settingsOverlay.count>8?"Прощай :(":
|
settingsOverlay.count > 8 ? "Прощай :(" :
|
||||||
(settingsOverlay.count>7?"Я умираю!":
|
(settingsOverlay.count > 7 ? "Я умираю!" :
|
||||||
(settingsOverlay.count>5?"DeathCry, спаси!":
|
(settingsOverlay.count > 5 ? "DeathCry, спаси!" :
|
||||||
(settingsOverlay.count>4?"Умоляю, перестань!":
|
(settingsOverlay.count > 4 ? "Умоляю, перестань!" :
|
||||||
(settingsOverlay.count>3?"Да хорош уже!":"Ещё раз")
|
(settingsOverlay.count > 3 ? "Да хорош уже!" : "Ещё раз")
|
||||||
))));
|
))));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -87,14 +104,25 @@ var settingsOverlay = {
|
||||||
debugBox.setSelected(settings.debug);
|
debugBox.setSelected(settings.debug);
|
||||||
debugBox.selectedProperty()["addListener(javafx.beans.value.ChangeListener)"](
|
debugBox.selectedProperty()["addListener(javafx.beans.value.ChangeListener)"](
|
||||||
function(o, ov, nv) settings.debug = nv);
|
function(o, ov, nv) settings.debug = nv);
|
||||||
|
debugBox.setOnMouseEntered(function() {
|
||||||
|
settingsOverlay.updateDesc(debugBox.getText(), "Режим отладки позволяет просмотреть лог запуска и работы программы в реальном времени прямо из лаунчера, что упрощает поиск нужной информации");
|
||||||
|
});
|
||||||
|
|
||||||
holder.lookup("#apply").setOnAction(function(event) overlay.hide(0, null));
|
holder.lookup("#apply").setOnAction(function(event) overlay.hide(0, null));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
updateDesc: function(label, desc) {
|
||||||
|
//На случай если человек решил избавится от этой фишки
|
||||||
|
if (this.descLabel == null) return;
|
||||||
|
if (this.description == null) return;
|
||||||
|
|
||||||
|
this.descLabel.setText(label);
|
||||||
|
this.description.setText(desc);
|
||||||
|
},
|
||||||
|
|
||||||
transferCatalogDialog: function(newDir) {
|
transferCatalogDialog: function(newDir) {
|
||||||
settingsOverlay.transferDialog.setVisible(true);
|
settingsOverlay.transferDialog.setVisible(true);
|
||||||
settingsOverlay.transferDialog.lookup("#cancelTransfer").setOnAction(function(event)
|
settingsOverlay.transferDialog.lookup("#cancelTransfer").setOnAction(function(event) {
|
||||||
{
|
|
||||||
settings.updatesDir = newDir;
|
settings.updatesDir = newDir;
|
||||||
DirBridge.dirUpdates = settings.updatesDir;
|
DirBridge.dirUpdates = settings.updatesDir;
|
||||||
settingsOverlay.updateDirLabel();
|
settingsOverlay.updateDirLabel();
|
||||||
|
@ -133,9 +161,9 @@ var settingsOverlay = {
|
||||||
|
|
||||||
|
|
||||||
setRAM: function(ram) {
|
setRAM: function(ram) {
|
||||||
if (ram>762&&ram<1024){
|
if (ram > 762 && ram < 1024) {
|
||||||
settings.ram = java.lang.Math["min(int,int)"](ram, FunctionalBridge.getJVMTotalMemory());
|
settings.ram = java.lang.Math["min(int,int)"](ram, FunctionalBridge.getJVMTotalMemory());
|
||||||
}else{
|
} else {
|
||||||
settings.ram = java.lang.Math["min(int,int)"](((ram / 256) | 0) * 256, FunctionalBridge.getJVMTotalMemory());
|
settings.ram = java.lang.Math["min(int,int)"](((ram / 256) | 0) * 256, FunctionalBridge.getJVMTotalMemory());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -148,9 +176,16 @@ LogHelper.debug("Dir: %s", DirBridge.dir);
|
||||||
|
|
||||||
/* ====================== CLI PARAMS ===================== */
|
/* ====================== CLI PARAMS ===================== */
|
||||||
var cliParams = {
|
var cliParams = {
|
||||||
login: null, password: null, profile: -1, autoLogin: false,
|
login: null,
|
||||||
updatesDir: null, autoEnter: null, fullScreen: null, ram: -1,
|
password: null,
|
||||||
offline: false, featureStore: null,
|
profile: -1,
|
||||||
|
autoLogin: false,
|
||||||
|
updatesDir: null,
|
||||||
|
autoEnter: null,
|
||||||
|
fullScreen: null,
|
||||||
|
ram: -1,
|
||||||
|
offline: false,
|
||||||
|
featureStore: null,
|
||||||
|
|
||||||
init: function(params) {
|
init: function(params) {
|
||||||
var named = params.getNamed();
|
var named = params.getNamed();
|
||||||
|
@ -200,8 +235,7 @@ var cliParams = {
|
||||||
if (cliParams.profile >= 0) {
|
if (cliParams.profile >= 0) {
|
||||||
settings.profile = cliParams.profile;
|
settings.profile = cliParams.profile;
|
||||||
}
|
}
|
||||||
if (cliParams.updatesDir !== null) {
|
if (cliParams.updatesDir !== null) {}
|
||||||
}
|
|
||||||
if (cliParams.autoEnter !== null) {
|
if (cliParams.autoEnter !== null) {
|
||||||
settings.autoLogin = cliParams.autoEnter;
|
settings.autoLogin = cliParams.autoEnter;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,16 +6,16 @@ #overlay {
|
||||||
-fx-background-image: url('../../images/downloader/blured.jpg');
|
-fx-background-image: url('../../images/downloader/blured.jpg');
|
||||||
}
|
}
|
||||||
|
|
||||||
#overlay > #utitle {
|
#overlay>#utitle {
|
||||||
-fx-alignment: top-left;
|
-fx-alignment: top-left;
|
||||||
}
|
}
|
||||||
|
|
||||||
#overlay > #description {
|
#overlay>#description {
|
||||||
-fx-alignment: top-left;
|
-fx-alignment: top-left;
|
||||||
-fx-wrap-text: true;
|
-fx-wrap-text: true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#overlay > #description.error {
|
#overlay>#description.error {
|
||||||
-fx-text-fill: #CE5757;
|
-fx-text-fill: #CE5757;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,15 +29,15 @@ .progress-bar {
|
||||||
-fx-background-color: transparent;
|
-fx-background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-indicator{
|
.progress-indicator {
|
||||||
-fx-background-color: transparent ;
|
-fx-background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-indicator .indicator {
|
.progress-indicator .indicator {
|
||||||
-fx-background-color: transparent ;
|
-fx-background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-bar > .bar {
|
.progress-bar>.bar {
|
||||||
-fx-background-image: url("../../images/downloader/line.png");
|
-fx-background-image: url("../../images/downloader/line.png");
|
||||||
-fx-background-color: transparent;
|
-fx-background-color: transparent;
|
||||||
-fx-background-insets: 0;
|
-fx-background-insets: 0;
|
||||||
|
@ -45,9 +45,10 @@ .progress-bar > .bar {
|
||||||
-fx-padding: 0;
|
-fx-padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-bar > .track {
|
.progress-bar>.track {
|
||||||
-fx-background-color: transparent;
|
-fx-background-color: transparent;
|
||||||
-fx-background-insets: 0;
|
-fx-background-insets: 0;
|
||||||
-fx-background-radius: 3px;
|
-fx-background-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-- DrLeonardo Design --*/
|
/*-- DrLeonardo Design --*/
|
|
@ -1,5 +1,8 @@
|
||||||
var update = {
|
var update = {
|
||||||
overlay: null, title: null, description: null, progress: null,
|
overlay: null,
|
||||||
|
title: null,
|
||||||
|
description: null,
|
||||||
|
progress: null,
|
||||||
|
|
||||||
initOverlay: function() {
|
initOverlay: function() {
|
||||||
update.overlay = loadFXML("dialog/overlay/update/update.fxml");
|
update.overlay = loadFXML("dialog/overlay/update/update.fxml");
|
||||||
|
@ -83,7 +86,7 @@ function offlineUpdateRequest(dirName, dir, matcher, digest) {
|
||||||
|
|
||||||
/* Export functions */
|
/* Export functions */
|
||||||
function makeUpdateRequest(dirName, dir, matcher, digest, callback) {
|
function makeUpdateRequest(dirName, dir, matcher, digest, callback) {
|
||||||
var request = settings.offline ? { setStateCallback: function(stateCallback) { } } :
|
var request = settings.offline ? { setStateCallback: function(stateCallback) {} } :
|
||||||
new UpdateRequest(dirName, dir, matcher, digest);
|
new UpdateRequest(dirName, dir, matcher, digest);
|
||||||
var task = settings.offline ? newTask(offlineUpdateRequest(dirName, dir, matcher, digest)) :
|
var task = settings.offline ? newTask(offlineUpdateRequest(dirName, dir, matcher, digest)) :
|
||||||
newRequestTask(request);
|
newRequestTask(request);
|
||||||
|
|
|
@ -1,54 +1,57 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import java.net.URL?>
|
||||||
|
<?import javafx.geometry.Insets?>
|
||||||
<?import javafx.scene.control.Button?>
|
<?import javafx.scene.control.Button?>
|
||||||
<?import javafx.scene.control.TextArea?>
|
<?import javafx.scene.control.TextArea?>
|
||||||
<?import javafx.scene.control.TextField?>
|
<?import javafx.scene.control.TextField?>
|
||||||
<?import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIconView?>
|
<?import javafx.scene.image.Image?>
|
||||||
<?import java.net.URL?>
|
<?import javafx.scene.image.ImageView?>
|
||||||
<?import javafx.geometry.Insets?>
|
|
||||||
<?import javafx.scene.layout.Pane?>
|
<?import javafx.scene.layout.Pane?>
|
||||||
<?import javafx.scene.shape.Line?>
|
<?import javafx.scene.shape.Line?>
|
||||||
|
|
||||||
<!-- DrLeonardo Design -->
|
<!-- DrLeonardo Design -->
|
||||||
|
|
||||||
<Pane fx:id="background" prefWidth="738.0" xmlns="http://javafx.com/javafx/8.0.201" xmlns:fx="http://javafx.com/fxml/1">
|
<Pane fx:id="background" prefWidth="738.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
<children>
|
<children>
|
||||||
<Pane fx:id="bar" layoutX="692.0" prefHeight="425.0" prefWidth="43.0" styleClass="bar">
|
<Pane fx:id="bar" layoutX="692.0" prefHeight="425.0" prefWidth="43.0" styleClass="bar">
|
||||||
<children>
|
<children>
|
||||||
<Button id="hide" alignment="CENTER" contentDisplay="CENTER" layoutY="45.0"
|
<Button id="hide" alignment="CENTER" contentDisplay="CENTER" layoutY="45.0" minHeight="-Infinity" minWidth="-Infinity" text="" textAlignment="CENTER">
|
||||||
text="" textAlignment="CENTER">
|
|
||||||
<graphic>
|
<graphic>
|
||||||
<MaterialDesignIconView fill="WHITE" glyphName="MINUS" size="30" textAlignment="CENTER"/>
|
<ImageView>
|
||||||
</graphic>
|
<image>
|
||||||
</Button>
|
<Image url="@../../images/icons/hide.png" />
|
||||||
<Button id="close" alignment="CENTER" contentDisplay="CENTER" text=""
|
</image>
|
||||||
textAlignment="CENTER">
|
</ImageView>
|
||||||
|
</graphic></Button>
|
||||||
|
<Button id="close" alignment="CENTER" contentDisplay="CENTER" minHeight="-Infinity" minWidth="-Infinity" text="" textAlignment="CENTER">
|
||||||
<graphic>
|
<graphic>
|
||||||
<MaterialDesignIconView fill="WHITE" glyphName="CLOSE" size="30" textAlignment="CENTER"/>
|
<ImageView>
|
||||||
</graphic>
|
<image>
|
||||||
</Button>
|
<Image url="@../../images/icons/close.png" />
|
||||||
|
</image>
|
||||||
|
</ImageView>
|
||||||
|
</graphic></Button>
|
||||||
</children>
|
</children>
|
||||||
</Pane>
|
</Pane>
|
||||||
<TextArea fx:id="output" prefHeight="419.0" prefWidth="692.0">
|
<TextArea fx:id="output" prefHeight="419.0" prefWidth="692.0">
|
||||||
<padding>
|
<padding>
|
||||||
<Insets left="10.0" top="10.0"/>
|
<Insets left="10.0" top="10.0" />
|
||||||
</padding>
|
</padding>
|
||||||
</TextArea>
|
</TextArea>
|
||||||
<TextField fx:id="textField" layoutY="420.0" prefHeight="30.0" prefWidth="543.0"
|
<TextField fx:id="textField" layoutY="420.0" prefHeight="30.0" prefWidth="543.0" promptText="Введите команду...">
|
||||||
promptText="Введите команду...">
|
|
||||||
<opaqueInsets>
|
<opaqueInsets>
|
||||||
<Insets/>
|
<Insets />
|
||||||
</opaqueInsets>
|
</opaqueInsets>
|
||||||
<padding>
|
<padding>
|
||||||
<Insets left="10.0"/>
|
<Insets left="10.0" />
|
||||||
</padding>
|
</padding>
|
||||||
</TextField>
|
</TextField>
|
||||||
<Button fx:id="send" defaultButton="true" layoutX="542.0" layoutY="420.0" prefHeight="30.0" prefWidth="147.0"
|
<Button fx:id="send" defaultButton="true" layoutX="542.0" layoutY="420.0" prefHeight="30.0" prefWidth="147.0" text="Выполнить" />
|
||||||
text="Выполнить"/>
|
<Line endX="594.0" layoutX="98.0" layoutY="420.0" startX="-100.0" stroke="#5b3636" styleClass="lineHead" />
|
||||||
<Line endX="594.0" layoutX="98.0" layoutY="420.0" startX="-100.0" stroke="#5b3636" styleClass="lineHead"/>
|
|
||||||
</children>
|
</children>
|
||||||
<stylesheets>
|
<stylesheets>
|
||||||
<URL value="@../../styles.css"/>
|
<URL value="@../../styles.css" />
|
||||||
<URL value="@../../overlay/debug/debug.css"/>
|
<URL value="@../../overlay/debug/debug.css" />
|
||||||
</stylesheets>
|
</stylesheets>
|
||||||
</Pane>
|
</Pane>
|
||||||
|
|
|
@ -1,19 +1,20 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import java.lang.String?>
|
||||||
|
<?import java.net.URL?>
|
||||||
<?import javafx.scene.control.Button?>
|
<?import javafx.scene.control.Button?>
|
||||||
<?import javafx.scene.control.CheckBox?>
|
<?import javafx.scene.control.CheckBox?>
|
||||||
<?import javafx.scene.control.ComboBox?>
|
<?import javafx.scene.control.ComboBox?>
|
||||||
|
<?import javafx.scene.control.Hyperlink?>
|
||||||
<?import javafx.scene.control.PasswordField?>
|
<?import javafx.scene.control.PasswordField?>
|
||||||
<?import javafx.scene.control.TextField?>
|
<?import javafx.scene.control.TextField?>
|
||||||
<?import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIconView?>
|
<?import javafx.scene.image.Image?>
|
||||||
<?import java.lang.String?>
|
<?import javafx.scene.image.ImageView?>
|
||||||
<?import java.net.URL?>
|
|
||||||
<?import javafx.scene.control.Hyperlink?>
|
|
||||||
<?import javafx.scene.layout.Pane?>
|
<?import javafx.scene.layout.Pane?>
|
||||||
|
|
||||||
<!-- DrLeonardo Design -->
|
<!-- DrLeonardo Design -->
|
||||||
|
|
||||||
<Pane fx:id="loginPane" prefWidth="740.0" xmlns="http://javafx.com/javafx/8.0.201" xmlns:fx="http://javafx.com/fxml/1">
|
<Pane fx:id="loginPane" prefWidth="740.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
<children>
|
<children>
|
||||||
<Pane fx:id="layout" prefWidth="740.0">
|
<Pane fx:id="layout" prefWidth="740.0">
|
||||||
<children>
|
<children>
|
||||||
|
@ -40,21 +41,30 @@
|
||||||
<Pane id="mask" opacity="0.0" prefHeight="450.0" prefWidth="694.0" visible="false" />
|
<Pane id="mask" opacity="0.0" prefHeight="450.0" prefWidth="694.0" visible="false" />
|
||||||
<Pane fx:id="bar" layoutX="694.0" prefHeight="425.0" prefWidth="43.0" styleClass="bar">
|
<Pane fx:id="bar" layoutX="694.0" prefHeight="425.0" prefWidth="43.0" styleClass="bar">
|
||||||
<children>
|
<children>
|
||||||
<Button id="hide" alignment="CENTER" contentDisplay="CENTER" layoutY="45.0" text="" textAlignment="CENTER">
|
<Button id="hide" alignment="CENTER" contentDisplay="CENTER" layoutY="45.0" minHeight="-Infinity" minWidth="-Infinity" text="" textAlignment="CENTER">
|
||||||
<graphic>
|
<graphic>
|
||||||
<MaterialDesignIconView fill="WHITE" glyphName="MINUS" size="30" textAlignment="CENTER" />
|
<ImageView>
|
||||||
</graphic>
|
<image>
|
||||||
</Button>
|
<Image url="@../../images/icons/hide.png" />
|
||||||
<Button id="close" alignment="CENTER" contentDisplay="CENTER" text="" textAlignment="CENTER">
|
</image>
|
||||||
|
</ImageView>
|
||||||
|
</graphic></Button>
|
||||||
|
<Button id="close" alignment="CENTER" contentDisplay="CENTER" minHeight="-Infinity" minWidth="-Infinity" text="" textAlignment="CENTER">
|
||||||
<graphic>
|
<graphic>
|
||||||
<MaterialDesignIconView fill="WHITE" glyphName="CLOSE" size="30" textAlignment="CENTER" />
|
<ImageView>
|
||||||
</graphic>
|
<image>
|
||||||
</Button>
|
<Image url="@../../images/icons/close.png" />
|
||||||
<Button id="discord" alignment="CENTER" contentDisplay="CENTER" layoutY="370.0" text="" textAlignment="CENTER">
|
</image>
|
||||||
|
</ImageView>
|
||||||
|
</graphic></Button>
|
||||||
|
<Button id="discord" alignment="CENTER" contentDisplay="CENTER" layoutY="370.0" minHeight="-Infinity" minWidth="-Infinity" text="" textAlignment="CENTER">
|
||||||
<graphic>
|
<graphic>
|
||||||
<MaterialDesignIconView fill="#5fd97a" glyphName="MESSAGE_TEXT" size="20" textAlignment="CENTER" />
|
<ImageView>
|
||||||
</graphic>
|
<image>
|
||||||
</Button>
|
<Image url="@../../images/icons/discord.png" />
|
||||||
|
</image>
|
||||||
|
</ImageView>
|
||||||
|
</graphic></Button>
|
||||||
</children>
|
</children>
|
||||||
</Pane>
|
</Pane>
|
||||||
</children>
|
</children>
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
<?import javafx.scene.control.Button?>
|
|
||||||
<?import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView?>
|
|
||||||
<?import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIconView?>
|
|
||||||
<?import java.net.URL?>
|
<?import java.net.URL?>
|
||||||
<?import javafx.geometry.Insets?>
|
<?import javafx.geometry.Insets?>
|
||||||
|
<?import javafx.scene.control.Button?>
|
||||||
<?import javafx.scene.control.Label?>
|
<?import javafx.scene.control.Label?>
|
||||||
<?import javafx.scene.control.ScrollPane?>
|
<?import javafx.scene.control.ScrollPane?>
|
||||||
|
<?import javafx.scene.image.Image?>
|
||||||
|
<?import javafx.scene.image.ImageView?>
|
||||||
<?import javafx.scene.layout.FlowPane?>
|
<?import javafx.scene.layout.FlowPane?>
|
||||||
<?import javafx.scene.layout.Pane?>
|
<?import javafx.scene.layout.Pane?>
|
||||||
<?import javafx.scene.text.Font?>
|
<?import javafx.scene.text.Font?>
|
||||||
|
|
||||||
<!-- DrLeonardo Design -->
|
<!-- DrLeonardo Design -->
|
||||||
|
|
||||||
<Pane fx:id="serverPaneLayout" maxHeight="-1.0" maxWidth="-1.0" prefWidth="740.0" visible="true" xmlns="http://javafx.com/javafx/8.0.201" xmlns:fx="http://javafx.com/fxml/1">
|
<Pane fx:id="serverPaneLayout" maxHeight="-1.0" maxWidth="-1.0" prefWidth="740.0" visible="true" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
<children>
|
<children>
|
||||||
<Pane fx:id="layout" maxHeight="-1.0" maxWidth="-1.0" prefWidth="740.0" visible="true" xmlns="http://javafx.com/javafx/8.0.201" xmlns:fx="http://javafx.com/fxml/1">
|
<Pane fx:id="layout" maxHeight="-1.0" maxWidth="-1.0" prefWidth="740.0" visible="true" xmlns="http://javafx.com/javafx/8.0.201" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
<children>
|
<children>
|
||||||
|
@ -51,9 +51,13 @@
|
||||||
<Font size="22.0" />
|
<Font size="22.0" />
|
||||||
</font>
|
</font>
|
||||||
</Button>
|
</Button>
|
||||||
<Button id="clientSettings" alignment="CENTER" centerShape="false" contentDisplay="CENTER" layoutX="305.0" layoutY="380.0" prefHeight="51.0" prefWidth="60.0" styleClass="clientSettings" text="" textAlignment="CENTER">
|
<Button id="clientSettings" alignment="CENTER" centerShape="false" contentDisplay="CENTER" layoutX="305.0" layoutY="380.0" minHeight="-Infinity" minWidth="-Infinity" prefHeight="51.0" prefWidth="60.0" styleClass="clientSettings" text="" textAlignment="CENTER">
|
||||||
<graphic>
|
<graphic>
|
||||||
<FontAwesomeIconView fill="WHITE" glyphName="SLIDERS" size="30.0" />
|
<ImageView>
|
||||||
|
<image>
|
||||||
|
<Image url="@../../images/icons/list.png" />
|
||||||
|
</image>
|
||||||
|
</ImageView>
|
||||||
</graphic></Button>
|
</graphic></Button>
|
||||||
<Label id="serverStatus" alignment="TOP_RIGHT" contentDisplay="RIGHT" layoutX="165.0" layoutY="12.0" prefHeight="25.0" prefWidth="97.0" text="12/100" textAlignment="RIGHT" textFill="WHITE">
|
<Label id="serverStatus" alignment="TOP_RIGHT" contentDisplay="RIGHT" layoutX="165.0" layoutY="12.0" prefHeight="25.0" prefWidth="97.0" text="12/100" textAlignment="RIGHT" textFill="WHITE">
|
||||||
<font>
|
<font>
|
||||||
|
@ -74,31 +78,46 @@
|
||||||
</Pane>
|
</Pane>
|
||||||
<Pane fx:id="bar" layoutX="694.0" prefHeight="425.0" prefWidth="43.0" styleClass="bar">
|
<Pane fx:id="bar" layoutX="694.0" prefHeight="425.0" prefWidth="43.0" styleClass="bar">
|
||||||
<children>
|
<children>
|
||||||
<Button id="hide" alignment="CENTER" contentDisplay="CENTER" layoutY="45.0" text="" textAlignment="CENTER">
|
<Button id="hide" alignment="CENTER" contentDisplay="CENTER" layoutY="45.0" minHeight="-Infinity" minWidth="-Infinity" text="" textAlignment="CENTER">
|
||||||
<graphic>
|
<graphic>
|
||||||
<MaterialDesignIconView fill="WHITE" glyphName="MINUS" size="30" textAlignment="CENTER" />
|
<ImageView>
|
||||||
</graphic>
|
<image>
|
||||||
</Button>
|
<Image url="@../../images/icons/hide.png" />
|
||||||
<Button id="close" alignment="CENTER" contentDisplay="CENTER" text="" textAlignment="CENTER">
|
</image>
|
||||||
|
</ImageView>
|
||||||
|
</graphic></Button>
|
||||||
|
<Button id="close" alignment="CENTER" contentDisplay="CENTER" minHeight="-Infinity" minWidth="-Infinity" text="" textAlignment="CENTER">
|
||||||
<graphic>
|
<graphic>
|
||||||
<MaterialDesignIconView fill="WHITE" glyphName="CLOSE" size="30" textAlignment="CENTER" />
|
<ImageView>
|
||||||
</graphic>
|
<image>
|
||||||
</Button>
|
<Image url="@../../images/icons/close.png" />
|
||||||
<Button id="discord" alignment="CENTER" contentDisplay="CENTER" layoutY="380.0" text="" textAlignment="CENTER">
|
</image>
|
||||||
|
</ImageView>
|
||||||
|
</graphic></Button>
|
||||||
|
<Button id="discord" alignment="CENTER" contentDisplay="CENTER" layoutY="380.0" minHeight="-Infinity" minWidth="-Infinity" text="" textAlignment="CENTER">
|
||||||
<graphic>
|
<graphic>
|
||||||
<MaterialDesignIconView fill="#5fd97a" glyphName="MESSAGE_TEXT" size="20" smooth="false" textAlignment="CENTER" />
|
<ImageView>
|
||||||
</graphic>
|
<image>
|
||||||
</Button>
|
<Image url="@../../images/icons/discord.png" />
|
||||||
<Button id="settings" alignment="CENTER" contentDisplay="CENTER" layoutY="90.0" text="" textAlignment="CENTER">
|
</image>
|
||||||
|
</ImageView>
|
||||||
|
</graphic></Button>
|
||||||
|
<Button id="settings" alignment="CENTER" contentDisplay="CENTER" layoutY="90.0" minHeight="-Infinity" minWidth="-Infinity" text="" textAlignment="CENTER">
|
||||||
<graphic>
|
<graphic>
|
||||||
<MaterialDesignIconView fill="WHITE" glyphName="SETTINGS" size="20" textAlignment="CENTER" />
|
<ImageView>
|
||||||
</graphic>
|
<image>
|
||||||
</Button>
|
<Image url="@../../images/icons/settings.png" />
|
||||||
<Button id="goConsole" alignment="CENTER" contentDisplay="CENTER" layoutY="138.0" text="" textAlignment="CENTER">
|
</image>
|
||||||
|
</ImageView>
|
||||||
|
</graphic></Button>
|
||||||
|
<Button id="goConsole" alignment="CENTER" contentDisplay="CENTER" layoutY="138.0" minHeight="-Infinity" minWidth="-Infinity" text="" textAlignment="CENTER">
|
||||||
<graphic>
|
<graphic>
|
||||||
<MaterialDesignIconView fill="WHITE" glyphName="CONSOLE" size="20" textAlignment="CENTER" />
|
<ImageView>
|
||||||
</graphic>
|
<image>
|
||||||
</Button>
|
<Image url="@../../images/icons/console.png" />
|
||||||
|
</image>
|
||||||
|
</ImageView>
|
||||||
|
</graphic></Button>
|
||||||
</children>
|
</children>
|
||||||
</Pane>
|
</Pane>
|
||||||
<Pane id="mask" opacity="0.0" prefHeight="450.0" prefWidth="694.0" visible="false" />
|
<Pane id="mask" opacity="0.0" prefHeight="450.0" prefWidth="694.0" visible="false" />
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
<?import javafx.scene.control.Button?>
|
|
||||||
<?import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIconView?>
|
|
||||||
<?import java.net.URL?>
|
<?import java.net.URL?>
|
||||||
<?import javafx.geometry.Insets?>
|
<?import javafx.geometry.Insets?>
|
||||||
|
<?import javafx.scene.control.Button?>
|
||||||
<?import javafx.scene.control.ScrollPane?>
|
<?import javafx.scene.control.ScrollPane?>
|
||||||
|
<?import javafx.scene.image.Image?>
|
||||||
|
<?import javafx.scene.image.ImageView?>
|
||||||
<?import javafx.scene.layout.Pane?>
|
<?import javafx.scene.layout.Pane?>
|
||||||
<?import javafx.scene.layout.VBox?>
|
<?import javafx.scene.layout.VBox?>
|
||||||
<?import javafx.scene.shape.Line?>
|
<?import javafx.scene.shape.Line?>
|
||||||
|
@ -13,7 +14,7 @@
|
||||||
|
|
||||||
<!-- DrLeonardo Design -->
|
<!-- DrLeonardo Design -->
|
||||||
|
|
||||||
<Pane fx:id="background" prefHeight="450.0" prefWidth="740.0" xmlns="http://javafx.com/javafx/8.0.201" xmlns:fx="http://javafx.com/fxml/1">
|
<Pane fx:id="background" prefHeight="450.0" prefWidth="740.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
<children>
|
<children>
|
||||||
<Pane id="optionsPane" prefHeight="450.0" prefWidth="692.0" styleClass="optionsPane">
|
<Pane id="optionsPane" prefHeight="450.0" prefWidth="692.0" styleClass="optionsPane">
|
||||||
<children>
|
<children>
|
||||||
|
@ -38,21 +39,30 @@
|
||||||
</Pane>
|
</Pane>
|
||||||
<Pane fx:id="bar" layoutX="694.0" prefHeight="425.0" prefWidth="43.0" styleClass="bar">
|
<Pane fx:id="bar" layoutX="694.0" prefHeight="425.0" prefWidth="43.0" styleClass="bar">
|
||||||
<children>
|
<children>
|
||||||
<Button id="hide" alignment="CENTER" contentDisplay="CENTER" layoutY="45.0" text="" textAlignment="CENTER">
|
<Button id="hide" alignment="CENTER" contentDisplay="CENTER" layoutY="45.0" minHeight="-Infinity" minWidth="-Infinity" text="" textAlignment="CENTER">
|
||||||
<graphic>
|
<graphic>
|
||||||
<MaterialDesignIconView fill="WHITE" glyphName="MINUS" size="30" textAlignment="CENTER" />
|
<ImageView>
|
||||||
</graphic>
|
<image>
|
||||||
</Button>
|
<Image url="@../../images/icons/hide.png" />
|
||||||
<Button id="close" alignment="CENTER" contentDisplay="CENTER" text="" textAlignment="CENTER">
|
</image>
|
||||||
|
</ImageView>
|
||||||
|
</graphic></Button>
|
||||||
|
<Button id="close" alignment="CENTER" contentDisplay="CENTER" minHeight="-Infinity" minWidth="-Infinity" text="" textAlignment="CENTER">
|
||||||
<graphic>
|
<graphic>
|
||||||
<MaterialDesignIconView fill="WHITE" glyphName="CLOSE" size="30" textAlignment="CENTER" />
|
<ImageView>
|
||||||
</graphic>
|
<image>
|
||||||
</Button>
|
<Image url="@../../images/icons/close.png" />
|
||||||
<Button id="back" alignment="CENTER" contentDisplay="CENTER" layoutY="405.0" text="" textAlignment="CENTER">
|
</image>
|
||||||
|
</ImageView>
|
||||||
|
</graphic></Button>
|
||||||
|
<Button id="back" alignment="CENTER" contentDisplay="CENTER" layoutY="405.0" minHeight="-Infinity" minWidth="-Infinity" text="" textAlignment="CENTER">
|
||||||
<graphic>
|
<graphic>
|
||||||
<MaterialDesignIconView fill="WHITE" glyphName="CHEVRON_LEFT" size="30" textAlignment="CENTER" />
|
<ImageView>
|
||||||
</graphic>
|
<image>
|
||||||
</Button>
|
<Image url="@../../images/icons/back.png" />
|
||||||
|
</image>
|
||||||
|
</ImageView>
|
||||||
|
</graphic></Button>
|
||||||
</children>
|
</children>
|
||||||
</Pane>
|
</Pane>
|
||||||
</children>
|
</children>
|
||||||
|
|
|
@ -5,7 +5,7 @@ var options = {
|
||||||
LogHelper.debug("Loading options file");
|
LogHelper.debug("Loading options file");
|
||||||
try {
|
try {
|
||||||
tryWithResources(new HInput(IOHelper.newInput(options.file)), options.read);
|
tryWithResources(new HInput(IOHelper.newInput(options.file)), options.read);
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
LogHelper.error(e);
|
LogHelper.error(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -14,7 +14,7 @@ var options = {
|
||||||
LogHelper.debug("Saving options file");
|
LogHelper.debug("Saving options file");
|
||||||
try {
|
try {
|
||||||
tryWithResources(new HOutput(IOHelper.newOutput(options.file)), options.write);
|
tryWithResources(new HOutput(IOHelper.newOutput(options.file)), options.write);
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
LogHelper.error(e);
|
LogHelper.error(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -25,32 +25,26 @@ var options = {
|
||||||
throw new java.io.IOException("options magic mismatch: " + java.lang.Integer.toString(magic, 16));
|
throw new java.io.IOException("options magic mismatch: " + java.lang.Integer.toString(magic, 16));
|
||||||
}
|
}
|
||||||
var profilesCount = input.readInt();
|
var profilesCount = input.readInt();
|
||||||
LogHelper.debug("Load options. ProfilesCount %d",profilesCount);
|
LogHelper.debug("Load options. ProfilesCount %d", profilesCount);
|
||||||
for(var i = 0;i<profilesCount;i++)
|
for (var i = 0; i < profilesCount; i++) {
|
||||||
{
|
|
||||||
var listSize = input.readInt();
|
var listSize = input.readInt();
|
||||||
var sortIndex = input.readInt();
|
var sortIndex = input.readInt();
|
||||||
var profile = null;
|
var profile = null;
|
||||||
settings.lastProfiles.forEach(function(hprofile,i,arr) {
|
settings.lastProfiles.forEach(function(hprofile, i, arr) {
|
||||||
if(hprofile.getSortIndex() == sortIndex)
|
if (hprofile.getSortIndex() == sortIndex) {
|
||||||
{
|
|
||||||
profile = hprofile;
|
profile = hprofile;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
for(var j = 0; j < listSize; j++)
|
for (var j = 0; j < listSize; j++) {
|
||||||
{
|
|
||||||
var mark = input.readBoolean();
|
var mark = input.readBoolean();
|
||||||
var modType = OptionalFile.readType(input);
|
var modType = OptionalFile.readType(input);
|
||||||
var modFile = input.readString(0);
|
var modFile = input.readString(0);
|
||||||
if(mark)
|
if (mark) {
|
||||||
{
|
profile.markOptional(modFile, modType);
|
||||||
profile.markOptional(modFile,modType);
|
LogHelper.debug("Load options %s marked", modFile);
|
||||||
LogHelper.debug("Load options %s marked",modFile);
|
} else {
|
||||||
}
|
profile.unmarkOptional(modFile, modType);
|
||||||
else
|
LogHelper.debug("Load options %s unmarked", modFile);
|
||||||
{
|
|
||||||
profile.unmarkOptional(modFile,modType);
|
|
||||||
LogHelper.debug("Load options %s unmarked",modFile);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,13 +53,13 @@ var options = {
|
||||||
write: function(output) {
|
write: function(output) {
|
||||||
output.writeInt(config.settingsMagic);
|
output.writeInt(config.settingsMagic);
|
||||||
output.writeInt(settings.lastProfiles.length);
|
output.writeInt(settings.lastProfiles.length);
|
||||||
settings.lastProfiles.forEach(function(hprofile,i,arr) {
|
settings.lastProfiles.forEach(function(hprofile, i, arr) {
|
||||||
var profile = hprofile;
|
var profile = hprofile;
|
||||||
LogHelper.debug("Save options %s",profile.getTitle());
|
LogHelper.debug("Save options %s", profile.getTitle());
|
||||||
var list = profile.getOptional();
|
var list = profile.getOptional();
|
||||||
output.writeInt(list.size());
|
output.writeInt(list.size());
|
||||||
output.writeInt(profile.getSortIndex());
|
output.writeInt(profile.getSortIndex());
|
||||||
list.forEach(function(modFile,j,arr2) {
|
list.forEach(function(modFile, j, arr2) {
|
||||||
output.writeBoolean(modFile.mark);
|
output.writeBoolean(modFile.mark);
|
||||||
modFile.writeType(output);
|
modFile.writeType(output);
|
||||||
output.writeString(modFile.name, 0);
|
output.writeString(modFile.name, 0);
|
||||||
|
@ -82,50 +76,47 @@ var options = {
|
||||||
var modlist = pane.lookup("#modlist").getContent();
|
var modlist = pane.lookup("#modlist").getContent();
|
||||||
var nodelist = new java.util.ArrayList;
|
var nodelist = new java.util.ArrayList;
|
||||||
|
|
||||||
modlist.getChildren().forEach(function(node,i,arr) {
|
modlist.getChildren().forEach(function(node, i, arr) {
|
||||||
if(node instanceof javafx.scene.control.CheckBox)
|
if (node instanceof javafx.scene.control.CheckBox)
|
||||||
nodelist.add(node);
|
nodelist.add(node);
|
||||||
});
|
});
|
||||||
nodelist.forEach(function(node,i,arr) {
|
nodelist.forEach(function(node, i, arr) {
|
||||||
modlist.getChildren().remove(node);
|
modlist.getChildren().remove(node);
|
||||||
});
|
});
|
||||||
var profile = profilesList[serverHolder.old];
|
var profile = profilesList[serverHolder.old];
|
||||||
var list = profile.getOptional();
|
var list = profile.getOptional();
|
||||||
var checkBoxList = new java.util.ArrayList;
|
var checkBoxList = new java.util.ArrayList;
|
||||||
list.forEach(function(modFile) {
|
list.forEach(function(modFile) {
|
||||||
var modName = modFile.name, modDescription = "", subLevel = 1;
|
var modName = modFile.name,
|
||||||
if(!modFile.visible)
|
modDescription = "",
|
||||||
{
|
subLevel = 1;
|
||||||
LogHelper.debug("optionalMod %s hidden",modFile.name);
|
if (!modFile.visible) {
|
||||||
|
LogHelper.debug("optionalMod %s hidden", modFile.name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(modFile.permissions != 0 && ((loginData.permissions.toLong() & modFile.permissions) == 0))
|
if (modFile.permissions != 0 && ((loginData.permissions.toLong() & modFile.permissions) == 0)) {
|
||||||
{
|
LogHelper.debug("optionalMod %s permissions deny", modFile.name);
|
||||||
LogHelper.debug("optionalMod %s permissions deny",modFile.name);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(modFile.info != null)
|
if (modFile.info != null)
|
||||||
modDescription = modFile.info;
|
modDescription = modFile.info;
|
||||||
if(modFile.subTreeLevel != null && modFile.subTreeLevel > 1)
|
if (modFile.subTreeLevel != null && modFile.subTreeLevel > 1)
|
||||||
subLevel = modFile.subTreeLevel;
|
subLevel = modFile.subTreeLevel;
|
||||||
var testMod = new javafx.scene.control.CheckBox(modName);
|
var testMod = new javafx.scene.control.CheckBox(modName);
|
||||||
testMod.getStyleClass().add("checkboxOpt");
|
testMod.getStyleClass().add("checkboxOpt");
|
||||||
|
|
||||||
if(subLevel > 1)
|
if (subLevel > 1)
|
||||||
for(var i = 1; i < subLevel; i++)
|
for (var i = 1; i < subLevel; i++)
|
||||||
testMod.setTranslateX(25*i);
|
testMod.setTranslateX(25 * i);
|
||||||
|
|
||||||
testMod.setSelected(modFile.mark);
|
testMod.setSelected(modFile.mark);
|
||||||
testMod.setOnAction(function(event) {
|
testMod.setOnAction(function(event) {
|
||||||
var isSelected = event.getSource().isSelected();
|
var isSelected = event.getSource().isSelected();
|
||||||
if(isSelected)
|
if (isSelected) {
|
||||||
{
|
|
||||||
profile.markOptional(modFile);
|
profile.markOptional(modFile);
|
||||||
LogHelper.debug("Selected mod %s", modFile.name);
|
LogHelper.debug("Selected mod %s", modFile.name);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
profile.unmarkOptional(modFile);
|
profile.unmarkOptional(modFile);
|
||||||
LogHelper.debug("Unselected mod %s", modFile.name);
|
LogHelper.debug("Unselected mod %s", modFile.name);
|
||||||
}
|
}
|
||||||
|
@ -134,12 +125,12 @@ var options = {
|
||||||
testMod.setFocusTraversable(false);
|
testMod.setFocusTraversable(false);
|
||||||
checkBoxList.add(testMod);
|
checkBoxList.add(testMod);
|
||||||
testMod.getStyleClass().add("modname");
|
testMod.getStyleClass().add("modname");
|
||||||
if(modDescription != "") {
|
if (modDescription != "") {
|
||||||
textDescr = new javafx.scene.text.Text(modDescription);
|
textDescr = new javafx.scene.text.Text(modDescription);
|
||||||
if(subLevel > 1) {
|
if (subLevel > 1) {
|
||||||
for(var i = 1; i < subLevel; i++){
|
for (var i = 1; i < subLevel; i++) {
|
||||||
textDescr.setWrappingWidth(620-(25*i));
|
textDescr.setWrappingWidth(620 - (25 * i));
|
||||||
textDescr.setTranslateX(25+(25*i));
|
textDescr.setTranslateX(25 + (25 * i));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
textDescr.setWrappingWidth(620);
|
textDescr.setWrappingWidth(620);
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
/*-- DrLeonardo Design --*/
|
/*-- DrLeonardo Design --*/
|
||||||
|
|
||||||
/* Server buttons */
|
/* Server buttons */
|
||||||
|
|
||||||
.server-button {
|
.server-button {
|
||||||
-jfx-button-type: FLAT;
|
|
||||||
-fx-font-weight: bold;
|
-fx-font-weight: bold;
|
||||||
-fx-font-size: 16pt;
|
-fx-font-size: 16pt;
|
||||||
-fx-background-color: transparent;
|
-fx-background-color: transparent;
|
||||||
|
@ -17,14 +16,14 @@ .server-button {
|
||||||
}
|
}
|
||||||
|
|
||||||
.server-button:selected {
|
.server-button:selected {
|
||||||
-fx-effect: dropshadow(gaussian, rgba(23, 25, 29, 0.3), 15,0,0,3);
|
-fx-effect: dropshadow(gaussian, rgba(23, 25, 29, 0.3), 15, 0, 0, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** server-button-<your profile name> **/
|
/** server-button-<your profile name> **/
|
||||||
|
|
||||||
.server-button-Example {
|
.server-button-Example {
|
||||||
-fx-background-image: url('images/servers/example.png');
|
-fx-background-image: url('images/servers/example.png');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-- DrLeonardo Design --*/
|
/*-- DrLeonardo Design --*/
|
|
@ -12,7 +12,7 @@ CheckBox .box-container {
|
||||||
|
|
||||||
CheckBox .box,
|
CheckBox .box,
|
||||||
CheckBox:indeterminate .box,
|
CheckBox:indeterminate .box,
|
||||||
CheckBox:indeterminate:selected .box{
|
CheckBox:indeterminate:selected .box {
|
||||||
-fx-pref-width: 18;
|
-fx-pref-width: 18;
|
||||||
-fx-pref-height: 18;
|
-fx-pref-height: 18;
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ CheckBox:selected .mark {
|
||||||
-fx-border-radius: 2;
|
-fx-border-radius: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckBox .indeterminate-mark{
|
CheckBox .indeterminate-mark {
|
||||||
-fx-background-color: #5fd97a;
|
-fx-background-color: #5fd97a;
|
||||||
-fx-background-radius: 2;
|
-fx-background-radius: 2;
|
||||||
-fx-border-width: 0;
|
-fx-border-width: 0;
|
||||||
|
@ -56,7 +56,10 @@ CheckBox .indeterminate-mark{
|
||||||
|
|
||||||
|
|
||||||
/*-- DrLeonardo Design --*/
|
/*-- DrLeonardo Design --*/
|
||||||
Button, CheckBox, ComboBox, RadioButton {
|
Button,
|
||||||
|
CheckBox,
|
||||||
|
ComboBox,
|
||||||
|
RadioButton {
|
||||||
-fx-cursor: hand;
|
-fx-cursor: hand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,20 +72,22 @@ #layout {
|
||||||
-fx-pref-height: 450px;
|
-fx-pref-height: 450px;
|
||||||
-fx-background-image: url('images/background.jpg');
|
-fx-background-image: url('images/background.jpg');
|
||||||
}
|
}
|
||||||
|
|
||||||
#background {
|
#background {
|
||||||
-fx-background-color: #fff;
|
-fx-background-color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Labels **/
|
/** Labels **/
|
||||||
#background > #settingsTitle {
|
#background>#settingsTitle {
|
||||||
-fx-font-size: 14pt;
|
-fx-font-size: 14pt;
|
||||||
-fx-alignment: baseline-center;
|
-fx-alignment: baseline-center;
|
||||||
}
|
}
|
||||||
|
|
||||||
#serverLabel{
|
#serverLabel {
|
||||||
-fx-text-fill: #323232;
|
-fx-text-fill: #323232;
|
||||||
}
|
}
|
||||||
|
|
||||||
#serverStatus{
|
#serverStatus {
|
||||||
-fx-text-fill: #323232;
|
-fx-text-fill: #323232;
|
||||||
-fx-pref-width: 120px;
|
-fx-pref-width: 120px;
|
||||||
-fx-pref-height: 25px;
|
-fx-pref-height: 25px;
|
||||||
|
@ -90,17 +95,17 @@ #serverStatus{
|
||||||
|
|
||||||
/* Mask */
|
/* Mask */
|
||||||
#mask {
|
#mask {
|
||||||
-fx-effect: DropShadow( gaussian , rgba(255,255,255,0.5) , 0,0,0,1 );
|
-fx-effect: DropShadow(gaussian, rgba(255, 255, 255, 0.5), 0, 0, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Errors **/
|
/** Errors **/
|
||||||
#errormessage{
|
#errormessage {
|
||||||
-fx-background-color: transparent;
|
-fx-background-color: transparent;
|
||||||
-fx-text-alignment: center;
|
-fx-text-alignment: center;
|
||||||
-fx-text-fill: #CE5757;
|
-fx-text-fill: #CE5757;
|
||||||
}
|
}
|
||||||
|
|
||||||
.error{
|
.error {
|
||||||
-fx-text-fill: #CE5757;
|
-fx-text-fill: #CE5757;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,51 +115,58 @@ #bar {
|
||||||
-fx-pref-width: 46px;
|
-fx-pref-width: 46px;
|
||||||
-fx-pref-height: 450px;
|
-fx-pref-height: 450px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** buttons in bar **/
|
/** buttons in bar **/
|
||||||
#close {
|
#close {
|
||||||
-fx-background-position: center;
|
-fx-background-position: center;
|
||||||
-jfx-button-type: FLAT;
|
|
||||||
-fx-background-radius: 0;
|
-fx-background-radius: 0;
|
||||||
-fx-background-color: #CE5757;
|
-fx-background-color: #CE5757;
|
||||||
-fx-pref-width: 46px;
|
-fx-pref-width: 46px;
|
||||||
-fx-pref-height: 45px;
|
-fx-pref-height: 45px;
|
||||||
}
|
}
|
||||||
#hide, #back, #goConsole, #settings, #discord {
|
|
||||||
|
#hide,
|
||||||
|
#back,
|
||||||
|
#goConsole,
|
||||||
|
#settings,
|
||||||
|
#discord {
|
||||||
-fx-background-position: center;
|
-fx-background-position: center;
|
||||||
-jfx-button-type: FLAT;
|
|
||||||
-fx-background-radius: 0;
|
-fx-background-radius: 0;
|
||||||
-fx-pref-width: 46px;
|
-fx-pref-width: 46px;
|
||||||
-fx-pref-height: 45px;
|
-fx-pref-height: 45px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#logout{
|
#logout {
|
||||||
-fx-text-fill:#323232;
|
-fx-text-fill: #323232;
|
||||||
-fx-font-size:12;
|
-fx-font-size: 12;
|
||||||
-fx-font-weight:normal;
|
-fx-font-weight: normal;
|
||||||
-fx-border-color:#CE5757;
|
-fx-border-color: #CE5757;
|
||||||
-fx-border-width:1;
|
-fx-border-width: 1;
|
||||||
-fx-background-color:transparent;
|
-fx-background-color: transparent;
|
||||||
-fx-padding:0;
|
-fx-padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#logout:hover,
|
#logout:hover,
|
||||||
#logout:focus{
|
#logout:focus {
|
||||||
-fx-text-fill:#ff6a5e;
|
-fx-text-fill: #ff6a5e;
|
||||||
}
|
}
|
||||||
#logout:pressed{
|
|
||||||
-fx-border-color:#cb4d43;
|
#logout:pressed {
|
||||||
|
-fx-border-color: #cb4d43;
|
||||||
}
|
}
|
||||||
|
|
||||||
#send {
|
#send {
|
||||||
-fx-background-radius: 0;
|
-fx-background-radius: 0;
|
||||||
-fx-text-fill: black;
|
-fx-text-fill: black;
|
||||||
-fx-background-position: center;
|
-fx-background-position: center;
|
||||||
-jfx-button-type: FLAT;
|
|
||||||
-fx-background-color: #ffffff;
|
-fx-background-color: #ffffff;
|
||||||
-fx-pref-width: 150px;
|
-fx-pref-width: 150px;
|
||||||
-fx-pref-height: 30px;
|
-fx-pref-height: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#send:pressed { -fx-background-color: #d8d8d8; }
|
#send:pressed {
|
||||||
|
-fx-background-color: #d8d8d8;
|
||||||
|
}
|
||||||
|
|
||||||
/* LoginMenu */
|
/* LoginMenu */
|
||||||
#authPane {
|
#authPane {
|
||||||
|
@ -172,7 +184,6 @@ #logo {
|
||||||
|
|
||||||
/** Buttons & textarea**/
|
/** Buttons & textarea**/
|
||||||
.auth {
|
.auth {
|
||||||
-jfx-button-type: FLAT;
|
|
||||||
-fx-font-weight: bold;
|
-fx-font-weight: bold;
|
||||||
-fx-font-size: 13pt;
|
-fx-font-size: 13pt;
|
||||||
-fx-background-radius: 0;
|
-fx-background-radius: 0;
|
||||||
|
@ -180,18 +191,22 @@ .auth {
|
||||||
-fx-text-fill: #ffffff;
|
-fx-text-fill: #ffffff;
|
||||||
-fx-pref-width: 200px;
|
-fx-pref-width: 200px;
|
||||||
-fx-pref-height: 45px;
|
-fx-pref-height: 45px;
|
||||||
-fx-effect: dropshadow(gaussian, rgba(23, 25, 29, 0.3), 15,0,0,3);
|
-fx-effect: dropshadow(gaussian, rgba(23, 25, 29, 0.3), 15, 0, 0, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.auth:hover, .auth:pressed { -fx-background-color: #75e18c; }
|
.auth:hover,
|
||||||
|
.auth:pressed {
|
||||||
|
-fx-background-color: #75e18c;
|
||||||
|
}
|
||||||
|
|
||||||
#password, #login {
|
#password,
|
||||||
|
#login {
|
||||||
-fx-background-radius: 0;
|
-fx-background-radius: 0;
|
||||||
-fx-pref-width: 200px;
|
-fx-pref-width: 200px;
|
||||||
-fx-pref-height: 30px;
|
-fx-pref-height: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-input{
|
.text-input {
|
||||||
-fx-focus-color: transparent;
|
-fx-focus-color: transparent;
|
||||||
-fx-background-repeat: no-repeat;
|
-fx-background-repeat: no-repeat;
|
||||||
-fx-text-fill: #909090;
|
-fx-text-fill: #909090;
|
||||||
|
@ -212,21 +227,26 @@ #link {
|
||||||
-fx-pref-height: 17px;
|
-fx-pref-height: 17px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#link:hover, #link:pressed { -fx-opacity: 0.8; }
|
#link:hover,
|
||||||
|
#link:pressed {
|
||||||
|
-fx-opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
/** CheckBox & ComboBox**/
|
/** CheckBox & ComboBox**/
|
||||||
#rememberchb{
|
#rememberchb {
|
||||||
-fx-font-size: 13;
|
-fx-font-size: 13;
|
||||||
-fx-text-fill: #909090;
|
-fx-text-fill: #909090;
|
||||||
-fx-pref-width: 145px;
|
-fx-pref-width: 145px;
|
||||||
-fx-pref-height: 30px;
|
-fx-pref-height: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#combologin {
|
#combologin {
|
||||||
-fx-text-fill: #909090;
|
-fx-text-fill: #909090;
|
||||||
-fx-prompt-text-fill: #909090;
|
-fx-prompt-text-fill: #909090;
|
||||||
-fx-pref-width: 200px;
|
-fx-pref-width: 200px;
|
||||||
-fx-pref-height: 30px;
|
-fx-pref-height: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.combologin,
|
.combologin,
|
||||||
.combologin {
|
.combologin {
|
||||||
-fx-font-size: 13px;
|
-fx-font-size: 13px;
|
||||||
|
@ -244,7 +264,7 @@ .combologin .list-cell {
|
||||||
.combologin-popup .list-view {
|
.combologin-popup .list-view {
|
||||||
-fx-background-color: white, white;
|
-fx-background-color: white, white;
|
||||||
-fx-background-insets: 0, 1;
|
-fx-background-insets: 0, 1;
|
||||||
-fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.6) , 8, 0.0 , 0 , 0 );
|
-fx-effect: dropshadow(three-pass-box, rgba(0, 0, 0, 0.6), 8, 0.0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.combologin .list-cell:filled:selected .text,
|
.combologin .list-cell:filled:selected .text,
|
||||||
|
@ -257,20 +277,18 @@ .combologin .arrow {
|
||||||
-fx-background-color: #5fd97a;
|
-fx-background-color: #5fd97a;
|
||||||
}
|
}
|
||||||
|
|
||||||
.combologin-popup .list-view .list-cell
|
.combologin-popup .list-view .list-cell {
|
||||||
{
|
|
||||||
-fx-background-color: white;
|
-fx-background-color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.combologin-popup .list-view .list-cell:filled:selected, .combologin-popup .list-view .list-cell:filled:selected:hover
|
.combologin-popup .list-view .list-cell:filled:selected,
|
||||||
{
|
.combologin-popup .list-view .list-cell:filled:selected:hover {
|
||||||
-fx-background: -fx-accent;
|
-fx-background: -fx-accent;
|
||||||
-fx-background-color: -fx-selection-bar;
|
-fx-background-color: -fx-selection-bar;
|
||||||
-fx-text-fill: #909090;
|
-fx-text-fill: #909090;
|
||||||
}
|
}
|
||||||
|
|
||||||
.combologin-popup .list-view .list-cell:filled:hover
|
.combologin-popup .list-view .list-cell:filled:hover {
|
||||||
{
|
|
||||||
-fx-background-color: white;
|
-fx-background-color: white;
|
||||||
-fx-text-fill: #909090;
|
-fx-text-fill: #909090;
|
||||||
}
|
}
|
||||||
|
@ -290,31 +308,23 @@ .serverentrance {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** buttons **/
|
/** buttons **/
|
||||||
.clientLaunch{
|
.clientLaunch {
|
||||||
-jfx-button-type: FLAT;
|
|
||||||
-fx-font-weight: bold;
|
-fx-font-weight: bold;
|
||||||
-fx-font-size: 16pt;
|
-fx-font-size: 16pt;
|
||||||
-fx-background-radius: 0;
|
-fx-background-radius: 0;
|
||||||
-fx-background-color: #5fd97a;
|
-fx-background-color: #5fd97a;
|
||||||
-fx-text-fill: #ffffff;
|
-fx-text-fill: #ffffff;
|
||||||
}
|
}
|
||||||
.clientSettings{
|
|
||||||
|
.clientSettings {
|
||||||
-fx-background-position: center;
|
-fx-background-position: center;
|
||||||
-jfx-button-type: FLAT;
|
|
||||||
-fx-background-color: #5fd97a;
|
-fx-background-color: #5fd97a;
|
||||||
-fx-background-radius: 0;
|
-fx-background-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.clientLaunch:hover, .clientLaunch:pressed { -fx-background-color: #75e18c; }
|
.clientLaunch:hover,
|
||||||
|
.clientLaunch:pressed {
|
||||||
/* Pressets options */
|
-fx-background-color: #75e18c;
|
||||||
.pressetLight, .pressetMedium, .pressetHigh {
|
|
||||||
-jfx-toggle-color: #5fd97a;
|
|
||||||
-jfx-untoggle-color: #FAFAFA;
|
|
||||||
-jfx-toggle-line-color: rgba(116, 192, 133, 0.79);
|
|
||||||
-jfx-untoggle-line-color: #999999;
|
|
||||||
-jfx-size: 10.0;
|
|
||||||
-jfx-disable-visual-focus: false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Scrolls */
|
/* Scrolls */
|
||||||
|
@ -356,11 +366,11 @@ .scroll-pane>.corner {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OptionsPane */
|
/* OptionsPane */
|
||||||
#optionsPane > #modlist {
|
#optionsPane>#modlist {
|
||||||
-fx-background-color: transparent;
|
-fx-background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
#optionsPane > #modlist > .viewport {
|
#optionsPane>#modlist>.viewport {
|
||||||
-fx-background-color: transparent;
|
-fx-background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,39 +394,42 @@ .separator *.line {
|
||||||
-fx-border-width: 0 0 10 0;
|
-fx-border-width: 0 0 10 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#serverlist{
|
#serverlist {
|
||||||
-fx-background-color: transparent;
|
|
||||||
}
|
|
||||||
#serverlist > .viewport {
|
|
||||||
-fx-background-color: transparent;
|
-fx-background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
#serverdesc{
|
#serverlist>.viewport {
|
||||||
-fx-background-color: transparent;
|
|
||||||
}
|
|
||||||
#serverdesc > .viewport {
|
|
||||||
-fx-background-color: transparent;
|
-fx-background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
#serverinfo{
|
#serverdesc {
|
||||||
-fx-background-color: transparent;
|
|
||||||
}
|
|
||||||
#serverinfo > .viewport {
|
|
||||||
-fx-background-color: transparent;
|
-fx-background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
#servercontainer{
|
#serverdesc>.viewport {
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#serverinfo {
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#serverinfo>.viewport {
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#servercontainer {
|
||||||
-fx-background-color: transparent;
|
-fx-background-color: transparent;
|
||||||
-jfx-button-type: FLAT;
|
|
||||||
-fx-pref-width: 282px;
|
-fx-pref-width: 282px;
|
||||||
-fx-pref-height: 75px;
|
-fx-pref-height: 75px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toggle-button:disabled{
|
.toggle-button:disabled {
|
||||||
-fx-opacity: 1.0;
|
-fx-opacity: 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.heading{
|
.heading {
|
||||||
-fx-text-fill: #555555;
|
-fx-text-fill: #555555;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-- DrLeonardo Design --*/
|
/*-- DrLeonardo Design --*/
|
|
@ -41,8 +41,6 @@ var HInput = HInputClass.static;
|
||||||
var HOutput = HOutputClass.static;
|
var HOutput = HOutputClass.static;
|
||||||
var StreamObject = StreamObjectClass.static;
|
var StreamObject = StreamObjectClass.static;
|
||||||
var StreamObjectAdapter = StreamObjectAdapterClass.static;
|
var StreamObjectAdapter = StreamObjectAdapterClass.static;
|
||||||
var SignedBytesHolder = SignedBytesHolderClass.static;
|
|
||||||
var SignedObjectHolder = SignedObjectHolderClass.static;
|
|
||||||
var EnumSerializer = EnumSerializerClass.static;
|
var EnumSerializer = EnumSerializerClass.static;
|
||||||
var OptionalFile = OptionalFileClass.static;
|
var OptionalFile = OptionalFileClass.static;
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ var settingsManagerClass = Java.extend(SettingsManagerClass.static, {
|
||||||
new_settings.fullScreen = config.fullScreenDefault;
|
new_settings.fullScreen = config.fullScreenDefault;
|
||||||
new_settings.ram = config.ramDefault;
|
new_settings.ram = config.ramDefault;
|
||||||
|
|
||||||
|
new_settings.featureStore = config.featureStoreDefault;
|
||||||
new_settings.lastDigest = null;
|
new_settings.lastDigest = null;
|
||||||
new_settings.lastProfiles.clear();
|
new_settings.lastProfiles.clear();
|
||||||
new_settings.lastHDirs.clear();
|
new_settings.lastHDirs.clear();
|
||||||
|
|
|
@ -9,7 +9,8 @@ var LauncherApp = Java.extend(JSApplication, {
|
||||||
settings = SettingsManager.settings;
|
settings = SettingsManager.settings;
|
||||||
settingsManager.loadHDirStore();
|
settingsManager.loadHDirStore();
|
||||||
cliParams.applySettings();
|
cliParams.applySettings();
|
||||||
}, start: function(primaryStage) {
|
},
|
||||||
|
start: function(primaryStage) {
|
||||||
stage = primaryStage;
|
stage = primaryStage;
|
||||||
stage.initStyle(javafx.stage.StageStyle.TRANSPARENT);
|
stage.initStyle(javafx.stage.StageStyle.TRANSPARENT);
|
||||||
stage.setResizable(false);
|
stage.setResizable(false);
|
||||||
|
@ -45,7 +46,8 @@ var LauncherApp = Java.extend(JSApplication, {
|
||||||
setCurrentScene(loginScene);
|
setCurrentScene(loginScene);
|
||||||
initLauncher();
|
initLauncher();
|
||||||
|
|
||||||
}, stop: function() {
|
},
|
||||||
|
stop: function() {
|
||||||
settingsManager.saveConfig();
|
settingsManager.saveConfig();
|
||||||
settingsManager.saveHDirStore();
|
settingsManager.saveHDirStore();
|
||||||
options.save();
|
options.save();
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.lang.instrument.Instrumentation;
|
import java.lang.instrument.Instrumentation;
|
||||||
import java.lang.management.ManagementFactory;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
@ -22,6 +21,7 @@
|
||||||
import cpw.mods.fml.SafeExitJVMLegacy;
|
import cpw.mods.fml.SafeExitJVMLegacy;
|
||||||
import net.minecraftforge.fml.SafeExitJVM;
|
import net.minecraftforge.fml.SafeExitJVM;
|
||||||
import pro.gravit.launcher.utils.NativeJVMHalt;
|
import pro.gravit.launcher.utils.NativeJVMHalt;
|
||||||
|
import pro.gravit.utils.helper.JVMHelper;
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
|
@ -46,6 +46,9 @@ public static void premain(String agentArgument, Instrumentation instrumentation
|
||||||
NativeJVMHalt.class.getName();
|
NativeJVMHalt.class.getName();
|
||||||
NativeJVMHalt.initFunc();
|
NativeJVMHalt.initFunc();
|
||||||
isAgentStarted = true;
|
isAgentStarted = true;
|
||||||
|
if (System.getProperty("java.vm.name").toUpperCase(Locale.US).contains("HOTSPOT"))
|
||||||
|
try {
|
||||||
|
if (JVMHelper.OS_TYPE == JVMHelper.OS.MUSTDIE) {
|
||||||
boolean pb = true;
|
boolean pb = true;
|
||||||
boolean rt = true;
|
boolean rt = true;
|
||||||
if (agentArgument != null) {
|
if (agentArgument != null) {
|
||||||
|
@ -55,10 +58,8 @@ public static void premain(String agentArgument, Instrumentation instrumentation
|
||||||
if (trimmedArg.contains("r")) rt = false;
|
if (trimmedArg.contains("r")) rt = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (System.getProperty("java.vm.name").toUpperCase(Locale.US).contains("HOTSPOT"))
|
replaceClasses(pb, rt);
|
||||||
try {
|
} else replaceClasses(false, false);
|
||||||
if (ManagementFactory.getOperatingSystemMXBean().getName().startsWith("Windows")) replaceClasses(pb, rt);
|
|
||||||
else replaceClasses(false, false);
|
|
||||||
} catch (Error e) {
|
} catch (Error e) {
|
||||||
NativeJVMHalt.haltA(294);
|
NativeJVMHalt.haltA(294);
|
||||||
throw e;
|
throw e;
|
||||||
|
|
|
@ -14,11 +14,15 @@
|
||||||
import java.nio.file.SimpleFileVisitor;
|
import java.nio.file.SimpleFileVisitor;
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
import java.nio.file.attribute.PosixFilePermission;
|
import java.nio.file.attribute.PosixFilePermission;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
|
|
||||||
|
@ -55,16 +59,16 @@
|
||||||
|
|
||||||
public final class ClientLauncher {
|
public final class ClientLauncher {
|
||||||
private static final class ClassPathFileVisitor extends SimpleFileVisitor<Path> {
|
private static final class ClassPathFileVisitor extends SimpleFileVisitor<Path> {
|
||||||
private final Collection<Path> result;
|
private final Stream.Builder<Path> result;
|
||||||
|
|
||||||
private ClassPathFileVisitor(Collection<Path> result) {
|
private ClassPathFileVisitor(Stream.Builder<Path> result) {
|
||||||
this.result = result;
|
this.result = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||||
if (IOHelper.hasExtension(file, "jar") || IOHelper.hasExtension(file, "zip"))
|
if (IOHelper.hasExtension(file, "jar") || IOHelper.hasExtension(file, "zip"))
|
||||||
result.add(file);
|
result.accept(file);
|
||||||
return super.visitFile(file, attrs);
|
return super.visitFile(file, attrs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -282,10 +286,17 @@ private static void launch(ClientProfile profile, Params params) throws Throwabl
|
||||||
System.setProperty("minecraft.applet.TargetDirectory", params.clientDir.toString());
|
System.setProperty("minecraft.applet.TargetDirectory", params.clientDir.toString());
|
||||||
}
|
}
|
||||||
Collections.addAll(args, profile.getClientArgs());
|
Collections.addAll(args, profile.getClientArgs());
|
||||||
LogHelper.debug("Args: " + args);
|
List<String> copy = new ArrayList<>(args);
|
||||||
|
for (int i = 0, l = copy.size(); i < l; i++) {
|
||||||
|
String s = copy.get(i);
|
||||||
|
if ( i + 1 < l && ("--accessToken".equals(s) || "--session".equals(s))) {
|
||||||
|
copy.set(i + 1, "censored");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LogHelper.debug("Args: " + copy);
|
||||||
// Resolve main class and method
|
// Resolve main class and method
|
||||||
Class<?> mainClass = classLoader.loadClass(profile.getMainClass());
|
Class<?> mainClass = classLoader.loadClass(profile.getMainClass());
|
||||||
MethodHandle mainMethod = MethodHandles.publicLookup().findStatic(mainClass, "main", MethodType.methodType(void.class, String[].class)).asFixedArity();
|
MethodHandle mainMethod = MethodHandles.publicLookup().findStatic(mainClass, "main", MethodType.methodType(void.class, String[].class));
|
||||||
Launcher.LAUNCHED.set(true);
|
Launcher.LAUNCHED.set(true);
|
||||||
JVMHelper.fullGC();
|
JVMHelper.fullGC();
|
||||||
// Invoke main method
|
// Invoke main method
|
||||||
|
@ -295,6 +306,7 @@ private static void launch(ClientProfile profile, Params params) throws Throwabl
|
||||||
private static Process process = null;
|
private static Process process = null;
|
||||||
private static boolean clientStarted = false;
|
private static boolean clientStarted = false;
|
||||||
private static Thread writeParamsThread;
|
private static Thread writeParamsThread;
|
||||||
|
public static PlayerProfile playerProfile;
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public static Process launch(
|
public static Process launch(
|
||||||
|
@ -407,7 +419,7 @@ public static Process launch(
|
||||||
Thread.sleep(200);
|
Thread.sleep(200);
|
||||||
}
|
}
|
||||||
if (!clientStarted) {
|
if (!clientStarted) {
|
||||||
LogHelper.error("Write Client Params not successful. Using debug mode for more information");
|
LogHelper.error("Client did not start properly. Enable debug mode for more information");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clientStarted = false;
|
clientStarted = false;
|
||||||
|
@ -450,6 +462,7 @@ public static void main(String... args) throws Throwable {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Launcher.profile = profile;
|
Launcher.profile = profile;
|
||||||
|
playerProfile = params.pp;
|
||||||
Request.setSession(params.session);
|
Request.setSession(params.session);
|
||||||
checkJVMBitsAndVersion();
|
checkJVMBitsAndVersion();
|
||||||
Launcher.modulesManager.initModules();
|
Launcher.modulesManager.initModules();
|
||||||
|
@ -515,32 +528,27 @@ public static void main(String... args) throws Throwable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static URL[] resolveClassPath(Path clientDir, String... classPath) throws IOException {
|
private static URL[] resolveClassPath(Path clientDir, String... classPath) throws IOException {
|
||||||
Collection<Path> result = new LinkedList<>();
|
return resolveClassPathStream(clientDir, classPath).map(IOHelper::toURL).toArray(URL[]::new);
|
||||||
for (String classPathEntry : classPath) {
|
|
||||||
Path path = clientDir.resolve(IOHelper.toPath(classPathEntry));
|
|
||||||
if (IOHelper.isDir(path)) { // Recursive walking and adding
|
|
||||||
IOHelper.walk(path, new ClassPathFileVisitor(result), false);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
result.add(path);
|
|
||||||
}
|
|
||||||
return result.stream().map(IOHelper::toURL).toArray(URL[]::new);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LinkedList<Path> resolveClassPathList(Path clientDir, String... classPath) throws IOException {
|
private static LinkedList<Path> resolveClassPathList(Path clientDir, String... classPath) throws IOException {
|
||||||
LinkedList<Path> result = new LinkedList<>();
|
return resolveClassPathStream(clientDir, classPath).collect(Collectors.toCollection(LinkedList::new));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Stream<Path> resolveClassPathStream(Path clientDir, String... classPath) throws IOException {
|
||||||
|
Stream.Builder<Path> builder = Stream.builder();
|
||||||
for (String classPathEntry : classPath) {
|
for (String classPathEntry : classPath) {
|
||||||
Path path = clientDir.resolve(IOHelper.toPath(classPathEntry));
|
Path path = clientDir.resolve(IOHelper.toPath(classPathEntry));
|
||||||
if (IOHelper.isDir(path)) { // Recursive walking and adding
|
if (IOHelper.isDir(path)) { // Recursive walking and adding
|
||||||
IOHelper.walk(path, new ClassPathFileVisitor(result), false);
|
IOHelper.walk(path, new ClassPathFileVisitor(builder), false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
result.add(path);
|
builder.accept(path);
|
||||||
}
|
}
|
||||||
return result;
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void initGson() {
|
private static void initGson() {
|
||||||
Launcher.gsonManager = new ClientGsonManager();
|
Launcher.gsonManager = new ClientGsonManager();
|
||||||
Launcher.gsonManager.initGson();
|
Launcher.gsonManager.initGson();
|
||||||
}
|
}
|
||||||
|
@ -552,8 +560,8 @@ public static void setProfile(ClientProfile profile) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void verifyHDir(Path dir, HashedDir hdir, FileNameMatcher matcher, boolean digest) throws IOException {
|
public static void verifyHDir(Path dir, HashedDir hdir, FileNameMatcher matcher, boolean digest) throws IOException {
|
||||||
if (matcher != null)
|
//if (matcher != null)
|
||||||
matcher = matcher.verifyOnly();
|
// matcher = matcher.verifyOnly();
|
||||||
|
|
||||||
// Hash directory and compare (ignore update-only matcher entries, it will break offline-mode)
|
// Hash directory and compare (ignore update-only matcher entries, it will break offline-mode)
|
||||||
HashedDir currentHDir = new HashedDir(dir, matcher, true, digest);
|
HashedDir currentHDir = new HashedDir(dir, matcher, true, digest);
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
import pro.gravit.launcher.managers.SimpleModuleManager;
|
import pro.gravit.launcher.managers.SimpleModuleManager;
|
||||||
|
|
||||||
public class ClientModuleManager extends SimpleModuleManager {
|
public class ClientModuleManager extends SimpleModuleManager {
|
||||||
|
|
||||||
public ClientModuleManager(LauncherEngine engine) {
|
public ClientModuleManager(LauncherEngine engine) {
|
||||||
context = new ClientModuleContext(engine);
|
context = new ClientModuleContext(engine);
|
||||||
modules = new ArrayList<>();
|
modules = new ArrayList<>();
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
import pro.gravit.launcher.managers.HasherManager;
|
import pro.gravit.launcher.managers.HasherManager;
|
||||||
import pro.gravit.launcher.managers.HasherStore;
|
import pro.gravit.launcher.managers.HasherStore;
|
||||||
import pro.gravit.launcher.request.Request;
|
import pro.gravit.launcher.request.Request;
|
||||||
import pro.gravit.launcher.serialize.signed.SignedObjectHolder;
|
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
import pro.gravit.utils.Version;
|
||||||
|
|
||||||
public class FunctionalBridge {
|
public class FunctionalBridge {
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
|
@ -33,12 +33,12 @@ public class FunctionalBridge {
|
||||||
private static long cachedMemorySize = -1;
|
private static long cachedMemorySize = -1;
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public static HashedDirRunnable offlineUpdateRequest(String dirName, Path dir, SignedObjectHolder<HashedDir> hdir, FileNameMatcher matcher, boolean digest) {
|
public static HashedDirRunnable offlineUpdateRequest(String dirName, Path dir, HashedDir hdir, FileNameMatcher matcher, boolean digest) {
|
||||||
return () -> {
|
return () -> {
|
||||||
if (hdir == null) {
|
if (hdir == null) {
|
||||||
Request.requestError(java.lang.String.format("Директории '%s' нет в кэше", dirName));
|
Request.requestError(java.lang.String.format("Директории '%s' нет в кэше", dirName));
|
||||||
}
|
}
|
||||||
ClientLauncher.verifyHDir(dir, hdir.object, matcher, digest);
|
ClientLauncher.verifyHDir(dir, hdir, matcher, digest);
|
||||||
return hdir;
|
return hdir;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ public static void setAuthParams(AuthRequestEvent event) {
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface HashedDirRunnable {
|
public interface HashedDirRunnable {
|
||||||
SignedObjectHolder<HashedDir> run() throws Exception;
|
HashedDir run() throws Exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
|
@ -112,4 +112,14 @@ public static void evalCommand(String cmd) {
|
||||||
public static void addPlainOutput(LogHelper.Output output) {
|
public static void addPlainOutput(LogHelper.Output output) {
|
||||||
LogHelper.addOutput(output, LogHelper.OutputTypes.PLAIN);
|
LogHelper.addOutput(output, LogHelper.OutputTypes.PLAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@LauncherAPI
|
||||||
|
public static String getLauncherVersion() {
|
||||||
|
return String.format("GravitLauncher v%d.%d.%d build %d",
|
||||||
|
Version.MAJOR,
|
||||||
|
Version.MINOR,
|
||||||
|
Version.PATCH,
|
||||||
|
Version.BUILD
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,9 @@ public void postDiff(UpdateRequest request, UpdateRequestEvent e, HashedDir.Diff
|
||||||
//if(file.isSame(ret, true))
|
//if(file.isSame(ret, true))
|
||||||
{
|
{
|
||||||
Path source = request.getDir().resolve(path);
|
Path source = request.getDir().resolve(path);
|
||||||
|
if (LogHelper.isDebugEnabled()) {
|
||||||
LogHelper.debug("Copy file %s to %s", ret.toAbsolutePath().toString(), source.toAbsolutePath().toString());
|
LogHelper.debug("Copy file %s to %s", ret.toAbsolutePath().toString(), source.toAbsolutePath().toString());
|
||||||
|
}
|
||||||
//Let's go!
|
//Let's go!
|
||||||
Files.copy(ret, source);
|
Files.copy(ret, source);
|
||||||
try (InputStream input = IOHelper.newInput(ret)) {
|
try (InputStream input = IOHelper.newInput(ret)) {
|
||||||
|
@ -93,11 +95,15 @@ public Path tryFind(NewLauncherSettings.HashedStoreEntry en, HashedFile file) th
|
||||||
if (entry.getType() == HashedEntry.Type.DIR) return HashedDir.WalkAction.CONTINUE;
|
if (entry.getType() == HashedEntry.Type.DIR) return HashedDir.WalkAction.CONTINUE;
|
||||||
HashedFile tfile = (HashedFile) entry;
|
HashedFile tfile = (HashedFile) entry;
|
||||||
if (tfile.isSame(file)) {
|
if (tfile.isSame(file)) {
|
||||||
|
if (LogHelper.isDevEnabled()) {
|
||||||
LogHelper.dev("[DIR:%s] Found file %s in %s", en.name, name, path);
|
LogHelper.dev("[DIR:%s] Found file %s in %s", en.name, name, path);
|
||||||
|
}
|
||||||
Path tdir = Paths.get(en.fullPath).resolve(path);
|
Path tdir = Paths.get(en.fullPath).resolve(path);
|
||||||
try {
|
try {
|
||||||
if (tfile.isSame(tdir, true)) {
|
if (tfile.isSame(tdir, true)) {
|
||||||
|
if (LogHelper.isDevEnabled()) {
|
||||||
LogHelper.dev("[DIR:%s] Confirmed file %s in %s", en.name, name, path);
|
LogHelper.dev("[DIR:%s] Confirmed file %s in %s", en.name, name, path);
|
||||||
|
}
|
||||||
ret.set(tdir);
|
ret.set(tdir);
|
||||||
return HashedDir.WalkAction.STOP;
|
return HashedDir.WalkAction.STOP;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,8 +49,6 @@
|
||||||
import pro.gravit.launcher.request.uuid.ProfileByUsernameRequest;
|
import pro.gravit.launcher.request.uuid.ProfileByUsernameRequest;
|
||||||
import pro.gravit.launcher.serialize.HInput;
|
import pro.gravit.launcher.serialize.HInput;
|
||||||
import pro.gravit.launcher.serialize.HOutput;
|
import pro.gravit.launcher.serialize.HOutput;
|
||||||
import pro.gravit.launcher.serialize.signed.SignedBytesHolder;
|
|
||||||
import pro.gravit.launcher.serialize.signed.SignedObjectHolder;
|
|
||||||
import pro.gravit.launcher.serialize.stream.EnumSerializer;
|
import pro.gravit.launcher.serialize.stream.EnumSerializer;
|
||||||
import pro.gravit.launcher.serialize.stream.StreamObject;
|
import pro.gravit.launcher.serialize.stream.StreamObject;
|
||||||
import pro.gravit.utils.HTTPRequest;
|
import pro.gravit.utils.HTTPRequest;
|
||||||
|
@ -64,7 +62,7 @@
|
||||||
|
|
||||||
public class JSRuntimeProvider implements RuntimeProvider {
|
public class JSRuntimeProvider implements RuntimeProvider {
|
||||||
|
|
||||||
private final ScriptEngine engine = CommonHelper.newScriptEngine();
|
public final ScriptEngine engine = CommonHelper.newScriptEngine();
|
||||||
private boolean isPreLoaded = false;
|
private boolean isPreLoaded = false;
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
|
@ -112,8 +110,6 @@ public static void addLauncherClassBindings(Map<String, Object> bindings) {
|
||||||
bindings.put("HOutputClass", HOutput.class);
|
bindings.put("HOutputClass", HOutput.class);
|
||||||
bindings.put("StreamObjectClass", StreamObject.class);
|
bindings.put("StreamObjectClass", StreamObject.class);
|
||||||
bindings.put("StreamObjectAdapterClass", StreamObject.Adapter.class);
|
bindings.put("StreamObjectAdapterClass", StreamObject.Adapter.class);
|
||||||
bindings.put("SignedBytesHolderClass", SignedBytesHolder.class);
|
|
||||||
bindings.put("SignedObjectHolderClass", SignedObjectHolder.class);
|
|
||||||
bindings.put("EnumSerializerClass", EnumSerializer.class);
|
bindings.put("EnumSerializerClass", EnumSerializer.class);
|
||||||
bindings.put("OptionalFileClass", OptionalFile.class);
|
bindings.put("OptionalFileClass", OptionalFile.class);
|
||||||
bindings.put("UserSettingsClass", UserSettings.class);
|
bindings.put("UserSettingsClass", UserSettings.class);
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
import oshi.hardware.HWDiskStore;
|
import oshi.hardware.HWDiskStore;
|
||||||
import oshi.hardware.HardwareAbstractionLayer;
|
import oshi.hardware.HardwareAbstractionLayer;
|
||||||
import oshi.hardware.NetworkIF;
|
import oshi.hardware.NetworkIF;
|
||||||
import oshi.hardware.SoundCard;
|
|
||||||
import oshi.hardware.UsbDevice;
|
import oshi.hardware.UsbDevice;
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
|
@ -67,15 +66,9 @@ public String getHWDisk() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSoundCardInfo() {
|
|
||||||
for (SoundCard soundcard : hardware.getSoundCards()) {
|
|
||||||
return soundcard.getName();
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMacAddr() {
|
public String getMacAddr() {
|
||||||
for (NetworkIF networkIF : hardware.getNetworkIFs()) {
|
for (NetworkIF networkIF : hardware.getNetworkIFs()) {
|
||||||
|
if (networkIF.getNetworkInterface().isVirtual()) continue;
|
||||||
for (String ipv4 : networkIF.getIPv4addr()) {
|
for (String ipv4 : networkIF.getIPv4addr()) {
|
||||||
if (ipv4.startsWith("127.")) continue;
|
if (ipv4.startsWith("127.")) continue;
|
||||||
if (ipv4.startsWith("10.")) continue;
|
if (ipv4.startsWith("10.")) continue;
|
||||||
|
@ -119,9 +112,6 @@ public void printHardwareInformation() {
|
||||||
LogHelper.subDebug("IPv4: %s", ipv4);
|
LogHelper.subDebug("IPv4: %s", ipv4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (SoundCard soundcard : hardware.getSoundCards()) {
|
|
||||||
LogHelper.debug("SoundCard %s", soundcard.getName());
|
|
||||||
}
|
|
||||||
CentralProcessor processor = hardware.getProcessor();
|
CentralProcessor processor = hardware.getProcessor();
|
||||||
LogHelper.debug("Processor Model: %s ID: %s", processor.getModel(), processor.getProcessorID());
|
LogHelper.debug("Processor Model: %s ID: %s", processor.getModel(), processor.getProcessorID());
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
|
|
@ -27,15 +27,6 @@
|
||||||
|
|
||||||
public final class DirWatcher implements Runnable, AutoCloseable {
|
public final class DirWatcher implements Runnable, AutoCloseable {
|
||||||
private final class RegisterFileVisitor extends SimpleFileVisitor<Path> {
|
private final class RegisterFileVisitor extends SimpleFileVisitor<Path> {
|
||||||
private final Deque<String> path = new LinkedList<>();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
|
|
||||||
FileVisitResult result = super.postVisitDirectory(dir, exc);
|
|
||||||
if (!DirWatcher.this.dir.equals(dir))
|
|
||||||
path.removeLast();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
|
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
|
||||||
|
@ -46,7 +37,6 @@ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) th
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maybe it's unnecessary to go deeper
|
// Maybe it's unnecessary to go deeper
|
||||||
path.add(IOHelper.getFileName(dir));
|
|
||||||
//if (matcher != null && !matcher.shouldVerify(path)) {
|
//if (matcher != null && !matcher.shouldVerify(path)) {
|
||||||
// return FileVisitResult.SKIP_SUBTREE;
|
// return FileVisitResult.SKIP_SUBTREE;
|
||||||
//}
|
//}
|
||||||
|
|
|
@ -6,3 +6,36 @@ compile project(':LauncherCore')
|
||||||
compileOnly 'org.apache.httpcomponents:httpclient:4.5.7'
|
compileOnly 'org.apache.httpcomponents:httpclient:4.5.7'
|
||||||
compileOnly 'io.netty:netty-codec-http:4.1.36.Final'
|
compileOnly 'io.netty:netty-codec-http:4.1.36.Final'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jar {
|
||||||
|
classifier = 'clean'
|
||||||
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
launcherwsapi(MavenPublication) {
|
||||||
|
artifactId = 'launcher-ws-api'
|
||||||
|
artifact jar
|
||||||
|
pom {
|
||||||
|
name = 'GravitLauncher WebSocket API'
|
||||||
|
description = 'GravitLauncher WebSocket Module API'
|
||||||
|
url = 'https://launcher.gravit.pro'
|
||||||
|
licenses {
|
||||||
|
license {
|
||||||
|
name = 'GNU General Public License, Version 3.0'
|
||||||
|
url = 'https://www.gnu.org/licenses/gpl-3.0.html'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scm {
|
||||||
|
connection = 'scm:git:https://github.com/GravitLauncher/Launcher.git'
|
||||||
|
developerConnection = 'scm:git:ssh://git@github.com:GravitLauncher/Launcher.git'
|
||||||
|
url = 'https://launcher.gravit.pro/'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
signing {
|
||||||
|
sign publishing.publications.launcherwsapi
|
||||||
|
}
|
||||||
|
|
|
@ -4,8 +4,6 @@ public class AutogenConfig {
|
||||||
public String projectname;
|
public String projectname;
|
||||||
public String address;
|
public String address;
|
||||||
public int clientPort;
|
public int clientPort;
|
||||||
@SuppressWarnings("unused")
|
|
||||||
private boolean isInitModules;
|
|
||||||
public String guardType;
|
public String guardType;
|
||||||
public String secretKeyClient;
|
public String secretKeyClient;
|
||||||
public String oemUnlockKey;
|
public String oemUnlockKey;
|
||||||
|
@ -23,5 +21,6 @@ public class AutogenConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initModules() {
|
public void initModules() {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,6 @@ public class ClientPermissions {
|
||||||
public boolean canUSR3;
|
public boolean canUSR3;
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public boolean canBot;
|
public boolean canBot;
|
||||||
@LauncherAPI
|
|
||||||
public boolean canProxy;
|
|
||||||
|
|
||||||
public ClientPermissions(HInput input) throws IOException {
|
public ClientPermissions(HInput input) throws IOException {
|
||||||
this(input.readLong());
|
this(input.readLong());
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipInputStream;
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
|
@ -19,10 +22,16 @@
|
||||||
import org.apache.http.impl.client.HttpClients;
|
import org.apache.http.impl.client.HttpClients;
|
||||||
import org.apache.http.impl.client.LaxRedirectStrategy;
|
import org.apache.http.impl.client.LaxRedirectStrategy;
|
||||||
|
|
||||||
import pro.gravit.utils.helper.IOHelper;
|
import pro.gravit.utils.helper.*;
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
|
||||||
|
|
||||||
public class ListDownloader {
|
public class ListDownloader {
|
||||||
|
private static final AtomicInteger COUNTER_THR = new AtomicInteger(0);
|
||||||
|
private static final ThreadFactory FACTORY = r -> CommonHelper.newThread("Downloader Thread #" + COUNTER_THR.incrementAndGet(), true, r);
|
||||||
|
|
||||||
|
private static ExecutorService newExecutor() {
|
||||||
|
return new ThreadPoolExecutor(0, VerifyHelper.verifyInt(Integer.parseInt(System.getProperty("launcher.downloadThreads", "3")), VerifyHelper.POSITIVE, "Thread max count must be positive."), 5, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), FACTORY);
|
||||||
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface DownloadCallback {
|
public interface DownloadCallback {
|
||||||
void stateChanged(String filename, long downloadedSize, long size);
|
void stateChanged(String filename, long downloadedSize, long size);
|
||||||
|
@ -47,19 +56,43 @@ public void download(String base, List<DownloadTask> applies, Path dstDirFile, D
|
||||||
try (CloseableHttpClient httpclient = HttpClients.custom()
|
try (CloseableHttpClient httpclient = HttpClients.custom()
|
||||||
.setRedirectStrategy(new LaxRedirectStrategy())
|
.setRedirectStrategy(new LaxRedirectStrategy())
|
||||||
.build()) {
|
.build()) {
|
||||||
|
applies.sort((a,b) -> Long.compare(a.size, b.size));
|
||||||
HttpGet get = null;
|
List<Callable<Void>> toExec = new ArrayList<>();
|
||||||
|
URI baseUri = new URI(base);
|
||||||
|
String scheme = baseUri.getScheme();
|
||||||
|
String host = baseUri.getHost();
|
||||||
|
int port = baseUri.getPort();
|
||||||
|
if (port != -1)
|
||||||
|
host = host + ":" + port;
|
||||||
|
String path = baseUri.getPath();
|
||||||
|
List<IOException> excs = new CopyOnWriteArrayList<>();
|
||||||
for (DownloadTask apply : applies) {
|
for (DownloadTask apply : applies) {
|
||||||
URI u = new URL(base.concat(IOHelper.urlEncode(apply.apply).replace("%2F", "/"))).toURI();
|
URI u = new URI(scheme, host, path + apply.apply, "", "");
|
||||||
callback.stateChanged(apply.apply, 0L, apply.size);
|
callback.stateChanged(apply.apply, 0L, apply.size);
|
||||||
Path targetPath = dstDirFile.resolve(apply.apply);
|
Path targetPath = dstDirFile.resolve(apply.apply);
|
||||||
|
toExec.add(() -> {
|
||||||
|
if (LogHelper.isDebugEnabled())
|
||||||
LogHelper.debug("Download URL: %s to file %s dir: %s", u.toString(), targetPath.toAbsolutePath().toString(), dstDirFile.toAbsolutePath().toString());
|
LogHelper.debug("Download URL: %s to file %s dir: %s", u.toString(), targetPath.toAbsolutePath().toString(), dstDirFile.toAbsolutePath().toString());
|
||||||
if (get == null) get = new HttpGet(u);
|
try {
|
||||||
else {
|
httpclient.execute(new HttpGet(u), new FileDownloadResponseHandler(targetPath, apply, callback, totalCallback, false));
|
||||||
get.reset();
|
} catch (IOException e) {
|
||||||
get.setURI(u);
|
excs.add(e);
|
||||||
}
|
}
|
||||||
httpclient.execute(get, new FileDownloadResponseHandler(targetPath, apply, callback, totalCallback, false));
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
ExecutorService e = newExecutor();
|
||||||
|
e.invokeAll(toExec);
|
||||||
|
e.shutdown();
|
||||||
|
e.awaitTermination(4, TimeUnit.HOURS);
|
||||||
|
} catch (InterruptedException t) {
|
||||||
|
LogHelper.error(t);
|
||||||
|
}
|
||||||
|
if (!excs.isEmpty()) {
|
||||||
|
IOException toThrow = excs.remove(0);
|
||||||
|
excs.forEach(toThrow::addSuppressed);
|
||||||
|
throw toThrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,7 +130,9 @@ public void downloadOne(String url, Path target) throws IOException, URISyntaxEx
|
||||||
|
|
||||||
HttpGet get;
|
HttpGet get;
|
||||||
URI u = new URL(url).toURI();
|
URI u = new URL(url).toURI();
|
||||||
|
if (LogHelper.isDebugEnabled()) {
|
||||||
LogHelper.debug("Download URL: %s", u.toString());
|
LogHelper.debug("Download URL: %s", u.toString());
|
||||||
|
}
|
||||||
get = new HttpGet(u);
|
get = new HttpGet(u);
|
||||||
httpclient.execute(get, new FileDownloadResponseHandler(target.toAbsolutePath()));
|
httpclient.execute(get, new FileDownloadResponseHandler(target.toAbsolutePath()));
|
||||||
}
|
}
|
||||||
|
@ -161,7 +196,9 @@ public Path handleResponse(HttpResponse response) throws IOException {
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
callback.stateChanged(entry.getName(), 0, entry.getSize());
|
callback.stateChanged(entry.getName(), 0, entry.getSize());
|
||||||
}
|
}
|
||||||
|
if (LogHelper.isDevEnabled()) {
|
||||||
LogHelper.dev("Resolved filename %s to %s", filename, target.toAbsolutePath().toString());
|
LogHelper.dev("Resolved filename %s to %s", filename, target.toAbsolutePath().toString());
|
||||||
|
}
|
||||||
transfer(source, target, filename, size, callback, totalCallback);
|
transfer(source, target, filename, size, callback, totalCallback);
|
||||||
entry = input.getNextEntry();
|
entry = input.getNextEntry();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
//Набор стандартных событий
|
//Набор стандартных событий
|
||||||
public class ControlEvent {
|
public class ControlEvent {
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private static final UUID uuid = UUID.fromString("f1051a64-0cd0-4ed8-8430-d856a196e91f");
|
private static final UUID uuid = UUID.fromString("f1051a64-0cd0-4ed8-8430-d856a196e91f");
|
||||||
|
|
||||||
public enum ControlCommand {
|
public enum ControlCommand {
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package pro.gravit.launcher.events.request;
|
package pro.gravit.launcher.events.request;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import pro.gravit.launcher.ClientPermissions;
|
import pro.gravit.launcher.ClientPermissions;
|
||||||
import pro.gravit.launcher.LauncherNetworkAPI;
|
import pro.gravit.launcher.LauncherNetworkAPI;
|
||||||
import pro.gravit.launcher.events.RequestEvent;
|
import pro.gravit.launcher.events.RequestEvent;
|
||||||
|
|