mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-11-15 11:39:11 +03:00
Merge branch 'release/5.5.0'
This commit is contained in:
commit
1df283d659
153 changed files with 1901 additions and 1994 deletions
4
.github/workflows/push.yml
vendored
4
.github/workflows/push.yml
vendored
|
@ -16,10 +16,10 @@ jobs:
|
||||||
path: ~/.gradle/caches
|
path: ~/.gradle/caches
|
||||||
key: gravit-${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}-launcher
|
key: gravit-${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}-launcher
|
||||||
|
|
||||||
- name: Set up JDK 17
|
- name: Set up JDK 21
|
||||||
uses: actions/setup-java@v1
|
uses: actions/setup-java@v1
|
||||||
with:
|
with:
|
||||||
java-version: 17
|
java-version: 21
|
||||||
|
|
||||||
- name: Grant execute permission for gradlew
|
- name: Grant execute permission for gradlew
|
||||||
run: chmod +x gradlew
|
run: chmod +x gradlew
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceCompatibility = '17'
|
sourceCompatibility = '21'
|
||||||
targetCompatibility = '17'
|
targetCompatibility = '21'
|
||||||
|
|
||||||
configurations {
|
configurations {
|
||||||
compileOnlyA
|
compileOnlyA
|
||||||
|
@ -75,6 +75,7 @@
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
pack project(':LauncherAPI')
|
pack project(':LauncherAPI')
|
||||||
|
pack project(':LauncherModernCore')
|
||||||
bundle group: 'me.tongfei', name: 'progressbar', version: '0.9.2'
|
bundle group: 'me.tongfei', name: 'progressbar', version: '0.9.2'
|
||||||
bundle group: 'com.github.Marcono1234', name: 'gson-record-type-adapter-factory', version: 'v0.2.0'
|
bundle group: 'com.github.Marcono1234', name: 'gson-record-type-adapter-factory', version: 'v0.2.0'
|
||||||
bundle group: 'org.fusesource.jansi', name: 'jansi', version: rootProject['verJansi']
|
bundle group: 'org.fusesource.jansi', name: 'jansi', version: rootProject['verJansi']
|
||||||
|
@ -85,7 +86,7 @@ pack project(':LauncherAPI')
|
||||||
bundle group: 'org.ow2.asm', name: 'asm-commons', version: rootProject['verAsm']
|
bundle group: 'org.ow2.asm', name: 'asm-commons', version: rootProject['verAsm']
|
||||||
bundle group: 'io.netty', name: 'netty-all', version: rootProject['verNetty']
|
bundle group: 'io.netty', name: 'netty-all', version: rootProject['verNetty']
|
||||||
bundle group: 'org.slf4j', name: 'slf4j-api', version: rootProject['verSlf4j']
|
bundle group: 'org.slf4j', name: 'slf4j-api', version: rootProject['verSlf4j']
|
||||||
bundle group: 'mysql', name: 'mysql-connector-java', version: rootProject['verMySQLConn']
|
bundle group: 'com.mysql', name: 'mysql-connector-j', version: rootProject['verMySQLConn']
|
||||||
bundle group: 'org.postgresql', name: 'postgresql', version: rootProject['verPostgreSQLConn']
|
bundle group: 'org.postgresql', name: 'postgresql', version: rootProject['verPostgreSQLConn']
|
||||||
bundle group: 'com.guardsquare', name: 'proguard-base', version: rootProject['verProguard']
|
bundle group: 'com.guardsquare', name: 'proguard-base', version: rootProject['verProguard']
|
||||||
bundle group: 'org.apache.logging.log4j', name: 'log4j-core', version: rootProject['verLog4j']
|
bundle group: 'org.apache.logging.log4j', name: 'log4j-core', version: rootProject['verLog4j']
|
||||||
|
@ -93,6 +94,7 @@ pack project(':LauncherAPI')
|
||||||
bundle group: 'io.jsonwebtoken', name: 'jjwt-api', version: rootProject['verJwt']
|
bundle group: 'io.jsonwebtoken', name: 'jjwt-api', version: rootProject['verJwt']
|
||||||
bundle group: 'io.jsonwebtoken', name: 'jjwt-impl', version: rootProject['verJwt']
|
bundle group: 'io.jsonwebtoken', name: 'jjwt-impl', version: rootProject['verJwt']
|
||||||
bundle group: 'io.jsonwebtoken', name: 'jjwt-gson', version: rootProject['verJwt']
|
bundle group: 'io.jsonwebtoken', name: 'jjwt-gson', version: rootProject['verJwt']
|
||||||
|
annotationProcessor(group: 'org.apache.logging.log4j', name: 'log4j-core', version: rootProject['verLog4j'])
|
||||||
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter', version: rootProject['verJunit']
|
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter', version: rootProject['verJunit']
|
||||||
|
|
||||||
hikari 'io.micrometer:micrometer-core:1.8.4'
|
hikari 'io.micrometer:micrometer-core:1.8.4'
|
||||||
|
|
|
@ -21,6 +21,10 @@ public <T> SimpleErrorHandler<T> makeEH(Class<T> clazz) {
|
||||||
return new SimpleErrorHandler<>(clazz);
|
return new SimpleErrorHandler<>(clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <T> SimpleErrorHandler<T> makeEH(Type clazz) {
|
||||||
|
return new SimpleErrorHandler<>(clazz);
|
||||||
|
}
|
||||||
|
|
||||||
public <T> HttpRequest get(String url, String token) {
|
public <T> HttpRequest get(String url, String token) {
|
||||||
try {
|
try {
|
||||||
var requestBuilder = HttpRequest.newBuilder()
|
var requestBuilder = HttpRequest.newBuilder()
|
||||||
|
@ -59,6 +63,10 @@ public <T> HttpHelper.HttpOptional<T, SimpleError> send(HttpRequest request, Cla
|
||||||
return HttpHelper.send(httpClient, request, makeEH(clazz));
|
return HttpHelper.send(httpClient, request, makeEH(clazz));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public <T> HttpHelper.HttpOptional<T, SimpleError> send(HttpRequest request, Type type) throws IOException {
|
||||||
|
return HttpHelper.send(httpClient, request, makeEH(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class SimpleErrorHandler<T> implements HttpHelper.HttpJsonErrorHandler<T, SimpleError> {
|
public static class SimpleErrorHandler<T> implements HttpHelper.HttpJsonErrorHandler<T, SimpleError> {
|
||||||
private final Type type;
|
private final Type type;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
import pro.gravit.launchserver.binary.LauncherBinary;
|
import pro.gravit.launchserver.binary.LauncherBinary;
|
||||||
import pro.gravit.launchserver.config.LaunchServerConfig;
|
import pro.gravit.launchserver.config.LaunchServerConfig;
|
||||||
import pro.gravit.launchserver.config.LaunchServerRuntimeConfig;
|
import pro.gravit.launchserver.config.LaunchServerRuntimeConfig;
|
||||||
|
import pro.gravit.launchserver.helper.SignHelper;
|
||||||
import pro.gravit.launchserver.launchermodules.LauncherModuleLoader;
|
import pro.gravit.launchserver.launchermodules.LauncherModuleLoader;
|
||||||
import pro.gravit.launchserver.manangers.*;
|
import pro.gravit.launchserver.manangers.*;
|
||||||
import pro.gravit.launchserver.manangers.hook.AuthHookManager;
|
import pro.gravit.launchserver.manangers.hook.AuthHookManager;
|
||||||
|
@ -36,13 +37,15 @@
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.ProcessBuilder.Redirect;
|
import java.lang.ProcessBuilder.Redirect;
|
||||||
import java.lang.invoke.MethodHandles;
|
|
||||||
import java.lang.invoke.MethodType;
|
|
||||||
import java.nio.file.*;
|
import java.nio.file.*;
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
|
import java.security.KeyStore;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -185,6 +188,10 @@ public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, La
|
||||||
}
|
}
|
||||||
launcherModuleLoader.init();
|
launcherModuleLoader.init();
|
||||||
nettyServerSocketHandler = new NettyServerSocketHandler(this);
|
nettyServerSocketHandler = new NettyServerSocketHandler(this);
|
||||||
|
if(config.sign.checkCertificateExpired) {
|
||||||
|
checkCertificateExpired();
|
||||||
|
service.scheduleAtFixedRate(this::checkCertificateExpired, 24, 24, TimeUnit.HOURS);
|
||||||
|
}
|
||||||
// post init modules
|
// post init modules
|
||||||
modulesManager.invokeEvent(new LaunchServerPostInitPhase(this));
|
modulesManager.invokeEvent(new LaunchServerPostInitPhase(this));
|
||||||
}
|
}
|
||||||
|
@ -234,7 +241,6 @@ public void invoke(String... args) throws Exception {
|
||||||
}
|
}
|
||||||
switch (args[0]) {
|
switch (args[0]) {
|
||||||
case "full" -> reload(ReloadType.FULL);
|
case "full" -> reload(ReloadType.FULL);
|
||||||
case "no_auth" -> reload(ReloadType.NO_AUTH);
|
|
||||||
case "no_components" -> reload(ReloadType.NO_COMPONENTS);
|
case "no_components" -> reload(ReloadType.NO_COMPONENTS);
|
||||||
default -> reload(ReloadType.NO_AUTH);
|
default -> reload(ReloadType.NO_AUTH);
|
||||||
}
|
}
|
||||||
|
@ -269,6 +275,25 @@ public void invoke(String... args) throws Exception {
|
||||||
return commands;
|
return commands;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void checkCertificateExpired() {
|
||||||
|
if(!config.sign.enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
KeyStore keyStore = SignHelper.getStore(Paths.get(config.sign.keyStore), config.sign.keyStorePass, config.sign.keyStoreType);
|
||||||
|
Instant date = SignHelper.getCertificateExpired(keyStore, config.sign.keyAlias);
|
||||||
|
if(date == null) {
|
||||||
|
logger.debug("The certificate will expire at unlimited");
|
||||||
|
} else if(date.minus(Duration.ofDays(30)).isBefore(Instant.now())) {
|
||||||
|
logger.warn("The certificate will expire at {}", date.toString());
|
||||||
|
} else {
|
||||||
|
logger.debug("The certificate will expire at {}", date.toString());
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
logger.error("Can't get certificate expire date", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private LauncherBinary binary() {
|
private LauncherBinary binary() {
|
||||||
LaunchServerLauncherExeInit event = new LaunchServerLauncherExeInit(this, null);
|
LaunchServerLauncherExeInit event = new LaunchServerLauncherExeInit(this, null);
|
||||||
modulesManager.invokeEvent(event);
|
modulesManager.invokeEvent(event);
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||||
import pro.gravit.launcher.request.auth.GetAvailabilityAuthRequest;
|
import pro.gravit.launcher.request.auth.GetAvailabilityAuthRequest;
|
||||||
import pro.gravit.launchserver.auth.core.AuthCoreProvider;
|
import pro.gravit.launchserver.auth.core.AuthCoreProvider;
|
||||||
|
import pro.gravit.launchserver.auth.mix.MixProvider;
|
||||||
import pro.gravit.launchserver.auth.password.PasswordVerifier;
|
import pro.gravit.launchserver.auth.password.PasswordVerifier;
|
||||||
import pro.gravit.launchserver.auth.protect.ProtectHandler;
|
import pro.gravit.launchserver.auth.protect.ProtectHandler;
|
||||||
import pro.gravit.launchserver.auth.texture.TextureProvider;
|
import pro.gravit.launchserver.auth.texture.TextureProvider;
|
||||||
|
@ -212,6 +213,7 @@ public static void registerAll() {
|
||||||
GetAvailabilityAuthRequest.registerProviders();
|
GetAvailabilityAuthRequest.registerProviders();
|
||||||
OptionalAction.registerProviders();
|
OptionalAction.registerProviders();
|
||||||
OptionalTrigger.registerProviders();
|
OptionalTrigger.registerProviders();
|
||||||
|
MixProvider.registerProviders();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void printExperimentalBranch() {
|
private static void printExperimentalBranch() {
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
public class InjectClassAcceptor implements MainBuildTask.ASMTransformer {
|
public class InjectClassAcceptor implements MainBuildTask.ASMTransformer {
|
||||||
|
|
|
@ -149,10 +149,7 @@ public static int opcodeEmulation(AbstractInsnNode e) {
|
||||||
break;
|
break;
|
||||||
case INVOKEVIRTUAL:
|
case INVOKEVIRTUAL:
|
||||||
case INVOKESPECIAL:
|
case INVOKESPECIAL:
|
||||||
case INVOKEINTERFACE:
|
case INVOKEINTERFACE, INVOKESTATIC:
|
||||||
stackSize += doMethodEmulation(((MethodInsnNode) e).desc);
|
|
||||||
break;
|
|
||||||
case INVOKESTATIC:
|
|
||||||
stackSize += doMethodEmulation(((MethodInsnNode) e).desc);
|
stackSize += doMethodEmulation(((MethodInsnNode) e).desc);
|
||||||
break;
|
break;
|
||||||
case INVOKEDYNAMIC:
|
case INVOKEDYNAMIC:
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
import pro.gravit.launchserver.auth.core.AuthCoreProvider;
|
import pro.gravit.launchserver.auth.core.AuthCoreProvider;
|
||||||
|
import pro.gravit.launchserver.auth.mix.MixProvider;
|
||||||
import pro.gravit.launchserver.auth.texture.TextureProvider;
|
import pro.gravit.launchserver.auth.texture.TextureProvider;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -16,6 +17,7 @@ public final class AuthProviderPair {
|
||||||
public boolean isDefault = true;
|
public boolean isDefault = true;
|
||||||
public AuthCoreProvider core;
|
public AuthCoreProvider core;
|
||||||
public TextureProvider textureProvider;
|
public TextureProvider textureProvider;
|
||||||
|
public Map<String, MixProvider> mixes;
|
||||||
public Map<String, String> links;
|
public Map<String, String> links;
|
||||||
public transient String name;
|
public transient String name;
|
||||||
public transient Set<String> features;
|
public transient Set<String> features;
|
||||||
|
@ -36,12 +38,14 @@ public static Set<String> getFeatures(Class<?> clazz) {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void getFeatures(Class<?> clazz, Set<String> list) {
|
public Set<String> getFeatures() {
|
||||||
Features features = clazz.getAnnotation(Features.class);
|
return features;
|
||||||
if (features != null) {
|
|
||||||
for (Feature feature : features.value()) {
|
|
||||||
list.add(feature.value());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void getFeatures(Class<?> clazz, Set<String> list) {
|
||||||
|
Feature[] features = clazz.getAnnotationsByType(Feature.class);
|
||||||
|
for (Feature feature : features) {
|
||||||
|
list.add(feature.value());
|
||||||
}
|
}
|
||||||
Class<?> superClass = clazz.getSuperclass();
|
Class<?> superClass = clazz.getSuperclass();
|
||||||
if (superClass != null && superClass != Object.class) {
|
if (superClass != null && superClass != Object.class) {
|
||||||
|
@ -55,8 +59,15 @@ public static void getFeatures(Class<?> clazz, Set<String> list) {
|
||||||
|
|
||||||
public final <T> T isSupport(Class<T> clazz) {
|
public final <T> T isSupport(Class<T> clazz) {
|
||||||
if (core == null) return null;
|
if (core == null) return null;
|
||||||
T result = null;
|
T result = core.isSupport(clazz);
|
||||||
if (result == null) result = core.isSupport(clazz);
|
if (result == null && mixes != null) {
|
||||||
|
for(var m : mixes.values()) {
|
||||||
|
result = m.isSupport(clazz);
|
||||||
|
if(result != null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,6 +77,12 @@ public final void init(LaunchServer srv, String name) {
|
||||||
core.init(srv);
|
core.init(srv);
|
||||||
features = new HashSet<>();
|
features = new HashSet<>();
|
||||||
getFeatures(core.getClass(), features);
|
getFeatures(core.getClass(), features);
|
||||||
|
if(mixes != null) {
|
||||||
|
for(var m : mixes.values()) {
|
||||||
|
m.init(srv, core);
|
||||||
|
getFeatures(m.getClass(), features);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void link(LaunchServer srv) {
|
public final void link(LaunchServer srv) {
|
||||||
|
@ -87,5 +104,10 @@ public final void close() throws IOException {
|
||||||
if (textureProvider != null) {
|
if (textureProvider != null) {
|
||||||
textureProvider.close();
|
textureProvider.close();
|
||||||
}
|
}
|
||||||
|
if(mixes != null) {
|
||||||
|
for(var m : mixes.values()) {
|
||||||
|
m.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
import pro.gravit.launchserver.auth.password.PasswordVerifier;
|
import pro.gravit.launchserver.auth.password.PasswordVerifier;
|
||||||
import pro.gravit.launchserver.helper.LegacySessionHelper;
|
import pro.gravit.launchserver.helper.LegacySessionHelper;
|
||||||
import pro.gravit.launchserver.manangers.AuthManager;
|
import pro.gravit.launchserver.manangers.AuthManager;
|
||||||
|
import pro.gravit.launchserver.socket.Client;
|
||||||
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
|
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
|
||||||
import pro.gravit.utils.helper.SecurityHelper;
|
import pro.gravit.utils.helper.SecurityHelper;
|
||||||
|
|
||||||
|
@ -162,6 +163,25 @@ public AuthManager.AuthReport authorize(String login, AuthResponse.AuthContext c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User checkServer(Client client, String username, String serverID) throws IOException {
|
||||||
|
SQLUser user = (SQLUser) getUserByUsername(username);
|
||||||
|
if (user == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (user.getUsername().equals(username) && user.getServerId().equals(serverID)) {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean joinServer(Client client, String username, UUID uuid, String accessToken, String serverID) throws IOException {
|
||||||
|
SQLUser user = (SQLUser) client.getUser();
|
||||||
|
if (user == null) return false;
|
||||||
|
return user.getUsername().equals(username) && user.getAccessToken().equals(accessToken) && updateServerID(user, serverID);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(LaunchServer server) {
|
public void init(LaunchServer server) {
|
||||||
this.server = server;
|
this.server = server;
|
||||||
|
@ -225,7 +245,6 @@ protected void updateAuth(User user, String accessToken) throws IOException {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean updateServerID(User user, String serverID) throws IOException {
|
protected boolean updateServerID(User user, String serverID) throws IOException {
|
||||||
try (Connection c = getSQLConfig().getConnection()) {
|
try (Connection c = getSQLConfig().getConnection()) {
|
||||||
SQLUser SQLUser = (SQLUser) user;
|
SQLUser SQLUser = (SQLUser) user;
|
||||||
|
@ -328,12 +347,10 @@ public UUID getUUID() {
|
||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getServerId() {
|
public String getServerId() {
|
||||||
return serverId;
|
return serverId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getAccessToken() {
|
public String getAccessToken() {
|
||||||
return accessToken;
|
return accessToken;
|
||||||
}
|
}
|
||||||
|
@ -372,6 +389,11 @@ public User getUser() {
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMinecraftAccessToken() {
|
||||||
|
return user.getAccessToken();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getExpireIn() {
|
public long getExpireIn() {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -45,7 +45,6 @@ public static void registerProviders() {
|
||||||
providers.register("mysql", MySQLCoreProvider.class);
|
providers.register("mysql", MySQLCoreProvider.class);
|
||||||
providers.register("postgresql", PostgresSQLCoreProvider.class);
|
providers.register("postgresql", PostgresSQLCoreProvider.class);
|
||||||
providers.register("memory", MemoryAuthCoreProvider.class);
|
providers.register("memory", MemoryAuthCoreProvider.class);
|
||||||
providers.register("http", HttpAuthCoreProvider.class);
|
|
||||||
providers.register("merge", MergeAuthCoreProvider.class);
|
providers.register("merge", MergeAuthCoreProvider.class);
|
||||||
registredProviders = true;
|
registredProviders = true;
|
||||||
}
|
}
|
||||||
|
@ -75,11 +74,6 @@ public AuthManager.AuthReport authorize(User user, AuthResponse.AuthContext cont
|
||||||
|
|
||||||
public abstract void init(LaunchServer server);
|
public abstract void init(LaunchServer server);
|
||||||
|
|
||||||
// Auth Handler methods
|
|
||||||
protected boolean updateServerID(User user, String serverID) throws IOException {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> getDetails(Client client) {
|
public List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> getDetails(Client client) {
|
||||||
return List.of(new AuthPasswordDetails());
|
return List.of(new AuthPasswordDetails());
|
||||||
}
|
}
|
||||||
|
@ -292,22 +286,9 @@ public void invoke(String... args) throws Exception {
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
public User checkServer(Client client, String username, String serverID) throws IOException {
|
public abstract User checkServer(Client client, String username, String serverID) throws IOException;
|
||||||
User user = getUserByUsername(username);
|
|
||||||
if (user == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (user.getUsername().equals(username) && user.getServerId().equals(serverID)) {
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean joinServer(Client client, String username, String accessToken, String serverID) throws IOException {
|
public abstract boolean joinServer(Client client, String username, UUID uuid, String accessToken, String serverID) throws IOException;
|
||||||
User user = client.getUser();
|
|
||||||
if (user == null) return false;
|
|
||||||
return user.getUsername().equals(username) && user.getAccessToken().equals(accessToken) && updateServerID(user, serverID);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> T isSupport(Class<T> clazz) {
|
public <T> T isSupport(Class<T> clazz) {
|
||||||
|
|
|
@ -1,646 +0,0 @@
|
||||||
package pro.gravit.launchserver.auth.core;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import pro.gravit.launcher.ClientPermissions;
|
|
||||||
import pro.gravit.launcher.events.request.AuthRequestEvent;
|
|
||||||
import pro.gravit.launcher.events.request.GetAvailabilityAuthRequestEvent;
|
|
||||||
import pro.gravit.launcher.profiles.Texture;
|
|
||||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
|
||||||
import pro.gravit.launcher.request.secure.HardwareReportRequest;
|
|
||||||
import pro.gravit.launchserver.HttpRequester;
|
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
|
||||||
import pro.gravit.launchserver.auth.AuthException;
|
|
||||||
import pro.gravit.launchserver.auth.core.interfaces.UserHardware;
|
|
||||||
import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportHardware;
|
|
||||||
import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportRemoteClientAccess;
|
|
||||||
import pro.gravit.launchserver.auth.core.interfaces.user.UserSupportHardware;
|
|
||||||
import pro.gravit.launchserver.auth.core.interfaces.user.UserSupportProperties;
|
|
||||||
import pro.gravit.launchserver.auth.core.interfaces.user.UserSupportTextures;
|
|
||||||
import pro.gravit.launchserver.helper.HttpHelper;
|
|
||||||
import pro.gravit.launchserver.manangers.AuthManager;
|
|
||||||
import pro.gravit.launchserver.socket.Client;
|
|
||||||
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
|
|
||||||
import pro.gravit.utils.helper.CommonHelper;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class HttpAuthCoreProvider extends AuthCoreProvider implements AuthSupportHardware, AuthSupportRemoteClientAccess {
|
|
||||||
private transient final Logger logger = LogManager.getLogger();
|
|
||||||
public String bearerToken;
|
|
||||||
public String getUserByUsernameUrl;
|
|
||||||
public String getUserByLoginUrl;
|
|
||||||
public String getUserByUUIDUrl;
|
|
||||||
public String getUserByTokenUrl;
|
|
||||||
public String getAuthDetailsUrl;
|
|
||||||
public String refreshTokenUrl;
|
|
||||||
public String authorizeUrl;
|
|
||||||
public String joinServerUrl;
|
|
||||||
public String checkServerUrl;
|
|
||||||
public String updateServerIdUrl;
|
|
||||||
//below fields can be empty if advanced protect handler disabled
|
|
||||||
public String getHardwareInfoByPublicKeyUrl;
|
|
||||||
public String getHardwareInfoByDataUrl;
|
|
||||||
public String getHardwareInfoByIdUrl;
|
|
||||||
public String createHardwareInfoUrl;
|
|
||||||
public String connectUserAndHardwareUrl;
|
|
||||||
public String addPublicKeyToHardwareInfoUrl;
|
|
||||||
public String getUsersByHardwareInfoUrl;
|
|
||||||
public String banHardwareUrl;
|
|
||||||
public String unbanHardwareUrl;
|
|
||||||
public String apiUrl;
|
|
||||||
public List<String> apiFeatures;
|
|
||||||
private transient HttpRequester requester;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public User getUserByUsername(String username) {
|
|
||||||
try {
|
|
||||||
return requester.send(requester.get(CommonHelper.replace(getUserByUsernameUrl, "username", username), null), HttpUser.class).getOrThrow();
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error(e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public User getUserByLogin(String login) {
|
|
||||||
if (getUserByLoginUrl != null) {
|
|
||||||
try {
|
|
||||||
return requester.send(requester.get(CommonHelper.replace(getUserByLoginUrl, "login", login), null), HttpUser.class).getOrThrow();
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error(e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return super.getUserByLogin(login);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public User getUserByUUID(UUID uuid) {
|
|
||||||
try {
|
|
||||||
return requester.send(requester.get(CommonHelper.replace(getUserByUUIDUrl, "uuid", uuid.toString()), null), HttpUser.class).getOrThrow();
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error(e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> getDetails(Client client) {
|
|
||||||
if (getAuthDetailsUrl == null) {
|
|
||||||
return super.getDetails(client);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
var result = requester.send(requester.get(getAuthDetailsUrl, bearerToken), GetAuthDetailsResponse.class).getOrThrow();
|
|
||||||
return result.details;
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error(e);
|
|
||||||
return super.getDetails(client);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserSession getUserSessionByOAuthAccessToken(String accessToken) throws OAuthAccessTokenExpired {
|
|
||||||
if (getUserByTokenUrl == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
var result = requester.send(requester.get(getUserByTokenUrl, accessToken), HttpUserSession.class);
|
|
||||||
if (!result.isSuccessful()) {
|
|
||||||
var error = result.error().error;
|
|
||||||
if (error.equals(AuthRequestEvent.OAUTH_TOKEN_EXPIRE)) {
|
|
||||||
throw new OAuthAccessTokenExpired();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return result.getOrThrow();
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error(e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AuthManager.AuthReport refreshAccessToken(String refreshToken, AuthResponse.AuthContext context) {
|
|
||||||
if (refreshTokenUrl == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return requester.send(requester.post(refreshTokenUrl, new RefreshTokenRequest(refreshToken, context),
|
|
||||||
null), HttpAuthReport.class).getOrThrow().toAuthReport();
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error(e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AuthManager.AuthReport authorize(String login, AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password, boolean minecraftAccess) throws IOException {
|
|
||||||
var result = requester.send(requester.post(authorizeUrl, new AuthorizeRequest(login, context, password, minecraftAccess),
|
|
||||||
bearerToken), HttpAuthReport.class);
|
|
||||||
if (!result.isSuccessful()) {
|
|
||||||
var error = result.error().error;
|
|
||||||
if (error != null) {
|
|
||||||
throw new AuthException(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result.getOrThrow().toAuthReport();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserHardware getHardwareInfoByPublicKey(byte[] publicKey) {
|
|
||||||
if (getHardwareInfoByPublicKeyUrl == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return requester.send(requester.post(getHardwareInfoByPublicKeyUrl, new HardwareRequest(publicKey),
|
|
||||||
bearerToken), HttpUserHardware.class).getOrThrow();
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error(e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserHardware getHardwareInfoByData(HardwareReportRequest.HardwareInfo info) {
|
|
||||||
if (getHardwareInfoByDataUrl == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
HardwareRequest request = new HardwareRequest(new HttpUserHardware(info));
|
|
||||||
HttpHelper.HttpOptional<HttpUserHardware, HttpRequester.SimpleError> hardware =
|
|
||||||
requester.send(requester.post(getHardwareInfoByDataUrl, request,
|
|
||||||
bearerToken), HttpUserHardware.class);
|
|
||||||
//should return null if not found
|
|
||||||
return hardware.isSuccessful() ? hardware.getOrThrow() : null;
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error(e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserHardware getHardwareInfoById(String id) {
|
|
||||||
if (getHardwareInfoByIdUrl == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return requester.send(requester.post(getHardwareInfoByIdUrl, new HardwareRequest(new HttpUserHardware(Long.parseLong(id))),
|
|
||||||
bearerToken), HttpUserHardware.class).getOrThrow();
|
|
||||||
} catch (IOException | NumberFormatException e) {
|
|
||||||
logger.error(e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserHardware createHardwareInfo(HardwareReportRequest.HardwareInfo info, byte[] publicKey) {
|
|
||||||
if (createHardwareInfoUrl == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return requester.send(requester.post(createHardwareInfoUrl, new HardwareRequest(new HttpUserHardware(info,
|
|
||||||
publicKey, false)), bearerToken), HttpUserHardware.class).getOrThrow();
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error(e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void connectUserAndHardware(UserSession userSession, UserHardware hardware) {
|
|
||||||
if (connectUserAndHardwareUrl == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
requester.send(requester.post(connectUserAndHardwareUrl, new HardwareRequest((HttpUserHardware) hardware, (HttpUserSession) userSession), bearerToken), Void.class);
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addPublicKeyToHardwareInfo(UserHardware hardware, byte[] publicKey) {
|
|
||||||
if (addPublicKeyToHardwareInfoUrl == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
requester.send(requester.post(addPublicKeyToHardwareInfoUrl, new HardwareRequest((HttpUserHardware) hardware, publicKey), bearerToken), Void.class);
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
|
||||||
@Override
|
|
||||||
public Iterable<User> getUsersByHardwareInfo(UserHardware hardware) {
|
|
||||||
if (getUsersByHardwareInfoUrl == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return (List<User>) (List) requester.send(requester
|
|
||||||
.post(getUsersByHardwareInfoUrl, new HardwareRequest((HttpUserHardware) hardware), bearerToken), GetHardwareListResponse.class).getOrThrow().list;
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error(e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void banHardware(UserHardware hardware) {
|
|
||||||
if (banHardwareUrl == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
requester.send(requester.post(banHardwareUrl, new HardwareRequest((HttpUserHardware) hardware), bearerToken), Void.class);
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unbanHardware(UserHardware hardware) {
|
|
||||||
if (unbanHardwareUrl == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
requester.send(requester.post(unbanHardwareUrl, new HardwareRequest((HttpUserHardware) hardware), bearerToken), Void.class);
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getClientApiUrl() {
|
|
||||||
return apiUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> getClientApiFeatures() {
|
|
||||||
return apiFeatures;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean updateServerID(User user, String serverID) throws IOException {
|
|
||||||
var result = requester.send(requester.post(updateServerIdUrl, new UpdateServerIdRequest(user.getUsername(), user.getUUID(), serverID),
|
|
||||||
null), Void.class);
|
|
||||||
return result.isSuccessful();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public User checkServer(Client client, String username, String serverID) throws IOException {
|
|
||||||
return requester.send(requester.post(checkServerUrl, new CheckServerRequest(username, serverID), bearerToken), HttpUser.class).getOrThrow();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean joinServer(Client client, String username, String accessToken, String serverID) throws IOException {
|
|
||||||
var result = requester.send(requester.post(joinServerUrl, new JoinServerRequest(username, accessToken, serverID), bearerToken), Void.class);
|
|
||||||
return result.isSuccessful();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(LaunchServer server) {
|
|
||||||
requester = new HttpRequester();
|
|
||||||
if (getUserByUsernameUrl == null) {
|
|
||||||
throw new IllegalArgumentException("'getUserByUsernameUrl' can't be null");
|
|
||||||
}
|
|
||||||
if (getUserByUUIDUrl == null) {
|
|
||||||
throw new IllegalArgumentException("'getUserByUUIDUrl' can't be null");
|
|
||||||
}
|
|
||||||
if (authorizeUrl == null) {
|
|
||||||
throw new IllegalArgumentException("'authorizeUrl' can't be null");
|
|
||||||
}
|
|
||||||
if (checkServerUrl == null && joinServerUrl == null && updateServerIdUrl == null) {
|
|
||||||
throw new IllegalArgumentException("Please set 'checkServerUrl' and 'joinServerUrl' or 'updateServerIdUrl'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public record HttpAuthReport(String minecraftAccessToken, String oauthAccessToken,
|
|
||||||
String oauthRefreshToken, long oauthExpire,
|
|
||||||
HttpUserSession session) {
|
|
||||||
public AuthManager.AuthReport toAuthReport() {
|
|
||||||
return new AuthManager.AuthReport(minecraftAccessToken, oauthAccessToken, oauthRefreshToken, oauthExpire, session);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class UpdateServerIdRequest {
|
|
||||||
public String username;
|
|
||||||
public UUID uuid;
|
|
||||||
public String serverId;
|
|
||||||
|
|
||||||
public UpdateServerIdRequest(String username, UUID uuid, String serverId) {
|
|
||||||
this.username = username;
|
|
||||||
this.uuid = uuid;
|
|
||||||
this.serverId = serverId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class CheckServerRequest {
|
|
||||||
public String username;
|
|
||||||
public String serverId;
|
|
||||||
|
|
||||||
public CheckServerRequest(String username, String serverId) {
|
|
||||||
this.username = username;
|
|
||||||
this.serverId = serverId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class GetAuthDetailsResponse {
|
|
||||||
public List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> details;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class GetHardwareListResponse {
|
|
||||||
public List<HttpUser> list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class JoinServerRequest {
|
|
||||||
public String username;
|
|
||||||
public String accessToken;
|
|
||||||
public String serverId;
|
|
||||||
|
|
||||||
public JoinServerRequest(String username, String accessToken, String serverId) {
|
|
||||||
this.username = username;
|
|
||||||
this.accessToken = accessToken;
|
|
||||||
this.serverId = serverId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class AuthorizeRequest {
|
|
||||||
public String login;
|
|
||||||
public AuthResponse.AuthContext context;
|
|
||||||
public AuthRequest.AuthPasswordInterface password;
|
|
||||||
public boolean minecraftAccess;
|
|
||||||
|
|
||||||
public AuthorizeRequest() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public AuthorizeRequest(String login, AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password, boolean minecraftAccess) {
|
|
||||||
this.login = login;
|
|
||||||
this.context = context;
|
|
||||||
this.password = password;
|
|
||||||
this.minecraftAccess = minecraftAccess;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class RefreshTokenRequest {
|
|
||||||
public String refreshToken;
|
|
||||||
public AuthResponse.AuthContext context;
|
|
||||||
|
|
||||||
public RefreshTokenRequest(String refreshToken, AuthResponse.AuthContext context) {
|
|
||||||
this.refreshToken = refreshToken;
|
|
||||||
this.context = context;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public record HardwareRequest(HttpUserHardware userHardware, byte[] key, HttpUserSession userSession) {
|
|
||||||
|
|
||||||
public HardwareRequest(HttpUserHardware userHardware) {
|
|
||||||
this(userHardware, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public HardwareRequest(HttpUserHardware userHardware, byte[] key) {
|
|
||||||
this(userHardware, key, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public HardwareRequest(HttpUserHardware userHardware, HttpUserSession userSession) {
|
|
||||||
this(userHardware, null, userSession);
|
|
||||||
}
|
|
||||||
|
|
||||||
public HardwareRequest(byte[] key) {
|
|
||||||
this(null, key, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class HttpUserSession implements UserSession {
|
|
||||||
private String id;
|
|
||||||
private HttpUser user;
|
|
||||||
private long expireIn;
|
|
||||||
|
|
||||||
public HttpUserSession() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpUserSession(String id, HttpUser user, long expireIn) {
|
|
||||||
this.id = id;
|
|
||||||
this.user = user;
|
|
||||||
this.expireIn = expireIn;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getID() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public User getUser() {
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getExpireIn() {
|
|
||||||
return expireIn;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "HttpUserSession{" +
|
|
||||||
"id='" + id + '\'' +
|
|
||||||
", user=" + user +
|
|
||||||
", expireIn=" + expireIn +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class HttpUserHardware implements UserHardware {
|
|
||||||
private final HardwareReportRequest.HardwareInfo hardwareInfo;
|
|
||||||
private final long id;
|
|
||||||
private byte[] publicKey;
|
|
||||||
private boolean banned;
|
|
||||||
|
|
||||||
public HttpUserHardware(HardwareReportRequest.HardwareInfo hardwareInfo, byte[] publicKey, long id, boolean banned) {
|
|
||||||
this.hardwareInfo = hardwareInfo;
|
|
||||||
this.publicKey = publicKey;
|
|
||||||
this.id = id;
|
|
||||||
this.banned = banned;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpUserHardware(HardwareReportRequest.HardwareInfo hardwareInfo) {
|
|
||||||
this.hardwareInfo = hardwareInfo;
|
|
||||||
this.id = Long.MIN_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpUserHardware(HardwareReportRequest.HardwareInfo hardwareInfo, byte[] publicKey, boolean banned) {
|
|
||||||
this.hardwareInfo = hardwareInfo;
|
|
||||||
this.publicKey = publicKey;
|
|
||||||
this.banned = banned;
|
|
||||||
this.id = Long.MIN_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpUserHardware(long id) {
|
|
||||||
this.id = id;
|
|
||||||
this.hardwareInfo = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HardwareReportRequest.HardwareInfo getHardwareInfo() {
|
|
||||||
return hardwareInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] getPublicKey() {
|
|
||||||
return publicKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getId() {
|
|
||||||
return String.valueOf(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isBanned() {
|
|
||||||
return banned;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "HttpUserHardware{" +
|
|
||||||
"hardwareInfo=" + hardwareInfo +
|
|
||||||
", publicKey=" + (publicKey == null ? null : new String(Base64.getEncoder().encode(publicKey))) +
|
|
||||||
", id=" + id +
|
|
||||||
", banned=" + banned +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class HttpUser implements User, UserSupportTextures, UserSupportProperties, UserSupportHardware {
|
|
||||||
private String username;
|
|
||||||
private UUID uuid;
|
|
||||||
private String serverId;
|
|
||||||
private String accessToken;
|
|
||||||
private ClientPermissions permissions;
|
|
||||||
private Map<String, Texture> assets;
|
|
||||||
private Map<String, String> properties;
|
|
||||||
private long hwidId;
|
|
||||||
private transient HttpUserHardware hardware;
|
|
||||||
|
|
||||||
public HttpUser() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpUser(String username, UUID uuid, String serverId, String accessToken, ClientPermissions permissions, long hwidId) {
|
|
||||||
this.username = username;
|
|
||||||
this.uuid = uuid;
|
|
||||||
this.serverId = serverId;
|
|
||||||
this.accessToken = accessToken;
|
|
||||||
this.permissions = permissions;
|
|
||||||
this.hwidId = hwidId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpUser(String username, UUID uuid, String serverId, String accessToken, ClientPermissions permissions, Texture skin, Texture cloak, long hwidId) {
|
|
||||||
this.username = username;
|
|
||||||
this.uuid = uuid;
|
|
||||||
this.serverId = serverId;
|
|
||||||
this.accessToken = accessToken;
|
|
||||||
this.permissions = permissions;
|
|
||||||
this.hwidId = hwidId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpUser(String username, UUID uuid, String serverId, String accessToken, ClientPermissions permissions, Texture skin, Texture cloak, Map<String, String> properties, long hwidId) {
|
|
||||||
this.username = username;
|
|
||||||
this.uuid = uuid;
|
|
||||||
this.serverId = serverId;
|
|
||||||
this.accessToken = accessToken;
|
|
||||||
this.permissions = permissions;
|
|
||||||
this.properties = properties;
|
|
||||||
this.hwidId = hwidId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpUser(String username, UUID uuid, String serverId, String accessToken, ClientPermissions permissions, Map<String, Texture> assets, Map<String, String> properties, long hwidId) {
|
|
||||||
this.username = username;
|
|
||||||
this.uuid = uuid;
|
|
||||||
this.serverId = serverId;
|
|
||||||
this.accessToken = accessToken;
|
|
||||||
this.permissions = permissions;
|
|
||||||
this.assets = assets;
|
|
||||||
this.properties = properties;
|
|
||||||
this.hwidId = hwidId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUsername() {
|
|
||||||
return username;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UUID getUUID() {
|
|
||||||
return uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getServerId() {
|
|
||||||
return serverId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getAccessToken() {
|
|
||||||
return accessToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ClientPermissions getPermissions() {
|
|
||||||
return permissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Texture getSkinTexture() {
|
|
||||||
return assets.get("SKIN");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Texture getCloakTexture() {
|
|
||||||
return assets.get("CAPE");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, Texture> getAssets() {
|
|
||||||
if (assets == null) {
|
|
||||||
return new HashMap<>();
|
|
||||||
}
|
|
||||||
return assets;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, String> getProperties() {
|
|
||||||
if (properties == null) {
|
|
||||||
return new HashMap<>();
|
|
||||||
}
|
|
||||||
return properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "HttpUser{" +
|
|
||||||
"username='" + username + '\'' +
|
|
||||||
", uuid=" + uuid +
|
|
||||||
", serverId='" + serverId + '\'' +
|
|
||||||
", accessToken='" + accessToken + '\'' +
|
|
||||||
", permissions=" + permissions +
|
|
||||||
", assets=" + getAssets() +
|
|
||||||
", properties=" + properties +
|
|
||||||
", hwidId=" + hwidId +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UserHardware getHardware() {
|
|
||||||
if (hardware != null) return hardware;
|
|
||||||
HttpAuthCoreProvider.HttpUserHardware result = (HttpUserHardware) getHardwareInfoById(String.valueOf(hwidId));
|
|
||||||
hardware = result;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -94,13 +94,6 @@ public AuthManager.AuthReport authorize(String login, AuthResponse.AuthContext c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean updateServerID(User user, String serverID) {
|
|
||||||
MemoryUser memoryUser = (MemoryUser) user;
|
|
||||||
memoryUser.serverId = serverID;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public User checkServer(Client client, String username, String serverID) {
|
public User checkServer(Client client, String username, String serverID) {
|
||||||
synchronized (memory) {
|
synchronized (memory) {
|
||||||
|
@ -116,7 +109,7 @@ public User checkServer(Client client, String username, String serverID) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean joinServer(Client client, String username, String accessToken, String serverID) {
|
public boolean joinServer(Client client, String username, UUID uuid, String accessToken, String serverID) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,16 +151,6 @@ public UUID getUUID() {
|
||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getServerId() {
|
|
||||||
return serverId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getAccessToken() {
|
|
||||||
return accessToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClientPermissions getPermissions() {
|
public ClientPermissions getPermissions() {
|
||||||
return permissions;
|
return permissions;
|
||||||
|
@ -208,6 +191,11 @@ public User getUser() {
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMinecraftAccessToken() {
|
||||||
|
return "IGNORED";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getExpireIn() {
|
public long getExpireIn() {
|
||||||
return expireIn;
|
return expireIn;
|
||||||
|
|
|
@ -67,7 +67,7 @@ public User checkServer(Client client, String username, String serverID) throws
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean joinServer(Client client, String username, String accessToken, String serverID) {
|
public boolean joinServer(Client client, String username, UUID uuid, String accessToken, String serverID) {
|
||||||
return false; // Authorization not supported
|
return false; // Authorization not supported
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
import pro.gravit.launchserver.auth.AuthException;
|
import pro.gravit.launchserver.auth.AuthException;
|
||||||
import pro.gravit.launchserver.manangers.AuthManager;
|
import pro.gravit.launchserver.manangers.AuthManager;
|
||||||
|
import pro.gravit.launchserver.socket.Client;
|
||||||
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
|
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -46,7 +47,12 @@ public void init(LaunchServer server) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean updateServerID(User user, String serverID) {
|
public User checkServer(Client client, String username, String serverID) throws IOException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean joinServer(Client client, String username, UUID uuid, String accessToken, String serverID) throws IOException {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,6 @@ public interface User {
|
||||||
|
|
||||||
UUID getUUID();
|
UUID getUUID();
|
||||||
|
|
||||||
String getServerId();
|
|
||||||
|
|
||||||
String getAccessToken();
|
|
||||||
|
|
||||||
ClientPermissions getPermissions();
|
ClientPermissions getPermissions();
|
||||||
|
|
||||||
default boolean isBanned() {
|
default boolean isBanned() {
|
||||||
|
|
|
@ -5,5 +5,7 @@ public interface UserSession {
|
||||||
|
|
||||||
User getUser();
|
User getUser();
|
||||||
|
|
||||||
|
String getMinecraftAccessToken();
|
||||||
|
|
||||||
long getExpireIn();
|
long getExpireIn();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
package pro.gravit.launchserver.auth.core.interfaces.provider;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.events.request.AssetUploadInfoRequestEvent;
|
||||||
|
import pro.gravit.launcher.events.request.AuthRequestEvent;
|
||||||
|
import pro.gravit.launcher.events.request.GetAssetUploadUrlRequestEvent;
|
||||||
|
import pro.gravit.launchserver.auth.Feature;
|
||||||
|
import pro.gravit.launchserver.auth.core.User;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@Feature(GetAssetUploadUrlRequestEvent.FEATURE_NAME)
|
||||||
|
public interface AuthSupportAssetUpload {
|
||||||
|
String getAssetUploadUrl(String name, User user);
|
||||||
|
|
||||||
|
default AuthRequestEvent.OAuthRequestEvent getAssetUploadToken(String name, User user) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
default AssetUploadInfoRequestEvent getAssetUploadInfo(User user) {
|
||||||
|
return new AssetUploadInfoRequestEvent(Set.of("SKIN", "CAPE"), AssetUploadInfoRequestEvent.SlimSupportConf.USER);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +0,0 @@
|
||||||
package pro.gravit.launchserver.auth.core.interfaces.provider;
|
|
||||||
|
|
||||||
import pro.gravit.launchserver.auth.Feature;
|
|
||||||
import pro.gravit.launchserver.auth.core.User;
|
|
||||||
import pro.gravit.launchserver.auth.core.UserSession;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Feature("sessions")
|
|
||||||
public interface AuthSupportGetSessionsFromUser extends AuthSupport {
|
|
||||||
List<UserSession> getSessionsByUser(User user);
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
package pro.gravit.launchserver.auth.core.interfaces.provider;
|
|
||||||
|
|
||||||
import pro.gravit.launchserver.auth.core.User;
|
|
||||||
import pro.gravit.launchserver.auth.core.interfaces.user.UserSupportBanInfo;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
public interface AuthSupportUserBan extends AuthSupport {
|
|
||||||
UserSupportBanInfo.UserBanInfo banUser(User user, String reason, String moderator, LocalDateTime startTime, LocalDateTime endTime);
|
|
||||||
|
|
||||||
default UserSupportBanInfo.UserBanInfo banUser(User user) {
|
|
||||||
return banUser(user, null, null, LocalDateTime.now(), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
void unbanUser(User user);
|
|
||||||
|
|
||||||
default UserSupportBanInfo fetchUserBanInfo(User user) {
|
|
||||||
return (UserSupportBanInfo) user;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
package pro.gravit.launchserver.auth.core.interfaces.user;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
public interface UserSupportBanInfo {
|
|
||||||
UserBanInfo getBanInfo();
|
|
||||||
|
|
||||||
interface UserBanInfo {
|
|
||||||
String getId();
|
|
||||||
|
|
||||||
default String getReason() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
default String getModerator() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
default LocalDateTime getStartDate() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
default LocalDateTime getEndDate() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package pro.gravit.launchserver.auth.mix;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
|
import pro.gravit.launchserver.auth.core.AuthCoreProvider;
|
||||||
|
import pro.gravit.utils.ProviderMap;
|
||||||
|
|
||||||
|
public abstract class MixProvider implements AutoCloseable{
|
||||||
|
public static final ProviderMap<MixProvider> providers = new ProviderMap<>("MixProvider");
|
||||||
|
private static final Logger logger = LogManager.getLogger();
|
||||||
|
private static boolean registredProviders = false;
|
||||||
|
|
||||||
|
public static void registerProviders() {
|
||||||
|
if (!registredProviders) {
|
||||||
|
providers.register("uploadAsset", UploadAssetMixProvider.class);
|
||||||
|
registredProviders = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void init(LaunchServer server, AuthCoreProvider core);
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> T isSupport(Class<T> clazz) {
|
||||||
|
if (clazz.isAssignableFrom(getClass())) return (T) this;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract void close();
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package pro.gravit.launchserver.auth.mix;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.events.request.AssetUploadInfoRequestEvent;
|
||||||
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
|
import pro.gravit.launchserver.auth.core.AuthCoreProvider;
|
||||||
|
import pro.gravit.launchserver.auth.core.User;
|
||||||
|
import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportAssetUpload;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class UploadAssetMixProvider extends MixProvider implements AuthSupportAssetUpload {
|
||||||
|
public Map<String, String> urls;
|
||||||
|
public AssetUploadInfoRequestEvent.SlimSupportConf slimSupportConf;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAssetUploadUrl(String name, User user) {
|
||||||
|
return urls.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AssetUploadInfoRequestEvent getAssetUploadInfo(User user) {
|
||||||
|
return new AssetUploadInfoRequestEvent(urls.keySet(), slimSupportConf);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(LaunchServer server, AuthCoreProvider core) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ public boolean allowGetSecureLevelInfo(Client client) {
|
||||||
@Override
|
@Override
|
||||||
public void onHardwareReport(HardwareReportResponse response, Client client) {
|
public void onHardwareReport(HardwareReportResponse response, Client client) {
|
||||||
if (!enableHardwareFeature) {
|
if (!enableHardwareFeature) {
|
||||||
response.sendResult(new HardwareReportRequestEvent(null));
|
response.sendResult(new HardwareReportRequestEvent());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!client.isAuth || client.trustLevel == null || client.trustLevel.publicKey == null) {
|
if (!client.isAuth || client.trustLevel == null || client.trustLevel.publicKey == null) {
|
||||||
|
@ -63,7 +64,7 @@ public void onHardwareReport(HardwareReportResponse response, Client client) {
|
||||||
throw new SecurityException("Your hardware banned");
|
throw new SecurityException("Your hardware banned");
|
||||||
}
|
}
|
||||||
client.trustLevel.hardwareInfo = hardware.getHardwareInfo();
|
client.trustLevel.hardwareInfo = hardware.getHardwareInfo();
|
||||||
response.sendResult(new HardwareReportRequestEvent(createHardwareToken(client.username, hardware)));
|
response.sendResult(new HardwareReportRequestEvent(createHardwareToken(client.username, hardware), SECONDS.toMillis(server.config.netty.security.hardwareTokenExpire)));
|
||||||
} else {
|
} else {
|
||||||
logger.error("AuthCoreProvider not supported hardware");
|
logger.error("AuthCoreProvider not supported hardware");
|
||||||
response.sendError("AuthCoreProvider not supported hardware");
|
response.sendError("AuthCoreProvider not supported hardware");
|
||||||
|
@ -78,22 +79,22 @@ public VerifySecureLevelKeyRequestEvent onSuccessVerify(Client client) {
|
||||||
if (authSupportHardware != null) {
|
if (authSupportHardware != null) {
|
||||||
UserHardware hardware = authSupportHardware.getHardwareInfoByPublicKey(client.trustLevel.publicKey);
|
UserHardware hardware = authSupportHardware.getHardwareInfoByPublicKey(client.trustLevel.publicKey);
|
||||||
if (hardware == null) //HWID not found?
|
if (hardware == null) //HWID not found?
|
||||||
return new VerifySecureLevelKeyRequestEvent(true, false, createPublicKeyToken(client.username, client.trustLevel.publicKey));
|
return new VerifySecureLevelKeyRequestEvent(true, false, createPublicKeyToken(client.username, client.trustLevel.publicKey), SECONDS.toMillis(server.config.netty.security.publicKeyTokenExpire));
|
||||||
if (hardware.isBanned()) {
|
if (hardware.isBanned()) {
|
||||||
throw new SecurityException("Your hardware banned");
|
throw new SecurityException("Your hardware banned");
|
||||||
}
|
}
|
||||||
client.trustLevel.hardwareInfo = hardware.getHardwareInfo();
|
client.trustLevel.hardwareInfo = hardware.getHardwareInfo();
|
||||||
authSupportHardware.connectUserAndHardware(client.sessionObject, hardware);
|
authSupportHardware.connectUserAndHardware(client.sessionObject, hardware);
|
||||||
return new VerifySecureLevelKeyRequestEvent(false, false, createPublicKeyToken(client.username, client.trustLevel.publicKey), createHardwareToken(client.username, hardware));
|
return new VerifySecureLevelKeyRequestEvent(false, false, createPublicKeyToken(client.username, client.trustLevel.publicKey), SECONDS.toMillis(server.config.netty.security.publicKeyTokenExpire));
|
||||||
} else {
|
} else {
|
||||||
logger.warn("AuthCoreProvider not supported hardware. HardwareInfo not checked!");
|
logger.warn("AuthCoreProvider not supported hardware. HardwareInfo not checked!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new VerifySecureLevelKeyRequestEvent(false, false, createPublicKeyToken(client.username, client.trustLevel.publicKey));
|
return new VerifySecureLevelKeyRequestEvent(false, false, createPublicKeyToken(client.username, client.trustLevel.publicKey), SECONDS.toMillis(server.config.netty.security.publicKeyTokenExpire));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onJoinServer(String serverID, String username, Client client) {
|
public boolean onJoinServer(String serverID, String username, UUID uuid, Client client) {
|
||||||
return !enableHardwareFeature || (client.trustLevel != null && client.trustLevel.hardwareInfo != null);
|
return !enableHardwareFeature || (client.trustLevel != null && client.trustLevel.hardwareInfo != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package pro.gravit.launchserver.auth.protect;
|
package pro.gravit.launchserver.auth.protect;
|
||||||
|
|
||||||
|
import pro.gravit.launchserver.socket.Client;
|
||||||
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
|
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
|
||||||
|
|
||||||
public class NoProtectHandler extends ProtectHandler {
|
public class NoProtectHandler extends ProtectHandler {
|
||||||
|
@ -9,4 +10,8 @@ public boolean allowGetAccessToken(AuthResponse.AuthContext context) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean allowJoinServer(Client client) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package pro.gravit.launchserver.auth.protect;
|
package pro.gravit.launchserver.auth.protect;
|
||||||
|
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
|
import pro.gravit.launchserver.socket.Client;
|
||||||
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
|
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
|
||||||
import pro.gravit.utils.ProviderMap;
|
import pro.gravit.utils.ProviderMap;
|
||||||
|
|
||||||
|
@ -19,6 +20,9 @@ public static void registerHandlers() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract boolean allowGetAccessToken(AuthResponse.AuthContext context);
|
public abstract boolean allowGetAccessToken(AuthResponse.AuthContext context);
|
||||||
|
public boolean allowJoinServer(Client client) {
|
||||||
|
return client.isAuth && client.type == AuthResponse.ConnectTypes.CLIENT;
|
||||||
|
}
|
||||||
|
|
||||||
public void init(LaunchServer server) {
|
public void init(LaunchServer server) {
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
|
|
||||||
import pro.gravit.launchserver.socket.Client;
|
import pro.gravit.launchserver.socket.Client;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public interface JoinServerProtectHandler {
|
public interface JoinServerProtectHandler {
|
||||||
default boolean onJoinServer(String serverID, String username, Client client) {
|
default boolean onJoinServer(String serverID, String username, UUID uuid, Client client) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,22 +3,23 @@
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import pro.gravit.launcher.HTTPRequest;
|
|
||||||
import pro.gravit.launcher.Launcher;
|
|
||||||
import pro.gravit.launcher.profiles.Texture;
|
import pro.gravit.launcher.profiles.Texture;
|
||||||
|
import pro.gravit.launchserver.HttpRequester;
|
||||||
|
import pro.gravit.utils.helper.SecurityHelper;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.net.URL;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class JsonTextureProvider extends TextureProvider {
|
public class JsonTextureProvider extends TextureProvider {
|
||||||
private static final Type MAP_TYPE = new TypeToken<Map<String, Texture>>() {
|
private static final Type MAP_TYPE = new TypeToken<Map<String, JsonTexture>>() {
|
||||||
}.getType();
|
}.getType();
|
||||||
private transient final Logger logger = LogManager.getLogger();
|
private transient final Logger logger = LogManager.getLogger();
|
||||||
|
private transient final HttpRequester requester = new HttpRequester();
|
||||||
public String url;
|
public String url;
|
||||||
|
public String bearerToken;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
|
@ -40,24 +41,28 @@ public Texture getSkinTexture(UUID uuid, String username, String client) {
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Texture> getAssets(UUID uuid, String username, String client) {
|
public Map<String, Texture> getAssets(UUID uuid, String username, String client) {
|
||||||
try {
|
try {
|
||||||
var result = HTTPRequest.jsonRequest(null, "GET", new URL(RequestTextureProvider.getTextureURL(url, uuid, username, client)));
|
Map<String, JsonTexture> map = requester.<Map<String, JsonTexture>>send(requester.get(RequestTextureProvider.getTextureURL(url, uuid, username, client), bearerToken), MAP_TYPE).getOrThrow();
|
||||||
|
return JsonTexture.convertMap(map);
|
||||||
Map<String, Texture> map = Launcher.gsonManager.gson.fromJson(result, MAP_TYPE);
|
|
||||||
if (map == null) {
|
|
||||||
return new HashMap<>();
|
|
||||||
}
|
|
||||||
if (map.get("skin") != null) { // Legacy script
|
|
||||||
map.put("SKIN", map.get("skin"));
|
|
||||||
map.remove("skin");
|
|
||||||
}
|
|
||||||
if (map.get("cloak") != null) {
|
|
||||||
map.put("CAPE", map.get("cloak"));
|
|
||||||
map.remove("cloak");
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.error("JsonTextureProvider", e);
|
logger.error("JsonTextureProvider", e);
|
||||||
return new HashMap<>();
|
return new HashMap<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public record JsonTexture(String url, String digest, Map<String, String> metadata) {
|
||||||
|
public Texture toTexture() {
|
||||||
|
return new Texture(url, digest == null ? null : SecurityHelper.fromHex(digest), metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<String, Texture> convertMap(Map<String, JsonTexture> map) {
|
||||||
|
if (map == null) {
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
Map<String, Texture> res = new HashMap<>();
|
||||||
|
for(var e : map.entrySet()) {
|
||||||
|
res.put(e.getKey(), e.getValue().toTexture());
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
|
|
||||||
public class BinaryPipeline {
|
public class BinaryPipeline {
|
||||||
public final List<LauncherBuildTask> tasks = new ArrayList<>();
|
public final List<LauncherBuildTask> tasks = new ArrayList<>();
|
||||||
public final AtomicLong count = new AtomicLong(0);
|
|
||||||
public final Path buildDir;
|
public final Path buildDir;
|
||||||
public final String nameFormat;
|
public final String nameFormat;
|
||||||
private transient final Logger logger = LogManager.getLogger();
|
private transient final Logger logger = LogManager.getLogger();
|
||||||
|
@ -72,11 +71,20 @@ public <T extends LauncherBuildTask> Optional<T> getTaskByClass(Class<T> taskCla
|
||||||
return tasks.stream().filter(taskClass::isInstance).map(taskClass::cast).findFirst();
|
return tasks.stream().filter(taskClass::isInstance).map(taskClass::cast).findFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Optional<LauncherBuildTask> getTaskBefore(Predicate<LauncherBuildTask> pred) {
|
||||||
|
LauncherBuildTask last = null;
|
||||||
|
for(var e : tasks) {
|
||||||
|
if(pred.test(e)) {
|
||||||
|
return Optional.ofNullable(last);
|
||||||
|
}
|
||||||
|
last = e;
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
public void build(Path target, boolean deleteTempFiles) throws IOException {
|
public void build(Path target, boolean deleteTempFiles) throws IOException {
|
||||||
logger.info("Building launcher binary file");
|
logger.info("Building launcher binary file");
|
||||||
count.set(0); // set jar number
|
|
||||||
Path thisPath = null;
|
Path thisPath = null;
|
||||||
boolean isNeedDelete = false;
|
|
||||||
long time_start = System.currentTimeMillis();
|
long time_start = System.currentTimeMillis();
|
||||||
long time_this = time_start;
|
long time_this = time_start;
|
||||||
for (LauncherBuildTask task : tasks) {
|
for (LauncherBuildTask task : tasks) {
|
||||||
|
@ -86,19 +94,17 @@ public void build(Path target, boolean deleteTempFiles) throws IOException {
|
||||||
long time_task_end = System.currentTimeMillis();
|
long time_task_end = System.currentTimeMillis();
|
||||||
long time_task = time_task_end - time_this;
|
long time_task = time_task_end - time_this;
|
||||||
time_this = time_task_end;
|
time_this = time_task_end;
|
||||||
if (isNeedDelete && deleteTempFiles && oldPath != thisPath) Files.deleteIfExists(oldPath);
|
|
||||||
isNeedDelete = task.allowDelete();
|
|
||||||
logger.info("Task {} processed from {} millis", task.getName(), time_task);
|
logger.info("Task {} processed from {} millis", task.getName(), time_task);
|
||||||
}
|
}
|
||||||
long time_end = System.currentTimeMillis();
|
long time_end = System.currentTimeMillis();
|
||||||
if (isNeedDelete && deleteTempFiles) IOHelper.move(thisPath, target);
|
if (deleteTempFiles) IOHelper.move(thisPath, target);
|
||||||
else IOHelper.copy(thisPath, target);
|
else IOHelper.copy(thisPath, target);
|
||||||
IOHelper.deleteDir(buildDir, false);
|
IOHelper.deleteDir(buildDir, false);
|
||||||
logger.info("Build successful from {} millis", time_end - time_start);
|
logger.info("Build successful from {} millis", time_end - time_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String nextName(String taskName) {
|
public String nextName(String taskName) {
|
||||||
return nameFormat.formatted(taskName, count.getAndIncrement());
|
return nameFormat.formatted(taskName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Path nextPath(String taskName) {
|
public Path nextPath(String taskName) {
|
||||||
|
|
|
@ -45,6 +45,7 @@ public class BuildContext {
|
||||||
public final MainBuildTask task;
|
public final MainBuildTask task;
|
||||||
public final HashSet<String> fileList;
|
public final HashSet<String> fileList;
|
||||||
public final HashSet<String> clientModules;
|
public final HashSet<String> clientModules;
|
||||||
|
public final HashSet<String> legacyClientModules;
|
||||||
|
|
||||||
public BuildContext(ZipOutputStream output, List<JarFile> readerClassPath, MainBuildTask task) {
|
public BuildContext(ZipOutputStream output, List<JarFile> readerClassPath, MainBuildTask task) {
|
||||||
this.output = output;
|
this.output = output;
|
||||||
|
@ -52,6 +53,7 @@ public BuildContext(ZipOutputStream output, List<JarFile> readerClassPath, MainB
|
||||||
this.task = task;
|
this.task = task;
|
||||||
fileList = new HashSet<>(1024);
|
fileList = new HashSet<>(1024);
|
||||||
clientModules = new HashSet<>();
|
clientModules = new HashSet<>();
|
||||||
|
legacyClientModules = new HashSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pushFile(String filename, InputStream inputStream) throws IOException {
|
public void pushFile(String filename, InputStream inputStream) throws IOException {
|
||||||
|
|
|
@ -7,7 +7,7 @@ public final class EXEL4JLauncherBinary extends LauncherBinary {
|
||||||
|
|
||||||
|
|
||||||
public EXEL4JLauncherBinary(LaunchServer server) {
|
public EXEL4JLauncherBinary(LaunchServer server) {
|
||||||
super(server, LauncherBinary.resolve(server, ".exe"), "Launcher-%s-%d.exe");
|
super(server, LauncherBinary.resolve(server, ".exe"), "Launcher-%s.exe");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
public class EXELauncherBinary extends LauncherBinary {
|
public class EXELauncherBinary extends LauncherBinary {
|
||||||
|
|
||||||
public EXELauncherBinary(LaunchServer server) {
|
public EXELauncherBinary(LaunchServer server) {
|
||||||
super(server, LauncherBinary.resolve(server, ".exe"), "Launcher-%s-%d.exe");
|
super(server, LauncherBinary.resolve(server, ".exe"), "Launcher-%s.exe");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -23,7 +23,7 @@ public final class JARLauncherBinary extends LauncherBinary {
|
||||||
public final Map<String, Path> files;
|
public final Map<String, Path> files;
|
||||||
|
|
||||||
public JARLauncherBinary(LaunchServer server) throws IOException {
|
public JARLauncherBinary(LaunchServer server) throws IOException {
|
||||||
super(server, resolve(server, ".jar"), "Launcher-%s-%d.jar");
|
super(server, resolve(server, ".jar"), "Launcher-%s.jar");
|
||||||
count = new AtomicLong(0);
|
count = new AtomicLong(0);
|
||||||
runtimeDir = server.dir.resolve(Launcher.RUNTIME_DIR);
|
runtimeDir = server.dir.resolve(Launcher.RUNTIME_DIR);
|
||||||
buildDir = server.dir.resolve("build");
|
buildDir = server.dir.resolve("build");
|
||||||
|
|
|
@ -69,7 +69,6 @@ public SignerJar(ZipOutputStream out, Supplier<CMSSignedDataGenerator> gen, Stri
|
||||||
*
|
*
|
||||||
* @param filename name of the file to add (use forward slash as a path separator)
|
* @param filename name of the file to add (use forward slash as a path separator)
|
||||||
* @param contents contents of the file
|
* @param contents contents of the file
|
||||||
* @throws IOException
|
|
||||||
* @throws NullPointerException if any of the arguments is {@code null}
|
* @throws NullPointerException if any of the arguments is {@code null}
|
||||||
*/
|
*/
|
||||||
public void addFileContents(String filename, byte[] contents) throws IOException {
|
public void addFileContents(String filename, byte[] contents) throws IOException {
|
||||||
|
@ -82,7 +81,6 @@ public void addFileContents(String filename, byte[] contents) throws IOException
|
||||||
*
|
*
|
||||||
* @param filename name of the file to add (use forward slash as a path separator)
|
* @param filename name of the file to add (use forward slash as a path separator)
|
||||||
* @param contents contents of the file
|
* @param contents contents of the file
|
||||||
* @throws IOException
|
|
||||||
* @throws NullPointerException if any of the arguments is {@code null}
|
* @throws NullPointerException if any of the arguments is {@code null}
|
||||||
*/
|
*/
|
||||||
public void addFileContents(String filename, InputStream contents) throws IOException {
|
public void addFileContents(String filename, InputStream contents) throws IOException {
|
||||||
|
@ -95,7 +93,6 @@ public void addFileContents(String filename, InputStream contents) throws IOExce
|
||||||
*
|
*
|
||||||
* @param entry name of the file to add (use forward slash as a path separator)
|
* @param entry name of the file to add (use forward slash as a path separator)
|
||||||
* @param contents contents of the file
|
* @param contents contents of the file
|
||||||
* @throws IOException
|
|
||||||
* @throws NullPointerException if any of the arguments is {@code null}
|
* @throws NullPointerException if any of the arguments is {@code null}
|
||||||
*/
|
*/
|
||||||
public void addFileContents(ZipEntry entry, byte[] contents) throws IOException {
|
public void addFileContents(ZipEntry entry, byte[] contents) throws IOException {
|
||||||
|
@ -108,7 +105,6 @@ public void addFileContents(ZipEntry entry, byte[] contents) throws IOException
|
||||||
*
|
*
|
||||||
* @param entry name of the file to add (use forward slash as a path separator)
|
* @param entry name of the file to add (use forward slash as a path separator)
|
||||||
* @param contents contents of the file
|
* @param contents contents of the file
|
||||||
* @throws IOException
|
|
||||||
* @throws NullPointerException if any of the arguments is {@code null}
|
* @throws NullPointerException if any of the arguments is {@code null}
|
||||||
*/
|
*/
|
||||||
public void addFileContents(ZipEntry entry, InputStream contents) throws IOException {
|
public void addFileContents(ZipEntry entry, InputStream contents) throws IOException {
|
||||||
|
@ -134,7 +130,6 @@ public void addManifestAttribute(String name, String value) {
|
||||||
* Closes the JAR file by writing the manifest and signature data to it and finishing the ZIP entries. It closes the
|
* Closes the JAR file by writing the manifest and signature data to it and finishing the ZIP entries. It closes the
|
||||||
* underlying stream.
|
* underlying stream.
|
||||||
*
|
*
|
||||||
* @throws IOException
|
|
||||||
* @throws RuntimeException if the signing goes wrong
|
* @throws RuntimeException if the signing goes wrong
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@ -148,7 +143,6 @@ public void close() throws IOException {
|
||||||
* Finishes the JAR file by writing the manifest and signature data to it and finishing the ZIP entries. It leaves the
|
* Finishes the JAR file by writing the manifest and signature data to it and finishing the ZIP entries. It leaves the
|
||||||
* underlying stream open.
|
* underlying stream open.
|
||||||
*
|
*
|
||||||
* @throws IOException
|
|
||||||
* @throws RuntimeException if the signing goes wrong
|
* @throws RuntimeException if the signing goes wrong
|
||||||
*/
|
*/
|
||||||
public void finish() throws IOException {
|
public void finish() throws IOException {
|
||||||
|
@ -205,7 +199,6 @@ private byte[] signSigFile(byte[] sigContents) throws Exception {
|
||||||
* Writes the manifest to the JAR. It also calculates the digests that are required to be placed in the the signature
|
* Writes the manifest to the JAR. It also calculates the digests that are required to be placed in the the signature
|
||||||
* file.
|
* file.
|
||||||
*
|
*
|
||||||
* @throws IOException
|
|
||||||
*/
|
*/
|
||||||
private void writeManifest() throws IOException {
|
private void writeManifest() throws IOException {
|
||||||
zos.putNextEntry(IOHelper.newZipEntry(MANIFEST_FN));
|
zos.putNextEntry(IOHelper.newZipEntry(MANIFEST_FN));
|
||||||
|
@ -268,7 +261,6 @@ private byte[] writeSigFile() throws IOException {
|
||||||
/**
|
/**
|
||||||
* Signs the .SIG file and writes the signature (.RSA file) to the JAR.
|
* Signs the .SIG file and writes the signature (.RSA file) to the JAR.
|
||||||
*
|
*
|
||||||
* @throws IOException
|
|
||||||
* @throws RuntimeException if the signing failed
|
* @throws RuntimeException if the signing failed
|
||||||
*/
|
*/
|
||||||
private void writeSignature(byte[] sigFile) throws IOException {
|
private void writeSignature(byte[] sigFile) throws IOException {
|
||||||
|
|
|
@ -74,9 +74,4 @@ public Path process(Path inputFile) throws IOException {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean allowDelete() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,11 +68,6 @@ private boolean filter(String name) {
|
||||||
return exclusions.stream().anyMatch(name::startsWith);
|
return exclusions.stream().anyMatch(name::startsWith);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean allowDelete() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Path> getJars() {
|
public List<Path> getJars() {
|
||||||
return jars;
|
return jars;
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,9 +81,4 @@ public Path process(Path inputFile) throws IOException {
|
||||||
}
|
}
|
||||||
return inputFile;
|
return inputFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean allowDelete() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,9 +43,4 @@ public Path process(Path inputFile) throws IOException {
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean allowDelete() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,4 @@ public interface LauncherBuildTask {
|
||||||
String getName();
|
String getName();
|
||||||
|
|
||||||
Path process(Path inputFile) throws IOException;
|
Path process(Path inputFile) throws IOException;
|
||||||
|
|
||||||
boolean allowDelete();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,11 +51,12 @@ public String getName() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Path process(Path inputJar) throws IOException {
|
public Path process(Path inputJar) throws IOException {
|
||||||
Path outputJar = server.launcherBinary.nextPath("main");
|
Path outputJar = server.launcherBinary.nextPath(this);
|
||||||
try (ZipOutputStream output = new ZipOutputStream(IOHelper.newOutput(outputJar))) {
|
try (ZipOutputStream output = new ZipOutputStream(IOHelper.newOutput(outputJar))) {
|
||||||
BuildContext context = new BuildContext(output, reader.getCp(), this);
|
BuildContext context = new BuildContext(output, reader.getCp(), this);
|
||||||
initProps();
|
initProps();
|
||||||
preBuildHook.hook(context);
|
preBuildHook.hook(context);
|
||||||
|
properties.put("launcher.legacymodules", context.legacyClientModules.stream().map(e -> Type.getObjectType(e.replace('.', '/'))).collect(Collectors.toList()));
|
||||||
properties.put("launcher.modules", context.clientModules.stream().map(e -> Type.getObjectType(e.replace('.', '/'))).collect(Collectors.toList()));
|
properties.put("launcher.modules", context.clientModules.stream().map(e -> Type.getObjectType(e.replace('.', '/'))).collect(Collectors.toList()));
|
||||||
postInitProps();
|
postInitProps();
|
||||||
reader.getCp().add(new JarFile(inputJar.toFile()));
|
reader.getCp().add(new JarFile(inputJar.toFile()));
|
||||||
|
@ -160,11 +161,6 @@ public byte[] transformClass(byte[] bytes, String classname, BuildContext contex
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean allowDelete() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface Transformer {
|
public interface Transformer {
|
||||||
byte[] transform(byte[] input, String classname, BuildContext context);
|
byte[] transform(byte[] input, String classname, BuildContext context);
|
||||||
|
|
|
@ -53,11 +53,6 @@ public Path process(Path inputFile) throws IOException {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean allowDelete() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void tryUnpack() throws IOException {
|
public void tryUnpack() throws IOException {
|
||||||
logger.info("Unpacking launcher native guard list and runtime");
|
logger.info("Unpacking launcher native guard list and runtime");
|
||||||
UnpackHelper.unpackZipNoCheck("runtime.zip", server.launcherBinary.runtimeDir);
|
UnpackHelper.unpackZipNoCheck("runtime.zip", server.launcherBinary.runtimeDir);
|
||||||
|
|
|
@ -104,9 +104,4 @@ private void autoSign(Path inputFile, Path signedFile) throws IOException {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean allowDelete() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,11 +59,6 @@ public Path process(Path inputFile) throws IOException {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean allowDelete() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Path setConfig() {
|
private Path setConfig() {
|
||||||
Path path = server.launcherEXEBinary.nextPath(getName());
|
Path path = server.launcherEXEBinary.nextPath(getName());
|
||||||
Config config = new Config();
|
Config config = new Config();
|
||||||
|
|
|
@ -3,11 +3,10 @@
|
||||||
import me.tongfei.progressbar.ProgressBar;
|
import me.tongfei.progressbar.ProgressBar;
|
||||||
import me.tongfei.progressbar.ProgressBarBuilder;
|
import me.tongfei.progressbar.ProgressBarBuilder;
|
||||||
import me.tongfei.progressbar.ProgressBarStyle;
|
import me.tongfei.progressbar.ProgressBarStyle;
|
||||||
import pro.gravit.launcher.AsyncDownloader;
|
|
||||||
import pro.gravit.launcher.Launcher;
|
import pro.gravit.launcher.Launcher;
|
||||||
|
import pro.gravit.launcher.modern.Downloader;
|
||||||
import pro.gravit.launcher.profiles.ClientProfile;
|
import pro.gravit.launcher.profiles.ClientProfile;
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
import pro.gravit.utils.Downloader;
|
|
||||||
import pro.gravit.utils.command.CommandException;
|
import pro.gravit.utils.command.CommandException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -45,9 +44,9 @@ protected boolean showApplyDialog(String text) throws IOException {
|
||||||
return response.equals("y");
|
return response.equals("y");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Downloader downloadWithProgressBar(String taskName, List<AsyncDownloader.SizedFile> list, String baseUrl, Path targetDir) throws Exception {
|
protected Downloader downloadWithProgressBar(String taskName, List<Downloader.SizedFile> list, String baseUrl, Path targetDir) throws Exception {
|
||||||
long total = 0;
|
long total = 0;
|
||||||
for (AsyncDownloader.SizedFile file : list) {
|
for (Downloader.SizedFile file : list) {
|
||||||
total += file.size;
|
total += file.size;
|
||||||
}
|
}
|
||||||
long totalFiles = list.size();
|
long totalFiles = list.size();
|
||||||
|
|
|
@ -3,12 +3,11 @@
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import pro.gravit.launcher.AsyncDownloader;
|
|
||||||
import pro.gravit.launcher.Launcher;
|
import pro.gravit.launcher.Launcher;
|
||||||
|
import pro.gravit.launcher.modern.Downloader;
|
||||||
import pro.gravit.launchserver.HttpRequester;
|
import pro.gravit.launchserver.HttpRequester;
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
import pro.gravit.launchserver.command.Command;
|
import pro.gravit.launchserver.command.Command;
|
||||||
import pro.gravit.utils.Downloader;
|
|
||||||
import pro.gravit.utils.helper.IOHelper;
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
|
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
|
@ -85,7 +84,7 @@ public void invoke(String... args) throws Exception {
|
||||||
logger.info("Copy {} into {}", indexPath, targetPath);
|
logger.info("Copy {} into {}", indexPath, targetPath);
|
||||||
Files.copy(indexPath, targetPath, StandardCopyOption.REPLACE_EXISTING);
|
Files.copy(indexPath, targetPath, StandardCopyOption.REPLACE_EXISTING);
|
||||||
}
|
}
|
||||||
List<AsyncDownloader.SizedFile> toDownload = new ArrayList<>(128);
|
List<Downloader.SizedFile> toDownload = new ArrayList<>(128);
|
||||||
for (var e : objects.entrySet()) {
|
for (var e : objects.entrySet()) {
|
||||||
var value = e.getValue().getAsJsonObject();
|
var value = e.getValue().getAsJsonObject();
|
||||||
var hash = value.get("hash").getAsString();
|
var hash = value.get("hash").getAsString();
|
||||||
|
@ -101,7 +100,7 @@ public void invoke(String... args) throws Exception {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
toDownload.add(new AsyncDownloader.SizedFile(hash, path, size));
|
toDownload.add(new Downloader.SizedFile(hash, path, size));
|
||||||
}
|
}
|
||||||
logger.info("Download {} files", toDownload.size());
|
logger.info("Download {} files", toDownload.size());
|
||||||
Downloader downloader = downloadWithProgressBar(dirName, toDownload, RESOURCES_DOWNLOAD_URL, assetDir);
|
Downloader downloader = downloadWithProgressBar(dirName, toDownload, RESOURCES_DOWNLOAD_URL, assetDir);
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
import pro.gravit.utils.helper.IOHelper;
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
|
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.nio.file.Files;
|
|
||||||
|
|
||||||
public class MakeProfileCommand extends Command {
|
public class MakeProfileCommand extends Command {
|
||||||
private transient final Logger logger = LogManager.getLogger();
|
private transient final Logger logger = LogManager.getLogger();
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class SecurityCheckCommand extends Command {
|
public class SecurityCheckCommand extends Command {
|
||||||
private static final Logger logger = LogManager.getLogger();
|
private static final Logger logger = LogManager.getLogger();
|
||||||
|
@ -113,7 +112,7 @@ public void invoke(String... args) {
|
||||||
List<X509Certificate> certChain = Arrays.stream(certChainPlain).map(e -> (X509Certificate) e).toList();
|
List<X509Certificate> certChain = Arrays.stream(certChainPlain).map(e -> (X509Certificate) e).toList();
|
||||||
X509Certificate cert = certChain.get(0);
|
X509Certificate cert = certChain.get(0);
|
||||||
cert.checkValidity();
|
cert.checkValidity();
|
||||||
if (certChain.size() <= 1) {
|
if (certChain.size() == 1) {
|
||||||
printCheckResult("sign", "certificate chain contains <2 element(recommend 2 and more)", false);
|
printCheckResult("sign", "certificate chain contains <2 element(recommend 2 and more)", false);
|
||||||
bad = true;
|
bad = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,7 @@
|
||||||
import proguard.ConfigurationParser;
|
import proguard.ConfigurationParser;
|
||||||
import proguard.ProGuard;
|
import proguard.ProGuard;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.*;
|
||||||
import java.io.OutputStreamWriter;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
@ -26,6 +24,9 @@
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipInputStream;
|
||||||
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
public class ProGuardComponent extends Component implements AutoCloseable, Reconfigurable {
|
public class ProGuardComponent extends Component implements AutoCloseable, Reconfigurable {
|
||||||
private static final Logger logger = LogManager.getLogger();
|
private static final Logger logger = LogManager.getLogger();
|
||||||
|
@ -36,6 +37,7 @@ public class ProGuardComponent extends Component implements AutoCloseable, Recon
|
||||||
public transient ProguardConf proguardConf;
|
public transient ProguardConf proguardConf;
|
||||||
private transient LaunchServer launchServer;
|
private transient LaunchServer launchServer;
|
||||||
private transient ProGuardBuildTask buildTask;
|
private transient ProGuardBuildTask buildTask;
|
||||||
|
private transient ProGuardMultiReleaseFixer fixerTask;
|
||||||
|
|
||||||
public static boolean checkFXJMods(Path path) {
|
public static boolean checkFXJMods(Path path) {
|
||||||
if (!IOHelper.exists(path.resolve("javafx.base.jmod")))
|
if (!IOHelper.exists(path.resolve("javafx.base.jmod")))
|
||||||
|
@ -75,7 +77,9 @@ public void init(LaunchServer launchServer) {
|
||||||
this.launchServer = launchServer;
|
this.launchServer = launchServer;
|
||||||
proguardConf = new ProguardConf(launchServer, this);
|
proguardConf = new ProguardConf(launchServer, this);
|
||||||
this.buildTask = new ProGuardBuildTask(launchServer, proguardConf, this);
|
this.buildTask = new ProGuardBuildTask(launchServer, proguardConf, this);
|
||||||
|
this.fixerTask = new ProGuardMultiReleaseFixer(launchServer, this, "ProGuard.".concat(componentName));
|
||||||
launchServer.launcherBinary.addAfter((v) -> v.getName().startsWith(modeAfter), buildTask);
|
launchServer.launcherBinary.addAfter((v) -> v.getName().startsWith(modeAfter), buildTask);
|
||||||
|
launchServer.launcherBinary.addAfter((v) -> v.getName().equals("ProGuard.".concat(componentName)), fixerTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -111,6 +115,62 @@ public void invoke(String... args) throws Exception {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class ProGuardMultiReleaseFixer implements LauncherBuildTask {
|
||||||
|
private final LaunchServer server;
|
||||||
|
private final ProGuardComponent component;
|
||||||
|
private final String proguardTaskName;
|
||||||
|
|
||||||
|
public ProGuardMultiReleaseFixer(LaunchServer server, ProGuardComponent component, String proguardTaskName) {
|
||||||
|
this.server = server;
|
||||||
|
this.component = component;
|
||||||
|
this.proguardTaskName = proguardTaskName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "ProGuardMultiReleaseFixer.".concat(component.componentName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Path process(Path inputFile) throws IOException {
|
||||||
|
if (!component.enabled) {
|
||||||
|
return inputFile;
|
||||||
|
}
|
||||||
|
LauncherBuildTask task = server.launcherBinary.getTaskBefore((x) -> proguardTaskName.equals(x.getName())).get();
|
||||||
|
Path lastPath = server.launcherBinary.nextPath(task);
|
||||||
|
if(Files.notExists(lastPath)) {
|
||||||
|
logger.error("{} not exist. Multi-Release JAR fix not applied!", lastPath);
|
||||||
|
return inputFile;
|
||||||
|
}
|
||||||
|
Path outputPath = server.launcherBinary.nextPath(this);
|
||||||
|
try(ZipOutputStream output = new ZipOutputStream(new FileOutputStream(outputPath.toFile()))) {
|
||||||
|
try(ZipInputStream input = new ZipInputStream(new FileInputStream(inputFile.toFile()))) {
|
||||||
|
ZipEntry entry = input.getNextEntry();
|
||||||
|
while(entry != null) {
|
||||||
|
ZipEntry newEntry = new ZipEntry(entry.getName());
|
||||||
|
output.putNextEntry(newEntry);
|
||||||
|
input.transferTo(output);
|
||||||
|
entry = input.getNextEntry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try(ZipInputStream input = new ZipInputStream(new FileInputStream(lastPath.toFile()))) {
|
||||||
|
ZipEntry entry = input.getNextEntry();
|
||||||
|
while(entry != null) {
|
||||||
|
if(!entry.getName().startsWith("META-INF/versions")) {
|
||||||
|
entry = input.getNextEntry();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ZipEntry newEntry = new ZipEntry(entry.getName());
|
||||||
|
output.putNextEntry(newEntry);
|
||||||
|
input.transferTo(output);
|
||||||
|
entry = input.getNextEntry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return outputPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class ProGuardBuildTask implements LauncherBuildTask {
|
public static class ProGuardBuildTask implements LauncherBuildTask {
|
||||||
private final LaunchServer server;
|
private final LaunchServer server;
|
||||||
private final ProGuardComponent component;
|
private final ProGuardComponent component;
|
||||||
|
@ -157,11 +217,6 @@ public Path process(Path inputFile) throws IOException {
|
||||||
IOHelper.copy(inputFile, outputJar);
|
IOHelper.copy(inputFile, outputJar);
|
||||||
return outputJar;
|
return outputJar;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean allowDelete() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ProguardConf {
|
public static class ProguardConf {
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||||
|
|
||||||
public final class LaunchServerConfig {
|
public final class LaunchServerConfig {
|
||||||
private final static List<String> oldMirrorList = List.of("https://mirror.gravit.pro/5.2.x/", "https://mirror.gravit.pro/5.3.x/", "https://mirror.gravitlauncher.com/5.2.x/", "https://mirror.gravitlauncher.com/5.3.x/");
|
private final static List<String> oldMirrorList = List.of("https://mirror.gravit.pro/5.2.x/", "https://mirror.gravit.pro/5.3.x/", "https://mirror.gravitlauncher.com/5.2.x/", "https://mirror.gravitlauncher.com/5.3.x/", "https://mirror.gravitlauncher.com/5.4.x/");
|
||||||
private transient final Logger logger = LogManager.getLogger();
|
private transient final Logger logger = LogManager.getLogger();
|
||||||
public String projectName;
|
public String projectName;
|
||||||
public String[] mirrors;
|
public String[] mirrors;
|
||||||
|
@ -49,7 +49,7 @@ public final class LaunchServerConfig {
|
||||||
|
|
||||||
public static LaunchServerConfig getDefault(LaunchServer.LaunchServerEnv env) {
|
public static LaunchServerConfig getDefault(LaunchServer.LaunchServerEnv env) {
|
||||||
LaunchServerConfig newConfig = new LaunchServerConfig();
|
LaunchServerConfig newConfig = new LaunchServerConfig();
|
||||||
newConfig.mirrors = new String[]{"https://mirror.gravitlauncher.com/5.4.x/", "https://gravit-launcher-mirror.storage.googleapis.com/"};
|
newConfig.mirrors = new String[]{"https://mirror.gravitlauncher.com/5.5.x/", "https://gravit-launcher-mirror.storage.googleapis.com/"};
|
||||||
newConfig.launch4j = new LaunchServerConfig.ExeConf();
|
newConfig.launch4j = new LaunchServerConfig.ExeConf();
|
||||||
newConfig.launch4j.enabled = false;
|
newConfig.launch4j.enabled = false;
|
||||||
newConfig.launch4j.copyright = "© GravitLauncher Team";
|
newConfig.launch4j.copyright = "© GravitLauncher Team";
|
||||||
|
@ -61,7 +61,7 @@ public static LaunchServerConfig getDefault(LaunchServer.LaunchServerEnv env) {
|
||||||
newConfig.launch4j.txtProductVersion = "%s, build %d";
|
newConfig.launch4j.txtProductVersion = "%s, build %d";
|
||||||
newConfig.launch4j.productName = "GravitLauncher";
|
newConfig.launch4j.productName = "GravitLauncher";
|
||||||
newConfig.launch4j.productVer = newConfig.launch4j.fileVer;
|
newConfig.launch4j.productVer = newConfig.launch4j.fileVer;
|
||||||
newConfig.launch4j.maxVersion = "1.8.999";
|
newConfig.launch4j.maxVersion = "99.0.0";
|
||||||
newConfig.env = LauncherConfig.LauncherEnvironment.STD;
|
newConfig.env = LauncherConfig.LauncherEnvironment.STD;
|
||||||
newConfig.startScript = JVMHelper.OS_TYPE.equals(JVMHelper.OS.MUSTDIE) ? "." + File.separator + "start.bat" : "." + File.separator + "start.sh";
|
newConfig.startScript = JVMHelper.OS_TYPE.equals(JVMHelper.OS.MUSTDIE) ? "." + File.separator + "start.bat" : "." + File.separator + "start.sh";
|
||||||
newConfig.auth = new HashMap<>();
|
newConfig.auth = new HashMap<>();
|
||||||
|
@ -171,8 +171,8 @@ public void verify() {
|
||||||
if (!updateMirror) {
|
if (!updateMirror) {
|
||||||
for (int i = 0; i < mirrors.length; ++i) {
|
for (int i = 0; i < mirrors.length; ++i) {
|
||||||
if (mirrors[i] != null && oldMirrorList.contains(mirrors[i])) {
|
if (mirrors[i] != null && oldMirrorList.contains(mirrors[i])) {
|
||||||
logger.warn("Replace mirror '{}' to 'https://mirror.gravitlauncher.com/5.4.x/'. If you really need to use original url, use '-Dlaunchserver.config.disableUpdateMirror=true'", mirrors[i]);
|
logger.warn("Replace mirror '{}' to 'https://mirror.gravitlauncher.com/5.5.x/'. If you really need to use original url, use '-Dlaunchserver.config.disableUpdateMirror=true'", mirrors[i]);
|
||||||
mirrors[i] = "https://mirror.gravitlauncher.com/5.4.x/";
|
mirrors[i] = "https://mirror.gravitlauncher.com/5.5.x/";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -234,7 +234,7 @@ public static class ExeConf {
|
||||||
public boolean enabled;
|
public boolean enabled;
|
||||||
public boolean setMaxVersion;
|
public boolean setMaxVersion;
|
||||||
public String maxVersion;
|
public String maxVersion;
|
||||||
public String minVersion = "1.8.0";
|
public String minVersion = "17.0.0";
|
||||||
public String supportURL = null;
|
public String supportURL = null;
|
||||||
public String downloadUrl = Launch4JTask.DOWNLOAD_URL;
|
public String downloadUrl = Launch4JTask.DOWNLOAD_URL;
|
||||||
public String productName;
|
public String productName;
|
||||||
|
@ -259,6 +259,7 @@ public static class JarSignerConf {
|
||||||
public String metaInfKeyName = "SIGNUMO.RSA";
|
public String metaInfKeyName = "SIGNUMO.RSA";
|
||||||
public String metaInfSfName = "SIGNUMO.SF";
|
public String metaInfSfName = "SIGNUMO.SF";
|
||||||
public String signAlgo = "SHA256WITHRSA";
|
public String signAlgo = "SHA256WITHRSA";
|
||||||
|
public boolean checkCertificateExpired = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class NettyUpdatesBind {
|
public static class NettyUpdatesBind {
|
||||||
|
|
|
@ -49,9 +49,7 @@ public static ClientProfile makeProfile(ClientProfile.Version version, String ti
|
||||||
} else if (version.compareTo(ClientProfileVersions.MINECRAFT_1_18) <= 0) { // 1.13 - 1.16.5
|
} else if (version.compareTo(ClientProfileVersions.MINECRAFT_1_18) <= 0) { // 1.13 - 1.16.5
|
||||||
jvmArgs.add("-XX:+UseG1GC");
|
jvmArgs.add("-XX:+UseG1GC");
|
||||||
jvmArgs.add("-XX:+UnlockExperimentalVMOptions");
|
jvmArgs.add("-XX:+UnlockExperimentalVMOptions");
|
||||||
} else { // 1.18+
|
} else {
|
||||||
//jvmArgs.add("-XX:+UseShenandoahGC");
|
|
||||||
//jvmArgs.add("-XX:+UnlockExperimentalVMOptions");
|
|
||||||
}
|
}
|
||||||
// -----------
|
// -----------
|
||||||
Optional<MakeProfileOptionForge> forge = findOption(options, MakeProfileOptionForge.class);
|
Optional<MakeProfileOptionForge> forge = findOption(options, MakeProfileOptionForge.class);
|
||||||
|
|
|
@ -21,8 +21,10 @@
|
||||||
import java.security.cert.CertificateEncodingException;
|
import java.security.cert.CertificateEncodingException;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class SignHelper {
|
public class SignHelper {
|
||||||
|
@ -46,6 +48,24 @@ public static KeyStore getStore(Path file, String storepass, String algo) throws
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static Instant getCertificateExpired(KeyStore keyStore, String keyAlias) throws KeyStoreException {
|
||||||
|
List<Certificate> certChain = new ArrayList<>(Arrays.asList(keyStore.getCertificateChain(keyAlias)));
|
||||||
|
Date date = null;
|
||||||
|
for(var e : certChain) {
|
||||||
|
if(e instanceof X509Certificate x509Certificate) {
|
||||||
|
if(x509Certificate.getNotAfter() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(date == null || date.after(x509Certificate.getNotAfter())) {
|
||||||
|
date = x509Certificate.getNotAfter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return date == null ? null : date.toInstant();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the beast that can actually sign the data (for JKS, for other make it).
|
* Creates the beast that can actually sign the data (for JKS, for other make it).
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import pro.gravit.launcher.Launcher;
|
import pro.gravit.launcher.Launcher;
|
||||||
import pro.gravit.launcher.LauncherTrustManager;
|
import pro.gravit.launcher.LauncherTrustManager;
|
||||||
import pro.gravit.launcher.modules.LauncherModule;
|
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
import pro.gravit.launchserver.asm.InjectClassAcceptor;
|
import pro.gravit.launchserver.asm.InjectClassAcceptor;
|
||||||
import pro.gravit.launchserver.binary.tasks.MainBuildTask;
|
import pro.gravit.launchserver.binary.tasks.MainBuildTask;
|
||||||
|
@ -50,7 +49,11 @@ public void init() {
|
||||||
mainTask.preBuildHook.registerHook((buildContext) -> {
|
mainTask.preBuildHook.registerHook((buildContext) -> {
|
||||||
for (ModuleEntity e : launcherModules) {
|
for (ModuleEntity e : launcherModules) {
|
||||||
if (e.propertyMap != null) buildContext.task.properties.putAll(e.propertyMap);
|
if (e.propertyMap != null) buildContext.task.properties.putAll(e.propertyMap);
|
||||||
|
if(e.modernModule) {
|
||||||
buildContext.clientModules.add(e.moduleMainClass);
|
buildContext.clientModules.add(e.moduleMainClass);
|
||||||
|
} else {
|
||||||
|
buildContext.legacyClientModules.add(e.moduleMainClass);
|
||||||
|
}
|
||||||
buildContext.readerClassPath.add(new JarFile(e.path.toFile()));
|
buildContext.readerClassPath.add(new JarFile(e.path.toFile()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -94,6 +97,7 @@ public static class ModuleEntity {
|
||||||
public String moduleMainClass;
|
public String moduleMainClass;
|
||||||
public String moduleConfigClass;
|
public String moduleConfigClass;
|
||||||
public String moduleConfigName;
|
public String moduleConfigName;
|
||||||
|
public boolean modernModule;
|
||||||
public Map<String, Object> propertyMap;
|
public Map<String, Object> propertyMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +108,6 @@ private ModulesVisitor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||||
if (file.toFile().getName().endsWith(".jar"))
|
if (file.toFile().getName().endsWith(".jar"))
|
||||||
try (JarFile f = new JarFile(file.toFile())) {
|
try (JarFile f = new JarFile(file.toFile())) {
|
||||||
|
@ -120,6 +123,8 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
|
||||||
entity.path = file;
|
entity.path = file;
|
||||||
entity.moduleMainClass = mainClass;
|
entity.moduleMainClass = mainClass;
|
||||||
entity.moduleConfigClass = attributes.getValue("Module-Config-Class");
|
entity.moduleConfigClass = attributes.getValue("Module-Config-Class");
|
||||||
|
String requiredModernJava = attributes.getValue("Required-Modern-Java");
|
||||||
|
entity.modernModule = Boolean.parseBoolean(requiredModernJava);
|
||||||
if (entity.moduleConfigClass != null) {
|
if (entity.moduleConfigClass != null) {
|
||||||
entity.moduleConfigName = attributes.getValue("Module-Config-Name");
|
entity.moduleConfigName = attributes.getValue("Module-Config-Name");
|
||||||
if (entity.moduleConfigName == null) {
|
if (entity.moduleConfigName == null) {
|
||||||
|
|
|
@ -115,7 +115,7 @@ public AuthReport auth(AuthResponse.AuthContext context, AuthRequest.AuthPasswor
|
||||||
context.client.sessionObject = session;
|
context.client.sessionObject = session;
|
||||||
internalAuth(context.client, context.authType, context.pair, user.getUsername(), user.getUUID(), user.getPermissions(), true);
|
internalAuth(context.client, context.authType, context.pair, user.getUsername(), user.getUUID(), user.getPermissions(), true);
|
||||||
if (context.authType == AuthResponse.ConnectTypes.CLIENT && server.config.protectHandler.allowGetAccessToken(context)) {
|
if (context.authType == AuthResponse.ConnectTypes.CLIENT && server.config.protectHandler.allowGetAccessToken(context)) {
|
||||||
return AuthReport.ofMinecraftAccessToken(user.getAccessToken(), session);
|
return AuthReport.ofMinecraftAccessToken(session.getMinecraftAccessToken(), session);
|
||||||
}
|
}
|
||||||
return AuthReport.ofMinecraftAccessToken(null, session);
|
return AuthReport.ofMinecraftAccessToken(null, session);
|
||||||
}
|
}
|
||||||
|
@ -166,9 +166,9 @@ public CheckServerReport checkServer(Client client, String username, String serv
|
||||||
else return CheckServerReport.ofUser(user, getPlayerProfile(client.auth, user));
|
else return CheckServerReport.ofUser(user, getPlayerProfile(client.auth, user));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean joinServer(Client client, String username, String accessToken, String serverID) throws IOException {
|
public boolean joinServer(Client client, String username, UUID uuid, String accessToken, String serverID) throws IOException {
|
||||||
if (client.auth == null) return false;
|
if (client.auth == null) return false;
|
||||||
return client.auth.core.joinServer(client, username, accessToken, serverID);
|
return client.auth.core.joinServer(client, username, uuid, accessToken, serverID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlayerProfile getPlayerProfile(Client client) {
|
public PlayerProfile getPlayerProfile(Client client) {
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||||
import pro.gravit.launcher.request.auth.GetAvailabilityAuthRequest;
|
import pro.gravit.launcher.request.auth.GetAvailabilityAuthRequest;
|
||||||
import pro.gravit.launchserver.auth.core.AuthCoreProvider;
|
import pro.gravit.launchserver.auth.core.AuthCoreProvider;
|
||||||
|
import pro.gravit.launchserver.auth.mix.MixProvider;
|
||||||
import pro.gravit.launchserver.auth.password.PasswordVerifier;
|
import pro.gravit.launchserver.auth.password.PasswordVerifier;
|
||||||
import pro.gravit.launchserver.auth.protect.ProtectHandler;
|
import pro.gravit.launchserver.auth.protect.ProtectHandler;
|
||||||
import pro.gravit.launchserver.auth.texture.TextureProvider;
|
import pro.gravit.launchserver.auth.texture.TextureProvider;
|
||||||
|
@ -48,6 +49,7 @@ public void registerAdapters(GsonBuilder builder) {
|
||||||
builder.registerTypeAdapter(GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails.class, new UniversalJsonAdapter<>(GetAvailabilityAuthRequest.providers));
|
builder.registerTypeAdapter(GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails.class, new UniversalJsonAdapter<>(GetAvailabilityAuthRequest.providers));
|
||||||
builder.registerTypeAdapter(OptionalAction.class, new UniversalJsonAdapter<>(OptionalAction.providers));
|
builder.registerTypeAdapter(OptionalAction.class, new UniversalJsonAdapter<>(OptionalAction.providers));
|
||||||
builder.registerTypeAdapter(OptionalTrigger.class, new UniversalJsonAdapter<>(OptionalTrigger.providers));
|
builder.registerTypeAdapter(OptionalTrigger.class, new UniversalJsonAdapter<>(OptionalTrigger.providers));
|
||||||
|
builder.registerTypeAdapter(MixProvider.class, new UniversalJsonAdapter<>(MixProvider.providers));
|
||||||
modulesManager.invokeEvent(new PreGsonPhase(builder));
|
modulesManager.invokeEvent(new PreGsonPhase(builder));
|
||||||
//ClientWebSocketService.appendTypeAdapters(builder);
|
//ClientWebSocketService.appendTypeAdapters(builder);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,20 +3,27 @@
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import pro.gravit.launcher.HTTPRequest;
|
import pro.gravit.launcher.Launcher;
|
||||||
import pro.gravit.utils.HttpDownloader;
|
|
||||||
import pro.gravit.utils.helper.IOHelper;
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.net.http.HttpClient;
|
||||||
|
import java.net.http.HttpRequest;
|
||||||
|
import java.net.http.HttpResponse;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
public class MirrorManager {
|
public class MirrorManager {
|
||||||
protected final ArrayList<Mirror> list = new ArrayList<>();
|
protected final ArrayList<Mirror> list = new ArrayList<>();
|
||||||
private transient final Logger logger = LogManager.getLogger();
|
private transient final Logger logger = LogManager.getLogger();
|
||||||
|
private transient final HttpClient client = HttpClient.newBuilder().build();
|
||||||
private Mirror defaultMirror;
|
private Mirror defaultMirror;
|
||||||
|
|
||||||
public void addMirror(String mirror) {
|
public void addMirror(String mirror) {
|
||||||
|
@ -58,7 +65,7 @@ public boolean downloadZip(Mirror mirror, Path path, String mask, Object... args
|
||||||
URL url = mirror.getURL(mask, args);
|
URL url = mirror.getURL(mask, args);
|
||||||
logger.debug("Try download {}", url.toString());
|
logger.debug("Try download {}", url.toString());
|
||||||
try {
|
try {
|
||||||
HttpDownloader.downloadZip(url, path);
|
downloadZip(url, path);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.error("Download {} failed({}: {})", url.toString(), e.getClass().getName(), e.getMessage());
|
logger.error("Download {} failed({}: {})", url.toString(), e.getClass().getName(), e.getMessage());
|
||||||
return false;
|
return false;
|
||||||
|
@ -82,8 +89,12 @@ public JsonElement jsonRequest(Mirror mirror, JsonElement request, String method
|
||||||
if (!mirror.enabled) return null;
|
if (!mirror.enabled) return null;
|
||||||
URL url = mirror.getURL(mask, args);
|
URL url = mirror.getURL(mask, args);
|
||||||
try {
|
try {
|
||||||
return HTTPRequest.jsonRequest(request, method, url);
|
var response = client.send(HttpRequest.newBuilder()
|
||||||
} catch (IOException e) {
|
.method(method, request == null ? HttpRequest.BodyPublishers.noBody() : HttpRequest.BodyPublishers.ofString(Launcher.gsonManager.gson.toJson(request)))
|
||||||
|
.uri(url.toURI())
|
||||||
|
.build(), HttpResponse.BodyHandlers.ofString());
|
||||||
|
return Launcher.gsonManager.gson.fromJson(response.body(), JsonElement.class);
|
||||||
|
} catch (IOException | URISyntaxException | InterruptedException e) {
|
||||||
logger.error("JsonRequest {} failed({}: {})", url.toString(), e.getClass().getName(), e.getMessage());
|
logger.error("JsonRequest {} failed({}: {})", url.toString(), e.getClass().getName(), e.getMessage());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -101,6 +112,22 @@ public JsonElement jsonRequest(JsonElement request, String method, String mask,
|
||||||
throw new IOException("Error jsonRequest. All mirrors return error");
|
throw new IOException("Error jsonRequest. All mirrors return error");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void downloadZip(URL url, Path dir) throws IOException {
|
||||||
|
try (ZipInputStream input = IOHelper.newZipInput(url)) {
|
||||||
|
Files.createDirectory(dir);
|
||||||
|
for (ZipEntry entry = input.getNextEntry(); entry != null; entry = input.getNextEntry()) {
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
Files.createDirectory(dir.resolve(IOHelper.toPath(entry.getName())));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Unpack entry
|
||||||
|
String name = entry.getName();
|
||||||
|
logger.debug("Downloading file: '{}'", name);
|
||||||
|
IOHelper.transfer(input, dir.resolve(IOHelper.toPath(name)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class Mirror {
|
public static class Mirror {
|
||||||
final String baseUrl;
|
final String baseUrl;
|
||||||
boolean enabled;
|
boolean enabled;
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||||
import pro.gravit.launchserver.socket.response.WebSocketServerResponse;
|
import pro.gravit.launchserver.socket.response.WebSocketServerResponse;
|
||||||
import pro.gravit.launchserver.socket.response.auth.*;
|
import pro.gravit.launchserver.socket.response.auth.*;
|
||||||
|
import pro.gravit.launchserver.socket.response.cabinet.AssetUploadInfoResponse;
|
||||||
|
import pro.gravit.launchserver.socket.response.cabinet.GetAssetUploadInfoResponse;
|
||||||
import pro.gravit.launchserver.socket.response.management.FeaturesResponse;
|
import pro.gravit.launchserver.socket.response.management.FeaturesResponse;
|
||||||
import pro.gravit.launchserver.socket.response.management.GetPublicKeyResponse;
|
import pro.gravit.launchserver.socket.response.management.GetPublicKeyResponse;
|
||||||
import pro.gravit.launchserver.socket.response.profile.BatchProfileByUsername;
|
import pro.gravit.launchserver.socket.response.profile.BatchProfileByUsername;
|
||||||
|
@ -65,7 +67,6 @@ public static void registerResponses() {
|
||||||
providers.register("updateList", UpdateListResponse.class);
|
providers.register("updateList", UpdateListResponse.class);
|
||||||
providers.register("setProfile", SetProfileResponse.class);
|
providers.register("setProfile", SetProfileResponse.class);
|
||||||
providers.register("update", UpdateResponse.class);
|
providers.register("update", UpdateResponse.class);
|
||||||
providers.register("restoreSession", RestoreSessionResponse.class);
|
|
||||||
providers.register("batchProfileByUsername", BatchProfileByUsername.class);
|
providers.register("batchProfileByUsername", BatchProfileByUsername.class);
|
||||||
providers.register("profileByUsername", ProfileByUsername.class);
|
providers.register("profileByUsername", ProfileByUsername.class);
|
||||||
providers.register("profileByUUID", ProfileByUUIDResponse.class);
|
providers.register("profileByUUID", ProfileByUUIDResponse.class);
|
||||||
|
@ -82,6 +83,8 @@ public static void registerResponses() {
|
||||||
providers.register("additionalData", AdditionalDataResponse.class);
|
providers.register("additionalData", AdditionalDataResponse.class);
|
||||||
providers.register("clientProfileKey", FetchClientProfileKeyResponse.class);
|
providers.register("clientProfileKey", FetchClientProfileKeyResponse.class);
|
||||||
providers.register("getPublicKey", GetPublicKeyResponse.class);
|
providers.register("getPublicKey", GetPublicKeyResponse.class);
|
||||||
|
providers.register("getAssetUploadUrl", GetAssetUploadInfoResponse.class);
|
||||||
|
providers.register("assetUploadInfo", AssetUploadInfoResponse.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getIPFromContext(ChannelHandlerContext ctx) {
|
public static String getIPFromContext(ChannelHandlerContext ctx) {
|
||||||
|
|
|
@ -20,14 +20,8 @@ public String getType() {
|
||||||
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 : server.config.auth.values()) {
|
for (AuthProviderPair pair : server.config.auth.values()) {
|
||||||
var rca = pair.isSupport(AuthSupportRemoteClientAccess.class);
|
list.add(new GetAvailabilityAuthRequestEvent.AuthAvailability(pair.core.getDetails(client), pair.name, pair.displayName,
|
||||||
if (rca != null) {
|
pair.visible, pair.getFeatures()));
|
||||||
list.add(new GetAvailabilityAuthRequestEvent.AuthAvailability(pair.name, pair.displayName,
|
|
||||||
pair.visible, pair.core.getDetails(client), rca.getClientApiUrl(), rca.getClientApiFeatures()));
|
|
||||||
} else {
|
|
||||||
list.add(new GetAvailabilityAuthRequestEvent.AuthAvailability(pair.name, pair.displayName,
|
|
||||||
pair.visible, pair.core.getDetails(client)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
sendResult(new GetAvailabilityAuthRequestEvent(list));
|
sendResult(new GetAvailabilityAuthRequestEvent(list));
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,14 @@
|
||||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||||
import pro.gravit.utils.HookException;
|
import pro.gravit.utils.HookException;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class JoinServerResponse extends SimpleResponse {
|
public class JoinServerResponse extends SimpleResponse {
|
||||||
private transient final Logger logger = LogManager.getLogger();
|
private transient final Logger logger = LogManager.getLogger();
|
||||||
public String serverID;
|
public String serverID;
|
||||||
public String accessToken;
|
public String accessToken;
|
||||||
public String username;
|
public String username;
|
||||||
|
public UUID uuid;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getType() {
|
public String getType() {
|
||||||
|
@ -23,11 +26,11 @@ public String getType() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(ChannelHandlerContext ctx, Client client) {
|
public void execute(ChannelHandlerContext ctx, Client client) {
|
||||||
if (!client.isAuth || client.type != AuthResponse.ConnectTypes.CLIENT) {
|
if (!server.config.protectHandler.allowJoinServer(client)) {
|
||||||
sendError("Permissions denied");
|
sendError("Permissions denied");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (username == null || accessToken == null || serverID == null) {
|
if ((username == null && uuid == null) || accessToken == null || serverID == null) {
|
||||||
sendError("Invalid request");
|
sendError("Invalid request");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -35,13 +38,13 @@ public void execute(ChannelHandlerContext ctx, Client client) {
|
||||||
try {
|
try {
|
||||||
server.authHookManager.joinServerHook.hook(this, client);
|
server.authHookManager.joinServerHook.hook(this, client);
|
||||||
if (server.config.protectHandler instanceof JoinServerProtectHandler joinServerProtectHandler) {
|
if (server.config.protectHandler instanceof JoinServerProtectHandler joinServerProtectHandler) {
|
||||||
success = joinServerProtectHandler.onJoinServer(serverID, username, client);
|
success = joinServerProtectHandler.onJoinServer(serverID, username, uuid, client);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
sendResult(new JoinServerRequestEvent(false));
|
sendResult(new JoinServerRequestEvent(false));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
success = server.authManager.joinServer(client, username, accessToken, serverID);
|
success = server.authManager.joinServer(client, username, uuid, accessToken, serverID);
|
||||||
if (success) {
|
if (success) {
|
||||||
logger.debug("joinServer: {} accessToken: {} serverID: {}", username, accessToken, serverID);
|
logger.debug("joinServer: {} accessToken: {} serverID: {}", username, accessToken, serverID);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
package pro.gravit.launchserver.socket.response.auth;
|
|
||||||
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import pro.gravit.launcher.LauncherNetworkAPI;
|
|
||||||
import pro.gravit.launchserver.socket.Client;
|
|
||||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class RestoreSessionResponse extends SimpleResponse {
|
|
||||||
@LauncherNetworkAPI
|
|
||||||
public UUID session;
|
|
||||||
public boolean needUserInfo;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getType() {
|
|
||||||
return "restoreSession";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(ChannelHandlerContext ctx, Client client) {
|
|
||||||
sendError("Legacy session system removed");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
package pro.gravit.launchserver.socket.response.cabinet;
|
||||||
|
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportAssetUpload;
|
||||||
|
import pro.gravit.launchserver.socket.Client;
|
||||||
|
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||||
|
|
||||||
|
public class AssetUploadInfoResponse extends SimpleResponse {
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "assetUploadInfo";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||||
|
if(!client.isAuth || client.auth == null || client.getUser() == null) {
|
||||||
|
sendError("Access denied");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var support = client.auth.isSupport(AuthSupportAssetUpload.class);
|
||||||
|
if(support == null) {
|
||||||
|
sendError("Not supported");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sendResult(support.getAssetUploadInfo(client.getUser()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package pro.gravit.launchserver.socket.response.cabinet;
|
||||||
|
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import pro.gravit.launcher.events.request.GetAssetUploadUrlRequestEvent;
|
||||||
|
import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportAssetUpload;
|
||||||
|
import pro.gravit.launchserver.socket.Client;
|
||||||
|
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||||
|
|
||||||
|
public class GetAssetUploadInfoResponse extends SimpleResponse {
|
||||||
|
public String name;
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "getAssetUploadUrl";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||||
|
if(!client.isAuth || client.auth == null || client.getUser() == null) {
|
||||||
|
sendError("Access denied");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var support = client.auth.isSupport(AuthSupportAssetUpload.class);
|
||||||
|
if(support == null) {
|
||||||
|
sendError("Not supported");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sendResult(new GetAssetUploadUrlRequestEvent(support.getAssetUploadUrl(name, client.getUser()), support.getAssetUploadToken(name, client.getUser())));
|
||||||
|
}
|
||||||
|
}
|
|
@ -50,9 +50,9 @@ public void execute(ChannelHandlerContext ctx, Client client) {
|
||||||
service.sendObjectAndClose(ctx, new LauncherRequestEvent(true, server.config.netty.launcherURL));
|
service.sendObjectAndClose(ctx, new LauncherRequestEvent(true, server.config.netty.launcherURL));
|
||||||
if (Arrays.equals(bytes, hash) && checkSecure(secureHash, secureSalt)) {
|
if (Arrays.equals(bytes, hash) && checkSecure(secureHash, secureSalt)) {
|
||||||
client.checkSign = true;
|
client.checkSign = true;
|
||||||
sendResult(new LauncherRequestEvent(false, server.config.netty.launcherURL, createLauncherExtendedToken()));
|
sendResult(new LauncherRequestEvent(false, server.config.netty.launcherURL, createLauncherExtendedToken(), server.config.netty.security.launcherTokenExpire*1000));
|
||||||
} else {
|
} else {
|
||||||
sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherURL, createLauncherExtendedToken()));
|
sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherURL, createLauncherExtendedToken(), server.config.netty.security.launcherTokenExpire*1000));
|
||||||
}
|
}
|
||||||
} else if (launcher_type == 2) //EXE
|
} else if (launcher_type == 2) //EXE
|
||||||
{
|
{
|
||||||
|
@ -60,9 +60,9 @@ public void execute(ChannelHandlerContext ctx, Client client) {
|
||||||
if (hash == null) sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherEXEURL));
|
if (hash == null) sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherEXEURL));
|
||||||
if (Arrays.equals(bytes, hash) && checkSecure(secureHash, secureSalt)) {
|
if (Arrays.equals(bytes, hash) && checkSecure(secureHash, secureSalt)) {
|
||||||
client.checkSign = true;
|
client.checkSign = true;
|
||||||
sendResult(new LauncherRequestEvent(false, server.config.netty.launcherEXEURL, createLauncherExtendedToken()));
|
sendResult(new LauncherRequestEvent(false, server.config.netty.launcherEXEURL, createLauncherExtendedToken(), server.config.netty.security.launcherTokenExpire*1000));
|
||||||
} else {
|
} else {
|
||||||
sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherEXEURL, createLauncherExtendedToken()));
|
sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherEXEURL, createLauncherExtendedToken(), server.config.netty.security.launcherTokenExpire*1000));
|
||||||
}
|
}
|
||||||
} else sendError("Request launcher type error");
|
} else sendError("Request launcher type error");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Configuration status="INFO" packages="pro.gravit.launchserver.config.log4j">
|
<Configuration status="INFO">
|
||||||
<Appenders>
|
<Appenders>
|
||||||
<Console name="Console" target="SYSTEM_OUT">
|
<Console name="Console" target="SYSTEM_OUT">
|
||||||
<PatternLayout
|
<PatternLayout
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
-dontshrink
|
-dontshrink
|
||||||
-dontoptimize
|
-dontoptimize
|
||||||
-ignorewarnings
|
-ignorewarnings
|
||||||
-target 8
|
|
||||||
-forceprocessing
|
-forceprocessing
|
||||||
|
|
||||||
-repackageclasses 'pro.gravit.launcher'
|
-repackageclasses 'pro.gravit.launcher'
|
||||||
|
@ -17,7 +16,7 @@
|
||||||
|
|
||||||
-keeppackagenames com.mojang.**,net.minecraftforge.fml.**,cpw.mods.fml.**,com.google.gson.**,pro.gravit.repackage.**,org.fusesource.**, pro.gravit.launcher.api.**, pro.gravit.utils.**, pro.gravit.launcher.request.**, pro.gravit.launcher.events.**, pro.gravit.launcher.profiles.**
|
-keeppackagenames com.mojang.**,net.minecraftforge.fml.**,cpw.mods.fml.**,com.google.gson.**,pro.gravit.repackage.**,org.fusesource.**, pro.gravit.launcher.api.**, pro.gravit.utils.**, pro.gravit.launcher.request.**, pro.gravit.launcher.events.**, pro.gravit.launcher.profiles.**
|
||||||
|
|
||||||
-keep class com.mojang.**,net.minecraftforge.fml.**,cpw.mods.fml.**,com.google.gson.**,pro.gravit.repackage.**,org.fusesource.**, pro.gravit.launcher.api.**, pro.gravit.utils.**, pro.gravit.launcher.request.**, pro.gravit.launcher.events.**, pro.gravit.launcher.profiles.** {
|
-keep class com.mojang.**,net.minecraftforge.fml.**,cpw.mods.fml.**,com.google.gson.**,pro.gravit.repackage.**,org.fusesource.**, pro.gravit.launcher.api.**, pro.gravit.utils.**, pro.gravit.launcher.request.**, pro.gravit.launcher.events.**, pro.gravit.launcher.profiles.**, pro.gravit.launcher.LauncherEngineWrapper {
|
||||||
*;
|
*;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
package pro.gravit.launchserver;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import pro.gravit.launchserver.auth.AuthProviderPair;
|
||||||
|
import pro.gravit.launchserver.auth.Feature;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class FeatureCollectionTest {
|
||||||
|
public static class TestClass1 implements TextInterface1 {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Feature("test")
|
||||||
|
public interface TextInterface1 {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void simpleTest() {
|
||||||
|
var set = AuthProviderPair.getFeatures(TestClass1.class);
|
||||||
|
Assertions.assertTrue(set.contains("test"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,8 +13,8 @@
|
||||||
version = "12"
|
version = "12"
|
||||||
modules = ['javafx.controls', 'javafx.fxml']
|
modules = ['javafx.controls', 'javafx.fxml']
|
||||||
}
|
}
|
||||||
sourceCompatibility = '1.8'
|
sourceCompatibility = '17'
|
||||||
targetCompatibility = '1.8'
|
targetCompatibility = '17'
|
||||||
|
|
||||||
configurations {
|
configurations {
|
||||||
bundle
|
bundle
|
||||||
|
@ -49,6 +49,9 @@
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
pack project(':LauncherAPI')
|
pack project(':LauncherAPI')
|
||||||
|
pack project(':LauncherModernCore')
|
||||||
|
pack project(':LauncherClient')
|
||||||
|
pack project(':LauncherStart')
|
||||||
bundle group: 'com.github.oshi', name: 'oshi-core', version: rootProject['verOshiCore']
|
bundle group: 'com.github.oshi', name: 'oshi-core', version: rootProject['verOshiCore']
|
||||||
pack group: 'io.netty', name: 'netty-codec-http', version: rootProject['verNetty']
|
pack group: 'io.netty', name: 'netty-codec-http', version: rootProject['verNetty']
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,8 @@
|
||||||
import pro.gravit.launcher.console.GetPublicKeyCommand;
|
import pro.gravit.launcher.console.GetPublicKeyCommand;
|
||||||
import pro.gravit.launcher.console.ModulesCommand;
|
import pro.gravit.launcher.console.ModulesCommand;
|
||||||
import pro.gravit.launcher.console.SignDataCommand;
|
import pro.gravit.launcher.console.SignDataCommand;
|
||||||
import pro.gravit.launcher.events.request.*;
|
|
||||||
import pro.gravit.launcher.gui.NoRuntimeProvider;
|
import pro.gravit.launcher.gui.NoRuntimeProvider;
|
||||||
import pro.gravit.launcher.gui.RuntimeProvider;
|
import pro.gravit.launcher.gui.RuntimeProvider;
|
||||||
import pro.gravit.launcher.managers.ClientGsonManager;
|
|
||||||
import pro.gravit.launcher.managers.ConsoleManager;
|
import pro.gravit.launcher.managers.ConsoleManager;
|
||||||
import pro.gravit.launcher.modules.events.OfflineModeEvent;
|
import pro.gravit.launcher.modules.events.OfflineModeEvent;
|
||||||
import pro.gravit.launcher.modules.events.PreConfigPhase;
|
import pro.gravit.launcher.modules.events.PreConfigPhase;
|
||||||
|
@ -20,11 +18,6 @@
|
||||||
import pro.gravit.launcher.request.RequestException;
|
import pro.gravit.launcher.request.RequestException;
|
||||||
import pro.gravit.launcher.request.RequestService;
|
import pro.gravit.launcher.request.RequestService;
|
||||||
import pro.gravit.launcher.request.auth.*;
|
import pro.gravit.launcher.request.auth.*;
|
||||||
import pro.gravit.launcher.request.auth.details.AuthLoginOnlyDetails;
|
|
||||||
import pro.gravit.launcher.request.management.FeaturesRequest;
|
|
||||||
import pro.gravit.launcher.request.secure.GetSecureLevelInfoRequest;
|
|
||||||
import pro.gravit.launcher.request.secure.SecurityReportRequest;
|
|
||||||
import pro.gravit.launcher.request.update.LauncherRequest;
|
|
||||||
import pro.gravit.launcher.request.websockets.OfflineRequestService;
|
import pro.gravit.launcher.request.websockets.OfflineRequestService;
|
||||||
import pro.gravit.launcher.request.websockets.StdWebSocketService;
|
import pro.gravit.launcher.request.websockets.StdWebSocketService;
|
||||||
import pro.gravit.launcher.utils.NativeJVMHalt;
|
import pro.gravit.launcher.utils.NativeJVMHalt;
|
||||||
|
@ -32,31 +25,31 @@
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.security.interfaces.ECPrivateKey;
|
import java.security.interfaces.ECPrivateKey;
|
||||||
import java.security.interfaces.ECPublicKey;
|
import java.security.interfaces.ECPublicKey;
|
||||||
import java.security.spec.InvalidKeySpecException;
|
import java.security.spec.InvalidKeySpecException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
public class LauncherEngine {
|
public class LauncherEngine {
|
||||||
public static ClientLauncherProcess.ClientParams clientParams;
|
public static ClientParams clientParams;
|
||||||
public static ClientModuleManager modulesManager;
|
public static RuntimeModuleManager modulesManager;
|
||||||
public final boolean clientInstance;
|
public final boolean clientInstance;
|
||||||
// Instance
|
// Instance
|
||||||
private final AtomicBoolean started = new AtomicBoolean(false);
|
private final AtomicBoolean started = new AtomicBoolean(false);
|
||||||
public RuntimeProvider runtimeProvider;
|
public RuntimeProvider runtimeProvider;
|
||||||
public ECPublicKey publicKey;
|
public ECPublicKey publicKey;
|
||||||
public ECPrivateKey privateKey;
|
public ECPrivateKey privateKey;
|
||||||
|
public Class<? extends RuntimeProvider> basicRuntimeProvider;
|
||||||
|
|
||||||
private LauncherEngine(boolean clientInstance) {
|
private LauncherEngine(boolean clientInstance, Class<? extends RuntimeProvider> basicRuntimeProvider) {
|
||||||
|
|
||||||
this.clientInstance = clientInstance;
|
this.clientInstance = clientInstance;
|
||||||
|
this.basicRuntimeProvider = basicRuntimeProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
//JVMHelper.getCertificates
|
//JVMHelper.getCertificates
|
||||||
|
@ -101,19 +94,32 @@ public static void exitLauncher(int code) {
|
||||||
forceExit(code);
|
forceExit(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean contains(String[] array, String value) {
|
||||||
|
for(String s : array) {
|
||||||
|
if(s.equals(value)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String... args) throws Throwable {
|
public static void main(String... args) throws Throwable {
|
||||||
JVMHelper.checkStackTrace(LauncherEngine.class);
|
JVMHelper.checkStackTrace(LauncherEngineWrapper.class);
|
||||||
JVMHelper.verifySystemProperties(Launcher.class, true);
|
JVMHelper.verifySystemProperties(Launcher.class, true);
|
||||||
EnvHelper.checkDangerousParams();
|
EnvHelper.checkDangerousParams();
|
||||||
//if(!LauncherAgent.isStarted()) throw new SecurityException("JavaAgent not set");
|
//if(!LauncherAgent.isStarted()) throw new SecurityException("JavaAgent not set");
|
||||||
verifyNoAgent();
|
verifyNoAgent();
|
||||||
|
if(contains(args, "--log-output") && Launcher.getConfig().environment != LauncherConfig.LauncherEnvironment.PROD) {
|
||||||
|
LogHelper.addOutput(Paths.get("Launcher.log"));
|
||||||
|
}
|
||||||
LogHelper.printVersion("Launcher");
|
LogHelper.printVersion("Launcher");
|
||||||
LogHelper.printLicense("Launcher");
|
LogHelper.printLicense("Launcher");
|
||||||
|
LauncherEngine.checkClass(LauncherEngineWrapper.class);
|
||||||
LauncherEngine.checkClass(LauncherEngine.class);
|
LauncherEngine.checkClass(LauncherEngine.class);
|
||||||
LauncherEngine.checkClass(LauncherAgent.class);
|
LauncherEngine.checkClass(LauncherAgent.class);
|
||||||
LauncherEngine.checkClass(ClientLauncherEntryPoint.class);
|
LauncherEngine.checkClass(ClientLauncherEntryPoint.class);
|
||||||
LauncherEngine.modulesManager = new ClientModuleManager();
|
LauncherEngine.modulesManager = new RuntimeModuleManager();
|
||||||
LauncherEngine.modulesManager.loadModule(new ClientLauncherCoreModule());
|
LauncherEngine.modulesManager.loadModule(new RuntimeLauncherCoreModule());
|
||||||
LauncherConfig.initModules(LauncherEngine.modulesManager);
|
LauncherConfig.initModules(LauncherEngine.modulesManager);
|
||||||
LauncherEngine.modulesManager.initModules(null);
|
LauncherEngine.modulesManager.initModules(null);
|
||||||
// Start Launcher
|
// Start Launcher
|
||||||
|
@ -123,7 +129,7 @@ public static void main(String... args) throws Throwable {
|
||||||
Launcher.getConfig(); // init config
|
Launcher.getConfig(); // init config
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
try {
|
try {
|
||||||
new LauncherEngine(false).start(args);
|
newInstance(false).start(args);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogHelper.error(e);
|
LogHelper.error(e);
|
||||||
return;
|
return;
|
||||||
|
@ -133,12 +139,12 @@ public static void main(String... args) throws Throwable {
|
||||||
LauncherEngine.exitLauncher(0);
|
LauncherEngine.exitLauncher(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void initGson(ClientModuleManager modulesManager) {
|
public static void initGson(RuntimeModuleManager modulesManager) {
|
||||||
AuthRequest.registerProviders();
|
AuthRequest.registerProviders();
|
||||||
GetAvailabilityAuthRequest.registerProviders();
|
GetAvailabilityAuthRequest.registerProviders();
|
||||||
OptionalAction.registerProviders();
|
OptionalAction.registerProviders();
|
||||||
OptionalTrigger.registerProviders();
|
OptionalTrigger.registerProviders();
|
||||||
Launcher.gsonManager = new ClientGsonManager(modulesManager);
|
Launcher.gsonManager = new RuntimeGsonManager(modulesManager);
|
||||||
Launcher.gsonManager.initGson();
|
Launcher.gsonManager.initGson();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,39 +155,18 @@ public static void verifyNoAgent() {
|
||||||
|
|
||||||
public static RequestService initOffline() {
|
public static RequestService initOffline() {
|
||||||
OfflineRequestService service = new OfflineRequestService();
|
OfflineRequestService service = new OfflineRequestService();
|
||||||
applyBasicOfflineProcessors(service);
|
ClientLauncherMethods.applyBasicOfflineProcessors(service);
|
||||||
OfflineModeEvent event = new OfflineModeEvent(service);
|
OfflineModeEvent event = new OfflineModeEvent(service);
|
||||||
modulesManager.invokeEvent(event);
|
modulesManager.invokeEvent(event);
|
||||||
return event.service;
|
return event.service;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void applyBasicOfflineProcessors(OfflineRequestService service) {
|
|
||||||
service.registerRequestProcessor(LauncherRequest.class, (r) -> new LauncherRequestEvent(false, (String) null));
|
|
||||||
service.registerRequestProcessor(CheckServerRequest.class, (r) -> {
|
|
||||||
throw new RequestException("CheckServer disabled in offline mode");
|
|
||||||
});
|
|
||||||
service.registerRequestProcessor(GetAvailabilityAuthRequest.class, (r) -> {
|
|
||||||
List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> details = new ArrayList<>();
|
|
||||||
details.add(new AuthLoginOnlyDetails());
|
|
||||||
GetAvailabilityAuthRequestEvent.AuthAvailability authAvailability = new GetAvailabilityAuthRequestEvent.AuthAvailability("offline", "Offline Mode", true, details);
|
|
||||||
List<GetAvailabilityAuthRequestEvent.AuthAvailability> list = new ArrayList<>(1);
|
|
||||||
list.add(authAvailability);
|
|
||||||
return new GetAvailabilityAuthRequestEvent(list);
|
|
||||||
});
|
|
||||||
service.registerRequestProcessor(JoinServerRequest.class, (r) -> new JoinServerRequestEvent(false));
|
|
||||||
service.registerRequestProcessor(ExitRequest.class, (r) -> new ExitRequestEvent(ExitRequestEvent.ExitReason.CLIENT));
|
|
||||||
service.registerRequestProcessor(SetProfileRequest.class, (r) -> new SetProfileRequestEvent(null));
|
|
||||||
service.registerRequestProcessor(FeaturesRequest.class, (r) -> new FeaturesRequestEvent());
|
|
||||||
service.registerRequestProcessor(GetSecureLevelInfoRequest.class, (r) -> new GetSecureLevelInfoRequestEvent(null, false));
|
|
||||||
service.registerRequestProcessor(SecurityReportRequest.class, (r) -> new SecurityReportRequestEvent(SecurityReportRequestEvent.ReportAction.NONE));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static LauncherEngine clientInstance() {
|
|
||||||
return new LauncherEngine(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static LauncherEngine newInstance(boolean clientInstance) {
|
public static LauncherEngine newInstance(boolean clientInstance) {
|
||||||
return new LauncherEngine(clientInstance);
|
return new LauncherEngine(clientInstance, NoRuntimeProvider.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LauncherEngine newInstance(boolean clientInstance, Class<? extends RuntimeProvider> basicRuntimeProvider) {
|
||||||
|
return new LauncherEngine(clientInstance, basicRuntimeProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ECPublicKey getClientPublicKey() {
|
public ECPublicKey getClientPublicKey() {
|
||||||
|
@ -219,7 +204,7 @@ public void start(String... args) throws Throwable {
|
||||||
ClientPreGuiPhase event = new ClientPreGuiPhase(null);
|
ClientPreGuiPhase event = new ClientPreGuiPhase(null);
|
||||||
LauncherEngine.modulesManager.invokeEvent(event);
|
LauncherEngine.modulesManager.invokeEvent(event);
|
||||||
runtimeProvider = event.runtimeProvider;
|
runtimeProvider = event.runtimeProvider;
|
||||||
if (runtimeProvider == null) runtimeProvider = new NoRuntimeProvider();
|
if (runtimeProvider == null) runtimeProvider = basicRuntimeProvider.getConstructor().newInstance();
|
||||||
runtimeProvider.init(clientInstance);
|
runtimeProvider.init(clientInstance);
|
||||||
//runtimeProvider.preLoad();
|
//runtimeProvider.preLoad();
|
||||||
if (!Request.isAvailable()) {
|
if (!Request.isAvailable()) {
|
||||||
|
@ -248,8 +233,9 @@ public void start(String... args) throws Throwable {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
service.registerEventHandler(new BasicLauncherEventHandler());
|
|
||||||
}
|
}
|
||||||
|
Request.startAutoRefresh();
|
||||||
|
Request.getRequestService().registerEventHandler(new BasicLauncherEventHandler());
|
||||||
Objects.requireNonNull(args, "args");
|
Objects.requireNonNull(args, "args");
|
||||||
if (started.getAndSet(true))
|
if (started.getAndSet(true))
|
||||||
throw new IllegalStateException("Launcher has been already started");
|
throw new IllegalStateException("Launcher has been already started");
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
package pro.gravit.launcher;
|
||||||
|
|
||||||
|
@LauncherNetworkAPI
|
||||||
|
public class LauncherEngineWrapper {
|
||||||
|
public static void main(String[] args) throws Throwable {
|
||||||
|
LauncherEngine.main(args);
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,33 +10,8 @@
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class NewLauncherSettings {
|
public class NewLauncherSettings {
|
||||||
@LauncherNetworkAPI
|
|
||||||
public final transient List<HashedStoreEntry> lastHDirs = new ArrayList<>(16);
|
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
public Map<String, UserSettings> userSettings = new HashMap<>();
|
public Map<String, UserSettings> userSettings = new HashMap<>();
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
public List<String> features = new ArrayList<>();
|
|
||||||
@LauncherNetworkAPI
|
|
||||||
public String consoleUnlockKey;
|
public String consoleUnlockKey;
|
||||||
|
|
||||||
public void putHDir(String name, Path path, HashedDir dir) {
|
|
||||||
String fullPath = path.toAbsolutePath().toString();
|
|
||||||
lastHDirs.removeIf((e) -> e.fullPath.equals(fullPath) && e.name.equals(name));
|
|
||||||
HashedStoreEntry e = new HashedStoreEntry(dir, name, fullPath);
|
|
||||||
e.needSave = true;
|
|
||||||
lastHDirs.add(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class HashedStoreEntry {
|
|
||||||
public final HashedDir hdir;
|
|
||||||
public final String name;
|
|
||||||
public final String fullPath;
|
|
||||||
public transient boolean needSave = false;
|
|
||||||
|
|
||||||
public HashedStoreEntry(HashedDir hdir, String name, String fullPath) {
|
|
||||||
this.hdir = hdir;
|
|
||||||
this.name = name;
|
|
||||||
this.fullPath = fullPath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,18 +7,14 @@
|
||||||
import pro.gravit.launcher.client.events.client.ClientProcessBuilderLaunchedEvent;
|
import pro.gravit.launcher.client.events.client.ClientProcessBuilderLaunchedEvent;
|
||||||
import pro.gravit.launcher.client.events.client.ClientProcessBuilderParamsWrittedEvent;
|
import pro.gravit.launcher.client.events.client.ClientProcessBuilderParamsWrittedEvent;
|
||||||
import pro.gravit.launcher.client.events.client.ClientProcessBuilderPreLaunchEvent;
|
import pro.gravit.launcher.client.events.client.ClientProcessBuilderPreLaunchEvent;
|
||||||
import pro.gravit.launcher.events.request.AuthRequestEvent;
|
|
||||||
import pro.gravit.launcher.hasher.HashedDir;
|
import pro.gravit.launcher.hasher.HashedDir;
|
||||||
import pro.gravit.launcher.profiles.ClientProfile;
|
import pro.gravit.launcher.profiles.ClientProfile;
|
||||||
import pro.gravit.launcher.profiles.ClientProfileVersions;
|
|
||||||
import pro.gravit.launcher.profiles.PlayerProfile;
|
import pro.gravit.launcher.profiles.PlayerProfile;
|
||||||
import pro.gravit.launcher.profiles.optional.OptionalView;
|
import pro.gravit.launcher.profiles.optional.OptionalView;
|
||||||
import pro.gravit.launcher.profiles.optional.actions.OptionalAction;
|
import pro.gravit.launcher.profiles.optional.actions.OptionalAction;
|
||||||
import pro.gravit.launcher.profiles.optional.actions.OptionalActionClientArgs;
|
|
||||||
import pro.gravit.launcher.profiles.optional.actions.OptionalActionJvmArgs;
|
import pro.gravit.launcher.profiles.optional.actions.OptionalActionJvmArgs;
|
||||||
import pro.gravit.launcher.request.Request;
|
import pro.gravit.launcher.request.Request;
|
||||||
import pro.gravit.launcher.serialize.HOutput;
|
import pro.gravit.launcher.serialize.HOutput;
|
||||||
import pro.gravit.utils.Version;
|
|
||||||
import pro.gravit.utils.helper.*;
|
import pro.gravit.utils.helper.*;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -238,120 +234,4 @@ public Process getProcess() {
|
||||||
return process;
|
return process;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ClientParams {
|
|
||||||
public String assetDir;
|
|
||||||
|
|
||||||
public String clientDir;
|
|
||||||
|
|
||||||
public String resourcePackDir;
|
|
||||||
|
|
||||||
public String nativesDir;
|
|
||||||
|
|
||||||
// Client params
|
|
||||||
|
|
||||||
public PlayerProfile playerProfile;
|
|
||||||
|
|
||||||
public ClientProfile profile;
|
|
||||||
|
|
||||||
public String accessToken;
|
|
||||||
|
|
||||||
//==Minecraft params==
|
|
||||||
|
|
||||||
public boolean autoEnter;
|
|
||||||
|
|
||||||
public boolean fullScreen;
|
|
||||||
|
|
||||||
public int ram;
|
|
||||||
|
|
||||||
public int width;
|
|
||||||
|
|
||||||
public int height;
|
|
||||||
|
|
||||||
public Set<OptionalAction> actions = new HashSet<>();
|
|
||||||
|
|
||||||
//========
|
|
||||||
|
|
||||||
public UUID session;
|
|
||||||
|
|
||||||
public AuthRequestEvent.OAuthRequestEvent oauth;
|
|
||||||
|
|
||||||
public String authId;
|
|
||||||
|
|
||||||
public long oauthExpiredTime;
|
|
||||||
|
|
||||||
public Map<String, String> extendedTokens;
|
|
||||||
|
|
||||||
public boolean offlineMode;
|
|
||||||
|
|
||||||
public transient HashedDir assetHDir;
|
|
||||||
|
|
||||||
public transient HashedDir clientHDir;
|
|
||||||
|
|
||||||
public transient HashedDir javaHDir;
|
|
||||||
|
|
||||||
public void addClientArgs(Collection<String> args) {
|
|
||||||
if (profile.getVersion().compareTo(ClientProfileVersions.MINECRAFT_1_6_4) >= 0)
|
|
||||||
addModernClientArgs(args);
|
|
||||||
else
|
|
||||||
addClientLegacyArgs(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addClientLegacyArgs(Collection<String> args) {
|
|
||||||
args.add(playerProfile.username);
|
|
||||||
args.add(accessToken);
|
|
||||||
|
|
||||||
// Add args for tweaker
|
|
||||||
Collections.addAll(args, "--version", profile.getVersion().toString());
|
|
||||||
Collections.addAll(args, "--gameDir", clientDir);
|
|
||||||
Collections.addAll(args, "--assetsDir", assetDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addModernClientArgs(Collection<String> args) {
|
|
||||||
|
|
||||||
// Add version-dependent args
|
|
||||||
ClientProfile.Version version = profile.getVersion();
|
|
||||||
Collections.addAll(args, "--username", playerProfile.username);
|
|
||||||
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_7_2) >= 0) {
|
|
||||||
Collections.addAll(args, "--uuid", Launcher.toHash(playerProfile.uuid));
|
|
||||||
Collections.addAll(args, "--accessToken", accessToken);
|
|
||||||
|
|
||||||
// Add 1.7.10+ args (user properties, asset index)
|
|
||||||
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_7_10) >= 0) {
|
|
||||||
// Add user properties
|
|
||||||
Collections.addAll(args, "--userType", "mojang");
|
|
||||||
Collections.addAll(args, "--userProperties", "{}");
|
|
||||||
|
|
||||||
// Add asset index
|
|
||||||
Collections.addAll(args, "--assetIndex", profile.getAssetIndex());
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
Collections.addAll(args, "--session", accessToken);
|
|
||||||
|
|
||||||
// Add version and dirs args
|
|
||||||
Collections.addAll(args, "--version", profile.getVersion().toString());
|
|
||||||
Collections.addAll(args, "--gameDir", clientDir);
|
|
||||||
Collections.addAll(args, "--assetsDir", assetDir);
|
|
||||||
Collections.addAll(args, "--resourcePackDir", resourcePackDir);
|
|
||||||
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_9_4) >= 0)
|
|
||||||
Collections.addAll(args, "--versionType", "Launcher v" + Version.getVersion().getVersionString());
|
|
||||||
|
|
||||||
// Add server args
|
|
||||||
if (autoEnter) {
|
|
||||||
Collections.addAll(args, "--server", profile.getServerAddress());
|
|
||||||
Collections.addAll(args, "--port", Integer.toString(profile.getServerPort()));
|
|
||||||
}
|
|
||||||
for (OptionalAction a : actions) {
|
|
||||||
if (a instanceof OptionalActionClientArgs) {
|
|
||||||
args.addAll(((OptionalActionClientArgs) a).args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Add window size args
|
|
||||||
if (fullScreen)
|
|
||||||
Collections.addAll(args, "--fullscreen", Boolean.toString(true));
|
|
||||||
if (width > 0 && height > 0) {
|
|
||||||
Collections.addAll(args, "--width", Integer.toString(width));
|
|
||||||
Collections.addAll(args, "--height", Integer.toString(height));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package pro.gravit.launcher.client;
|
||||||
|
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import pro.gravit.launcher.managers.GsonManager;
|
||||||
|
import pro.gravit.launcher.modules.events.PreGsonPhase;
|
||||||
|
import pro.gravit.launcher.request.websockets.ClientWebSocketService;
|
||||||
|
import pro.gravit.utils.UniversalJsonAdapter;
|
||||||
|
|
||||||
|
public class RuntimeGsonManager extends GsonManager {
|
||||||
|
private final RuntimeModuleManager moduleManager;
|
||||||
|
|
||||||
|
public RuntimeGsonManager(RuntimeModuleManager moduleManager) {
|
||||||
|
this.moduleManager = moduleManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerAdapters(GsonBuilder builder) {
|
||||||
|
super.registerAdapters(builder);
|
||||||
|
builder.registerTypeAdapter(UserSettings.class, new UniversalJsonAdapter<>(UserSettings.providers));
|
||||||
|
ClientWebSocketService.appendTypeAdapters(builder);
|
||||||
|
moduleManager.invokeEvent(new PreGsonPhase(builder));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package pro.gravit.launcher.client;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.modules.LauncherInitContext;
|
||||||
|
import pro.gravit.launcher.modules.LauncherModule;
|
||||||
|
import pro.gravit.launcher.modules.LauncherModuleInfo;
|
||||||
|
import pro.gravit.utils.Version;
|
||||||
|
|
||||||
|
public class RuntimeLauncherCoreModule extends LauncherModule {
|
||||||
|
public RuntimeLauncherCoreModule() {
|
||||||
|
super(new LauncherModuleInfo("ClientLauncherCore", Version.getVersion()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(LauncherInitContext initContext) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +0,0 @@
|
||||||
package pro.gravit.launcher.client.events.client;
|
|
||||||
|
|
||||||
import pro.gravit.launcher.LauncherEngine;
|
|
||||||
import pro.gravit.launcher.client.ClientLauncherProcess;
|
|
||||||
import pro.gravit.launcher.modules.events.InitPhase;
|
|
||||||
|
|
||||||
public class ClientProcessInitPhase extends InitPhase {
|
|
||||||
public final LauncherEngine clientInstance;
|
|
||||||
public final ClientLauncherProcess.ClientParams params;
|
|
||||||
|
|
||||||
public ClientProcessInitPhase(LauncherEngine clientInstance, ClientLauncherProcess.ClientParams params) {
|
|
||||||
this.clientInstance = clientInstance;
|
|
||||||
this.params = params;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
package pro.gravit.launcher.client.events.client;
|
|
||||||
|
|
||||||
import pro.gravit.launcher.LauncherEngine;
|
|
||||||
import pro.gravit.launcher.client.ClientLauncherProcess;
|
|
||||||
import pro.gravit.launcher.modules.LauncherModule;
|
|
||||||
|
|
||||||
public class ClientProcessLaunchEvent extends LauncherModule.Event {
|
|
||||||
public final LauncherEngine clientInstance;
|
|
||||||
public final ClientLauncherProcess.ClientParams params;
|
|
||||||
|
|
||||||
public ClientProcessLaunchEvent(LauncherEngine clientInstance, ClientLauncherProcess.ClientParams params) {
|
|
||||||
this.clientInstance = clientInstance;
|
|
||||||
this.params = params;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
package pro.gravit.launcher.client.events.client;
|
|
||||||
|
|
||||||
import pro.gravit.launcher.LauncherEngine;
|
|
||||||
import pro.gravit.launcher.client.ClientLauncherProcess;
|
|
||||||
import pro.gravit.launcher.modules.events.PostInitPhase;
|
|
||||||
|
|
||||||
public class ClientProcessReadyEvent extends PostInitPhase {
|
|
||||||
public final LauncherEngine clientInstance;
|
|
||||||
public final ClientLauncherProcess.ClientParams params;
|
|
||||||
|
|
||||||
public ClientProcessReadyEvent(LauncherEngine clientInstance, ClientLauncherProcess.ClientParams params) {
|
|
||||||
this.clientInstance = clientInstance;
|
|
||||||
this.params = params;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
package pro.gravit.launcher.debug;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.ClientPermissions;
|
||||||
|
import pro.gravit.launcher.LauncherEngine;
|
||||||
|
import pro.gravit.launcher.api.AuthService;
|
||||||
|
import pro.gravit.launcher.events.request.AuthRequestEvent;
|
||||||
|
import pro.gravit.launcher.events.request.ProfilesRequestEvent;
|
||||||
|
import pro.gravit.launcher.gui.RuntimeProvider;
|
||||||
|
import pro.gravit.launcher.profiles.ClientProfile;
|
||||||
|
import pro.gravit.launcher.request.Request;
|
||||||
|
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||||
|
import pro.gravit.launcher.request.update.ProfilesRequest;
|
||||||
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class ClientRuntimeProvider implements RuntimeProvider {
|
||||||
|
@Override
|
||||||
|
public void run(String[] args) {
|
||||||
|
ArrayList<String> newArgs = new ArrayList<>(Arrays.asList(args));
|
||||||
|
try {
|
||||||
|
String username = System.getProperty("launcher.runtime.username", null);
|
||||||
|
String uuid = System.getProperty("launcher.runtime.uuid", null);
|
||||||
|
String login = System.getProperty("launcher.runtime.login", username);
|
||||||
|
String password = System.getProperty("launcher.runtime.password", "Player");
|
||||||
|
String authId = System.getProperty("launcher.runtime.auth.authid", "std");
|
||||||
|
String accessToken = System.getProperty("launcher.runtime.auth.accesstoken", null);
|
||||||
|
String refreshToken = System.getProperty("launcher.runtime.auth.refreshtoken", null);
|
||||||
|
String minecraftAccessToken = System.getProperty("launcher.runtime.auth.minecraftaccesstoken", "DEBUG");
|
||||||
|
long expire = Long.parseLong(System.getProperty("launcher.runtime.auth.expire", "0"));
|
||||||
|
String profileUUID = System.getProperty("launcher.runtime.profileuuid", null);
|
||||||
|
String mainClass = System.getProperty("launcher.runtime.mainclass", null);
|
||||||
|
ClientPermissions permissions = new ClientPermissions();
|
||||||
|
if(mainClass == null) {
|
||||||
|
throw new NullPointerException("Add `-Dlauncher.runtime.mainclass=YOUR_MAIN_CLASS` to jvmArgs");
|
||||||
|
}
|
||||||
|
if(uuid == null) {
|
||||||
|
if(accessToken != null) {
|
||||||
|
Request.setOAuth(authId, new AuthRequestEvent.OAuthRequestEvent(accessToken, refreshToken, expire));
|
||||||
|
Request.RequestRestoreReport report = Request.restore(true, false);
|
||||||
|
permissions = report.userInfo.permissions;
|
||||||
|
username = report.userInfo.playerProfile.username;
|
||||||
|
uuid = report.userInfo.playerProfile.uuid.toString();
|
||||||
|
if(report.userInfo.accessToken != null) {
|
||||||
|
minecraftAccessToken = report.userInfo.accessToken;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
AuthRequest request = new AuthRequest(login, password, authId, AuthRequest.ConnectTypes.API);
|
||||||
|
AuthRequestEvent event = request.request();
|
||||||
|
Request.setOAuth(authId, event.oauth);
|
||||||
|
if(event.accessToken != null) {
|
||||||
|
minecraftAccessToken = event.accessToken;
|
||||||
|
}
|
||||||
|
username = event.playerProfile.username;
|
||||||
|
uuid = event.playerProfile.uuid.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(profileUUID != null) {
|
||||||
|
UUID profileUuid = UUID.fromString(profileUUID);
|
||||||
|
ProfilesRequest profiles = new ProfilesRequest();
|
||||||
|
ProfilesRequestEvent event = profiles.request();
|
||||||
|
for(ClientProfile profile : event.profiles) {
|
||||||
|
if(profile.getUUID().equals(profileUuid)) {
|
||||||
|
AuthService.profile = profile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(username == null) {
|
||||||
|
username = "Player";
|
||||||
|
}
|
||||||
|
if(uuid == null) {
|
||||||
|
uuid = "a7899336-e61c-4e51-b480-0c815b18aed8";
|
||||||
|
}
|
||||||
|
replaceOrCreateArgument(newArgs, "--username", username);
|
||||||
|
replaceOrCreateArgument(newArgs, "--uuid", uuid);
|
||||||
|
replaceOrCreateArgument(newArgs, "--accessToken", minecraftAccessToken);
|
||||||
|
AuthService.uuid = UUID.fromString(uuid);
|
||||||
|
AuthService.username = username;
|
||||||
|
AuthService.permissions = permissions;
|
||||||
|
Class<?> mainClazz = Class.forName(mainClass);
|
||||||
|
mainClazz.getMethod("main", String[].class).invoke(null, (Object) newArgs.toArray(new String[0]));
|
||||||
|
} catch (Throwable e) {
|
||||||
|
LogHelper.error(e);
|
||||||
|
LauncherEngine.exitLauncher(-15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void replaceOrCreateArgument(ArrayList<String> args, String name, String value) {
|
||||||
|
int index = args.indexOf(name);
|
||||||
|
if(index < 0) {
|
||||||
|
args.add(name);
|
||||||
|
if(value != null) {
|
||||||
|
args.add(value);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(value != null) {
|
||||||
|
int valueIndex = index+1;
|
||||||
|
args.set(valueIndex, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void preLoad() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(boolean clientInstance) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,11 @@
|
||||||
package pro.gravit.launcher.debug;
|
package pro.gravit.launcher.debug;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.ClientLauncherMethods;
|
||||||
import pro.gravit.launcher.Launcher;
|
import pro.gravit.launcher.Launcher;
|
||||||
import pro.gravit.launcher.LauncherConfig;
|
import pro.gravit.launcher.LauncherConfig;
|
||||||
import pro.gravit.launcher.LauncherEngine;
|
import pro.gravit.launcher.LauncherEngine;
|
||||||
import pro.gravit.launcher.client.ClientLauncherCoreModule;
|
import pro.gravit.launcher.client.RuntimeLauncherCoreModule;
|
||||||
import pro.gravit.launcher.client.ClientModuleManager;
|
import pro.gravit.launcher.client.RuntimeModuleManager;
|
||||||
import pro.gravit.launcher.managers.ConsoleManager;
|
import pro.gravit.launcher.managers.ConsoleManager;
|
||||||
import pro.gravit.launcher.modules.LauncherModule;
|
import pro.gravit.launcher.modules.LauncherModule;
|
||||||
import pro.gravit.launcher.modules.events.OfflineModeEvent;
|
import pro.gravit.launcher.modules.events.OfflineModeEvent;
|
||||||
|
@ -28,6 +29,7 @@ public class DebugMain {
|
||||||
public static String projectName = System.getProperty("launcherdebug.projectname", "Minecraft");
|
public static String projectName = System.getProperty("launcherdebug.projectname", "Minecraft");
|
||||||
public static String unlockSecret = System.getProperty("launcherdebug.unlocksecret", "");
|
public static String unlockSecret = System.getProperty("launcherdebug.unlocksecret", "");
|
||||||
public static boolean offlineMode = Boolean.getBoolean("launcherdebug.offlinemode");
|
public static boolean offlineMode = Boolean.getBoolean("launcherdebug.offlinemode");
|
||||||
|
public static boolean disableAutoRefresh = Boolean.getBoolean("launcherdebug.disableautorefresh");
|
||||||
public static String[] moduleClasses = System.getProperty("launcherdebug.modules", "").split(",");
|
public static String[] moduleClasses = System.getProperty("launcherdebug.modules", "").split(",");
|
||||||
public static String[] moduleFiles = System.getProperty("launcherdebug.modulefiles", "").split(",");
|
public static String[] moduleFiles = System.getProperty("launcherdebug.modulefiles", "").split(",");
|
||||||
public static LauncherConfig.LauncherEnvironment environment = LauncherConfig.LauncherEnvironment.valueOf(System.getProperty("launcherdebug.env", "STD"));
|
public static LauncherConfig.LauncherEnvironment environment = LauncherConfig.LauncherEnvironment.valueOf(System.getProperty("launcherdebug.env", "STD"));
|
||||||
|
@ -42,8 +44,8 @@ public static void main(String[] args) throws Throwable {
|
||||||
config.unlockSecret = unlockSecret;
|
config.unlockSecret = unlockSecret;
|
||||||
Launcher.setConfig(config);
|
Launcher.setConfig(config);
|
||||||
Launcher.applyLauncherEnv(environment);
|
Launcher.applyLauncherEnv(environment);
|
||||||
LauncherEngine.modulesManager = new ClientModuleManager();
|
LauncherEngine.modulesManager = new RuntimeModuleManager();
|
||||||
LauncherEngine.modulesManager.loadModule(new ClientLauncherCoreModule());
|
LauncherEngine.modulesManager.loadModule(new RuntimeLauncherCoreModule());
|
||||||
for (String moduleClassName : moduleClasses) {
|
for (String moduleClassName : moduleClasses) {
|
||||||
if (moduleClassName.isEmpty()) continue;
|
if (moduleClassName.isEmpty()) continue;
|
||||||
LauncherEngine.modulesManager.loadModule(newModule(moduleClassName));
|
LauncherEngine.modulesManager.loadModule(newModule(moduleClassName));
|
||||||
|
@ -59,7 +61,7 @@ public static void main(String[] args) throws Throwable {
|
||||||
RequestService service;
|
RequestService service;
|
||||||
if (offlineMode) {
|
if (offlineMode) {
|
||||||
OfflineRequestService offlineRequestService = new OfflineRequestService();
|
OfflineRequestService offlineRequestService = new OfflineRequestService();
|
||||||
LauncherEngine.applyBasicOfflineProcessors(offlineRequestService);
|
ClientLauncherMethods.applyBasicOfflineProcessors(offlineRequestService);
|
||||||
OfflineModeEvent event = new OfflineModeEvent(offlineRequestService);
|
OfflineModeEvent event = new OfflineModeEvent(offlineRequestService);
|
||||||
LauncherEngine.modulesManager.invokeEvent(event);
|
LauncherEngine.modulesManager.invokeEvent(event);
|
||||||
service = event.service;
|
service = event.service;
|
||||||
|
@ -67,9 +69,13 @@ public static void main(String[] args) throws Throwable {
|
||||||
service = StdWebSocketService.initWebSockets(webSocketURL).get();
|
service = StdWebSocketService.initWebSockets(webSocketURL).get();
|
||||||
}
|
}
|
||||||
Request.setRequestService(service);
|
Request.setRequestService(service);
|
||||||
|
if(!disableAutoRefresh) {
|
||||||
|
Request.startAutoRefresh();
|
||||||
|
}
|
||||||
LogHelper.debug("Initialization LauncherEngine");
|
LogHelper.debug("Initialization LauncherEngine");
|
||||||
LauncherEngine instance = LauncherEngine.newInstance(false);
|
LauncherEngine instance = LauncherEngine.newInstance(false, ClientRuntimeProvider.class);
|
||||||
instance.start(args);
|
instance.start(args);
|
||||||
|
LauncherEngine.exitLauncher(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
public class NoRuntimeProvider implements RuntimeProvider {
|
public class NoRuntimeProvider implements RuntimeProvider {
|
||||||
@Override
|
@Override
|
||||||
public void run(String[] args) {
|
public void run(String[] args) {
|
||||||
JOptionPane.showMessageDialog(null, "GUI часть лаунчера не найдена.\nС 5.1.0 вам необходимо самостоятельно установить модуль, отвечающий за GUI. Рантайм на JS более не поддерживается");
|
JOptionPane.showMessageDialog(null, "Модуль графического интерфейса лаунчера отсутствует");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -44,48 +44,4 @@ public void setConfig(NewLauncherSettings config) {
|
||||||
public NewLauncherSettings getDefaultConfig() {
|
public NewLauncherSettings getDefaultConfig() {
|
||||||
return new NewLauncherSettings();
|
return new NewLauncherSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadHDirStore(Path storePath) throws IOException {
|
|
||||||
Files.createDirectories(storePath);
|
|
||||||
IOHelper.walk(storePath, new StoreFileVisitor(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void saveHDirStore(Path storeProjectPath) throws IOException {
|
|
||||||
Files.createDirectories(storeProjectPath);
|
|
||||||
for (NewLauncherSettings.HashedStoreEntry e : settings.lastHDirs) {
|
|
||||||
if (!e.needSave) continue;
|
|
||||||
Path file = storeProjectPath.resolve(e.name.concat(".bin"));
|
|
||||||
if (!Files.exists(file)) Files.createFile(file);
|
|
||||||
try (HOutput output = new HOutput(IOHelper.newOutput(file))) {
|
|
||||||
output.writeString(e.name, 128);
|
|
||||||
output.writeString(e.fullPath, 1024);
|
|
||||||
e.hdir.write(output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loadHDirStore() throws IOException {
|
|
||||||
loadHDirStore(DirBridge.dirStore);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void saveHDirStore() throws IOException {
|
|
||||||
saveHDirStore(DirBridge.dirProjectStore);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class StoreFileVisitor extends SimpleFileVisitor<Path> {
|
|
||||||
@Override
|
|
||||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
|
|
||||||
throws IOException {
|
|
||||||
try (HInput input = new HInput(IOHelper.newInput(file))) {
|
|
||||||
String dirName = input.readString(128);
|
|
||||||
String fullPath = input.readString(1024);
|
|
||||||
HashedDir dir = new HashedDir(input);
|
|
||||||
settings.lastHDirs.add(new NewLauncherSettings.HashedStoreEntry(dir, dirName, fullPath));
|
|
||||||
} catch (IOException e) {
|
|
||||||
LogHelper.error("Skip file %s exception: %s", file.toAbsolutePath().toString(), e.getMessage());
|
|
||||||
}
|
|
||||||
return super.visitFile(file, attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package pro.gravit.launcher.utils;
|
package pro.gravit.launcher.utils;
|
||||||
|
|
||||||
import pro.gravit.launcher.AsyncDownloader;
|
|
||||||
import pro.gravit.launcher.LauncherEngine;
|
import pro.gravit.launcher.LauncherEngine;
|
||||||
import pro.gravit.launcher.LauncherInject;
|
import pro.gravit.launcher.LauncherInject;
|
||||||
import pro.gravit.launcher.request.update.LauncherRequest;
|
import pro.gravit.launcher.request.update.LauncherRequest;
|
||||||
|
@ -23,6 +22,8 @@
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static pro.gravit.launcher.modern.Downloader.makeSSLSocketFactory;
|
||||||
|
|
||||||
public class LauncherUpdater {
|
public class LauncherUpdater {
|
||||||
@LauncherInject("launcher.certificatePinning")
|
@LauncherInject("launcher.certificatePinning")
|
||||||
private static boolean isCertificatePinning;
|
private static boolean isCertificatePinning;
|
||||||
|
@ -49,7 +50,7 @@ public static Path prepareUpdate(URL url) throws Exception {
|
||||||
if (isCertificatePinning) {
|
if (isCertificatePinning) {
|
||||||
HttpsURLConnection connection1 = (HttpsURLConnection) connection;
|
HttpsURLConnection connection1 = (HttpsURLConnection) connection;
|
||||||
try {
|
try {
|
||||||
connection1.setSSLSocketFactory(AsyncDownloader.makeSSLSocketFactory());
|
connection1.setSSLSocketFactory(makeSSLSocketFactory());
|
||||||
} catch (NoSuchAlgorithmException | CertificateException | KeyStoreException | KeyManagementException e) {
|
} catch (NoSuchAlgorithmException | CertificateException | KeyStoreException | KeyManagementException e) {
|
||||||
throw new IOException(e);
|
throw new IOException(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,11 @@
|
||||||
import pro.gravit.utils.helper.IOHelper;
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
import pro.gravit.utils.helper.JVMHelper;
|
import pro.gravit.utils.helper.JVMHelper;
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
import pro.gravit.utils.helper.SecurityHelper;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.file.NoSuchFileException;
|
import java.nio.file.NoSuchFileException;
|
||||||
import java.security.spec.InvalidKeySpecException;
|
import java.security.spec.InvalidKeySpecException;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
@ -22,23 +20,9 @@ public final class Launcher {
|
||||||
|
|
||||||
// Authlib constants
|
// Authlib constants
|
||||||
|
|
||||||
public static final String SKIN_URL_PROPERTY = "skinURL";
|
|
||||||
|
|
||||||
public static final String SKIN_DIGEST_PROPERTY = "skinDigest";
|
|
||||||
|
|
||||||
public static final String SKIN_METADATA_PROPERTY = "skinMetadata";
|
|
||||||
|
|
||||||
public static final String CLOAK_URL_PROPERTY = "cloakURL";
|
|
||||||
|
|
||||||
public static final String CLOAK_DIGEST_PROPERTY = "cloakDigest";
|
|
||||||
|
|
||||||
public static final String CLOAK_METADATA_PROPERTY = "cloakMetadata";
|
|
||||||
|
|
||||||
|
|
||||||
// Used to determine from clientside is launched from launcher
|
// Used to determine from clientside is launched from launcher
|
||||||
public static final AtomicBoolean LAUNCHED = new AtomicBoolean(false);
|
public static final AtomicBoolean LAUNCHED = new AtomicBoolean(false);
|
||||||
public static final int PROTOCOL_MAGIC_LEGACY = 0x724724_00 + 24;
|
|
||||||
public static final int PROTOCOL_MAGIC = 0xA205B064; // e = 2.718281828
|
|
||||||
public static final String RUNTIME_DIR = "runtime";
|
public static final String RUNTIME_DIR = "runtime";
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
import pro.gravit.launcher.serialize.HInput;
|
import pro.gravit.launcher.serialize.HInput;
|
||||||
import pro.gravit.launcher.serialize.HOutput;
|
import pro.gravit.launcher.serialize.HOutput;
|
||||||
import pro.gravit.launcher.serialize.stream.StreamObject;
|
import pro.gravit.launcher.serialize.stream.StreamObject;
|
||||||
|
import pro.gravit.utils.helper.JVMHelper;
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
import pro.gravit.utils.helper.SecurityHelper;
|
import pro.gravit.utils.helper.SecurityHelper;
|
||||||
import pro.gravit.utils.helper.VerifyHelper;
|
import pro.gravit.utils.helper.VerifyHelper;
|
||||||
|
@ -21,7 +22,7 @@
|
||||||
public final class LauncherConfig extends StreamObject {
|
public final class LauncherConfig extends StreamObject {
|
||||||
@LauncherInject("launchercore.certificates")
|
@LauncherInject("launchercore.certificates")
|
||||||
private static final List<byte[]> secureConfigCertificates = null;
|
private static final List<byte[]> secureConfigCertificates = null;
|
||||||
@LauncherInject("launcher.modules")
|
@LauncherInject("launcher.legacymodules")
|
||||||
private static final List<Class<?>> modulesClasses = null;
|
private static final List<Class<?>> modulesClasses = null;
|
||||||
private static final MethodType VOID_TYPE = MethodType.methodType(void.class);
|
private static final MethodType VOID_TYPE = MethodType.methodType(void.class);
|
||||||
@LauncherInject("launcher.projectName")
|
@LauncherInject("launcher.projectName")
|
||||||
|
@ -51,6 +52,11 @@ public final class LauncherConfig extends StreamObject {
|
||||||
@LauncherInject("runtimeconfig.buildNumber")
|
@LauncherInject("runtimeconfig.buildNumber")
|
||||||
public long buildNumber;
|
public long buildNumber;
|
||||||
|
|
||||||
|
private static class ModernModulesClass {
|
||||||
|
@LauncherInject("launcher.modules")
|
||||||
|
private static final List<Class<?>> modulesClasses = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@LauncherInjectionConstructor
|
@LauncherInjectionConstructor
|
||||||
public LauncherConfig(HInput input) throws IOException, InvalidKeySpecException {
|
public LauncherConfig(HInput input) throws IOException, InvalidKeySpecException {
|
||||||
|
@ -114,6 +120,9 @@ public LauncherConfig(String address, Map<String, byte[]> runtime, String projec
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void initModules(LauncherModulesManager modulesManager) {
|
public static void initModules(LauncherModulesManager modulesManager) {
|
||||||
|
if(JVMHelper.JVM_VERSION >= 17) {
|
||||||
|
modulesClasses.addAll(ModernModulesClass.modulesClasses);
|
||||||
|
}
|
||||||
for (Class<?> clazz : modulesClasses)
|
for (Class<?> clazz : modulesClasses)
|
||||||
try {
|
try {
|
||||||
modulesManager.loadModule((LauncherModule) MethodHandles.publicLookup().findConstructor(clazz, VOID_TYPE).invokeWithArguments(Collections.emptyList()));
|
modulesManager.loadModule((LauncherModule) MethodHandles.publicLookup().findConstructor(clazz, VOID_TYPE).invokeWithArguments(Collections.emptyList()));
|
||||||
|
|
|
@ -41,7 +41,13 @@ default String toJsonString() {
|
||||||
default void loadConfig(Gson gson, Path configPath) throws IOException {
|
default void loadConfig(Gson gson, Path configPath) throws IOException {
|
||||||
if (generateConfigIfNotExists(configPath)) return;
|
if (generateConfigIfNotExists(configPath)) return;
|
||||||
try (BufferedReader reader = IOHelper.newReader(configPath)) {
|
try (BufferedReader reader = IOHelper.newReader(configPath)) {
|
||||||
setConfig(gson.fromJson(reader, getType()));
|
T value = gson.fromJson(reader, getType());
|
||||||
|
if(value == null) {
|
||||||
|
LogHelper.warning("Config %s is null", configPath);
|
||||||
|
resetConfig(configPath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setConfig(value);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogHelper.error(e);
|
LogHelper.error(e);
|
||||||
resetConfig(configPath);
|
resetConfig(configPath);
|
||||||
|
|
|
@ -4,4 +4,6 @@ public interface ExtendedTokenRequestEvent {
|
||||||
String getExtendedTokenName();
|
String getExtendedTokenName();
|
||||||
|
|
||||||
String getExtendedToken();
|
String getExtendedToken();
|
||||||
|
|
||||||
|
long getExtendedTokenExpire();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package pro.gravit.launcher.events.request;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.events.RequestEvent;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class AssetUploadInfoRequestEvent extends RequestEvent {
|
||||||
|
public Set<String> available;
|
||||||
|
public SlimSupportConf slimSupportConf;
|
||||||
|
|
||||||
|
public AssetUploadInfoRequestEvent(Set<String> available, SlimSupportConf slimSupportConf) {
|
||||||
|
this.available = available;
|
||||||
|
this.slimSupportConf = slimSupportConf;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "assetUploadInfo";
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum SlimSupportConf {
|
||||||
|
UNSUPPORTED, USER, SERVER
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package pro.gravit.launcher.events.request;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.events.RequestEvent;
|
||||||
|
|
||||||
|
public class GetAssetUploadUrlRequestEvent extends RequestEvent {
|
||||||
|
public static final String FEATURE_NAME = "assetupload";
|
||||||
|
public String url;
|
||||||
|
public AuthRequestEvent.OAuthRequestEvent token;
|
||||||
|
|
||||||
|
public GetAssetUploadUrlRequestEvent() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public GetAssetUploadUrlRequestEvent(String url, AuthRequestEvent.OAuthRequestEvent token) {
|
||||||
|
this.url = url;
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "getAssetUploadUrl";
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@
|
||||||
import pro.gravit.utils.TypeSerializeInterface;
|
import pro.gravit.utils.TypeSerializeInterface;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class GetAvailabilityAuthRequestEvent extends RequestEvent {
|
public class GetAvailabilityAuthRequestEvent extends RequestEvent {
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
|
@ -49,24 +50,14 @@ public static class AuthAvailability {
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
public boolean visible;
|
public boolean visible;
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
public String apiUrl;
|
public Set<String> features;
|
||||||
@LauncherNetworkAPI
|
|
||||||
public List<String> apiFeatures;
|
|
||||||
|
|
||||||
public AuthAvailability(String name, String displayName, boolean visible, List<AuthAvailabilityDetails> details) {
|
public AuthAvailability(List<AuthAvailabilityDetails> details, String name, String displayName, boolean visible, Set<String> features) {
|
||||||
this.name = name;
|
|
||||||
this.displayName = displayName;
|
|
||||||
this.visible = visible;
|
|
||||||
this.details = details;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AuthAvailability(String name, String displayName, boolean visible, List<AuthAvailabilityDetails> details, String apiUrl, List<String> apiFeatures) {
|
|
||||||
this.visible = visible;
|
|
||||||
this.details = details;
|
this.details = details;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.displayName = displayName;
|
this.displayName = displayName;
|
||||||
this.apiUrl = apiUrl;
|
this.visible = visible;
|
||||||
this.apiFeatures = apiFeatures;
|
this.features = features;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,37 @@
|
||||||
package pro.gravit.launcher.events.request;
|
package pro.gravit.launcher.events.request;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.events.ExtendedTokenRequestEvent;
|
||||||
import pro.gravit.launcher.events.RequestEvent;
|
import pro.gravit.launcher.events.RequestEvent;
|
||||||
|
|
||||||
public class HardwareReportRequestEvent extends RequestEvent {
|
public class HardwareReportRequestEvent extends RequestEvent implements ExtendedTokenRequestEvent {
|
||||||
public String extendedToken;
|
public String extendedToken;
|
||||||
|
public long expire;
|
||||||
|
|
||||||
public HardwareReportRequestEvent() {
|
public HardwareReportRequestEvent() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public HardwareReportRequestEvent(String extendedToken) {
|
public HardwareReportRequestEvent(String extendedToken, long expire) {
|
||||||
this.extendedToken = extendedToken;
|
this.extendedToken = extendedToken;
|
||||||
|
this.expire = expire;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getType() {
|
public String getType() {
|
||||||
return "hardwareReport";
|
return "hardwareReport";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getExtendedTokenName() {
|
||||||
|
return "hardware";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getExtendedToken() {
|
||||||
|
return extendedToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getExtendedTokenExpire() {
|
||||||
|
return expire;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
package pro.gravit.launcher.events.request;
|
package pro.gravit.launcher.events.request;
|
||||||
|
|
||||||
import pro.gravit.launcher.LauncherNetworkAPI;
|
import pro.gravit.launcher.LauncherNetworkAPI;
|
||||||
|
import pro.gravit.launcher.events.ExtendedTokenRequestEvent;
|
||||||
import pro.gravit.launcher.events.RequestEvent;
|
import pro.gravit.launcher.events.RequestEvent;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
||||||
public class LauncherRequestEvent extends RequestEvent {
|
public class LauncherRequestEvent extends RequestEvent implements ExtendedTokenRequestEvent {
|
||||||
public static final String LAUNCHER_EXTENDED_TOKEN_NAME = "launcher";
|
public static final String LAUNCHER_EXTENDED_TOKEN_NAME = "launcher";
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private static final UUID uuid = UUID.fromString("d54cc12a-4f59-4f23-9b10-f527fdd2e38f");
|
private static final UUID uuid = UUID.fromString("d54cc12a-4f59-4f23-9b10-f527fdd2e38f");
|
||||||
|
@ -19,6 +20,7 @@ public class LauncherRequestEvent extends RequestEvent {
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
public boolean needUpdate;
|
public boolean needUpdate;
|
||||||
public String launcherExtendedToken;
|
public String launcherExtendedToken;
|
||||||
|
public long launcherExtendedTokenExpire;
|
||||||
|
|
||||||
public LauncherRequestEvent(boolean needUpdate, String url) {
|
public LauncherRequestEvent(boolean needUpdate, String url) {
|
||||||
this.needUpdate = needUpdate;
|
this.needUpdate = needUpdate;
|
||||||
|
@ -30,10 +32,11 @@ public LauncherRequestEvent(boolean b, byte[] digest) {
|
||||||
this.digest = digest;
|
this.digest = digest;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LauncherRequestEvent(boolean needUpdate, String url, String launcherExtendedToken) {
|
public LauncherRequestEvent(boolean needUpdate, String url, String launcherExtendedToken, long expire) {
|
||||||
this.url = url;
|
this.url = url;
|
||||||
this.needUpdate = needUpdate;
|
this.needUpdate = needUpdate;
|
||||||
this.launcherExtendedToken = launcherExtendedToken;
|
this.launcherExtendedToken = launcherExtendedToken;
|
||||||
|
this.launcherExtendedTokenExpire = expire;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LauncherRequestEvent(byte[] binary, byte[] digest) { //Legacy support constructor
|
public LauncherRequestEvent(byte[] binary, byte[] digest) { //Legacy support constructor
|
||||||
|
@ -45,4 +48,19 @@ public LauncherRequestEvent(byte[] binary, byte[] digest) { //Legacy support con
|
||||||
public String getType() {
|
public String getType() {
|
||||||
return "launcher";
|
return "launcher";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getExtendedTokenName() {
|
||||||
|
return "launcher";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getExtendedToken() {
|
||||||
|
return launcherExtendedToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getExtendedTokenExpire() {
|
||||||
|
return launcherExtendedTokenExpire;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ public enum ReportAction {
|
||||||
LOGOUT,
|
LOGOUT,
|
||||||
TOKEN_EXPIRED,
|
TOKEN_EXPIRED,
|
||||||
EXIT,
|
EXIT,
|
||||||
|
@Deprecated
|
||||||
CRASH,
|
CRASH,
|
||||||
OTHER
|
OTHER
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
package pro.gravit.launcher.events.request;
|
package pro.gravit.launcher.events.request;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.events.ExtendedTokenRequestEvent;
|
||||||
import pro.gravit.launcher.events.RequestEvent;
|
import pro.gravit.launcher.events.RequestEvent;
|
||||||
|
|
||||||
public class VerifySecureLevelKeyRequestEvent extends RequestEvent {
|
public class VerifySecureLevelKeyRequestEvent extends RequestEvent implements ExtendedTokenRequestEvent {
|
||||||
public boolean needHardwareInfo;
|
public boolean needHardwareInfo;
|
||||||
public boolean onlyStatisticInfo;
|
public boolean onlyStatisticInfo;
|
||||||
public String extendedToken;
|
public String extendedToken;
|
||||||
public String hardwareExtendedToken;
|
public long expire;
|
||||||
|
|
||||||
public VerifySecureLevelKeyRequestEvent() {
|
public VerifySecureLevelKeyRequestEvent() {
|
||||||
}
|
}
|
||||||
|
@ -15,21 +16,30 @@ public VerifySecureLevelKeyRequestEvent(boolean needHardwareInfo) {
|
||||||
this.needHardwareInfo = needHardwareInfo;
|
this.needHardwareInfo = needHardwareInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public VerifySecureLevelKeyRequestEvent(boolean needHardwareInfo, boolean onlyStatisticInfo, String extendedToken) {
|
public VerifySecureLevelKeyRequestEvent(boolean needHardwareInfo, boolean onlyStatisticInfo, String extendedToken, long expire) {
|
||||||
this.needHardwareInfo = needHardwareInfo;
|
this.needHardwareInfo = needHardwareInfo;
|
||||||
this.onlyStatisticInfo = onlyStatisticInfo;
|
this.onlyStatisticInfo = onlyStatisticInfo;
|
||||||
this.extendedToken = extendedToken;
|
this.extendedToken = extendedToken;
|
||||||
}
|
this.expire = expire;
|
||||||
|
|
||||||
public VerifySecureLevelKeyRequestEvent(boolean needHardwareInfo, boolean onlyStatisticInfo, String extendedToken, String hardwareExtendedToken) {
|
|
||||||
this.needHardwareInfo = needHardwareInfo;
|
|
||||||
this.onlyStatisticInfo = onlyStatisticInfo;
|
|
||||||
this.extendedToken = extendedToken;
|
|
||||||
this.hardwareExtendedToken = hardwareExtendedToken;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getType() {
|
public String getType() {
|
||||||
return "verifySecureLevelKey";
|
return "verifySecureLevelKey";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getExtendedTokenName() {
|
||||||
|
return "publicKey";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getExtendedToken() {
|
||||||
|
return extendedToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getExtendedTokenExpire() {
|
||||||
|
return expire;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,4 +16,5 @@ private ClientProfileVersions() {
|
||||||
public static final ClientProfile.Version MINECRAFT_1_18 = ClientProfile.Version.of("1.18");
|
public static final ClientProfile.Version MINECRAFT_1_18 = ClientProfile.Version.of("1.18");
|
||||||
public static final ClientProfile.Version MINECRAFT_1_19 = ClientProfile.Version.of("1.19");
|
public static final ClientProfile.Version MINECRAFT_1_19 = ClientProfile.Version.of("1.19");
|
||||||
public static final ClientProfile.Version MINECRAFT_1_20 = ClientProfile.Version.of("1.20");
|
public static final ClientProfile.Version MINECRAFT_1_20 = ClientProfile.Version.of("1.20");
|
||||||
|
public static final ClientProfile.Version MINECRAFT_1_20_2 = ClientProfile.Version.of("1.20.2");
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,9 @@ public class OptionalFile {
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
public boolean limited;
|
public boolean limited;
|
||||||
|
|
||||||
|
@LauncherNetworkAPI
|
||||||
|
public String category;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
import pro.gravit.launcher.LauncherNetworkAPI;
|
import pro.gravit.launcher.LauncherNetworkAPI;
|
||||||
import pro.gravit.launcher.events.request.AuthRequestEvent;
|
import pro.gravit.launcher.events.request.AuthRequestEvent;
|
||||||
|
import pro.gravit.launcher.events.request.CurrentUserRequestEvent;
|
||||||
import pro.gravit.launcher.events.request.RefreshTokenRequestEvent;
|
import pro.gravit.launcher.events.request.RefreshTokenRequestEvent;
|
||||||
import pro.gravit.launcher.events.request.RestoreRequestEvent;
|
import pro.gravit.launcher.events.request.RestoreRequestEvent;
|
||||||
import pro.gravit.launcher.request.auth.RefreshTokenRequest;
|
import pro.gravit.launcher.request.auth.RefreshTokenRequest;
|
||||||
|
@ -11,32 +12,55 @@
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
public abstract class Request<R extends WebSocketEvent> implements WebSocketRequest {
|
public abstract class Request<R extends WebSocketEvent> implements WebSocketRequest {
|
||||||
private static final List<ExtendedTokenCallback> extendedTokenCallbacks = new ArrayList<>(4);
|
private static final List<ExtendedTokenCallback> extendedTokenCallbacks = new ArrayList<>(4);
|
||||||
private static final List<BiConsumer<String, AuthRequestEvent.OAuthRequestEvent>> oauthChangeHandlers = new ArrayList<>(4);
|
private static final List<BiConsumer<String, AuthRequestEvent.OAuthRequestEvent>> oauthChangeHandlers = new ArrayList<>(4);
|
||||||
@Deprecated
|
|
||||||
public static StdWebSocketService service;
|
private static volatile RequestService requestService;
|
||||||
private static RequestService requestService;
|
private static volatile AuthRequestEvent.OAuthRequestEvent oauth;
|
||||||
private static AuthRequestEvent.OAuthRequestEvent oauth;
|
private static volatile Map<String, ExtendedToken> extendedTokens;
|
||||||
private static Map<String, String> extendedTokens;
|
private static volatile String authId;
|
||||||
private static String authId;
|
private static volatile long tokenExpiredTime;
|
||||||
private static long tokenExpiredTime;
|
private static volatile ScheduledExecutorService executorService;
|
||||||
|
private static volatile boolean autoRefreshRunning;
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
public final UUID requestUUID = UUID.randomUUID();
|
public final UUID requestUUID = UUID.randomUUID();
|
||||||
private transient final AtomicBoolean started = new AtomicBoolean(false);
|
private transient final AtomicBoolean started = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
public static synchronized void startAutoRefresh() {
|
||||||
|
if(!autoRefreshRunning) {
|
||||||
|
if(executorService == null) {
|
||||||
|
executorService = Executors.newSingleThreadScheduledExecutor((t) -> {
|
||||||
|
Thread thread = new Thread(t);
|
||||||
|
thread.setName("AutoRefresh thread");
|
||||||
|
thread.setDaemon(true);
|
||||||
|
return thread;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
executorService.scheduleAtFixedRate(() -> {
|
||||||
|
try {
|
||||||
|
restore(false, true);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogHelper.error(e);
|
||||||
|
}
|
||||||
|
}, 5, 5, TimeUnit.SECONDS);
|
||||||
|
autoRefreshRunning = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static RequestService getRequestService() {
|
public static RequestService getRequestService() {
|
||||||
return requestService;
|
return requestService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setRequestService(RequestService service) {
|
public static void setRequestService(RequestService service) {
|
||||||
requestService = service;
|
requestService = service;
|
||||||
if (service instanceof StdWebSocketService) {
|
|
||||||
Request.service = (StdWebSocketService) service;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isAvailable() {
|
public static boolean isAvailable() {
|
||||||
|
@ -64,7 +88,7 @@ public static String getAuthId() {
|
||||||
return authId;
|
return authId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<String, String> getExtendedTokens() {
|
public static Map<String, ExtendedToken> getExtendedTokens() {
|
||||||
if (extendedTokens != null) {
|
if (extendedTokens != null) {
|
||||||
return Collections.unmodifiableMap(extendedTokens);
|
return Collections.unmodifiableMap(extendedTokens);
|
||||||
} else {
|
} else {
|
||||||
|
@ -72,22 +96,34 @@ public static Map<String, String> getExtendedTokens() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Map<String, String> getStringExtendedTokens() {
|
||||||
|
if(extendedTokens != null) {
|
||||||
|
Map<String, String> map = new HashMap<>();
|
||||||
|
for(Map.Entry<String, ExtendedToken> e : extendedTokens.entrySet()) {
|
||||||
|
map.put(e.getKey(), e.getValue().token);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void clearExtendedTokens() {
|
public static void clearExtendedTokens() {
|
||||||
if (extendedTokens != null) {
|
if (extendedTokens != null) {
|
||||||
extendedTokens.clear();
|
extendedTokens.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addExtendedToken(String name, String token) {
|
public static void addExtendedToken(String name, ExtendedToken token) {
|
||||||
if (extendedTokens == null) {
|
if (extendedTokens == null) {
|
||||||
extendedTokens = new HashMap<>();
|
extendedTokens = new ConcurrentHashMap<>();
|
||||||
}
|
}
|
||||||
extendedTokens.put(name, token);
|
extendedTokens.put(name, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addAllExtendedToken(Map<String, String> map) {
|
public static void addAllExtendedToken(Map<String, ExtendedToken> map) {
|
||||||
if (extendedTokens == null) {
|
if (extendedTokens == null) {
|
||||||
extendedTokens = new HashMap<>();
|
extendedTokens = new ConcurrentHashMap<>();
|
||||||
}
|
}
|
||||||
extendedTokens.putAll(map);
|
extendedTokens.putAll(map);
|
||||||
}
|
}
|
||||||
|
@ -117,11 +153,32 @@ public static String getRefreshToken() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void reconnect() throws Exception {
|
public static void reconnect() throws Exception {
|
||||||
service.open();
|
|
||||||
|
getRequestService().open();
|
||||||
restore();
|
restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RequestRestoreReport restore() throws Exception {
|
public static RequestRestoreReport restore() throws Exception {
|
||||||
|
return restore(false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized static Map<String, String> getExpiredExtendedTokens() {
|
||||||
|
if(extendedTokens == null) {
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
Set<String> set = new HashSet<>();
|
||||||
|
for(Map.Entry<String, ExtendedToken> e : extendedTokens.entrySet()) {
|
||||||
|
if(e.getValue().expire != 0 && e.getValue().expire < System.currentTimeMillis()) {
|
||||||
|
set.add(e.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(set.isEmpty()) {
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
return makeNewTokens(set);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static synchronized RequestRestoreReport restore(boolean needUserInfo, boolean refreshOnly) throws Exception {
|
||||||
boolean refreshed = false;
|
boolean refreshed = false;
|
||||||
RestoreRequest request;
|
RestoreRequest request;
|
||||||
if (oauth != null) {
|
if (oauth != null) {
|
||||||
|
@ -131,26 +188,18 @@ public static RequestRestoreReport restore() throws Exception {
|
||||||
setOAuth(authId, event.oauth);
|
setOAuth(authId, event.oauth);
|
||||||
refreshed = true;
|
refreshed = true;
|
||||||
}
|
}
|
||||||
request = new RestoreRequest(authId, oauth.accessToken, extendedTokens, false);
|
request = new RestoreRequest(authId, oauth.accessToken, refreshOnly ? getExpiredExtendedTokens() : getStringExtendedTokens(), needUserInfo);
|
||||||
} else {
|
} else {
|
||||||
request = new RestoreRequest(authId, null, extendedTokens, false);
|
request = new RestoreRequest(authId, null, refreshOnly ? getExpiredExtendedTokens() : getStringExtendedTokens(), false);
|
||||||
|
}
|
||||||
|
if(refreshOnly && (request.extended == null || request.extended.isEmpty())) {
|
||||||
|
return new RequestRestoreReport(refreshed, null, null);
|
||||||
}
|
}
|
||||||
RestoreRequestEvent event = request.request();
|
RestoreRequestEvent event = request.request();
|
||||||
List<String> invalidTokens = null;
|
List<String> invalidTokens = null;
|
||||||
if (event.invalidTokens != null && event.invalidTokens.size() > 0) {
|
if (event.invalidTokens != null && event.invalidTokens.size() > 0) {
|
||||||
boolean needRequest = false;
|
Map<String, String> tokens = makeNewTokens(event.invalidTokens);
|
||||||
Map<String, String> tokens = new HashMap<>();
|
if (!tokens.isEmpty()) {
|
||||||
for (ExtendedTokenCallback cb : extendedTokenCallbacks) {
|
|
||||||
for (String tokenName : event.invalidTokens) {
|
|
||||||
String newToken = cb.tryGetNewToken(tokenName);
|
|
||||||
if (newToken != null) {
|
|
||||||
needRequest = true;
|
|
||||||
tokens.put(tokenName, newToken);
|
|
||||||
addExtendedToken(tokenName, newToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (needRequest) {
|
|
||||||
request = new RestoreRequest(authId, null, tokens, false);
|
request = new RestoreRequest(authId, null, tokens, false);
|
||||||
event = request.request();
|
event = request.request();
|
||||||
if (event.invalidTokens != null && event.invalidTokens.size() > 0) {
|
if (event.invalidTokens != null && event.invalidTokens.size() > 0) {
|
||||||
|
@ -159,7 +208,21 @@ public static RequestRestoreReport restore() throws Exception {
|
||||||
}
|
}
|
||||||
invalidTokens = event.invalidTokens;
|
invalidTokens = event.invalidTokens;
|
||||||
}
|
}
|
||||||
return new RequestRestoreReport(false, refreshed, invalidTokens);
|
return new RequestRestoreReport(refreshed, invalidTokens, event.userInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized static Map<String, String> makeNewTokens(Collection<String> keys) {
|
||||||
|
Map<String, String> tokens = new HashMap<>();
|
||||||
|
for (ExtendedTokenCallback cb : extendedTokenCallbacks) {
|
||||||
|
for (String tokenName : keys) {
|
||||||
|
ExtendedToken newToken = cb.tryGetNewToken(tokenName);
|
||||||
|
if (newToken != null) {
|
||||||
|
tokens.put(tokenName, newToken.token);
|
||||||
|
addExtendedToken(tokenName, newToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void requestError(String message) throws RequestException {
|
public static void requestError(String message) throws RequestException {
|
||||||
|
@ -209,18 +272,29 @@ protected R requestDo(RequestService service) throws Exception {
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ExtendedTokenCallback {
|
public interface ExtendedTokenCallback {
|
||||||
String tryGetNewToken(String name);
|
ExtendedToken tryGetNewToken(String name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class RequestRestoreReport {
|
public static class RequestRestoreReport {
|
||||||
public final boolean legacySession;
|
|
||||||
public final boolean refreshed;
|
public final boolean refreshed;
|
||||||
public final List<String> invalidExtendedTokens;
|
public final List<String> invalidExtendedTokens;
|
||||||
|
public final CurrentUserRequestEvent.UserInfo userInfo;
|
||||||
|
|
||||||
public RequestRestoreReport(boolean legacySession, boolean refreshed, List<String> invalidExtendedTokens) {
|
public RequestRestoreReport(boolean refreshed, List<String> invalidExtendedTokens, CurrentUserRequestEvent.UserInfo userInfo) {
|
||||||
this.legacySession = legacySession;
|
|
||||||
this.refreshed = refreshed;
|
this.refreshed = refreshed;
|
||||||
this.invalidExtendedTokens = invalidExtendedTokens;
|
this.invalidExtendedTokens = invalidExtendedTokens;
|
||||||
|
this.userInfo = userInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ExtendedToken {
|
||||||
|
public final String token;
|
||||||
|
public final long expire;
|
||||||
|
|
||||||
|
public ExtendedToken(String token, long expire) {
|
||||||
|
this.token = token;
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
|
this.expire = expire < time/2 ? time+expire : expire;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
public interface RequestService {
|
public interface RequestService {
|
||||||
<T extends WebSocketEvent> CompletableFuture<T> request(Request<T> request) throws IOException;
|
<T extends WebSocketEvent> CompletableFuture<T> request(Request<T> request) throws IOException;
|
||||||
|
void open() throws Exception;
|
||||||
|
|
||||||
void registerEventHandler(EventHandler handler);
|
void registerEventHandler(EventHandler handler);
|
||||||
|
|
||||||
|
|
|
@ -6,12 +6,16 @@
|
||||||
import pro.gravit.launcher.request.websockets.WebSocketRequest;
|
import pro.gravit.launcher.request.websockets.WebSocketRequest;
|
||||||
import pro.gravit.utils.helper.VerifyHelper;
|
import pro.gravit.utils.helper.VerifyHelper;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public final class JoinServerRequest extends Request<JoinServerRequestEvent> implements WebSocketRequest {
|
public final class JoinServerRequest extends Request<JoinServerRequestEvent> implements WebSocketRequest {
|
||||||
|
|
||||||
// Instance
|
// Instance
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
public final String username;
|
public final String username;
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
|
public final UUID uuid;
|
||||||
|
@LauncherNetworkAPI
|
||||||
public final String accessToken;
|
public final String accessToken;
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
public final String serverID;
|
public final String serverID;
|
||||||
|
@ -19,10 +23,18 @@ public final class JoinServerRequest extends Request<JoinServerRequestEvent> imp
|
||||||
|
|
||||||
public JoinServerRequest(String username, String accessToken, String serverID) {
|
public JoinServerRequest(String username, String accessToken, String serverID) {
|
||||||
this.username = username;
|
this.username = username;
|
||||||
|
this.uuid = null;
|
||||||
this.accessToken = accessToken;
|
this.accessToken = accessToken;
|
||||||
this.serverID = VerifyHelper.verifyServerID(serverID);
|
this.serverID = VerifyHelper.verifyServerID(serverID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JoinServerRequest(UUID uuid, String accessToken, String serverID) {
|
||||||
|
this.username = null;
|
||||||
|
this.uuid = uuid;
|
||||||
|
this.accessToken = accessToken;
|
||||||
|
this.serverID = serverID;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getType() {
|
public String getType() {
|
||||||
return "joinServer";
|
return "joinServer";
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package pro.gravit.launcher.request.cabinet;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.events.request.AssetUploadInfoRequestEvent;
|
||||||
|
import pro.gravit.launcher.request.Request;
|
||||||
|
|
||||||
|
public class AssetUploadInfoRequest extends Request<AssetUploadInfoRequestEvent> {
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "assetUploadInfo";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package pro.gravit.launcher.request.cabinet;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.events.request.GetAssetUploadUrlRequestEvent;
|
||||||
|
import pro.gravit.launcher.request.Request;
|
||||||
|
|
||||||
|
public class GetAssetUploadUrl extends Request<GetAssetUploadUrlRequestEvent> {
|
||||||
|
public String name;
|
||||||
|
|
||||||
|
public GetAssetUploadUrl() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public GetAssetUploadUrl(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "getAssetUploadUrl";
|
||||||
|
}
|
||||||
|
}
|
|
@ -111,6 +111,8 @@ public void registerResults() {
|
||||||
results.register("additionalData", AdditionalDataRequestEvent.class);
|
results.register("additionalData", AdditionalDataRequestEvent.class);
|
||||||
results.register("clientProfileKey", FetchClientProfileKeyRequestEvent.class);
|
results.register("clientProfileKey", FetchClientProfileKeyRequestEvent.class);
|
||||||
results.register("getPublicKey", GetPublicKeyRequestEvent.class);
|
results.register("getPublicKey", GetPublicKeyRequestEvent.class);
|
||||||
|
results.register("getAssetUploadUrl", GetAssetUploadUrlRequestEvent.class);
|
||||||
|
results.register("assetUploadInfo", AssetUploadInfoRequestEvent.class);
|
||||||
resultsRegistered = true;
|
resultsRegistered = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,11 @@ public <T extends WebSocketEvent> CompletableFuture<T> request(Request<T> reques
|
||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void open() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerEventHandler(EventHandler handler) {
|
public void registerEventHandler(EventHandler handler) {
|
||||||
eventHandlers.add(handler);
|
eventHandlers.add(handler);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue