Merge branch 'dev' into feature/design

This commit is contained in:
Dmitriy Leo 2019-05-19 22:28:25 +03:00 committed by GitHub
commit 405caef0f4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
123 changed files with 1018 additions and 920 deletions

37
.gitlab-ci.yml Normal file
View file

@ -0,0 +1,37 @@
image: java:8-jdk
stages:
- build
- test
- deploy
before_script:
# - echo `pwd` # debug
# - echo "$CI_BUILD_NAME, $CI_BUILD_REF_NAME $CI_BUILD_STAGE" # debug
- export GRADLE_USER_HOME=`pwd`/.gradle
cache:
paths:
- .gradle/wrapper
- .gradle/caches
build:
stage: build
script:
- sed -i 's/git@github.com:/https:\/\/github.com\//' .gitmodules
- git submodule sync
- git submodule update --init --recursive
- ./gradlew assemble
artifacts:
paths:
- LaunchServer/build/libs/*
- ServerWrapper/build/libs/*.jar
expire_in: 1 week
test:
stage: test
script:
- ./gradlew check
after_script:
- echo "End CI"

View file

@ -44,13 +44,15 @@
pack project(':libLauncher') pack project(':libLauncher')
pack project(':LauncherAPI') pack project(':LauncherAPI')
bundle project(':Radon') bundle project(':Radon')
bundle 'mysql:mysql-connector-java:8.0.13' bundle 'mysql:mysql-connector-java:8.0.16'
bundle 'jline:jline:2.14.6' bundle 'org.jline:jline:3.11.0'
bundle 'net.sf.proguard:proguard-base:6.0.3' bundle 'org.jline:jline-reader:3.11.0'
bundle 'org.fusesource.jansi:jansi:1.17.1' bundle 'org.jline:jline-terminal:3.11.0'
bundle 'net.sf.proguard:proguard-base:6.1.0'
bundle 'org.fusesource.jansi:jansi:1.18'
bundle 'commons-io:commons-io:2.6' bundle 'commons-io:commons-io:2.6'
bundle 'commons-codec:commons-codec:1.11' bundle 'commons-codec:commons-codec:1.12'
bundle 'org.javassist:javassist:3.24.1-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.slf4j:slf4j-simple:1.7.25' bundle 'org.slf4j:slf4j-simple:1.7.25'

View file

@ -4,6 +4,7 @@
import ru.gravit.launcher.Launcher; import ru.gravit.launcher.Launcher;
import ru.gravit.launcher.LauncherConfig; import ru.gravit.launcher.LauncherConfig;
import ru.gravit.launcher.NeedGarbageCollection; import ru.gravit.launcher.NeedGarbageCollection;
import ru.gravit.launcher.config.JsonConfigurable;
import ru.gravit.launcher.hasher.HashedDir; import ru.gravit.launcher.hasher.HashedDir;
import ru.gravit.launcher.managers.ConfigManager; import ru.gravit.launcher.managers.ConfigManager;
import ru.gravit.launcher.managers.GarbageManager; import ru.gravit.launcher.managers.GarbageManager;
@ -38,7 +39,6 @@
import ru.gravit.utils.command.CommandHandler; import ru.gravit.utils.command.CommandHandler;
import ru.gravit.utils.command.JLineCommandHandler; import ru.gravit.utils.command.JLineCommandHandler;
import ru.gravit.utils.command.StdCommandHandler; import ru.gravit.utils.command.StdCommandHandler;
import ru.gravit.launcher.config.JsonConfigurable;
import ru.gravit.utils.helper.*; import ru.gravit.utils.helper.*;
import java.io.*; import java.io.*;
@ -200,8 +200,8 @@ public void verify() {
throw new NullPointerException("Netty must not be null"); throw new NullPointerException("Netty must not be null");
} }
} }
public void init()
{ public void init() {
Launcher.applyLauncherEnv(env); Launcher.applyLauncherEnv(env);
for (AuthProviderPair provider : auth) { for (AuthProviderPair provider : auth) {
provider.init(); provider.init();
@ -212,8 +212,7 @@ public void init()
protectHandler.checkLaunchServerLicense(); protectHandler.checkLaunchServerLicense();
} }
LaunchServer.server.registerObject("permissionsHandler", permissionsHandler); LaunchServer.server.registerObject("permissionsHandler", permissionsHandler);
for (int i = 0; i < auth.length; ++i) { for (AuthProviderPair pair : auth) {
AuthProviderPair pair = auth[i];
LaunchServer.server.registerObject("auth.".concat(pair.name).concat(".provider"), pair.provider); LaunchServer.server.registerObject("auth.".concat(pair.name).concat(".provider"), pair.provider);
LaunchServer.server.registerObject("auth.".concat(pair.name).concat(".handler"), pair.handler); LaunchServer.server.registerObject("auth.".concat(pair.name).concat(".handler"), pair.handler);
LaunchServer.server.registerObject("auth.".concat(pair.name).concat(".texture"), pair.textureProvider); LaunchServer.server.registerObject("auth.".concat(pair.name).concat(".texture"), pair.textureProvider);
@ -225,14 +224,12 @@ public void init()
public void close() { public void close() {
try { try {
LaunchServer.server.unregisterObject("permissionsHandler", permissionsHandler); LaunchServer.server.unregisterObject("permissionsHandler", permissionsHandler);
for (int i = 0; i < auth.length; ++i) { for (AuthProviderPair pair : auth) {
AuthProviderPair pair = auth[i];
LaunchServer.server.unregisterObject("auth.".concat(pair.name).concat(".provider"), pair.provider); LaunchServer.server.unregisterObject("auth.".concat(pair.name).concat(".provider"), pair.provider);
LaunchServer.server.unregisterObject("auth.".concat(pair.name).concat(".handler"), pair.handler); LaunchServer.server.unregisterObject("auth.".concat(pair.name).concat(".handler"), pair.handler);
LaunchServer.server.unregisterObject("auth.".concat(pair.name).concat(".texture"), pair.textureProvider); LaunchServer.server.unregisterObject("auth.".concat(pair.name).concat(".texture"), pair.textureProvider);
} }
} catch (Exception e) } catch (Exception e) {
{
LogHelper.error(e); LogHelper.error(e);
} }
try { try {
@ -266,10 +263,15 @@ public static class ExeConf {
public String txtFileVersion; public String txtFileVersion;
public String txtProductVersion; public String txtProductVersion;
} }
public static class NettyUpdatesBind
public class LauncherConf
{ {
public String url;
public boolean zip;
}
public class LauncherConf {
public String guardType; public String guardType;
public boolean attachLibraryBeforeProGuard;
} }
public class NettyConfig { public class NettyConfig {
@ -280,19 +282,19 @@ public class NettyConfig {
public String downloadURL; public String downloadURL;
public String launcherEXEURL; public String launcherEXEURL;
public String address; public String address;
public Map<String, String> bindings = new HashMap<>(); public Map<String, NettyUpdatesBind> bindings = new HashMap<>();
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 NettyProxyConfig proxy = new NettyProxyConfig();
} }
public class NettyPerformanceConfig
{ public class NettyPerformanceConfig {
public int bossThread; public int bossThread;
public int workerThread; public int workerThread;
} }
public class NettyProxyConfig
{ public class NettyProxyConfig {
public boolean enabled; public boolean enabled;
public String address = "ws://localhost:9275/api"; public String address = "ws://localhost:9275/api";
public String login = "login"; public String login = "login";
@ -300,8 +302,8 @@ public class NettyProxyConfig
public String auth_id = "std"; public String auth_id = "std";
public ArrayList<String> requests = new ArrayList<>(); public ArrayList<String> requests = new ArrayList<>();
} }
public class NettyBindAddress
{ public class NettyBindAddress {
public String address; public String address;
public int port; public int port;
@ -481,7 +483,7 @@ public LaunchServer(Path dir, boolean testEnv, String[] args) throws IOException
localCommandHandler = new StdCommandHandler(false); localCommandHandler = new StdCommandHandler(false);
else else
try { try {
Class.forName("jline.Terminal"); Class.forName("org.jline.terminal.Terminal");
// JLine2 available // JLine2 available
localCommandHandler = new JLineCommandHandler(); localCommandHandler = new JLineCommandHandler();
@ -532,14 +534,11 @@ public LaunchServer(Path dir, boolean testEnv, String[] args) throws IOException
try (BufferedReader reader = IOHelper.newReader(configFile)) { try (BufferedReader reader = IOHelper.newReader(configFile)) {
config = Launcher.gsonManager.gson.fromJson(reader, Config.class); config = Launcher.gsonManager.gson.fromJson(reader, Config.class);
} }
if(!Files.exists(runtimeConfigFile)) if (!Files.exists(runtimeConfigFile)) {
{
LogHelper.info("Reset LaunchServer runtime config file"); LogHelper.info("Reset LaunchServer runtime config file");
runtime = new LaunchServerRuntimeConfig(); runtime = new LaunchServerRuntimeConfig();
runtime.reset(); runtime.reset();
} } else {
else
{
LogHelper.info("Reading LaunchServer runtime config file"); LogHelper.info("Reading LaunchServer runtime config file");
try (BufferedReader reader = IOHelper.newReader(runtimeConfigFile)) { try (BufferedReader reader = IOHelper.newReader(runtimeConfigFile)) {
runtime = Launcher.gsonManager.gson.fromJson(reader, LaunchServerRuntimeConfig.class); runtime = Launcher.gsonManager.gson.fromJson(reader, LaunchServerRuntimeConfig.class);
@ -674,10 +673,8 @@ public void close() {
config.close(); config.close();
modulesManager.close(); modulesManager.close();
LogHelper.info("Save LaunchServer runtime config"); LogHelper.info("Save LaunchServer runtime config");
try(Writer writer = IOHelper.newWriter(runtimeConfigFile)) try (Writer writer = IOHelper.newWriter(runtimeConfigFile)) {
{ if (Launcher.gsonManager.configGson != null) {
if(Launcher.gsonManager.configGson != null)
{
Launcher.gsonManager.configGson.toJson(runtime, writer); Launcher.gsonManager.configGson.toJson(runtime, writer);
} else { } else {
LogHelper.error("Error writing LaunchServer runtime config file. Gson is null"); LogHelper.error("Error writing LaunchServer runtime config file. Gson is null");
@ -762,13 +759,11 @@ private void generateConfigIfNotExists(boolean testEnv) throws IOException {
System.out.println("LaunchServer projectName: "); System.out.println("LaunchServer projectName: ");
newConfig.setProjectName(commandHandler.readLine()); newConfig.setProjectName(commandHandler.readLine());
} }
if(address == null || address.isEmpty()) if (address == null || address.isEmpty()) {
{
LogHelper.error("Address null. Using localhost"); LogHelper.error("Address null. Using localhost");
address = "localhost"; address = "localhost";
} }
if(newConfig.projectName == null || newConfig.projectName.isEmpty()) if (newConfig.projectName == null || newConfig.projectName.isEmpty()) {
{
LogHelper.error("ProjectName null. Using MineCraft"); LogHelper.error("ProjectName null. Using MineCraft");
newConfig.projectName = "MineCraft"; newConfig.projectName = "MineCraft";
} }
@ -869,7 +864,8 @@ public void syncUpdatesDir(Collection<String> dirs) throws IOException {
// Resolve name and verify is dir // Resolve name and verify is dir
String name = IOHelper.getFileName(updateDir); String name = IOHelper.getFileName(updateDir);
if (!IOHelper.isDir(updateDir)) { if (!IOHelper.isDir(updateDir)) {
if (!IOHelper.isFile(updateDir) && Arrays.asList(".jar", ".exe", ".hash").stream().noneMatch(e -> updateDir.toString().endsWith(e))) LogHelper.warning("Not update dir: '%s'", name); if (!IOHelper.isFile(updateDir) && Arrays.asList(".jar", ".exe", ".hash").stream().noneMatch(e -> updateDir.toString().endsWith(e)))
LogHelper.warning("Not update dir: '%s'", name);
continue; continue;
} }
@ -920,6 +916,7 @@ public void registerObject(String name, Object object) {
} }
} }
public void unregisterObject(String name, Object object) { public void unregisterObject(String name, Object object) {
if (object instanceof Reloadable) { if (object instanceof Reloadable) {
reloadManager.unregisterReloadable(name); reloadManager.unregisterReloadable(name);

View file

@ -16,6 +16,7 @@ public final class StarterAgent {
private static final class StarterVisitor extends SimpleFileVisitor<Path> { private static final class StarterVisitor extends SimpleFileVisitor<Path> {
private static final Set<PosixFilePermission> DPERMS; private static final Set<PosixFilePermission> DPERMS;
static { static {
Set<PosixFilePermission> perms = new HashSet<>(Arrays.asList(PosixFilePermission.values())); Set<PosixFilePermission> perms = new HashSet<>(Arrays.asList(PosixFilePermission.values()));
perms.remove(PosixFilePermission.OTHERS_WRITE); perms.remove(PosixFilePermission.OTHERS_WRITE);
@ -33,13 +34,15 @@ private StarterVisitor() {
try { try {
Files.deleteIfExists(filef); Files.deleteIfExists(filef);
Files.createFile(filef); Files.createFile(filef);
} catch (Throwable t) { } } catch (Throwable ignored) {
}
} }
} }
@Override @Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
if (fixLib && Files.getFileAttributeView(file, PosixFileAttributeView.class) != null) Files.setPosixFilePermissions(file, DPERMS); if (fixLib && Files.getFileAttributeView(file, PosixFileAttributeView.class) != null)
Files.setPosixFilePermissions(file, DPERMS);
if (file.toFile().getName().endsWith(".jar")) if (file.toFile().getName().endsWith(".jar"))
inst.appendToSystemClassLoaderSearch(new JarFile(file.toFile())); inst.appendToSystemClassLoaderSearch(new JarFile(file.toFile()));
return super.visitFile(file, attrs); return super.visitFile(file, attrs);

View file

@ -11,24 +11,24 @@ public class JsonAuthHandler extends CachedAuthHandler {
public URL getUrl; public URL getUrl;
public URL updateAuthUrl; public URL updateAuthUrl;
public URL updateServerIdUrl; public URL updateServerIdUrl;
public class EntryRequestByUsername
{ public class EntryRequestByUsername {
public String username; public String username;
public EntryRequestByUsername(String username) { public EntryRequestByUsername(String username) {
this.username = username; this.username = username;
} }
} }
public class EntryRequestByUUID
{ public class EntryRequestByUUID {
public UUID uuid; public UUID uuid;
public EntryRequestByUUID(UUID uuid) { public EntryRequestByUUID(UUID uuid) {
this.uuid = uuid; this.uuid = uuid;
} }
} }
public class UpdateAuthRequest
{ public class UpdateAuthRequest {
public UUID uuid; public UUID uuid;
public String username; public String username;
public String accessToken; public String accessToken;
@ -39,8 +39,8 @@ public UpdateAuthRequest(UUID uuid, String username, String accessToken) {
this.accessToken = accessToken; this.accessToken = accessToken;
} }
} }
public class UpdateServerIDRequest
{ public class UpdateServerIDRequest {
public UUID uuid; public UUID uuid;
public String serverID; public String serverID;
@ -49,10 +49,11 @@ public UpdateServerIDRequest(UUID uuid, String serverID) {
this.serverID = serverID; this.serverID = serverID;
} }
} }
public class SuccessResponse
{ public class SuccessResponse {
public boolean success; public boolean success;
} }
@Override @Override
protected Entry fetchEntry(String username) throws IOException { protected Entry fetchEntry(String username) throws IOException {
return Launcher.gsonManager.configGson.fromJson(HTTPRequest.jsonRequest(Launcher.gsonManager.configGson.toJsonTree(new EntryRequestByUsername(username)), getUrl), Entry.class); return Launcher.gsonManager.configGson.fromJson(HTTPRequest.jsonRequest(Launcher.gsonManager.configGson.toJsonTree(new EntryRequestByUsername(username)), getUrl), Entry.class);

View file

@ -8,7 +8,6 @@ public abstract class ProtectHandler {
private static boolean registredHandl = false; private static boolean registredHandl = false;
public static void registerHandlers() { public static void registerHandlers() {
if (!registredHandl) { if (!registredHandl) {
providers.register("none", NoProtectHandler.class); providers.register("none", NoProtectHandler.class);
@ -19,7 +18,9 @@ public static void registerHandlers() {
public abstract String generateSecureToken(AuthResponse.AuthContext context); //Генерация токена для передачи его в LauncherGuardInterface public abstract String generateSecureToken(AuthResponse.AuthContext context); //Генерация токена для передачи его в LauncherGuardInterface
public abstract String generateClientSecureToken(); public abstract String generateClientSecureToken();
public abstract boolean verifyClientSecureToken(String token, String secureKey); public abstract boolean verifyClientSecureToken(String token, String secureKey);
public abstract boolean allowGetAccessToken(AuthResponse.AuthContext context); public abstract boolean allowGetAccessToken(AuthResponse.AuthContext context);
public abstract void checkLaunchServerLicense(); //Выдает SecurityException при ошибке проверки лицензии public abstract void checkLaunchServerLicense(); //Выдает SecurityException при ошибке проверки лицензии

View file

@ -29,7 +29,6 @@ public static void registerProviders() {
public abstract AuthProviderResult auth(String login, String password, String ip) throws Exception; public abstract AuthProviderResult auth(String login, String password, String ip) throws Exception;
public void preAuth(String login, String password, String customText, String ip) { public void preAuth(String login, String password, String customText, String ip) {
return;
} }
@Override @Override

View file

@ -42,10 +42,11 @@ public JARLauncherBinary(LaunchServer server) throws IOException {
public void init() { public void init() {
tasks.add(new PrepareBuildTask(server)); tasks.add(new PrepareBuildTask(server));
tasks.add(new MainBuildTask(server)); tasks.add(new MainBuildTask(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)); tasks.add(new RadonBuildTask(server));
tasks.add(new AttachJarsTask(server)); if(!server.config.launcher.attachLibraryBeforeProGuard) tasks.add(new AttachJarsTask(server));
} }
@Override @Override

View file

@ -46,7 +46,7 @@ public final boolean sync() throws IOException {
return exists; return exists;
} }
public static final Path resolve(LaunchServer server, String ext) { public static Path resolve(LaunchServer server, String ext) {
return server.config.copyBinaries ? server.updatesDir.resolve(server.config.binaryName + ext) : server.dir.resolve(server.config.binaryName + ext); return server.config.copyBinaries ? server.updatesDir.resolve(server.config.binaryName + ext) : server.dir.resolve(server.config.binaryName + ext);
} }
} }

View file

@ -40,8 +40,8 @@ public Path process(Path inputFile) throws IOException {
SessionInfo info = p.createSessionFromConfig(); SessionInfo info = p.createSessionFromConfig();
info.setInput(inputFile.toFile()); info.setInput(inputFile.toFile());
info.setOutput(outputFile.toFile()); info.setOutput(outputFile.toFile());
List<File> libs = srv.launcherBinary.coreLibs.stream().map(e -> e.toFile()).collect(Collectors.toList()); List<File> libs = srv.launcherBinary.coreLibs.stream().map(Path::toFile).collect(Collectors.toList());
libs.addAll(srv.launcherBinary.addonLibs.stream().map(e -> e.toFile()).collect(Collectors.toList())); libs.addAll(srv.launcherBinary.addonLibs.stream().map(Path::toFile).collect(Collectors.toList()));
info.setLibraries(libs); info.setLibraries(libs);
Radon r = new Radon(info); Radon r = new Radon(info);
r.run(); r.run();

View file

@ -8,13 +8,13 @@
public final class TaskUtil { public final class TaskUtil {
public static void addCounted(List<LauncherBuildTask> tasks, int count, Predicate<LauncherBuildTask> pred, LauncherBuildTask taskAdd) { public static void addCounted(List<LauncherBuildTask> tasks, int count, Predicate<LauncherBuildTask> pred, LauncherBuildTask taskAdd) {
List<LauncherBuildTask> indexes = new ArrayList<>(); List<LauncherBuildTask> indexes = new ArrayList<>();
tasks.stream().filter(pred).forEach(e -> indexes.add(e)); tasks.stream().filter(pred).forEach(indexes::add);
indexes.forEach(e -> tasks.add(tasks.indexOf(e) + count, taskAdd)); indexes.forEach(e -> tasks.add(tasks.indexOf(e) + count, taskAdd));
} }
public static void replaceCounted(List<LauncherBuildTask> tasks, int count, Predicate<LauncherBuildTask> pred, LauncherBuildTask taskRep) { public static void replaceCounted(List<LauncherBuildTask> tasks, int count, Predicate<LauncherBuildTask> pred, LauncherBuildTask taskRep) {
List<LauncherBuildTask> indexes = new ArrayList<>(); List<LauncherBuildTask> indexes = new ArrayList<>();
tasks.stream().filter(pred).forEach(e -> indexes.add(e)); tasks.stream().filter(pred).forEach(indexes::add);
indexes.forEach(e -> tasks.set(tasks.indexOf(e) + count, taskRep)); indexes.forEach(e -> tasks.set(tasks.indexOf(e) + count, taskRep));
} }

View file

@ -26,10 +26,8 @@ public String getUsageDescription() {
public void invoke(String... args) throws Exception { public void invoke(String... args) throws Exception {
verifyArgs(args, 1); verifyArgs(args, 1);
List<HWID> target = server.config.hwidHandler.getHwid(args[0]); List<HWID> target = server.config.hwidHandler.getHwid(args[0]);
for(HWID hwid : target) for (HWID hwid : target) {
{ if (hwid == null) {
if(hwid == null)
{
LogHelper.error("HWID %s: null", args[0]); LogHelper.error("HWID %s: null", args[0]);
continue; continue;
} }

View file

@ -35,8 +35,7 @@ public void invoke(String... args) throws Exception {
if (args[0].equals("stop")) { if (args[0].equals("stop")) {
handler.close(); handler.close();
} }
if (args[0].equals("eventAll")) if (args[0].equals("eventAll")) {
{
WebSocketFrameHandler.service.sendObjectAll(new PingEvent()); WebSocketFrameHandler.service.sendObjectAll(new PingEvent());
} }
} }

View file

@ -35,8 +35,7 @@ public void invoke(String... args) {
LogHelper.info("Uptime: %d days %d hours %d minutes %d seconds", days, hour, min, second); LogHelper.info("Uptime: %d days %d hours %d minutes %d seconds", days, hour, min, second);
LogHelper.info("Uptime (double): %f", (double) JVMHelper.RUNTIME_MXBEAN.getUptime() / 1000); LogHelper.info("Uptime (double): %f", (double) JVMHelper.RUNTIME_MXBEAN.getUptime() / 1000);
int commands = server.commandHandler.getBaseCategory().commandsMap().size(); int commands = server.commandHandler.getBaseCategory().commandsMap().size();
for(CommandHandler.Category category : server.commandHandler.getCategories()) for (CommandHandler.Category category : server.commandHandler.getCategories()) {
{
commands += category.category.commandsMap().size(); commands += category.category.commandsMap().size();
} }
LogHelper.info("Sessions: %d | Modules: %d | Commands: %d(%d categories)", server.sessionManager.getSessions().size(), server.modulesManager.modules.size(), commands, server.commandHandler.getCategories().size() + 1); LogHelper.info("Sessions: %d | Modules: %d | Commands: %d(%d categories)", server.sessionManager.getSessions().size(), server.modulesManager.modules.size(), commands, server.commandHandler.getCategories().size() + 1);

View file

@ -5,12 +5,12 @@
public class LaunchServerRuntimeConfig { public class LaunchServerRuntimeConfig {
public String clientToken; public String clientToken;
public void verify()
{ public void verify() {
if (clientToken == null) LogHelper.error("[RuntimeConfig] clientToken must not be null"); if (clientToken == null) LogHelper.error("[RuntimeConfig] clientToken must not be null");
} }
public void reset()
{ public void reset() {
clientToken = SecurityHelper.randomStringToken(); clientToken = SecurityHelper.randomStringToken();
} }
} }

View file

@ -82,7 +82,7 @@ protected final void debug(String message, Object... args) {
public abstract void reply() throws Exception; public abstract void reply() throws Exception;
protected static final void writeNoError(HOutput output) throws IOException { protected static void writeNoError(HOutput output) throws IOException {
output.writeString("", 0); output.writeString("", 0);
} }
} }

View file

@ -14,8 +14,8 @@ public void registerReconfigurable(String name, Reconfigurable reconfigurable) {
VerifyHelper.putIfAbsent(RECONFIGURABLE, name.toLowerCase(), Objects.requireNonNull(reconfigurable, "adapter"), VerifyHelper.putIfAbsent(RECONFIGURABLE, name.toLowerCase(), Objects.requireNonNull(reconfigurable, "adapter"),
String.format("Reloadable has been already registered: '%s'", name)); String.format("Reloadable has been already registered: '%s'", name));
} }
public Reconfigurable unregisterReconfigurable(String name)
{ public Reconfigurable unregisterReconfigurable(String name) {
return RECONFIGURABLE.remove(name); return RECONFIGURABLE.remove(name);
} }

View file

@ -14,8 +14,8 @@ public void registerReloadable(String name, Reloadable reloadable) {
VerifyHelper.putIfAbsent(RELOADABLES, name.toLowerCase(), Objects.requireNonNull(reloadable, "adapter"), VerifyHelper.putIfAbsent(RELOADABLES, name.toLowerCase(), Objects.requireNonNull(reloadable, "adapter"),
String.format("Reloadable has been already registered: '%s'", name.toLowerCase())); String.format("Reloadable has been already registered: '%s'", name.toLowerCase()));
} }
public Reloadable unregisterReloadable(String name)
{ public Reloadable unregisterReloadable(String name) {
return RELOADABLES.remove(name); return RELOADABLES.remove(name);
} }

View file

@ -44,15 +44,16 @@ public void initChannel(NioSocketChannel ch) {
//p.addLast(new LoggingHandler(LogLevel.INFO)); //p.addLast(new LoggingHandler(LogLevel.INFO));
pipeline.addLast(new HttpServerCodec()); pipeline.addLast(new HttpServerCodec());
pipeline.addLast(new HttpObjectAggregator(65536)); pipeline.addLast(new HttpObjectAggregator(65536));
if (LaunchServer.server.config.netty.ipForwarding) pipeline.addLast(new NettyIpForwardHandler(context)); if (LaunchServer.server.config.netty.ipForwarding)
pipeline.addLast(new NettyIpForwardHandler(context));
pipeline.addLast(new WebSocketServerCompressionHandler()); pipeline.addLast(new WebSocketServerCompressionHandler());
pipeline.addLast(new WebSocketServerProtocolHandler(WEBSOCKET_PATH, null, true)); pipeline.addLast(new WebSocketServerProtocolHandler(WEBSOCKET_PATH, null, true));
if (LaunchServer.server.config.netty.fileServerEnabled) pipeline.addLast(new FileServerHandler(LaunchServer.server.updatesDir, true)); if (LaunchServer.server.config.netty.fileServerEnabled)
pipeline.addLast(new FileServerHandler(LaunchServer.server.updatesDir, true));
pipeline.addLast(new WebSocketFrameHandler(context)); pipeline.addLast(new WebSocketFrameHandler(context));
} }
}); });
if(config.proxy != null && config.proxy.enabled) if (config.proxy != null && config.proxy.enabled) {
{
LogHelper.info("Connect to main server %s"); LogHelper.info("Connect to main server %s");
Request.service = StandartClientWebSocketService.initWebSockets(config.proxy.address, false); 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 authRequest = new AuthRequest(config.proxy.login, config.proxy.password, config.proxy.auth_id, AuthRequest.ConnectTypes.PROXY);
@ -64,8 +65,8 @@ public void initChannel(NioSocketChannel ch) {
} }
} }
} }
public ChannelFuture bind(InetSocketAddress address)
{ public ChannelFuture bind(InetSocketAddress address) {
return serverBootstrap.bind(address); return serverBootstrap.bind(address);
} }

View file

@ -19,8 +19,7 @@ public NettyIpForwardHandler(NettyConnectContext context) {
@Override @Override
protected void decode(ChannelHandlerContext ctx, HttpRequest msg, List<Object> out) throws Exception { protected void decode(ChannelHandlerContext ctx, HttpRequest msg, List<Object> out) throws Exception {
if(msg instanceof ReferenceCounted) if (msg instanceof ReferenceCounted) {
{
((ReferenceCounted) msg).retain(); ((ReferenceCounted) msg).retain();
} }
if (context.ip != null) { if (context.ip != null) {

View file

@ -105,8 +105,7 @@ public void run() {
//engine.setUseClientMode(false); //engine.setUseClientMode(false);
WebSocketFrameHandler.server = LaunchServer.server; WebSocketFrameHandler.server = LaunchServer.server;
nettyServer = new LauncherNettyServer(); nettyServer = new LauncherNettyServer();
for(LaunchServer.NettyBindAddress address : LaunchServer.server.config.netty.binds) for (LaunchServer.NettyBindAddress address : LaunchServer.server.config.netty.binds) {
{
nettyServer.bind(new InetSocketAddress(address.address, address.port)); nettyServer.bind(new InetSocketAddress(address.address, address.port));
} }
/* /*

View file

@ -28,8 +28,8 @@ public WebSocketFrameHandler(NettyConnectContext context) {
static { static {
service.registerResponses(); service.registerResponses();
} }
public void setClient(Client client)
{ public void setClient(Client client) {
this.client = client; this.client = client;
} }
@ -52,11 +52,9 @@ protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) {
frame.content().retain(); frame.content().retain();
ctx.channel().writeAndFlush(new PongWebSocketFrame(frame.content())); ctx.channel().writeAndFlush(new PongWebSocketFrame(frame.content()));
//return; //return;
} } else if ((frame instanceof PongWebSocketFrame)) {
else if ((frame instanceof PongWebSocketFrame)) {
LogHelper.dev("WebSocket Client received pong"); LogHelper.dev("WebSocket Client received pong");
} } else if ((frame instanceof CloseWebSocketFrame)) {
else if ((frame instanceof CloseWebSocketFrame)) {
ctx.channel().close(); ctx.channel().close();
} else { } else {
String message = "unsupported frame type: " + frame.getClass().getName(); String message = "unsupported frame type: " + frame.getClass().getName();

View file

@ -66,14 +66,11 @@ public WebSocketService(ChannelGroup channels, LaunchServer server, GsonBuilder
void process(ChannelHandlerContext ctx, TextWebSocketFrame frame, Client client, String ip) { void process(ChannelHandlerContext ctx, TextWebSocketFrame frame, Client client, String ip) {
String request = frame.text(); String request = frame.text();
JsonResponseInterface response = gson.fromJson(request, JsonResponseInterface.class); JsonResponseInterface response = gson.fromJson(request, JsonResponseInterface.class);
if(server.config.netty.proxy.enabled) if (server.config.netty.proxy.enabled) {
{ if (server.config.netty.proxy.requests.contains(response.getType())) {
if(server.config.netty.proxy.requests.contains(response.getType()))
{
UUID origRequestUUID = null; UUID origRequestUUID = null;
if(response instanceof SimpleResponse) if (response instanceof SimpleResponse) {
{
SimpleResponse simpleResponse = (SimpleResponse) response; SimpleResponse simpleResponse = (SimpleResponse) response;
simpleResponse.server = server; simpleResponse.server = server;
simpleResponse.service = this; simpleResponse.service = this;
@ -85,42 +82,35 @@ void process(ChannelHandlerContext ctx, TextWebSocketFrame frame, Client client,
LogHelper.debug("Proxy %s request", response.getType()); LogHelper.debug("Proxy %s request", response.getType());
if (client.session == 0) client.session = new Random().nextLong(); if (client.session == 0) client.session = new Random().nextLong();
ProxyRequest proxyRequest = new ProxyRequest(response, client.session); ProxyRequest proxyRequest = new ProxyRequest(response, client.session);
if(response instanceof SimpleResponse) if (response instanceof SimpleResponse) {
{
((SimpleResponse) response).requestUUID = proxyRequest.requestUUID; ((SimpleResponse) response).requestUUID = proxyRequest.requestUUID;
} }
proxyRequest.isCheckSign = client.checkSign; proxyRequest.isCheckSign = client.checkSign;
try { try {
ResultInterface result = proxyRequest.request(); ResultInterface result = proxyRequest.request();
if(result instanceof AuthRequestEvent) if (result instanceof AuthRequestEvent) {
{
LogHelper.debug("Client auth params get successful"); LogHelper.debug("Client auth params get successful");
AuthRequestEvent authRequestEvent = (AuthRequestEvent) result; AuthRequestEvent authRequestEvent = (AuthRequestEvent) result;
client.isAuth = true; client.isAuth = true;
client.session = authRequestEvent.session; client.session = authRequestEvent.session;
if(authRequestEvent.playerProfile != null) client.username = authRequestEvent.playerProfile.username; if (authRequestEvent.playerProfile != null)
client.username = authRequestEvent.playerProfile.username;
} }
if(result instanceof Request && response instanceof SimpleResponse) if (result instanceof Request && response instanceof SimpleResponse) {
{
((Request) result).requestUUID = origRequestUUID; ((Request) result).requestUUID = origRequestUUID;
} }
sendObject(ctx, result); sendObject(ctx, result);
} catch (RequestException e) } catch (RequestException e) {
{
sendObject(ctx, new ErrorRequestEvent(e.getMessage())); sendObject(ctx, new ErrorRequestEvent(e.getMessage()));
} catch (Exception e) { } catch (Exception e) {
LogHelper.error(e); LogHelper.error(e);
RequestEvent event; RequestEvent event;
if(server.config.netty.sendExceptionEnabled) if (server.config.netty.sendExceptionEnabled) {
{
event = new ExceptionEvent(e); event = new ExceptionEvent(e);
} } else {
else
{
event = new ErrorRequestEvent("Fatal server error. Contact administrator"); event = new ErrorRequestEvent("Fatal server error. Contact administrator");
} }
if(response instanceof SimpleResponse) if (response instanceof SimpleResponse) {
{
event.requestUUID = ((SimpleResponse) response).requestUUID; event.requestUUID = ((SimpleResponse) response).requestUUID;
} }
sendObject(ctx, event); sendObject(ctx, event);
@ -130,10 +120,9 @@ void process(ChannelHandlerContext ctx, TextWebSocketFrame frame, Client client,
} }
process(ctx, response, client, ip); process(ctx, response, client, ip);
} }
void process(ChannelHandlerContext ctx, JsonResponseInterface response, Client client, String ip)
{ void process(ChannelHandlerContext ctx, JsonResponseInterface response, Client client, String ip) {
if(response instanceof SimpleResponse) if (response instanceof SimpleResponse) {
{
SimpleResponse simpleResponse = (SimpleResponse) response; SimpleResponse simpleResponse = (SimpleResponse) response;
simpleResponse.server = server; simpleResponse.server = server;
simpleResponse.service = this; simpleResponse.service = this;
@ -146,16 +135,12 @@ void process(ChannelHandlerContext ctx, JsonResponseInterface response, Client c
} catch (Exception e) { } catch (Exception e) {
LogHelper.error(e); LogHelper.error(e);
RequestEvent event; RequestEvent event;
if(server.config.netty.sendExceptionEnabled) if (server.config.netty.sendExceptionEnabled) {
{
event = new ExceptionEvent(e); event = new ExceptionEvent(e);
} } else {
else
{
event = new ErrorRequestEvent("Fatal server error. Contact administrator"); event = new ErrorRequestEvent("Fatal server error. Contact administrator");
} }
if(response instanceof SimpleResponse) if (response instanceof SimpleResponse) {
{
event.requestUUID = ((SimpleResponse) response).requestUUID; event.requestUUID = ((SimpleResponse) response).requestUUID;
} }
sendObject(ctx, event); sendObject(ctx, event);
@ -204,15 +189,13 @@ public void sendObject(ChannelHandlerContext ctx, Object obj, Type type) {
} }
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, ResultInterface.class))); ch.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, ResultInterface.class)));
} }
} }
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)));
} }
} }

View file

@ -15,18 +15,18 @@ public abstract class SimpleResponse implements JsonResponseInterface {
public transient WebSocketService service; public transient WebSocketService service;
public transient ChannelHandlerContext ctx; public transient ChannelHandlerContext ctx;
public transient String ip; public transient String ip;
public void sendResult(RequestEvent result)
{ public void sendResult(RequestEvent result) {
result.requestUUID = requestUUID; result.requestUUID = requestUUID;
service.sendObject(ctx, result); service.sendObject(ctx, result);
} }
public void sendResultAndClose(RequestEvent result)
{ public void sendResultAndClose(RequestEvent result) {
result.requestUUID = requestUUID; result.requestUUID = requestUUID;
service.sendObjectAndClose(ctx, result); service.sendObjectAndClose(ctx, result);
} }
public void sendError(String errorMessage)
{ public void sendError(String errorMessage) {
ErrorRequestEvent event = new ErrorRequestEvent(errorMessage); ErrorRequestEvent event = new ErrorRequestEvent(errorMessage);
event.requestUUID = requestUUID; event.requestUUID = requestUUID;
service.sendObject(ctx, event); service.sendObject(ctx, event);

View file

@ -9,6 +9,7 @@ public class ProxyCommandResponse extends SimpleResponse {
public JsonResponseInterface response; public JsonResponseInterface response;
public long session; public long session;
public boolean isCheckSign; public boolean isCheckSign;
@Override @Override
public void execute(ChannelHandlerContext ctx, Client client) throws Exception { public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
if (!client.proxy) { if (!client.proxy) {

View file

@ -113,21 +113,18 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti
clientData.updateAuth(); clientData.updateAuth();
result.accessToken = aresult.accessToken; result.accessToken = aresult.accessToken;
result.permissions = clientData.permissions; result.permissions = clientData.permissions;
if(getSession) if (getSession) {
{
if (clientData.session == 0) { if (clientData.session == 0) {
clientData.session = random.nextLong(); clientData.session = random.nextLong();
LaunchServer.server.sessionManager.addClient(clientData); LaunchServer.server.sessionManager.addClient(clientData);
} }
result.session = clientData.session; result.session = clientData.session;
} }
if(initProxy) if (initProxy) {
{
if (!clientData.permissions.canProxy) throw new AuthException("initProxy not allow"); if (!clientData.permissions.canProxy) throw new AuthException("initProxy not allow");
clientData.proxy = true; clientData.proxy = true;
} }
if(LaunchServer.server.config.protectHandler.allowGetAccessToken(context)) if (LaunchServer.server.config.protectHandler.allowGetAccessToken(context)) {
{
UUID uuid = pair.handler.auth(aresult); UUID uuid = pair.handler.auth(aresult);
result.playerProfile = ProfileByUUIDResponse.getProfile(LaunchServer.server, uuid, aresult.username, client, clientData.auth.textureProvider); result.playerProfile = ProfileByUUIDResponse.getProfile(LaunchServer.server, uuid, aresult.username, client, clientData.auth.textureProvider);
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());
@ -137,6 +134,7 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti
sendError(e.getMessage()); sendError(e.getMessage());
} }
} }
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, boolean isServerAuth) { public AuthContext(long session, String login, int password_lenght, String customText, String client, String hwid, String ip, boolean isServerAuth) {
this.session = session; this.session = session;

View file

@ -19,8 +19,7 @@ public String getType() {
@Override @Override
public void execute(ChannelHandlerContext ctx, Client client) { public void execute(ChannelHandlerContext ctx, Client client) {
List<GetAvailabilityAuthRequestEvent.AuthAvailability> list = new ArrayList<>(); List<GetAvailabilityAuthRequestEvent.AuthAvailability> list = new ArrayList<>();
for(AuthProviderPair pair : LaunchServer.server.config.auth) for (AuthProviderPair pair : LaunchServer.server.config.auth) {
{
list.add(new GetAvailabilityAuthRequestEvent.AuthAvailability(pair.name, pair.displayName)); list.add(new GetAvailabilityAuthRequestEvent.AuthAvailability(pair.name, pair.displayName));
} }
sendResult(new GetAvailabilityAuthRequestEvent(list)); sendResult(new GetAvailabilityAuthRequestEvent(list));

View file

@ -18,17 +18,16 @@ public class JoinServerResponse extends SimpleResponse {
public String getType() { public String getType() {
return "joinServer"; return "joinServer";
} }
@Override @Override
public void execute(ChannelHandlerContext ctx, Client client) { public void execute(ChannelHandlerContext ctx, Client client) {
boolean success; boolean success;
try { try {
server.authHookManager.joinServerHook.hook(this, client); server.authHookManager.joinServerHook.hook(this, client);
if(client.auth == null) if (client.auth == null) {
{
LogHelper.warning("Client auth is null. Using default."); LogHelper.warning("Client auth is null. Using default.");
success = LaunchServer.server.config.getAuthProviderPair().handler.joinServer(username, accessToken, serverID); success = LaunchServer.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);
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());

View file

@ -11,6 +11,7 @@
public class RestoreSessionResponse extends SimpleResponse { public class RestoreSessionResponse extends SimpleResponse {
@LauncherNetworkAPI @LauncherNetworkAPI
public long session; public long session;
@Override @Override
public String getType() { public String getType() {
return "restoreSession"; return "restoreSession";
@ -19,8 +20,7 @@ public String getType() {
@Override @Override
public void execute(ChannelHandlerContext ctx, Client client) { public void execute(ChannelHandlerContext ctx, Client client) {
Client rClient = LaunchServer.server.sessionManager.getClient(session); Client rClient = LaunchServer.server.sessionManager.getClient(session);
if(rClient == null) if (rClient == null) {
{
sendError("Session invalid"); sendError("Session invalid");
} }
WebSocketFrameHandler frameHandler = ctx.pipeline().get(WebSocketFrameHandler.class); WebSocketFrameHandler frameHandler = ctx.pipeline().get(WebSocketFrameHandler.class);

View file

@ -26,8 +26,7 @@ public void execute(ChannelHandlerContext ctx, Client client) {
} }
try { try {
server.authHookManager.setProfileHook.hook(this, client); server.authHookManager.setProfileHook.hook(this, client);
} catch (HookException e) } catch (HookException e) {
{
sendError(e.getMessage()); sendError(e.getMessage());
} }
Collection<ClientProfile> profiles = LaunchServer.server.getProfiles(); Collection<ClientProfile> profiles = LaunchServer.server.getProfiles();

View file

@ -29,12 +29,10 @@ public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
result.playerProfiles = new PlayerProfile[list.length]; result.playerProfiles = new PlayerProfile[list.length];
for (int i = 0; i < list.length; ++i) { for (int i = 0; i < list.length; ++i) {
UUID uuid; UUID uuid;
if(client.auth == null) if (client.auth == null) {
{
LogHelper.warning("Client auth is null. Using default."); LogHelper.warning("Client auth is null. Using default.");
uuid = LaunchServer.server.config.getAuthProviderPair().handler.usernameToUUID(list[i].username); uuid = LaunchServer.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(LaunchServer.server, uuid, list[i].username, list[i].client, client.auth.textureProvider); result.playerProfiles[i] = ProfileByUUIDResponse.getProfile(LaunchServer.server, uuid, list[i].username, list[i].client, client.auth.textureProvider);
} }
sendResult(result); sendResult(result);

View file

@ -48,12 +48,10 @@ 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;
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 = LaunchServer.server.config.getAuthProviderPair().handler.uuidToUsername(uuid); username = LaunchServer.server.config.getAuthProviderPair().handler.uuidToUsername(uuid);
} } else username = client.auth.handler.uuidToUsername(uuid);
else username = client.auth.handler.uuidToUsername(uuid);
sendResult(new ProfileByUUIDRequestEvent(getProfile(LaunchServer.server, uuid, username, this.client, client.auth.textureProvider))); sendResult(new ProfileByUUIDRequestEvent(getProfile(LaunchServer.server, uuid, username, this.client, client.auth.textureProvider)));
} }
} }

View file

@ -23,12 +23,10 @@ public String getType() {
@Override @Override
public void execute(ChannelHandlerContext ctx, Client client) throws Exception { public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
UUID uuid; UUID uuid;
if(client.auth == null) if (client.auth == null) {
{
LogHelper.warning("Client auth is null. Using default."); LogHelper.warning("Client auth is null. Using default.");
uuid = LaunchServer.server.config.getAuthProviderPair().handler.usernameToUUID(username); uuid = LaunchServer.server.config.getAuthProviderPair().handler.usernameToUUID(username);
} } else uuid = client.auth.handler.usernameToUUID(username);
else uuid = client.auth.handler.usernameToUUID(username);
sendResult(new ProfileByUsernameRequestEvent(getProfile(LaunchServer.server, uuid, username, this.client, client.auth.textureProvider))); sendResult(new ProfileByUsernameRequestEvent(getProfile(LaunchServer.server, uuid, username, this.client, client.auth.textureProvider)));
} }
} }

View file

@ -34,13 +34,18 @@ public void execute(ChannelHandlerContext ctx, Client client) {
} }
} }
SignedObjectHolder<HashedDir> dir = LaunchServer.server.updatesDirMap.get(dirName); SignedObjectHolder<HashedDir> dir = LaunchServer.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;
} }
String url = LaunchServer.server.config.netty.downloadURL.replace("%dirname%", dirName); String url = LaunchServer.server.config.netty.downloadURL.replace("%dirname%", dirName);
if(server.config.netty.bindings.get(dirName) != null) url = server.config.netty.bindings.get(dirName); boolean zip = false;
service.sendObject(ctx, new UpdateRequestEvent(dir.object, url)); if (server.config.netty.bindings.get(dirName) != null)
{
LaunchServer.NettyUpdatesBind bind = server.config.netty.bindings.get(dirName);
url = bind.url;
zip = bind.zip;
}
service.sendObject(ctx, new UpdateRequestEvent(dir.object, url, zip));
} }
} }

View file

@ -20,7 +20,7 @@ public static void main(String[] args) throws IOException {
LogHelper.warning("Permission canAdmin not found"); LogHelper.warning("Permission canAdmin not found");
} }
try { try {
Class.forName("jline.Terminal"); Class.forName("org.jline.terminal.Terminal");
// JLine2 available // JLine2 available
commandHandler = new JLineCommandHandler(); commandHandler = new JLineCommandHandler();
@ -33,8 +33,8 @@ public static void main(String[] args) throws IOException {
LogHelper.info("CommandHandler started. Use 'exit' to exit this console"); LogHelper.info("CommandHandler started. Use 'exit' to exit this console");
commandHandler.run(); commandHandler.run();
} }
public static void registerCommands()
{ public static void registerCommands() {
commandHandler.registerCommand("help", new HelpCommand(commandHandler)); commandHandler.registerCommand("help", new HelpCommand(commandHandler));
commandHandler.registerCommand("exit", new ExitCommand()); commandHandler.registerCommand("exit", new ExitCommand());
commandHandler.registerCommand("logListener", new LogListenerCommand()); commandHandler.registerCommand("logListener", new LogListenerCommand());

View file

@ -8,8 +8,7 @@
import ru.gravit.utils.helper.LogHelper; import ru.gravit.utils.helper.LogHelper;
public class LogListenerCommand extends Command { public class LogListenerCommand extends Command {
public class LogListenerRequest implements RequestInterface public class LogListenerRequest implements RequestInterface {
{
@LauncherNetworkAPI @LauncherNetworkAPI
public LogHelper.OutputTypes outputType; public LogHelper.OutputTypes outputType;
@ -22,6 +21,7 @@ public String getType() {
return "addLogListener"; return "addLogListener";
} }
} }
@Override @Override
public String getArgsDescription() { public String getArgsDescription() {
return null; return null;
@ -38,8 +38,7 @@ public void invoke(String... args) throws Exception {
Request.service.sendObject(new LogListenerRequest(LogHelper.JANSI ? LogHelper.OutputTypes.JANSI : LogHelper.OutputTypes.PLAIN)); Request.service.sendObject(new LogListenerRequest(LogHelper.JANSI ? LogHelper.OutputTypes.JANSI : LogHelper.OutputTypes.PLAIN));
LogHelper.info("Add log handler"); LogHelper.info("Add log handler");
Request.service.registerHandler((result) -> { Request.service.registerHandler((result) -> {
if(result instanceof LogEvent) if (result instanceof LogEvent) {
{
System.out.println(((LogEvent) result).string); System.out.println(((LogEvent) result).string);
} }
}); });

View file

@ -45,7 +45,6 @@ function initLoginScene() {
var loginLayout = loginPane.lookup("#layout"); var loginLayout = loginPane.lookup("#layout");
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);
@ -419,7 +418,6 @@ var overlay = {
dimPane.setVisible(true); dimPane.setVisible(true);
dimPane.toFront(); dimPane.toFront();
loginPaneLayout.setEffect(new javafx.scene.effect.GaussianBlur(10)); loginPaneLayout.setEffect(new javafx.scene.effect.GaussianBlur(10));
serverPaneLayout.setEffect(new javafx.scene.effect.GaussianBlur(10)); serverPaneLayout.setEffect(new javafx.scene.effect.GaussianBlur(10));
fade(dimPane, 0.0, 0.0, 1.0, function(event) { fade(dimPane, 0.0, 0.0, 1.0, function(event) {
@ -441,7 +439,6 @@ var overlay = {
authPane.setDisable(false); authPane.setDisable(false);
rootPane.requestFocus(); rootPane.requestFocus();
loginPaneLayout.setEffect(new javafx.scene.effect.GaussianBlur(0)); loginPaneLayout.setEffect(new javafx.scene.effect.GaussianBlur(0));
serverPaneLayout.setEffect(new javafx.scene.effect.GaussianBlur(0)); serverPaneLayout.setEffect(new javafx.scene.effect.GaussianBlur(0));
overlay.current = null; overlay.current = null;

View file

@ -8,7 +8,8 @@
<body style="color:red"> <body style="color:red">
<h2>Offline-режим</h2> <h2>Offline-режим</h2>
Лаунчер запущен в Offline-режиме. В этом режиме Вы можете запустить любой ранее загруженный клиент Лаунчер запущен в Offline-режиме. В этом режиме Вы можете запустить любой ранее загруженный клиент
с любым именем пользователя, при этом вход на серверы с авторизацией, а так же система скинов и плащей <b>может не работать</b>. с любым именем пользователя, при этом вход на серверы с авторизацией, а так же система скинов и плащей <b>может не
работать</b>.
Скорее всего, проблема вызвана сбоем на сервере или неполадками в интернет-подключении. Скорее всего, проблема вызвана сбоем на сервере или неполадками в интернет-подключении.
Проверьте состояние интернет-подключения или обратитесь к администратору сервера. Проверьте состояние интернет-подключения или обратитесь к администратору сервера.
</body> </body>

View file

@ -8,7 +8,8 @@
<!-- 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.201"
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"/>
@ -18,7 +19,9 @@
<JFXTextArea fx:id="output" focusColor="#5fd97a" prefHeight="450.0" prefWidth="693.0"> <JFXTextArea fx:id="output" focusColor="#5fd97a" prefHeight="450.0" prefWidth="693.0">
<padding> <padding>
<Insets left="10.0" right="10.0"/> <Insets left="10.0" right="10.0"/>
</padding></JFXTextArea> </padding>
<JFXButton fx:id="copy" defaultButton="true" layoutX="373.0" layoutY="415.0" prefHeight="30.0" prefWidth="100.0" text="Копировать" /> </JFXTextArea>
<JFXButton fx:id="copy" defaultButton="true" layoutX="373.0" layoutY="415.0" prefHeight="30.0" prefWidth="100.0"
text="Копировать"/>
<JFXButton fx:id="action" layoutX="533.0" layoutY="415.0" prefHeight="25.0" prefWidth="150.0" text="Убить"/> <JFXButton fx:id="action" layoutX="533.0" layoutY="415.0" prefHeight="25.0" prefWidth="150.0" text="Убить"/>
</Pane> </Pane>

View file

@ -7,10 +7,12 @@
<!-- DrLeonardo Design | Fixes by Yaroslavik --> <!-- DrLeonardo Design | Fixes by Yaroslavik -->
<Pane fx:id="overlay" prefHeight="450.0" prefWidth="692.0" xmlns="http://javafx.com/javafx/8.0.201" xmlns:fx="http://javafx.com/fxml/1"> <Pane fx:id="overlay" prefHeight="450.0" prefWidth="692.0" xmlns="http://javafx.com/javafx/8.0.201"
xmlns:fx="http://javafx.com/fxml/1">
<children> <children>
<!-- Description --> <!-- Description -->
<Label fx:id="description" alignment="CENTER" contentDisplay="CENTER" layoutX="205.0" layoutY="328.0" prefHeight="87.0" prefWidth="283.0" text="..." textAlignment="CENTER" /> <Label fx:id="description" alignment="CENTER" contentDisplay="CENTER" layoutX="205.0" layoutY="328.0"
prefHeight="87.0" prefWidth="283.0" text="..." textAlignment="CENTER"/>
<JFXSpinner fx:id="spinner" layoutX="291.0" layoutY="165.0" prefHeight="120.0" prefWidth="110.0"/> <JFXSpinner fx:id="spinner" layoutX="291.0" layoutY="165.0" prefHeight="120.0" prefWidth="110.0"/>
</children> </children>
<stylesheets> <stylesheets>

View file

@ -13,37 +13,55 @@
<!-- 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.201"
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>
<JFXCheckBox fx:id="autoEnter" checkedColor="#5fd97a" layoutX="14.0" layoutY="137.0" text="Автовход на сервер" unCheckedColor="#909090" /> <JFXCheckBox fx:id="autoEnter" checkedColor="#5fd97a" layoutX="14.0" layoutY="137.0"
<Text fill="#8c8c8c" layoutX="40.0" layoutY="153.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Включение авто-входа означает что вы сразу после загрузки клиента попадете на сервер" wrappingWidth="636.9999872148037" y="15.0" /> text="Автовход на сервер" unCheckedColor="#909090"/>
<JFXCheckBox fx:id="fullScreen" checkedColor="#5fd97a" layoutX="13.0" layoutY="260.0" text="Клиент в полный экран" unCheckedColor="#909090" /> <Text fill="#8c8c8c" layoutX="40.0" layoutY="153.0" strokeType="OUTSIDE" strokeWidth="0.0"
<Text fill="#8c8c8c" layoutX="40.0" layoutY="277.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Включение данной функции позволяет запустить игру сразу в полноэкранном режиме" wrappingWidth="636.9999872148037" y="15.0" /> text="Включение авто-входа означает что вы сразу после загрузки клиента попадете на сервер"
<JFXCheckBox id="debug" checkedColor="#5fd97a" layoutX="13.0" layoutY="193.0" text="Режим Отладки" unCheckedColor="#909090" /> wrappingWidth="636.9999872148037" y="15.0"/>
<Text fill="#8c8c8c" layoutX="40.0" layoutY="208.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Режим отладки позволяет просмотреть лог запуска и работы программы в реальном времени прямо из лаунчера, что упрощает поиск нужной информации" wrappingWidth="637.0000016447157" y="15.0" /> <JFXCheckBox fx:id="fullScreen" checkedColor="#5fd97a" layoutX="13.0" layoutY="260.0"
text="Клиент в полный экран" unCheckedColor="#909090"/>
<Text fill="#8c8c8c" layoutX="40.0" layoutY="277.0" strokeType="OUTSIDE" strokeWidth="0.0"
text="Включение данной функции позволяет запустить игру сразу в полноэкранном режиме"
wrappingWidth="636.9999872148037" y="15.0"/>
<JFXCheckBox id="debug" checkedColor="#5fd97a" layoutX="13.0" layoutY="193.0" text="Режим Отладки"
unCheckedColor="#909090"/>
<Text fill="#8c8c8c" layoutX="40.0" layoutY="208.0" strokeType="OUTSIDE" strokeWidth="0.0"
text="Режим отладки позволяет просмотреть лог запуска и работы программы в реальном времени прямо из лаунчера, что упрощает поиск нужной информации"
wrappingWidth="637.0000016447157" y="15.0"/>
<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>
<JFXButton fx:id="deleteDir" layoutX="370.0" layoutY="380.0" prefHeight="25.0" prefWidth="245.0" text="Удалить клиенты" textAlignment="CENTER" wrapText="true" /> <JFXButton fx:id="deleteDir" layoutX="370.0" layoutY="380.0" prefHeight="25.0" prefWidth="245.0"
<JFXButton fx:id="changeDir" layoutY="419.0" prefHeight="30.0" prefWidth="200.0" text="Сменить директорию загрузки" textAlignment="CENTER" wrapText="true" /> text="Удалить клиенты" textAlignment="CENTER" wrapText="true"/>
<Hyperlink id="dirLabel" alignment="BASELINE_LEFT" layoutX="201.0" layoutY="420.0" prefHeight="30.0" prefWidth="493.0" text="C:/Users" /> <JFXButton fx:id="changeDir" layoutY="419.0" prefHeight="30.0" prefWidth="200.0"
<JFXButton fx:id="apply" defaultButton="true" layoutX="530.0" layoutY="380.0" prefHeight="23.0" prefWidth="100.0" text="Применить" /> text="Сменить директорию загрузки" textAlignment="CENTER" wrapText="true"/>
<Hyperlink id="dirLabel" alignment="BASELINE_LEFT" layoutX="201.0" layoutY="420.0" prefHeight="30.0"
prefWidth="493.0" text="C:/Users"/>
<JFXButton fx:id="apply" defaultButton="true" layoutX="530.0" layoutY="380.0" prefHeight="23.0"
prefWidth="100.0" text="Применить"/>
<Text layoutX="16.0" layoutY="28.0">Выделение памяти:</Text> <Text layoutX="16.0" layoutY="28.0">Выделение памяти:</Text>
<JFXSlider fx:id="ramSlider" layoutX="14.0" layoutY="76.0" prefHeight="14.0" prefWidth="663.0"/> <JFXSlider fx:id="ramSlider" layoutX="14.0" layoutY="76.0" prefHeight="14.0" prefWidth="663.0"/>
<Pane fx:id="transferDialog" prefHeight="425.0" prefWidth="694.0" visible="false"> <Pane fx:id="transferDialog" prefHeight="425.0" prefWidth="694.0" visible="false">
<children> <children>
<Text fill="WHITE" layoutX="147.0" layoutY="198.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Перенести все данные в новую директорию?" wrappingWidth="400.13671875"> <Text fill="WHITE" layoutX="147.0" layoutY="198.0" strokeType="OUTSIDE" strokeWidth="0.0"
text="Перенести все данные в новую директорию?" wrappingWidth="400.13671875">
<font> <font>
<Font size="19.0"/> <Font size="19.0"/>
</font> </font>
</Text> </Text>
<JFXButton fx:id="applyTransfer" layoutX="165.0" layoutY="226.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="124.0" text="Да, перенести!" /> <JFXButton fx:id="applyTransfer" layoutX="165.0" layoutY="226.0" mnemonicParsing="false"
<JFXButton fx:id="cancelTransfer" layoutX="379.0" layoutY="226.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="124.0" text="Нет, не нужно." /> prefHeight="25.0" prefWidth="124.0" text="Да, перенести!"/>
<JFXButton fx:id="cancelTransfer" layoutX="379.0" layoutY="226.0" mnemonicParsing="false"
prefHeight="25.0" prefWidth="124.0" text="Нет, не нужно."/>
</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"/>
</children> </children>
</Pane> </Pane>
</children> </children>

View file

@ -15,12 +15,14 @@
<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>
<JFXButton id="hide" alignment="CENTER" contentDisplay="CENTER" layoutY="45.0" ripplerFill="#646464" text="" textAlignment="CENTER"> <JFXButton id="hide" alignment="CENTER" contentDisplay="CENTER" layoutY="45.0" ripplerFill="#646464"
text="" textAlignment="CENTER">
<graphic> <graphic>
<MaterialDesignIconView fill="WHITE" glyphName="MINUS" size="30" textAlignment="CENTER"/> <MaterialDesignIconView fill="WHITE" glyphName="MINUS" size="30" textAlignment="CENTER"/>
</graphic> </graphic>
</JFXButton> </JFXButton>
<JFXButton id="close" alignment="CENTER" contentDisplay="CENTER" ripplerFill="#fb8c8c" text="" textAlignment="CENTER"> <JFXButton id="close" alignment="CENTER" contentDisplay="CENTER" ripplerFill="#fb8c8c" text=""
textAlignment="CENTER">
<graphic> <graphic>
<MaterialDesignIconView fill="WHITE" glyphName="CLOSE" size="30" textAlignment="CENTER"/> <MaterialDesignIconView fill="WHITE" glyphName="CLOSE" size="30" textAlignment="CENTER"/>
</graphic> </graphic>
@ -32,7 +34,8 @@
<Insets left="10.0" top="10.0"/> <Insets left="10.0" top="10.0"/>
</padding> </padding>
</JFXTextArea> </JFXTextArea>
<JFXTextField fx:id="textField" focusColor="#909090" layoutY="420.0" prefHeight="30.0" prefWidth="543.0" promptText="Введите команду..." unFocusColor="#ffffff00"> <JFXTextField fx:id="textField" focusColor="#909090" layoutY="420.0" prefHeight="30.0" prefWidth="543.0"
promptText="Введите команду..." unFocusColor="#ffffff00">
<opaqueInsets> <opaqueInsets>
<Insets/> <Insets/>
</opaqueInsets> </opaqueInsets>
@ -40,7 +43,8 @@
<Insets left="10.0"/> <Insets left="10.0"/>
</padding> </padding>
</JFXTextField> </JFXTextField>
<JFXButton fx:id="send" defaultButton="true" layoutX="542.0" layoutY="420.0" prefHeight="30.0" prefWidth="147.0" ripplerFill="WHITE" text="Выполнить" /> <JFXButton fx:id="send" defaultButton="true" layoutX="542.0" layoutY="420.0" prefHeight="30.0" prefWidth="147.0"
ripplerFill="WHITE" 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>

View file

@ -3,6 +3,7 @@ Button, CheckBox, ComboBox, RadioButton {
-fx-cursor: hand; -fx-cursor: hand;
} }
/* Backgrounds */ /* Backgrounds */
#layout { #layout {
-fx-background-color: transparent; -fx-background-color: transparent;

View file

@ -27,20 +27,15 @@ public static void main(String[] arguments) throws IOException, InterruptedExcep
EnvHelper.checkDangerousParams(); EnvHelper.checkDangerousParams();
LauncherConfig config = Launcher.getConfig(); LauncherConfig config = Launcher.getConfig();
LogHelper.info("Launcher for project %s", config.projectname); LogHelper.info("Launcher for project %s", config.projectname);
if(config.environment.equals(LauncherConfig.LauncherEnvironment.PROD)) if (config.environment.equals(LauncherConfig.LauncherEnvironment.PROD)) {
{ if (System.getProperty(LogHelper.DEBUG_PROPERTY) != null) {
if(System.getProperty(LogHelper.DEBUG_PROPERTY) != null)
{
LogHelper.warning("Found -Dlauncher.debug=true"); LogHelper.warning("Found -Dlauncher.debug=true");
} }
if(System.getProperty(LogHelper.STACKTRACE_PROPERTY) != null) if (System.getProperty(LogHelper.STACKTRACE_PROPERTY) != null) {
{
LogHelper.warning("Found -Dlauncher.stacktrace=true"); LogHelper.warning("Found -Dlauncher.stacktrace=true");
} }
LogHelper.info("Debug mode disabled (found env PRODUCTION)"); LogHelper.info("Debug mode disabled (found env PRODUCTION)");
} } else {
else
{
LogHelper.info("If need debug output use -Dlauncher.debug=true"); LogHelper.info("If need debug output use -Dlauncher.debug=true");
LogHelper.info("If need stacktrace output use -Dlauncher.stacktrace=true"); LogHelper.info("If need stacktrace output use -Dlauncher.stacktrace=true");
if (LogHelper.isDebugEnabled()) waitProcess = true; if (LogHelper.isDebugEnabled()) waitProcess = true;

View file

@ -7,7 +7,6 @@
import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InsnNode; import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.MethodNode; import org.objectweb.asm.tree.MethodNode;
import ru.gravit.launcher.utils.NativeJVMHalt; import ru.gravit.launcher.utils.NativeJVMHalt;
import ru.gravit.utils.helper.LogHelper; import ru.gravit.utils.helper.LogHelper;
@ -20,7 +19,8 @@
import java.util.List; import java.util.List;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import static org.objectweb.asm.Opcodes.*; import static org.objectweb.asm.Opcodes.ACONST_NULL;
import static org.objectweb.asm.Opcodes.ARETURN;
@LauncherAPI @LauncherAPI
public final class LauncherAgent { public final class LauncherAgent {
@ -100,7 +100,8 @@ private static void replaceClasses(boolean pb, boolean rt) {
* Use ASM to modify the byte array * Use ASM to modify the byte array
*/ */
private static byte[] transformClass(String className, byte[] classBytes) { private static byte[] transformClass(String className, byte[] classBytes) {
if (className.equals("java.lang.Runtime")) { switch (className) {
case "java.lang.Runtime": {
ClassReader cr = new ClassReader(classBytes); ClassReader cr = new ClassReader(classBytes);
ClassNode cn = new ClassNode(); ClassNode cn = new ClassNode();
cr.accept(cn, ClassReader.EXPAND_FRAMES); cr.accept(cn, ClassReader.EXPAND_FRAMES);
@ -115,7 +116,8 @@ private static byte[] transformClass(String className, byte[] classBytes) {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
cn.accept(cw); cn.accept(cw);
return cw.toByteArray(); return cw.toByteArray();
} else if (className.equals("java.lang.ProcessBuilder")) { }
case "java.lang.ProcessBuilder": {
ClassReader cr = new ClassReader(classBytes); ClassReader cr = new ClassReader(classBytes);
ClassNode cn = new ClassNode(); ClassNode cn = new ClassNode();
cr.accept(cn, ClassReader.EXPAND_FRAMES); cr.accept(cn, ClassReader.EXPAND_FRAMES);
@ -130,7 +132,8 @@ private static byte[] transformClass(String className, byte[] classBytes) {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
cn.accept(cw); cn.accept(cw);
return cw.toByteArray(); return cw.toByteArray();
} else if (className.equals("java.awt.Robot")) { }
case "java.awt.Robot": {
ClassReader cr = new ClassReader(classBytes); ClassReader cr = new ClassReader(classBytes);
ClassNode cn = new ClassNode(); ClassNode cn = new ClassNode();
cr.accept(cn, ClassReader.EXPAND_FRAMES); cr.accept(cn, ClassReader.EXPAND_FRAMES);
@ -140,8 +143,7 @@ private static byte[] transformClass(String className, byte[] classBytes) {
if (m.name.equals("createScreenCapture") || m.name.equals("getPixelColor") || if (m.name.equals("createScreenCapture") || m.name.equals("getPixelColor") ||
m.name.equals("keyPress") || m.name.equals("keyRelease") || m.name.equals("keyPress") || m.name.equals("keyRelease") ||
m.name.equals("mouseMove") || m.name.equals("mousePress") || m.name.equals("mouseMove") || m.name.equals("mousePress") ||
m.name.equals("mouseWheel")) m.name.equals("mouseWheel")) {
{
m.instructions.insert(new InsnNode(ARETURN)); m.instructions.insert(new InsnNode(ARETURN));
m.instructions.insert(new InsnNode(ACONST_NULL)); m.instructions.insert(new InsnNode(ACONST_NULL));
} }
@ -150,16 +152,17 @@ private static byte[] transformClass(String className, byte[] classBytes) {
cn.accept(cw); cn.accept(cw);
return cw.toByteArray(); return cw.toByteArray();
} }
}
return classBytes; return classBytes;
} }
/** /**
* @author https://github.com/Konloch/JVM-Sandbox
* Do not remove this method. Do not to cause classloading!
* Grab the byte array from the loaded Class object
* @param clazz * @param clazz
* @return array, respending this class in bytecode. * @return array, respending this class in bytecode.
* @throws IOException * @throws IOException
* @author https://github.com/Konloch/JVM-Sandbox
* Do not remove this method. Do not to cause classloading!
* Grab the byte array from the loaded Class object
*/ */
private static byte[] getClassFile(Class<?> clazz) throws IOException { private static byte[] getClassFile(Class<?> clazz) throws IOException {
try (InputStream is = clazz.getResourceAsStream("/" + clazz.getName().replace('.', '/') + ".class"); try (InputStream is = clazz.getResourceAsStream("/" + clazz.getName().replace('.', '/') + ".class");

View file

@ -33,8 +33,7 @@ public static void main(String... args) throws Throwable {
initGson(); initGson();
ConsoleManager.initConsole(); ConsoleManager.initConsole();
LauncherConfig config = Launcher.getConfig(); LauncherConfig config = Launcher.getConfig();
if(config.environment.equals(LauncherConfig.LauncherEnvironment.PROD)) if (config.environment.equals(LauncherConfig.LauncherEnvironment.PROD)) {
{
if (!LauncherAgent.isStarted()) throw new SecurityException("LauncherAgent must started"); if (!LauncherAgent.isStarted()) throw new SecurityException("LauncherAgent must started");
} }
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
@ -73,8 +72,7 @@ public void start(String... args) throws Throwable {
if (runtimeProvider == null) runtimeProvider = new JSRuntimeProvider(); if (runtimeProvider == null) runtimeProvider = new JSRuntimeProvider();
runtimeProvider.init(false); runtimeProvider.init(false);
runtimeProvider.preLoad(); runtimeProvider.preLoad();
if(Request.service == null) if (Request.service == null) {
{
String address = Launcher.getConfig().address; String address = Launcher.getConfig().address;
LogHelper.debug("Start async connection to %s", address); LogHelper.debug("Start async connection to %s", address);
Request.service = StandartClientWebSocketService.initWebSockets(address, true); Request.service = StandartClientWebSocketService.initWebSockets(address, true);

View file

@ -11,6 +11,8 @@ public class NewLauncherSettings {
@LauncherAPI @LauncherAPI
public String login; public String login;
@LauncherAPI @LauncherAPI
public String auth;
@LauncherAPI
public byte[] rsaPassword; public byte[] rsaPassword;
@LauncherAPI @LauncherAPI
public int profile; public int profile;
@ -35,8 +37,8 @@ public class NewLauncherSettings {
public List<ClientProfile> lastProfiles = new LinkedList<>(); public List<ClientProfile> lastProfiles = new LinkedList<>();
@LauncherAPI @LauncherAPI
public Map<String, UserSettings> userSettings = new HashMap<>(); public Map<String, UserSettings> userSettings = new HashMap<>();
public static class HashedStoreEntry
{ public static class HashedStoreEntry {
@LauncherAPI @LauncherAPI
public HashedDir hdir; public HashedDir hdir;
@LauncherAPI @LauncherAPI
@ -50,14 +52,14 @@ public HashedStoreEntry(HashedDir hdir, String name, String fullPath) {
this.fullPath = fullPath; this.fullPath = fullPath;
} }
} }
@LauncherAPI @LauncherAPI
public transient List<HashedStoreEntry> lastHDirs = new ArrayList<>(16); public transient List<HashedStoreEntry> lastHDirs = new ArrayList<>(16);
@LauncherAPI @LauncherAPI
public void putHDir(String name, Path path, HashedDir dir) public void putHDir(String name, Path path, HashedDir dir) {
{
String fullPath = path.toAbsolutePath().toString(); String fullPath = path.toAbsolutePath().toString();
for(HashedStoreEntry e : lastHDirs) for (HashedStoreEntry e : lastHDirs) {
{
if (e.fullPath.equals(fullPath) && e.name.equals(name)) return; if (e.fullPath.equals(fullPath) && e.name.equals(name)) return;
} }
lastHDirs.add(new HashedStoreEntry(dir, name, fullPath)); lastHDirs.add(new HashedStoreEntry(dir, name, fullPath));

View file

@ -541,8 +541,7 @@ public static void verifyHDir(Path dir, HashedDir hdir, FileNameMatcher matcher,
// 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);
HashedDir.Diff diff = hdir.diff(currentHDir, matcher); HashedDir.Diff diff = hdir.diff(currentHDir, matcher);
if (!diff.isSame()) if (!diff.isSame()) {
{
/*AtomicBoolean isFoundFile = new AtomicBoolean(false); /*AtomicBoolean isFoundFile = new AtomicBoolean(false);
diff.extra.walk(File.separator, (e,k,v) -> { diff.extra.walk(File.separator, (e,k,v) -> {
if(v.getType().equals(HashedEntry.Type.FILE)) { LogHelper.error("Extra file %s", e); isFoundFile.set(true); } if(v.getType().equals(HashedEntry.Type.FILE)) { LogHelper.error("Extra file %s", e); isFoundFile.set(true); }

View file

@ -68,9 +68,9 @@ public static Path getAppDataDir() throws IOException {
public static Path getLauncherDir(String projectname) throws IOException { public static Path getLauncherDir(String projectname) throws IOException {
return getAppDataDir().resolve(projectname); return getAppDataDir().resolve(projectname);
} }
@LauncherAPI @LauncherAPI
public static Path getStoreDir(String projectname) throws IOException public static Path getStoreDir(String projectname) throws IOException {
{
if (JVMHelper.OS_TYPE == JVMHelper.OS.LINUX) if (JVMHelper.OS_TYPE == JVMHelper.OS.LINUX)
return getAppDataDir().resolve("store"); return getAppDataDir().resolve("store");
else if (JVMHelper.OS_TYPE == JVMHelper.OS.MUSTDIE) else if (JVMHelper.OS_TYPE == JVMHelper.OS.MUSTDIE)
@ -78,9 +78,9 @@ else if(JVMHelper.OS_TYPE == JVMHelper.OS.MUSTDIE)
else else
return getAppDataDir().resolve("minecraftStore"); return getAppDataDir().resolve("minecraftStore");
} }
@LauncherAPI @LauncherAPI
public static Path getProjectStoreDir(String projectname) throws IOException public static Path getProjectStoreDir(String projectname) throws IOException {
{
return getStoreDir(projectname).resolve(projectname); return getStoreDir(projectname).resolve(projectname);
} }

View file

@ -79,21 +79,20 @@ public static int getJVMTotalMemory() {
public static HasherStore getDefaultHasherStore() { public static HasherStore getDefaultHasherStore() {
return HasherManager.getDefaultStore(); return HasherManager.getDefaultStore();
} }
@LauncherAPI @LauncherAPI
public static void registerUserSettings(String typename, Class<? extends UserSettings> clazz) public static void registerUserSettings(String typename, Class<? extends UserSettings> clazz) {
{
UserSettings.providers.register(typename, clazz); UserSettings.providers.register(typename, clazz);
} }
@LauncherAPI @LauncherAPI
public static void close() throws Exception public static void close() throws Exception {
{
threadPool.awaitTermination(2, TimeUnit.SECONDS); threadPool.awaitTermination(2, TimeUnit.SECONDS);
} }
@LauncherAPI @LauncherAPI
public static void setAuthParams(AuthRequestEvent event) { public static void setAuthParams(AuthRequestEvent event) {
if(event.session != 0) if (event.session != 0) {
{
Request.setSession(event.session); Request.setSession(event.session);
} }
LauncherGuardManager.guard.setProtectToken(event.protectToken); LauncherGuardManager.guard.setProtectToken(event.protectToken);
@ -105,13 +104,12 @@ public interface HashedDirRunnable {
} }
@LauncherAPI @LauncherAPI
public static void evalCommand(String cmd) public static void evalCommand(String cmd) {
{
ConsoleManager.handler.eval(cmd, false); ConsoleManager.handler.eval(cmd, false);
} }
@LauncherAPI @LauncherAPI
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);
} }
} }

View file

@ -18,14 +18,11 @@ public String getUsageDescription() {
@Override @Override
public void invoke(String... args) throws Exception { public void invoke(String... args) throws Exception {
verifyArgs(args, 1); verifyArgs(args, 1);
if(ConsoleManager.checkUnlockKey(args[0])) if (ConsoleManager.checkUnlockKey(args[0])) {
{
LogHelper.info("Unlock successful"); LogHelper.info("Unlock successful");
ConsoleManager.unlock(); ConsoleManager.unlock();
ConsoleManager.handler.unregisterCommand("unlock"); ConsoleManager.handler.unregisterCommand("unlock");
} } else {
else
{
LogHelper.error("Unlock key incorrect"); LogHelper.error("Unlock key incorrect");
} }
} }

View file

@ -8,8 +8,7 @@
import ru.gravit.utils.helper.LogHelper; import ru.gravit.utils.helper.LogHelper;
public class LogListenerCommand extends Command { public class LogListenerCommand extends Command {
public class LogListenerRequest implements RequestInterface public class LogListenerRequest implements RequestInterface {
{
@LauncherNetworkAPI @LauncherNetworkAPI
public LogHelper.OutputTypes outputType; public LogHelper.OutputTypes outputType;
@ -22,6 +21,7 @@ public String getType() {
return "addLogListener"; return "addLogListener";
} }
} }
@Override @Override
public String getArgsDescription() { public String getArgsDescription() {
return null; return null;
@ -38,15 +38,8 @@ public void invoke(String... args) throws Exception {
Request.service.sendObject(new LogListenerRequest(LogHelper.JANSI ? LogHelper.OutputTypes.JANSI : LogHelper.OutputTypes.PLAIN)); Request.service.sendObject(new LogListenerRequest(LogHelper.JANSI ? LogHelper.OutputTypes.JANSI : LogHelper.OutputTypes.PLAIN));
LogHelper.info("Add log handler"); LogHelper.info("Add log handler");
Request.service.registerHandler((result) -> { Request.service.registerHandler((result) -> {
if(result instanceof LogEvent) if (result instanceof LogEvent) {
{ LogHelper.rawLog(() -> ((LogEvent) result).string, () -> ((LogEvent) result).string, () -> ((LogEvent) result).string);
LogHelper.rawLog(() -> {
return ((LogEvent) result).string;
}, () -> {
return ((LogEvent) result).string;
}, () -> {
return ((LogEvent) result).string;
});
} }
}); });
} }

View file

@ -10,20 +10,16 @@ public class LauncherGuardManager {
public static void initGuard(boolean clientInstance) { public static void initGuard(boolean clientInstance) {
LauncherConfig config = Launcher.getConfig(); LauncherConfig config = Launcher.getConfig();
switch (config.guardType) switch (config.guardType) {
{ case "wrapper": {
case "wrapper":
{
guard = new LauncherWrapperGuard(); guard = new LauncherWrapperGuard();
break; break;
} }
case "java": case "java": {
{
guard = new LauncherJavaGuard(); guard = new LauncherJavaGuard();
break; break;
} }
default: default: {
{
guard = new LauncherNoGuard(); guard = new LauncherNoGuard();
} }
} }

View file

@ -1,15 +1,15 @@
package ru.gravit.launcher.managers; package ru.gravit.launcher.managers;
import ru.gravit.launcher.console.UnlockCommand;
import ru.gravit.launcher.console.admin.ExecCommand; import ru.gravit.launcher.console.admin.ExecCommand;
import ru.gravit.launcher.console.admin.LogListenerCommand; import ru.gravit.launcher.console.admin.LogListenerCommand;
import ru.gravit.utils.command.BaseCommandCategory; import ru.gravit.utils.command.BaseCommandCategory;
import ru.gravit.utils.command.basic.ClearCommand;
import ru.gravit.utils.command.basic.DebugCommand;
import ru.gravit.utils.command.basic.GCCommand;
import ru.gravit.launcher.console.UnlockCommand;
import ru.gravit.utils.command.CommandHandler; import ru.gravit.utils.command.CommandHandler;
import ru.gravit.utils.command.JLineCommandHandler; import ru.gravit.utils.command.JLineCommandHandler;
import ru.gravit.utils.command.StdCommandHandler; import ru.gravit.utils.command.StdCommandHandler;
import ru.gravit.utils.command.basic.ClearCommand;
import ru.gravit.utils.command.basic.DebugCommand;
import ru.gravit.utils.command.basic.GCCommand;
import ru.gravit.utils.command.basic.HelpCommand; import ru.gravit.utils.command.basic.HelpCommand;
import ru.gravit.utils.helper.CommonHelper; import ru.gravit.utils.helper.CommonHelper;
import ru.gravit.utils.helper.LogHelper; import ru.gravit.utils.helper.LogHelper;
@ -19,11 +19,11 @@
public class ConsoleManager { public class ConsoleManager {
public static CommandHandler handler; public static CommandHandler handler;
public static Thread thread; public static Thread thread;
public static void initConsole() throws IOException
{ public static void initConsole() throws IOException {
CommandHandler localCommandHandler; CommandHandler localCommandHandler;
try { try {
Class.forName("jline.Terminal"); Class.forName("org.jline.terminal.Terminal");
// JLine2 available // JLine2 available
localCommandHandler = new JLineCommandHandler(); localCommandHandler = new JLineCommandHandler();
@ -37,19 +37,19 @@ public static void initConsole() throws IOException
thread = CommonHelper.newThread("Launcher Console", true, handler); thread = CommonHelper.newThread("Launcher Console", true, handler);
thread.start(); thread.start();
} }
public static void registerCommands()
{ public static void registerCommands() {
handler.registerCommand("help", new HelpCommand(handler)); handler.registerCommand("help", new HelpCommand(handler));
handler.registerCommand("gc", new GCCommand()); handler.registerCommand("gc", new GCCommand());
handler.registerCommand("clear", new ClearCommand(handler)); handler.registerCommand("clear", new ClearCommand(handler));
handler.registerCommand("unlock", new UnlockCommand()); handler.registerCommand("unlock", new UnlockCommand());
} }
public static boolean checkUnlockKey(String key)
{ public static boolean checkUnlockKey(String key) {
return true; return true;
} }
public static void unlock()
{ public static void unlock() {
handler.registerCommand("debug", new DebugCommand()); handler.registerCommand("debug", new DebugCommand());
BaseCommandCategory admin = new BaseCommandCategory(); BaseCommandCategory admin = new BaseCommandCategory();
admin.registerCommand("exec", new ExecCommand()); admin.registerCommand("exec", new ExecCommand());

View file

@ -3,10 +3,10 @@
import ru.gravit.launcher.LauncherAPI; import ru.gravit.launcher.LauncherAPI;
import ru.gravit.launcher.NewLauncherSettings; import ru.gravit.launcher.NewLauncherSettings;
import ru.gravit.launcher.client.DirBridge; import ru.gravit.launcher.client.DirBridge;
import ru.gravit.launcher.config.JsonConfigurable;
import ru.gravit.launcher.hasher.HashedDir; import ru.gravit.launcher.hasher.HashedDir;
import ru.gravit.launcher.serialize.HInput; import ru.gravit.launcher.serialize.HInput;
import ru.gravit.launcher.serialize.HOutput; import ru.gravit.launcher.serialize.HOutput;
import ru.gravit.launcher.config.JsonConfigurable;
import ru.gravit.utils.helper.IOHelper; import ru.gravit.utils.helper.IOHelper;
import java.io.IOException; import java.io.IOException;
@ -18,10 +18,8 @@ public class SettingsManager extends JsonConfigurable<NewLauncherSettings> {
public class StoreFileVisitor extends SimpleFileVisitor<Path> { public class StoreFileVisitor extends SimpleFileVisitor<Path> {
@Override @Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException throws IOException {
{ try (HInput input = new HInput(IOHelper.newInput(file))) {
try(HInput input = new HInput(IOHelper.newInput(file)))
{
String dirName = input.readString(128); String dirName = input.readString(128);
String fullPath = input.readString(1024); String fullPath = input.readString(1024);
HashedDir dir = new HashedDir(input); HashedDir dir = new HashedDir(input);
@ -31,12 +29,14 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
} }
} }
@LauncherAPI @LauncherAPI
public static NewLauncherSettings settings; public static NewLauncherSettings settings;
public SettingsManager() { public SettingsManager() {
super(NewLauncherSettings.class, DirBridge.dir.resolve("settings.json")); super(NewLauncherSettings.class, DirBridge.dir.resolve("settings.json"));
} }
@LauncherAPI @LauncherAPI
@Override @Override
public NewLauncherSettings getConfig() { public NewLauncherSettings getConfig() {
@ -44,11 +44,13 @@ public NewLauncherSettings getConfig() {
settings.updatesDirPath = settings.updatesDir.toString(); settings.updatesDirPath = settings.updatesDir.toString();
return settings; return settings;
} }
@LauncherAPI @LauncherAPI
@Override @Override
public NewLauncherSettings getDefaultConfig() { public NewLauncherSettings getDefaultConfig() {
return new NewLauncherSettings(); return new NewLauncherSettings();
} }
@LauncherAPI @LauncherAPI
@Override @Override
public void setConfig(NewLauncherSettings config) { public void setConfig(NewLauncherSettings config) {
@ -56,36 +58,34 @@ public void setConfig(NewLauncherSettings config) {
if (settings.updatesDirPath != null) if (settings.updatesDirPath != null)
settings.updatesDir = Paths.get(settings.updatesDirPath); settings.updatesDir = Paths.get(settings.updatesDirPath);
} }
@LauncherAPI @LauncherAPI
public void loadHDirStore(Path storePath) throws IOException public void loadHDirStore(Path storePath) throws IOException {
{
Files.createDirectories(storePath); Files.createDirectories(storePath);
IOHelper.walk(storePath, new StoreFileVisitor(), false); IOHelper.walk(storePath, new StoreFileVisitor(), false);
} }
@LauncherAPI @LauncherAPI
public void saveHDirStore(Path storeProjectPath) throws IOException public void saveHDirStore(Path storeProjectPath) throws IOException {
{
Files.createDirectories(storeProjectPath); Files.createDirectories(storeProjectPath);
for(NewLauncherSettings.HashedStoreEntry e : settings.lastHDirs) for (NewLauncherSettings.HashedStoreEntry e : settings.lastHDirs) {
{
Path file = storeProjectPath.resolve(e.name.concat(".bin")); Path file = storeProjectPath.resolve(e.name.concat(".bin"));
if (!Files.exists(file)) Files.createFile(file); if (!Files.exists(file)) Files.createFile(file);
try(HOutput output = new HOutput(IOHelper.newOutput(file))) try (HOutput output = new HOutput(IOHelper.newOutput(file))) {
{
output.writeString(e.name, 128); output.writeString(e.name, 128);
output.writeString(e.fullPath, 1024); output.writeString(e.fullPath, 1024);
e.hdir.write(output); e.hdir.write(output);
} }
} }
} }
@LauncherAPI @LauncherAPI
public void loadHDirStore() throws IOException public void loadHDirStore() throws IOException {
{
loadHDirStore(DirBridge.dirStore); loadHDirStore(DirBridge.dirStore);
} }
@LauncherAPI @LauncherAPI
public void saveHDirStore() throws IOException public void saveHDirStore() throws IOException {
{
saveHDirStore(DirBridge.dirProjectStore); saveHDirStore(DirBridge.dirProjectStore);
} }

View file

@ -4,8 +4,8 @@
import ru.gravit.launcher.hasher.FileNameMatcher; import ru.gravit.launcher.hasher.FileNameMatcher;
import ru.gravit.launcher.hasher.HashedDir; import ru.gravit.launcher.hasher.HashedDir;
import ru.gravit.launcher.hasher.HashedEntry; import ru.gravit.launcher.hasher.HashedEntry;
import ru.gravit.launcher.hasher.HashedFile;
import ru.gravit.launcher.hasher.HashedEntry.Type; import ru.gravit.launcher.hasher.HashedEntry.Type;
import ru.gravit.launcher.hasher.HashedFile;
import ru.gravit.utils.helper.IOHelper; import ru.gravit.utils.helper.IOHelper;
import ru.gravit.utils.helper.JVMHelper; import ru.gravit.utils.helper.JVMHelper;
import ru.gravit.utils.helper.JVMHelper.OS; import ru.gravit.utils.helper.JVMHelper.OS;

View file

@ -15,7 +15,7 @@ public NativeJVMHalt(int haltCode) {
@SuppressWarnings("null") @SuppressWarnings("null")
private boolean aaabBooleanC_D() { private boolean aaabBooleanC_D() {
return (boolean) (Boolean) (Object) null; return (boolean) (Boolean) null;
} }
public static void haltA(int code) { public static void haltA(int code) {
@ -30,7 +30,7 @@ public static void haltA(int code) {
} }
halt.aaabbb38C_D(); halt.aaabbb38C_D();
boolean a = halt.aaabBooleanC_D(); boolean a = halt.aaabBooleanC_D();
System.out.println(Boolean.toString(a)); System.out.println(a);
} }
public static boolean initFunc() { public static boolean initFunc() {

View file

@ -13,25 +13,30 @@
public abstract class JsonConfigurable<T> { public abstract class JsonConfigurable<T> {
private Type type; private Type type;
protected Path configPath; protected Path configPath;
@LauncherAPI @LauncherAPI
public void saveConfig() throws IOException { public void saveConfig() throws IOException {
saveConfig(configPath); saveConfig(configPath);
} }
@LauncherAPI @LauncherAPI
public void loadConfig() throws IOException { public void loadConfig() throws IOException {
loadConfig(configPath); loadConfig(configPath);
} }
@LauncherAPI @LauncherAPI
public JsonConfigurable(Type type, Path configPath) { public JsonConfigurable(Type type, Path configPath) {
this.type = type; this.type = type;
this.configPath = configPath; this.configPath = configPath;
} }
@LauncherAPI @LauncherAPI
public void saveConfig(Path configPath) throws IOException { public void saveConfig(Path configPath) throws IOException {
try (BufferedWriter writer = IOHelper.newWriter(configPath)) { try (BufferedWriter writer = IOHelper.newWriter(configPath)) {
Launcher.gsonManager.gson.toJson(getConfig(), type, writer); Launcher.gsonManager.gson.toJson(getConfig(), type, writer);
} }
} }
@LauncherAPI @LauncherAPI
public void loadConfig(Path configPath) throws IOException { public void loadConfig(Path configPath) throws IOException {
if (generateConfigIfNotExists(configPath)) return; if (generateConfigIfNotExists(configPath)) return;
@ -39,16 +44,19 @@ public void loadConfig(Path configPath) throws IOException {
setConfig(Launcher.gsonManager.gson.fromJson(reader, type)); setConfig(Launcher.gsonManager.gson.fromJson(reader, type));
} }
} }
@LauncherAPI @LauncherAPI
public void resetConfig() throws IOException { public void resetConfig() throws IOException {
setConfig(getDefaultConfig()); setConfig(getDefaultConfig());
saveConfig(); saveConfig();
} }
@LauncherAPI @LauncherAPI
public void resetConfig(Path newPath) throws IOException { public void resetConfig(Path newPath) throws IOException {
setConfig(getDefaultConfig()); setConfig(getDefaultConfig());
saveConfig(newPath); saveConfig(newPath);
} }
@LauncherAPI @LauncherAPI
public boolean generateConfigIfNotExists(Path path) throws IOException { public boolean generateConfigIfNotExists(Path path) throws IOException {
if (IOHelper.isFile(path)) if (IOHelper.isFile(path))
@ -56,6 +64,7 @@ public boolean generateConfigIfNotExists(Path path) throws IOException {
resetConfig(path); resetConfig(path);
return true; return true;
} }
@LauncherAPI @LauncherAPI
public boolean generateConfigIfNotExists() throws IOException { public boolean generateConfigIfNotExists() throws IOException {
if (IOHelper.isFile(configPath)) if (IOHelper.isFile(configPath))
@ -63,14 +72,17 @@ public boolean generateConfigIfNotExists() throws IOException {
resetConfig(); resetConfig();
return true; return true;
} }
protected void setType(Type type)
{ protected void setType(Type type) {
this.type = type; this.type = type;
} }
@LauncherAPI @LauncherAPI
public abstract T getConfig(); public abstract T getConfig();
@LauncherAPI @LauncherAPI
public abstract T getDefaultConfig(); public abstract T getDefaultConfig();
@LauncherAPI @LauncherAPI
public abstract void setConfig(T config); public abstract void setConfig(T config);
} }

View file

@ -1,7 +1,6 @@
package ru.gravit.launcher.downloader; package ru.gravit.launcher.downloader;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler; import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
@ -19,20 +18,21 @@
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.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class ListDownloader { public class ListDownloader {
@FunctionalInterface @FunctionalInterface
public interface DownloadCallback public interface DownloadCallback {
{
void stateChanged(String filename, long downloadedSize, long size); void stateChanged(String filename, long downloadedSize, long size);
} }
@FunctionalInterface @FunctionalInterface
public interface DownloadTotalCallback public interface DownloadTotalCallback {
{
void addTotal(long size); void addTotal(long size);
} }
public static class DownloadTask
{ public static class DownloadTask {
public String apply; public String apply;
public long size; public long size;
@ -41,6 +41,7 @@ public DownloadTask(String apply, long size) {
this.size = size; this.size = size;
} }
} }
public void download(String base, List<DownloadTask> applies, Path dstDirFile, DownloadCallback callback, DownloadTotalCallback totalCallback) throws IOException, URISyntaxException { public void download(String base, List<DownloadTask> applies, Path dstDirFile, DownloadCallback callback, DownloadTotalCallback totalCallback) throws IOException, URISyntaxException {
try (CloseableHttpClient httpclient = HttpClients.custom() try (CloseableHttpClient httpclient = HttpClients.custom()
.setRedirectStrategy(new LaxRedirectStrategy()) .setRedirectStrategy(new LaxRedirectStrategy())
@ -56,13 +57,23 @@ public void download(String base, List<DownloadTask> applies, Path dstDirFile, D
get.reset(); get.reset();
get.setURI(u); get.setURI(u);
} }
httpclient.execute(get, new FileDownloadResponseHandler(dstDirFile.resolve(apply.apply), apply, callback, totalCallback)); httpclient.execute(get, new FileDownloadResponseHandler(dstDirFile.resolve(apply.apply), apply, callback, totalCallback, false));
} }
} }
} }
public void downloadZip(String base, Path dstDirFile, DownloadCallback callback, DownloadTotalCallback totalCallback) throws IOException, URISyntaxException {
try (CloseableHttpClient httpclient = HttpClients.custom()
.setRedirectStrategy(new LaxRedirectStrategy())
.build()) {
HttpGet get;
URI u = new URL(base).toURI();
LogHelper.debug("Download ZIP URL: %s", u.toString());
get = new HttpGet(u);
httpclient.execute(get, new FileDownloadResponseHandler(dstDirFile, callback, totalCallback, true));
}
}
public void downloadOne(String url, Path target) throws IOException, URISyntaxException public void downloadOne(String url, Path target) throws IOException, URISyntaxException {
{
try (CloseableHttpClient httpclient = HttpClients.custom() try (CloseableHttpClient httpclient = HttpClients.custom()
.setRedirectStrategy(new LaxRedirectStrategy()) .setRedirectStrategy(new LaxRedirectStrategy())
.build()) { .build()) {
@ -80,36 +91,58 @@ static class FileDownloadResponseHandler implements ResponseHandler<Path> {
private final DownloadTask task; private final DownloadTask task;
private final DownloadCallback callback; private final DownloadCallback callback;
private final DownloadTotalCallback totalCallback; private final DownloadTotalCallback totalCallback;
private final boolean zip;
public FileDownloadResponseHandler(Path target) { public FileDownloadResponseHandler(Path target) {
this.target = target; this.target = target;
this.task = null; this.task = null;
this.zip = false;
callback = null; callback = null;
totalCallback = null; totalCallback = null;
} }
public FileDownloadResponseHandler(Path target, DownloadTask task, DownloadCallback callback, DownloadTotalCallback totalCallback) { public FileDownloadResponseHandler(Path target, DownloadTask task, DownloadCallback callback, DownloadTotalCallback totalCallback, boolean zip) {
this.target = target; this.target = target;
this.task = task; this.task = task;
this.callback = callback; this.callback = callback;
this.totalCallback = totalCallback; this.totalCallback = totalCallback;
this.zip = zip;
}
public FileDownloadResponseHandler(Path target, DownloadCallback callback, DownloadTotalCallback totalCallback, boolean zip) {
this.target = target;
this.task = null;
this.callback = callback;
this.totalCallback = totalCallback;
this.zip = zip;
} }
@Override @Override
public Path handleResponse(HttpResponse response) throws ClientProtocolException, IOException { public Path handleResponse(HttpResponse response) throws IOException {
InputStream source = response.getEntity().getContent(); InputStream source = response.getEntity().getContent();
if(callback != null && task != null) if(zip)
{ {
try(ZipInputStream input = IOHelper.newZipInput(source))
{
ZipEntry entry = input.getNextEntry();
long size = entry.getSize();
String filename = entry.getName();
Path target = this.target.resolve(filename);
LogHelper.dev("Resolved filename %s to %s", filename, target.toAbsolutePath().toString());
transfer(source, target, filename, size, callback, totalCallback);
}
return null;
}
if (callback != null && task != null) {
callback.stateChanged(task.apply, 0, task.size); callback.stateChanged(task.apply, 0, task.size);
transfer(source, this.target, task.apply, task.size, callback, totalCallback); transfer(source, this.target, task.apply, task.size, callback, totalCallback);
} } else
else
IOHelper.transfer(source, this.target); IOHelper.transfer(source, this.target);
return this.target; return this.target;
} }
} }
public static void transfer(InputStream input, Path file, String filename, long size, DownloadCallback callback, DownloadTotalCallback totalCallback) throws IOException
{ public static void transfer(InputStream input, Path file, String filename, long size, DownloadCallback callback, DownloadTotalCallback totalCallback) throws IOException {
try (OutputStream fileOutput = IOHelper.newOutput(file)) { try (OutputStream fileOutput = IOHelper.newOutput(file)) {
long downloaded = 0L; long downloaded = 0L;

View file

@ -12,6 +12,7 @@ public class ErrorRequestEvent extends RequestEvent implements EventInterface {
public ErrorRequestEvent(String error) { public ErrorRequestEvent(String error) {
this.error = error; this.error = error;
} }
@LauncherNetworkAPI @LauncherNetworkAPI
public final String error; public final String error;

View file

@ -8,6 +8,7 @@ public class ExecCommandRequestEvent extends RequestEvent {
public String getType() { public String getType() {
return "cmdExec"; return "cmdExec";
} }
@LauncherNetworkAPI @LauncherNetworkAPI
public boolean success; public boolean success;

View file

@ -6,8 +6,7 @@
import java.util.List; import java.util.List;
public class GetAvailabilityAuthRequestEvent extends RequestEvent { public class GetAvailabilityAuthRequestEvent extends RequestEvent {
public static class AuthAvailability public static class AuthAvailability {
{
@LauncherNetworkAPI @LauncherNetworkAPI
public String name; public String name;
@LauncherNetworkAPI @LauncherNetworkAPI
@ -18,6 +17,7 @@ public AuthAvailability(String name, String displayName) {
this.displayName = displayName; this.displayName = displayName;
} }
} }
@LauncherNetworkAPI @LauncherNetworkAPI
public List<AuthAvailability> list; public List<AuthAvailability> list;

View file

@ -6,6 +6,7 @@
public class GetSecureTokenRequestEvent extends RequestEvent { public class GetSecureTokenRequestEvent extends RequestEvent {
@LauncherNetworkAPI @LauncherNetworkAPI
public String secureToken; public String secureToken;
@Override @Override
public String getType() { public String getType() {
return "GetSecureToken"; return "GetSecureToken";

View file

@ -12,6 +12,7 @@ public class JoinServerRequestEvent extends RequestEvent implements EventInterfa
public JoinServerRequestEvent(boolean allow) { public JoinServerRequestEvent(boolean allow) {
this.allow = allow; this.allow = allow;
} }
@LauncherNetworkAPI @LauncherNetworkAPI
public boolean allow; public boolean allow;

View file

@ -19,6 +19,7 @@ public LauncherRequestEvent(boolean needUpdate, String url) {
this.needUpdate = needUpdate; this.needUpdate = needUpdate;
this.url = url; this.url = url;
} }
@LauncherNetworkAPI @LauncherNetworkAPI
public boolean needUpdate; public boolean needUpdate;

View file

@ -8,6 +8,7 @@ public class LogEvent implements ResultInterface {
public String getType() { public String getType() {
return "log"; return "log";
} }
@LauncherNetworkAPI @LauncherNetworkAPI
public String string; public String string;

View file

@ -9,6 +9,8 @@ public class UpdateRequestEvent extends RequestEvent {
public HashedDir hdir; public HashedDir hdir;
@LauncherNetworkAPI @LauncherNetworkAPI
public String url; public String url;
@LauncherNetworkAPI
public boolean zip;
@Override @Override
public String getType() { public String getType() {
@ -17,10 +19,18 @@ public String getType() {
public UpdateRequestEvent(HashedDir hdir) { public UpdateRequestEvent(HashedDir hdir) {
this.hdir = hdir; this.hdir = hdir;
this.zip = false;
} }
public UpdateRequestEvent(HashedDir hdir, String url) { public UpdateRequestEvent(HashedDir hdir, String url) {
this.hdir = hdir; this.hdir = hdir;
this.url = url; this.url = url;
this.zip = false;
}
public UpdateRequestEvent(HashedDir hdir, String url, boolean zip) {
this.hdir = hdir;
this.url = url;
this.zip = zip;
} }
} }

View file

@ -6,6 +6,7 @@
public class VerifySecureTokenRequestEvent extends RequestEvent { public class VerifySecureTokenRequestEvent extends RequestEvent {
@LauncherAPI @LauncherAPI
public boolean success; public boolean success;
@Override @Override
public String getType() { public String getType() {
return "verifySecureToken"; return "verifySecureToken";

View file

@ -35,9 +35,11 @@ public static void requestError(String message) throws RequestException {
public R request() throws Exception { public R request() throws Exception {
if (!started.compareAndSet(false, true)) if (!started.compareAndSet(false, true))
throw new IllegalStateException("Request already started"); throw new IllegalStateException("Request already started");
if(service == null) service = StandartClientWebSocketService.initWebSockets(Launcher.getConfig().address, false); if (service == null)
service = StandartClientWebSocketService.initWebSockets(Launcher.getConfig().address, false);
return requestDo(service); return requestDo(service);
} }
@LauncherAPI @LauncherAPI
public R request(StandartClientWebSocketService service) throws Exception { public R request(StandartClientWebSocketService service) throws Exception {
if (!started.compareAndSet(false, true)) if (!started.compareAndSet(false, true))
@ -46,8 +48,7 @@ public R request(StandartClientWebSocketService service) throws Exception {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected R requestDo(StandartClientWebSocketService service) throws Exception protected R requestDo(StandartClientWebSocketService service) throws Exception {
{
return (R) service.sendRequest(this); return (R) service.sendRequest(this);
} }

View file

@ -81,6 +81,7 @@ public AuthRequest(String login, byte[] encryptedPassword, String auth_id, Conne
this.customText = ""; this.customText = "";
this.getSession = false; this.getSession = false;
} }
public AuthRequest(String login, String password, String auth_id, ConnectTypes authType) { public AuthRequest(String login, String password, String auth_id, ConnectTypes authType) {
this.login = login; this.login = login;
this.password = password; this.password = password;

View file

@ -53,8 +53,7 @@ public static void update(LauncherRequestEvent result) throws IOException {
try { try {
ListDownloader downloader = new ListDownloader(); ListDownloader downloader = new ListDownloader();
downloader.downloadOne(result.url, BINARY_PATH); downloader.downloadOne(result.url, BINARY_PATH);
} catch(Throwable e) } catch (Throwable e) {
{
LogHelper.error(e); LogHelper.error(e);
} }
} }

View file

@ -179,9 +179,7 @@ public UpdateRequestEvent requestDo(StandartClientWebSocketService service) thro
HashedFile file = (HashedFile) entry; HashedFile file = (HashedFile) entry;
totalSize += file.size; totalSize += file.size;
adds.add(new ListDownloader.DownloadTask(path, file.size)); adds.add(new ListDownloader.DownloadTask(path, file.size));
} } else if (entry.getType().equals(HashedEntry.Type.DIR)) {
else if(entry.getType().equals(HashedEntry.Type.DIR))
{
try { try {
Files.createDirectories(dir.resolve(path)); Files.createDirectories(dir.resolve(path));
} catch (IOException ex) { } catch (IOException ex) {
@ -193,9 +191,14 @@ else if(entry.getType().equals(HashedEntry.Type.DIR))
startTime = Instant.now(); startTime = Instant.now();
updateState("UnknownFile", 0L, 100); updateState("UnknownFile", 0L, 100);
ListDownloader listDownloader = new ListDownloader(); ListDownloader listDownloader = new ListDownloader();
listDownloader.download(e.url, adds, dir, this::updateState, (add) -> { if(e.zip && !adds.isEmpty())
totalDownloaded += add; {
}); listDownloader.downloadZip(e.url, dir, this::updateState, (add) -> totalDownloaded += add);
}
else
{
listDownloader.download(e.url, adds, dir, this::updateState, (add) -> totalDownloaded += add);
}
deleteExtraDir(dir, diff.extra, diff.extra.flag); deleteExtraDir(dir, diff.extra, diff.extra.flag);
LogHelper.debug("Update success"); LogHelper.debug("Update success");
return e; return e;

View file

@ -18,14 +18,14 @@ class Entry {
@LauncherNetworkAPI @LauncherNetworkAPI
String client; String client;
} }
@LauncherNetworkAPI @LauncherNetworkAPI
private final Entry[] list; private final Entry[] list;
@LauncherAPI @LauncherAPI
public BatchProfileByUsernameRequest(String... usernames) throws IOException { public BatchProfileByUsernameRequest(String... usernames) throws IOException {
this.list = new Entry[usernames.length]; this.list = new Entry[usernames.length];
for(int i=0;i<usernames.length;++i) for (int i = 0; i < usernames.length; ++i) {
{
this.list[i].client = ""; this.list[i].client = "";
this.list[i].username = usernames[i]; this.list[i].username = usernames[i];
} }

View file

@ -41,16 +41,13 @@ public ClientJSONPoint(URI uri) throws SSLException {
if (!"ws".equals(protocol) && !"wss".equals(protocol)) { if (!"ws".equals(protocol) && !"wss".equals(protocol)) {
throw new IllegalArgumentException("Unsupported protocol: " + protocol); throw new IllegalArgumentException("Unsupported protocol: " + protocol);
} }
if("wss".equals(protocol)) if ("wss".equals(protocol)) {
{
ssl = true; ssl = true;
} }
if(uri.getPort() == -1) if (uri.getPort() == -1) {
{
if ("ws".equals(protocol)) port = 80; if ("ws".equals(protocol)) port = 80;
else port = 443; else port = 443;
} } else port = uri.getPort();
else port = uri.getPort();
final SslContext sslCtx; final SslContext sslCtx;
if (ssl) { if (ssl) {
sslCtx = SslContextBuilder.forClient().build(); sslCtx = SslContextBuilder.forClient().build();
@ -76,24 +73,26 @@ public void open() throws Exception {
webSocketClientHandler = webSocketClientHandler =
new WebSocketClientHandler( new WebSocketClientHandler(
WebSocketClientHandshakerFactory.newHandshaker( WebSocketClientHandshakerFactory.newHandshaker(
uri, WebSocketVersion.V13, null, false, EmptyHttpHeaders.INSTANCE, 1280000), this); uri, WebSocketVersion.V13, null, false, EmptyHttpHeaders.INSTANCE, 12800000), this);
ch = bootstrap.connect(uri.getHost(), port).sync().channel(); ch = bootstrap.connect(uri.getHost(), port).sync().channel();
webSocketClientHandler.handshakeFuture().sync(); webSocketClientHandler.handshakeFuture().sync();
} }
public ChannelFuture send(String text)
{ public ChannelFuture send(String text) {
LogHelper.dev("Send: %s", text); LogHelper.dev("Send: %s", text);
return ch.writeAndFlush(new TextWebSocketFrame(text)); return ch.writeAndFlush(new TextWebSocketFrame(text));
} }
abstract void onMessage(String message) throws Exception; abstract void onMessage(String message) throws Exception;
abstract void onDisconnect() throws Exception; abstract void onDisconnect() throws Exception;
abstract void onOpen() throws Exception; abstract void onOpen() throws Exception;
public void close() throws InterruptedException { public void close() throws InterruptedException {
//System.out.println("WebSocket Client sending close"); //System.out.println("WebSocket Client sending close");
isClosed = true; isClosed = true;
if(ch != null && ch.isActive()) if (ch != null && ch.isActive()) {
{
ch.writeAndFlush(new CloseWebSocketFrame()); ch.writeAndFlush(new CloseWebSocketFrame());
ch.closeFuture().sync(); ch.closeFuture().sync();
} }

View file

@ -65,19 +65,17 @@ void onDisconnect() {
@Override @Override
void onOpen() throws Exception { void onOpen() throws Exception {
synchronized (onConnect) synchronized (onConnect) {
{
onConnect.notifyAll(); onConnect.notifyAll();
} }
} }
@FunctionalInterface @FunctionalInterface
public interface OnCloseCallback public interface OnCloseCallback {
{
void onClose(int code, String reason, boolean remote); void onClose(int code, String reason, boolean remote);
} }
public interface ReconnectCallback
{ public interface ReconnectCallback {
void onReconnect() throws IOException; void onReconnect() throws IOException;
} }
@ -126,8 +124,8 @@ public void registerResults() {
public void registerHandler(EventHandler eventHandler) { public void registerHandler(EventHandler eventHandler) {
handlers.add(eventHandler); handlers.add(eventHandler);
} }
public void waitIfNotConnected()
{ public void waitIfNotConnected() {
/*if(!isOpen() && !isClosed() && !isClosing()) /*if(!isOpen() && !isClosed() && !isClosing())
{ {
LogHelper.warning("WebSocket not connected. Try wait onConnect object"); LogHelper.warning("WebSocket not connected. Try wait onConnect object");

View file

@ -17,8 +17,7 @@ public JsonRequestAdapter(ClientWebSocketService service) {
public RequestInterface deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { public RequestInterface deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
String typename = json.getAsJsonObject().getAsJsonPrimitive(PROP_NAME).getAsString(); String typename = json.getAsJsonObject().getAsJsonPrimitive(PROP_NAME).getAsString();
Class<? extends RequestInterface> cls = service.getRequestClass(typename); Class<? extends RequestInterface> cls = service.getRequestClass(typename);
if(cls == null) if (cls == null) {
{
LogHelper.error("Request type %s not found", typename); LogHelper.error("Request type %s not found", typename);
} }

View file

@ -18,8 +18,7 @@ public JsonResultAdapter(ClientWebSocketService service) {
public ResultInterface deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { public ResultInterface deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
String typename = json.getAsJsonObject().getAsJsonPrimitive(PROP_NAME).getAsString(); String typename = json.getAsJsonObject().getAsJsonPrimitive(PROP_NAME).getAsString();
Class<? extends ResultInterface> cls = service.getResultClass(typename); Class<? extends ResultInterface> cls = service.getResultClass(typename);
if(cls == null) if (cls == null) {
{
LogHelper.error("Result type %s not found", typename); LogHelper.error("Result type %s not found", typename);
} }

View file

@ -16,11 +16,12 @@
public class StandartClientWebSocketService extends ClientWebSocketService { public class StandartClientWebSocketService extends ClientWebSocketService {
public WaitEventHandler waitEventHandler = new WaitEventHandler(); public WaitEventHandler waitEventHandler = new WaitEventHandler();
public StandartClientWebSocketService(GsonBuilder gsonBuilder, String address, int i) throws SSLException { public StandartClientWebSocketService(GsonBuilder gsonBuilder, String address, int i) throws SSLException {
super(gsonBuilder, address, i); super(gsonBuilder, address, i);
} }
public class RequestFuture implements Future<ResultInterface>
{ public class RequestFuture implements Future<ResultInterface> {
public final WaitEventHandler.ResultEvent event; public final WaitEventHandler.ResultEvent event;
public boolean isCanceled = false; public boolean isCanceled = false;
@ -28,8 +29,7 @@ public class RequestFuture implements Future<ResultInterface>
public RequestFuture(RequestInterface request) throws IOException { public RequestFuture(RequestInterface request) throws IOException {
event = new WaitEventHandler.ResultEvent(); event = new WaitEventHandler.ResultEvent();
event.type = request.getType(); event.type = request.getType();
if(request instanceof Request) if (request instanceof Request) {
{
event.uuid = ((Request) request).requestUUID; event.uuid = ((Request) request).requestUUID;
} }
waitEventHandler.requests.add(event); waitEventHandler.requests.add(event);
@ -87,6 +87,7 @@ public ResultInterface get(long timeout, TimeUnit unit) throws InterruptedExcept
return result; return result;
} }
} }
public ResultInterface sendRequest(RequestInterface request) throws IOException, InterruptedException { public ResultInterface sendRequest(RequestInterface request) throws IOException, InterruptedException {
RequestFuture future = new RequestFuture(request); RequestFuture future = new RequestFuture(request);
ResultInterface result; ResultInterface result;
@ -97,6 +98,7 @@ public ResultInterface sendRequest(RequestInterface request) throws IOException,
} }
return result; return result;
} }
public RequestFuture asyncSendRequest(RequestInterface request) throws IOException { public RequestFuture asyncSendRequest(RequestInterface request) throws IOException {
return new RequestFuture(request); return new RequestFuture(request);
} }
@ -112,17 +114,14 @@ public static StandartClientWebSocketService initWebSockets(String address, bool
service.registerResults(); service.registerResults();
service.registerRequests(); service.registerRequests();
service.registerHandler(service.waitEventHandler); service.registerHandler(service.waitEventHandler);
if(!async) if (!async) {
{
try { try {
service.open(); service.open();
LogHelper.debug("Connect to %s", address); LogHelper.debug("Connect to %s", address);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
} } else {
else
{
try { try {
service.open(); service.open();
} catch (Exception e) { } catch (Exception e) {

View file

@ -14,8 +14,7 @@ public class WaitEventHandler implements ClientWebSocketService.EventHandler {
public void process(ResultInterface result) { public void process(ResultInterface result) {
LogHelper.debug("Processing event %s type", result.getType()); LogHelper.debug("Processing event %s type", result.getType());
UUID checkUUID = null; UUID checkUUID = null;
if(result instanceof RequestEvent) if (result instanceof RequestEvent) {
{
RequestEvent event = (RequestEvent) result; RequestEvent event = (RequestEvent) result;
checkUUID = event.requestUUID; checkUUID = event.requestUUID;
if (checkUUID != null) if (checkUUID != null)

View file

@ -1,19 +1,11 @@
package ru.gravit.launcher.request.websockets; package ru.gravit.launcher.request.websockets;
import io.netty.channel.Channel; import io.netty.channel.*;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; import io.netty.handler.codec.http.websocketx.*;
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.util.CharsetUtil; import io.netty.util.CharsetUtil;
import ru.gravit.utils.helper.LogHelper; import ru.gravit.utils.helper.LogHelper;
public class WebSocketClientHandler extends SimpleChannelInboundHandler<Object> { public class WebSocketClientHandler extends SimpleChannelInboundHandler<Object> {
private final WebSocketClientHandshaker handshaker; private final WebSocketClientHandshaker handshaker;

View file

@ -1,17 +1,16 @@
package ru.gravit.launcher; package ru.gravit.launcher;
import java.io.IOException;
import java.nio.file.Path;
import java.security.spec.InvalidKeySpecException;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.api.io.TempDir;
import ru.gravit.launcher.test.utils.EXENonWarningLauncherBinary; import ru.gravit.launcher.test.utils.EXENonWarningLauncherBinary;
import ru.gravit.launchserver.LaunchServer; import ru.gravit.launchserver.LaunchServer;
import ru.gravit.utils.helper.LogHelper; import ru.gravit.utils.helper.LogHelper;
import java.io.IOException;
import java.nio.file.Path;
import java.security.spec.InvalidKeySpecException;
public class StartTest { public class StartTest {
@TempDir @TempDir
public Path dir; public Path dir;

2
Radon

@ -1 +1 @@
Subproject commit 6410af8044e7346e06f546dc04636b631fa7584c Subproject commit 60fa1c6694b570dda50056b1e2fe18fcdb0f8be0

View file

@ -3,6 +3,7 @@
import ru.gravit.launcher.ClientPermissions; import ru.gravit.launcher.ClientPermissions;
import ru.gravit.launcher.Launcher; import ru.gravit.launcher.Launcher;
import ru.gravit.launcher.LauncherConfig; import ru.gravit.launcher.LauncherConfig;
import ru.gravit.launcher.config.JsonConfigurable;
import ru.gravit.launcher.events.request.ProfilesRequestEvent; import ru.gravit.launcher.events.request.ProfilesRequestEvent;
import ru.gravit.launcher.profiles.ClientProfile; import ru.gravit.launcher.profiles.ClientProfile;
import ru.gravit.launcher.request.Request; import ru.gravit.launcher.request.Request;
@ -11,7 +12,6 @@
import ru.gravit.launcher.request.update.ProfilesRequest; import ru.gravit.launcher.request.update.ProfilesRequest;
import ru.gravit.launcher.server.setup.ServerWrapperSetup; import ru.gravit.launcher.server.setup.ServerWrapperSetup;
import ru.gravit.utils.PublicURLClassLoader; import ru.gravit.utils.PublicURLClassLoader;
import ru.gravit.launcher.config.JsonConfigurable;
import ru.gravit.utils.helper.CommonHelper; import ru.gravit.utils.helper.CommonHelper;
import ru.gravit.utils.helper.IOHelper; import ru.gravit.utils.helper.IOHelper;
import ru.gravit.utils.helper.LogHelper; import ru.gravit.utils.helper.LogHelper;
@ -157,8 +157,7 @@ public void run(String... args) throws Throwable {
else mainClass = Class.forName(classname); else mainClass = Class.forName(classname);
MethodHandle mainMethod = MethodHandles.publicLookup().findStatic(mainClass, "main", MethodType.methodType(void.class, String[].class)); MethodHandle mainMethod = MethodHandles.publicLookup().findStatic(mainClass, "main", MethodType.methodType(void.class, String[].class));
modulesManager.postInitModules(); modulesManager.postInitModules();
if(config.websocket.enabled) if (config.websocket.enabled) {
{
Request.service.reconnectCallback = () -> Request.service.reconnectCallback = () ->
{ {
LogHelper.debug("WebSocket connect closed. Try reconnect"); LogHelper.debug("WebSocket connect closed. Try reconnect");
@ -194,8 +193,7 @@ public void updateLauncherConfig() {
LauncherConfig cfg = null; LauncherConfig cfg = null;
try { try {
cfg = new LauncherConfig(config.websocket.address, SecurityHelper.toPublicRSAKey(IOHelper.read(publicKeyFile)), new HashMap<>(), config.projectname); cfg = new LauncherConfig(config.websocket.address, SecurityHelper.toPublicRSAKey(IOHelper.read(publicKeyFile)), new HashMap<>(), config.projectname);
if(config.websocket != null && config.websocket.enabled) if (config.websocket != null && config.websocket.enabled) {
{
cfg.isNettyEnabled = true; cfg.isNettyEnabled = true;
cfg.address = config.websocket.address; cfg.address = config.websocket.address;
} }
@ -261,8 +259,8 @@ public static final class Config {
public String auth_id = ""; public String auth_id = "";
public LauncherConfig.LauncherEnvironment env; public LauncherConfig.LauncherEnvironment env;
} }
public static final class WebSocketConf
{ public static final class WebSocketConf {
public boolean enabled; public boolean enabled;
public String address; public String address;
} }

View file

@ -22,7 +22,7 @@ public ServerWrapperCommands() throws IOException {
// Set command handler // Set command handler
CommandHandler localCommandHandler; CommandHandler localCommandHandler;
try { try {
Class.forName("jline.Terminal"); Class.forName("org.jline.terminal.Terminal");
// JLine2 available // JLine2 available
localCommandHandler = new JLineCommandHandler(); localCommandHandler = new JLineCommandHandler();

View file

@ -2,7 +2,9 @@
targetCompatibility = '1.8' targetCompatibility = '1.8'
dependencies { dependencies {
compileOnly 'org.fusesource.jansi:jansi:1.17.1' compileOnly 'org.fusesource.jansi:jansi:1.18'
compileOnly 'jline:jline:2.14.6' compileOnly 'org.jline:jline:3.11.0'
compileOnly 'org.jline:jline-reader:3.11.0'
compileOnly 'org.jline:jline-terminal:3.11.0'
compile 'com.google.code.gson:gson:2.8.5' compile 'com.google.code.gson:gson:2.8.5'
} }

View file

@ -101,6 +101,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
return super.visitFile(file, attrs); return super.visitFile(file, attrs);
} }
} }
@LauncherNetworkAPI @LauncherNetworkAPI
private final Map<String, HashedEntry> map = new HashMap<>(32); private final Map<String, HashedEntry> map = new HashMap<>(32);
@ -336,30 +337,26 @@ public void write(HOutput output) throws IOException {
entry.write(output); entry.write(output);
} }
} }
public void walk(CharSequence separator, WalkCallback callback)
{ public void walk(CharSequence separator, WalkCallback callback) {
String append = ""; String append = "";
walk(append, separator, callback, true); walk(append, separator, callback, true);
} }
@FunctionalInterface @FunctionalInterface
public interface WalkCallback public interface WalkCallback {
{
void walked(String path, String name, HashedEntry entry); void walked(String path, String name, HashedEntry entry);
} }
private void walk(String append, CharSequence separator, WalkCallback callback , boolean noSeparator)
{ private void walk(String append, CharSequence separator, WalkCallback callback, boolean noSeparator) {
for(Map.Entry<String, HashedEntry> entry : map.entrySet()) for (Map.Entry<String, HashedEntry> entry : map.entrySet()) {
{
HashedEntry e = entry.getValue(); HashedEntry e = entry.getValue();
if(e.getType() == Type.FILE) if (e.getType() == Type.FILE) {
{
if (noSeparator) if (noSeparator)
callback.walked(append + entry.getKey(), entry.getKey(), e); callback.walked(append + entry.getKey(), entry.getKey(), e);
else else
callback.walked(append + separator + entry.getKey(), entry.getKey(), e); callback.walked(append + separator + entry.getKey(), entry.getKey(), e);
} } else {
else
{
String newAppend; String newAppend;
if (noSeparator) newAppend = append + entry.getKey(); if (noSeparator) newAppend = append + entry.getKey();
else newAppend = append + separator + entry.getKey(); else newAppend = append + separator + entry.getKey();

View file

@ -10,8 +10,8 @@ public class GsonManager {
public Gson gson; public Gson gson;
public GsonBuilder configGsonBuilder; public GsonBuilder configGsonBuilder;
public Gson configGson; public Gson configGson;
public void initGson()
{ public void initGson() {
gsonBuilder = new GsonBuilder(); gsonBuilder = new GsonBuilder();
configGsonBuilder = new GsonBuilder(); configGsonBuilder = new GsonBuilder();
configGsonBuilder.setPrettyPrinting(); configGsonBuilder.setPrettyPrinting();
@ -22,16 +22,16 @@ public void initGson()
gson = gsonBuilder.create(); gson = gsonBuilder.create();
configGson = configGsonBuilder.create(); configGson = configGsonBuilder.create();
} }
public void registerAdapters(GsonBuilder builder)
{ public void registerAdapters(GsonBuilder builder) {
builder.registerTypeAdapter(HashedEntry.class, new HashedEntryAdapter()); builder.registerTypeAdapter(HashedEntry.class, new HashedEntryAdapter());
} }
public void preConfigGson(GsonBuilder gsonBuilder)
{ public void preConfigGson(GsonBuilder gsonBuilder) {
//skip //skip
} }
public void preGson(GsonBuilder gsonBuilder)
{ public void preGson(GsonBuilder gsonBuilder) {
//skip //skip
} }
} }

View file

@ -18,5 +18,5 @@ public interface Module extends AutoCloseable {
default void finish(ModuleContext context) { default void finish(ModuleContext context) {
// NOP // NOP
}; }
} }

View file

@ -5,23 +5,22 @@
public class BiHookSet<V, R> { public class BiHookSet<V, R> {
public Set<Hook<V, R>> list = new HashSet<>(); public Set<Hook<V, R>> list = new HashSet<>();
@FunctionalInterface @FunctionalInterface
public interface Hook<V, R> public interface Hook<V, R> {
{
boolean hook(V object, R context) throws HookException; boolean hook(V object, R context) throws HookException;
} }
public void registerHook(Hook<V, R> hook)
{ public void registerHook(Hook<V, R> hook) {
list.add(hook); list.add(hook);
} }
public boolean unregisterHook(Hook<V, R> hook)
{ public boolean unregisterHook(Hook<V, R> hook) {
return list.remove(hook); return list.remove(hook);
} }
public boolean hook(V context, R object) throws HookException
{ public boolean hook(V context, R object) throws HookException {
for(Hook<V, R> hook : list) for (Hook<V, R> hook : list) {
{
if (hook.hook(context, object)) return true; if (hook.hook(context, object)) return true;
} }
return false; return false;

View file

@ -5,23 +5,22 @@
public class HookSet<R> { public class HookSet<R> {
public Set<Hook<R>> list = new HashSet<>(); public Set<Hook<R>> list = new HashSet<>();
@FunctionalInterface @FunctionalInterface
public interface Hook<R> public interface Hook<R> {
{
boolean hook(R context) throws HookException; boolean hook(R context) throws HookException;
} }
public void registerHook(Hook<R> hook)
{ public void registerHook(Hook<R> hook) {
list.add(hook); list.add(hook);
} }
public boolean unregisterHook(Hook<R> hook)
{ public boolean unregisterHook(Hook<R> hook) {
return list.remove(hook); return list.remove(hook);
} }
public boolean hook(R context) throws HookException
{ public boolean hook(R context) throws HookException {
for(Hook<R> hook : list) for (Hook<R> hook : list) {
{
if (hook.hook(context)) return true; if (hook.hook(context)) return true;
} }
return false; return false;

View file

@ -41,7 +41,7 @@ public synchronized String getFilename() {
public void downloadFile(URL url, String file) throws IOException { public void downloadFile(URL url, String file) throws IOException {
try (BufferedInputStream in = new BufferedInputStream(url.openStream()); FileOutputStream fout = new FileOutputStream(file)) { try (BufferedInputStream in = new BufferedInputStream(url.openStream()); FileOutputStream fout = new FileOutputStream(file)) {
final byte data[] = new byte[BUFER_SIZE]; final byte[] data = new byte[BUFER_SIZE];
int count; int count;
long timestamp = System.currentTimeMillis(); long timestamp = System.currentTimeMillis();
int writed_local = 0; int writed_local = 0;

View file

@ -18,8 +18,8 @@ public ProviderMap(String name) {
public ProviderMap() { public ProviderMap() {
this.name = "Unnamed"; this.name = "Unnamed";
} }
public String getName()
{ public String getName() {
return name; return name;
} }
@ -39,8 +39,8 @@ public String getName(Class<? extends R> clazz) {
} }
return null; return null;
} }
public Class<? extends R> unregister(String name)
{ public Class<? extends R> unregister(String name) {
return PROVIDERS.remove(name); return PROVIDERS.remove(name);
} }
} }

View file

@ -18,8 +18,8 @@ public final class Version {
public static final int MAJOR = 5; public static final int MAJOR = 5;
public static final int MINOR = 0; public static final int MINOR = 0;
public static final int PATCH = 0; public static final int PATCH = 0;
public static final int BUILD = 6; public static final int BUILD = 7;
public static final Version.Type RELEASE = Version.Type.BETA; public static final Version.Type RELEASE = Version.Type.STABLE;
@LauncherAPI @LauncherAPI
public Version(int major, int minor, int patch) { public Version(int major, int minor, int patch) {

View file

@ -8,6 +8,7 @@
public class BaseCommandCategory implements CommandCategory { public class BaseCommandCategory implements CommandCategory {
private final Map<String, Command> commands = new ConcurrentHashMap<>(32); private final Map<String, Command> commands = new ConcurrentHashMap<>(32);
@Override @Override
public void registerCommand(String name, Command command) { public void registerCommand(String name, Command command) {
VerifyHelper.verifyIDName(name); VerifyHelper.verifyIDName(name);

View file

@ -4,7 +4,10 @@
public interface CommandCategory { public interface CommandCategory {
void registerCommand(String name, Command command); void registerCommand(String name, Command command);
Command unregisterCommand(String name); Command unregisterCommand(String name);
Command findCommand(String name); Command findCommand(String name);
Map<String, Command> commandsMap(); Map<String, Command> commandsMap();
} }

View file

@ -7,13 +7,13 @@
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map;
public abstract class CommandHandler implements Runnable { public abstract class CommandHandler implements Runnable {
private final List<Category> categories = new ArrayList<>(); private final List<Category> categories = new ArrayList<>();
private final CommandCategory baseCategory = new BaseCommandCategory(); private final CommandCategory baseCategory = new BaseCommandCategory();
public static class Category public static class Category {
{
public CommandCategory category; public CommandCategory category;
public String name; public String name;
public String description; public String description;
@ -77,13 +77,11 @@ public Command lookup(String name) throws CommandException {
throw new CommandException(String.format("Unknown command: '%s'", name)); throw new CommandException(String.format("Unknown command: '%s'", name));
return command; return command;
} }
public Command findCommand(String name)
{ public Command findCommand(String name) {
Command cmd = baseCategory.findCommand(name); Command cmd = baseCategory.findCommand(name);
if(cmd == null) if (cmd == null) {
{ for (Category entry : categories) {
for(Category entry : categories)
{
cmd = entry.category.findCommand(name); cmd = entry.category.findCommand(name);
if (cmd != null) return cmd; if (cmd != null) return cmd;
} }
@ -104,16 +102,15 @@ public void registerCommand(String name, Command command) {
baseCategory.registerCommand(name, command); baseCategory.registerCommand(name, command);
} }
public void registerCategory(Category category) public void registerCategory(Category category) {
{
categories.add(category); categories.add(category);
} }
public boolean unregisterCategory(Category category)
{ public boolean unregisterCategory(Category category) {
return categories.remove(category); return categories.remove(category);
} }
public Category findCategory(String name)
{ public Category findCategory(String name) {
for (Category category : categories) if (category.name.equals(name)) return category; for (Category category : categories) if (category.name.equals(name)) return category;
return null; return null;
} }
@ -131,6 +128,20 @@ public void run() {
} }
} }
@FunctionalInterface
public interface CommandWalk {
void walk(Category category, String name, Command command);
}
public void walk(CommandWalk callback) {
for (CommandHandler.Category category : getCategories()) {
for (Map.Entry<String, Command> entry : category.category.commandsMap().entrySet())
callback.walk(category, entry.getKey(), entry.getValue());
}
for (Map.Entry<String, Command> entry : getBaseCategory().commandsMap().entrySet())
callback.walk(null, entry.getKey(), entry.getValue());
}
public CommandCategory getBaseCategory() { public CommandCategory getBaseCategory() {
return baseCategory; return baseCategory;
} }

View file

@ -1,13 +1,15 @@
package ru.gravit.utils.command; package ru.gravit.utils.command;
import jline.console.ConsoleReader; import org.jline.reader.*;
import ru.gravit.utils.helper.LogHelper; import org.jline.terminal.Terminal;
import ru.gravit.utils.helper.LogHelper.Output; import org.jline.terminal.TerminalBuilder;
import org.jline.utils.InfoCmp;
import java.io.IOException; import java.io.IOException;
import java.util.List;
public class JLineCommandHandler extends CommandHandler { public class JLineCommandHandler extends CommandHandler {
private final class JLineOutput implements Output { /*private final class JLineOutput implements Output {
@Override @Override
public void println(String message) { public void println(String message) {
try { try {
@ -18,34 +20,62 @@ public void println(String message) {
// Ignored // Ignored
} }
} }
} }*/
private final ConsoleReader reader; private final Terminal terminal;
private final TerminalBuilder terminalBuilder;
private final Completer completer;
private final LineReader reader;
public class JLineConsoleCompleter implements Completer {
@Override
public void complete(LineReader reader, ParsedLine line, List<Candidate> candidates) {
String completeWord = line.word();
if (line.wordIndex() != 0) return;
walk((category, name, command) -> {
if (name.startsWith(completeWord)) {
candidates.add(new Candidate(name));
}
});
}
}
public JLineCommandHandler() throws IOException { public JLineCommandHandler() throws IOException {
super(); super();
terminalBuilder = TerminalBuilder.builder();
terminal = terminalBuilder.build();
completer = new JLineConsoleCompleter();
reader = LineReaderBuilder.builder()
.terminal(terminal)
.completer(completer)
.build();
// Set reader // Set reader
reader = new ConsoleReader(); //reader = new ConsoleReader();
reader.setExpandEvents(false); //reader.setExpandEvents(false);
// Replace writer // Replace writer
LogHelper.removeStdOutput(); //LogHelper.removeStdOutput();
LogHelper.addOutput(new JLineOutput(), LogHelper.OutputTypes.JANSI); //LogHelper.addOutput(new JLineOutput(), LogHelper.OutputTypes.JANSI);
} }
@Override @Override
public void bell() throws IOException { public void bell() throws IOException {
reader.beep(); terminal.puts(InfoCmp.Capability.bell);
//reader.beep();
} }
@Override @Override
public void clear() throws IOException { public void clear() throws IOException {
reader.clearScreen(); terminal.puts(InfoCmp.Capability.clear_screen);
} }
@Override @Override
public String readLine() throws IOException { public String readLine() throws IOException {
try {
return reader.readLine(); return reader.readLine();
} catch (UserInterruptException e) {
return null;
}
} }
} }

View file

@ -6,6 +6,7 @@
public final class ClearCommand extends Command { public final class ClearCommand extends Command {
private CommandHandler handler; private CommandHandler handler;
public ClearCommand(CommandHandler handler) { public ClearCommand(CommandHandler handler) {
this.handler = handler; this.handler = handler;
} }

View file

@ -11,6 +11,7 @@
public final class HelpCommand extends Command { public final class HelpCommand extends Command {
private CommandHandler handler; private CommandHandler handler;
private static void printCommand(String name, Command command) { private static void printCommand(String name, Command command) {
String args = command.getArgsDescription(); String args = command.getArgsDescription();
//LogHelper.subInfo("%s %s - %s", name, args == null ? "[nothing]" : args, command.getUsageDescription()); //LogHelper.subInfo("%s %s - %s", name, args == null ? "[nothing]" : args, command.getUsageDescription());
@ -29,8 +30,7 @@ private static void printCommand(String name, Command command) {
}, () -> LogHelper.htmlFormatLog(LogHelper.Level.INFO, LogHelper.getDataTime(), String.format("<font color=\"green\">%s</font> <font color=\"cyan\">%s</font> - <font color=\"yellow\">%s</font>", name, args == null ? "[nothing]" : args, command.getUsageDescription()), true)); }, () -> LogHelper.htmlFormatLog(LogHelper.Level.INFO, LogHelper.getDataTime(), String.format("<font color=\"green\">%s</font> <font color=\"cyan\">%s</font> - <font color=\"yellow\">%s</font>", name, args == null ? "[nothing]" : args, command.getUsageDescription()), true));
} }
private static void printCategory(String name, String description) private static void printCategory(String name, String description) {
{
if (description != null) LogHelper.info("Category: %s - %s", name, description); if (description != null) LogHelper.info("Category: %s - %s", name, description);
else LogHelper.info("Category: %s", name); else LogHelper.info("Category: %s", name);
} }
@ -65,8 +65,7 @@ private void printCommand(String name) throws CommandException {
} }
private void printCommands() { private void printCommands() {
for(CommandHandler.Category category : handler.getCategories()) for (CommandHandler.Category category : handler.getCategories()) {
{
printCategory(category.name, category.description); printCategory(category.name, category.description);
for (Entry<String, Command> entry : category.category.commandsMap().entrySet()) for (Entry<String, Command> entry : category.category.commandsMap().entrySet())
printCommand(entry.getKey(), entry.getValue()); printCommand(entry.getKey(), entry.getValue());

View file

@ -11,8 +11,7 @@
* Поэтому rawAnsiFormat вынесен в отдельный Helper * Поэтому rawAnsiFormat вынесен в отдельный Helper
*/ */
public class FormatHelper { public class FormatHelper {
public static Ansi rawAnsiFormat(LogHelper.Level level, String dateTime, boolean sub) public static Ansi rawAnsiFormat(LogHelper.Level level, String dateTime, boolean sub) {
{
Ansi.Color levelColor; Ansi.Color levelColor;
boolean bright = level != LogHelper.Level.DEBUG; boolean bright = level != LogHelper.Level.DEBUG;
switch (level) { switch (level) {
@ -73,8 +72,7 @@ static String ansiFormatLicense(String product) {
reset().toString(); // To file reset().toString(); // To file
} }
public static String rawFormat(LogHelper.Level level, String dateTime, boolean sub) public static String rawFormat(LogHelper.Level level, String dateTime, boolean sub) {
{
return dateTime + " [" + level.name + (sub ? "] " : "] "); return dateTime + " [" + level.name + (sub ? "] " : "] ");
} }

Some files were not shown because too many files have changed in this diff Show more