mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-12-23 17:11:39 +03:00
Compare commits
No commits in common. "3b8c01835dd517b292fe7a48a987b9c38a9943db" and "c6f8793031e5176be9bd483417b3362b3381beee" have entirely different histories.
3b8c01835d
...
c6f8793031
184 changed files with 2532 additions and 662 deletions
|
@ -50,18 +50,17 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register('sourcesJar', Jar) {
|
task sourcesJar(type: Jar) {
|
||||||
from sourceSets.main.allJava
|
from sourceSets.main.allJava
|
||||||
archiveClassifier.set('sources')
|
archiveClassifier.set('sources')
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register('javadocJar', Jar) {
|
task javadocJar(type: Jar) {
|
||||||
from javadoc
|
from javadoc
|
||||||
archiveClassifier.set('javadoc')
|
archiveClassifier.set('javadoc')
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register('cleanjar', Jar) {
|
task cleanjar(type: Jar, dependsOn: jar) {
|
||||||
dependsOn jar
|
|
||||||
archiveClassifier.set('clean')
|
archiveClassifier.set('clean')
|
||||||
manifest.attributes("Main-Class": mainClassName,
|
manifest.attributes("Main-Class": mainClassName,
|
||||||
"Premain-Class": mainAgentName,
|
"Premain-Class": mainAgentName,
|
||||||
|
@ -118,13 +117,13 @@ pack project(':LauncherAPI')
|
||||||
compileOnlyA 'org.apache.logging.log4j:log4j-core:2.14.1'
|
compileOnlyA 'org.apache.logging.log4j:log4j-core:2.14.1'
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register('hikari', Copy) {
|
task hikari(type: Copy) {
|
||||||
duplicatesStrategy = 'EXCLUDE'
|
duplicatesStrategy = 'EXCLUDE'
|
||||||
into "$buildDir/libs/libraries/hikaricp"
|
into "$buildDir/libs/libraries/hikaricp"
|
||||||
from configurations.hikari
|
from configurations.hikari
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register('launch4j', Copy) {
|
task launch4j(type: Copy) {
|
||||||
duplicatesStrategy = 'EXCLUDE'
|
duplicatesStrategy = 'EXCLUDE'
|
||||||
into "$buildDir/libs/libraries/launch4j"
|
into "$buildDir/libs/libraries/launch4j"
|
||||||
from(configurations.launch4j.collect {
|
from(configurations.launch4j.collect {
|
||||||
|
@ -142,20 +141,20 @@ pack project(':LauncherAPI')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register('dumpLibs', Copy) {
|
task dumpLibs(type: Copy) {
|
||||||
duplicatesStrategy = 'EXCLUDE'
|
duplicatesStrategy = 'EXCLUDE'
|
||||||
dependsOn tasks.hikari, tasks.launch4j
|
dependsOn tasks.hikari, tasks.launch4j
|
||||||
into "$buildDir/libs/libraries"
|
into "$buildDir/libs/libraries"
|
||||||
from configurations.bundleOnly
|
from configurations.bundleOnly
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register('dumpCompileOnlyLibs', Copy) {
|
task dumpCompileOnlyLibs(type: Copy) {
|
||||||
duplicatesStrategy = 'EXCLUDE'
|
duplicatesStrategy = 'EXCLUDE'
|
||||||
into "$buildDir/libs/launcher-libraries-compile"
|
into "$buildDir/libs/launcher-libraries-compile"
|
||||||
from configurations.compileOnlyA
|
from configurations.compileOnlyA
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register('bundle', Zip) {
|
task bundle(type: Zip) {
|
||||||
duplicatesStrategy = 'EXCLUDE'
|
duplicatesStrategy = 'EXCLUDE'
|
||||||
dependsOn parent.childProjects.Launcher.tasks.build, tasks.dumpLibs, tasks.dumpCompileOnlyLibs, tasks.jar
|
dependsOn parent.childProjects.Launcher.tasks.build, tasks.dumpLibs, tasks.dumpCompileOnlyLibs, tasks.jar
|
||||||
archiveFileName = 'LaunchServer.zip'
|
archiveFileName = 'LaunchServer.zip'
|
||||||
|
@ -166,7 +165,7 @@ pack project(':LauncherAPI')
|
||||||
from(parent.childProjects.Launcher.tasks.dumpLibs) { into 'launcher-libraries' }
|
from(parent.childProjects.Launcher.tasks.dumpLibs) { into 'launcher-libraries' }
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register('dumpClientLibs', Copy) {
|
task dumpClientLibs(type: Copy) {
|
||||||
dependsOn parent.childProjects.Launcher.tasks.build
|
dependsOn parent.childProjects.Launcher.tasks.build
|
||||||
into "$buildDir/libs/launcher-libraries"
|
into "$buildDir/libs/launcher-libraries"
|
||||||
from parent.childProjects.Launcher.tasks.dumpLibs
|
from parent.childProjects.Launcher.tasks.dumpLibs
|
||||||
|
|
|
@ -121,6 +121,7 @@ public final class LaunchServer implements Runnable, AutoCloseable, Reconfigurab
|
||||||
// Updates and profiles
|
// Updates and profiles
|
||||||
private volatile Set<ClientProfile> profilesList;
|
private volatile Set<ClientProfile> profilesList;
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, LaunchServerConfig config, LaunchServerRuntimeConfig runtimeConfig, LaunchServerConfigManager launchServerConfigManager, LaunchServerModulesManager modulesManager, KeyAgreementManager keyAgreementManager, CommandHandler commandHandler, CertificateManager certificateManager) throws IOException {
|
public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, LaunchServerConfig config, LaunchServerRuntimeConfig runtimeConfig, LaunchServerConfigManager launchServerConfigManager, LaunchServerModulesManager modulesManager, KeyAgreementManager keyAgreementManager, CommandHandler commandHandler, CertificateManager certificateManager) throws IOException {
|
||||||
this.dir = directories.dir;
|
this.dir = directories.dir;
|
||||||
this.tmpDir = directories.tmpDir;
|
this.tmpDir = directories.tmpDir;
|
||||||
|
@ -218,14 +219,7 @@ public void reload(ReloadType type) throws Exception {
|
||||||
});
|
});
|
||||||
logger.debug("Init components successful");
|
logger.debug("Init components successful");
|
||||||
}
|
}
|
||||||
if(!type.equals(ReloadType.NO_AUTH)) {
|
|
||||||
nettyServerSocketHandler.nettyServer.service.forEachActiveChannels((channel, wsHandler) -> {
|
|
||||||
Client client = wsHandler.getClient();
|
|
||||||
if(client.auth != null) {
|
|
||||||
client.auth = config.getAuthProviderPair(client.auth_id);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -242,7 +236,7 @@ public void invoke(String... args) throws Exception {
|
||||||
case "full" -> reload(ReloadType.FULL);
|
case "full" -> reload(ReloadType.FULL);
|
||||||
case "no_auth" -> reload(ReloadType.NO_AUTH);
|
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.FULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
import pro.gravit.launchserver.manangers.LaunchServerGsonManager;
|
import pro.gravit.launchserver.manangers.LaunchServerGsonManager;
|
||||||
import pro.gravit.launchserver.modules.impl.LaunchServerModulesManager;
|
import pro.gravit.launchserver.modules.impl.LaunchServerModulesManager;
|
||||||
import pro.gravit.launchserver.socket.WebSocketService;
|
import pro.gravit.launchserver.socket.WebSocketService;
|
||||||
|
import pro.gravit.utils.Version;
|
||||||
import pro.gravit.utils.command.CommandHandler;
|
import pro.gravit.utils.command.CommandHandler;
|
||||||
import pro.gravit.utils.command.JLineCommandHandler;
|
import pro.gravit.utils.command.JLineCommandHandler;
|
||||||
import pro.gravit.utils.command.StdCommandHandler;
|
import pro.gravit.utils.command.StdCommandHandler;
|
||||||
|
@ -201,6 +202,7 @@ public static void initGson(LaunchServerModulesManager modulesManager) {
|
||||||
Launcher.gsonManager.initGson();
|
Launcher.gsonManager.initGson();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public static void registerAll() {
|
public static void registerAll() {
|
||||||
AuthCoreProvider.registerProviders();
|
AuthCoreProvider.registerProviders();
|
||||||
PasswordVerifier.registerProviders();
|
PasswordVerifier.registerProviders();
|
||||||
|
|
|
@ -65,7 +65,7 @@ private static void visit(ClassNode classNode, Map<String, Object> values) {
|
||||||
return newClinitMethod;
|
return newClinitMethod;
|
||||||
});
|
});
|
||||||
List<MethodNode> constructors = classNode.methods.stream().filter(method -> "<init>".equals(method.name))
|
List<MethodNode> constructors = classNode.methods.stream().filter(method -> "<init>".equals(method.name))
|
||||||
.toList();
|
.collect(Collectors.toList());
|
||||||
MethodNode initMethod = constructors.stream().filter(method -> method.invisibleAnnotations != null
|
MethodNode initMethod = constructors.stream().filter(method -> method.invisibleAnnotations != null
|
||||||
&& method.invisibleAnnotations.stream().anyMatch(annotation -> INJECTED_CONSTRUCTOR_DESC.equals(annotation.desc))).findFirst()
|
&& method.invisibleAnnotations.stream().anyMatch(annotation -> INJECTED_CONSTRUCTOR_DESC.equals(annotation.desc))).findFirst()
|
||||||
.orElseGet(() -> constructors.stream().filter(method -> method.desc.equals("()V")).findFirst().orElse(null));
|
.orElseGet(() -> constructors.stream().filter(method -> method.desc.equals("()V")).findFirst().orElse(null));
|
||||||
|
@ -112,7 +112,7 @@ public void visit(final String name, final Object value) {
|
||||||
}
|
}
|
||||||
List<FieldInsnNode> putStaticNodes = Arrays.stream(initMethod.instructions.toArray())
|
List<FieldInsnNode> putStaticNodes = Arrays.stream(initMethod.instructions.toArray())
|
||||||
.filter(node -> node instanceof FieldInsnNode && node.getOpcode() == Opcodes.PUTSTATIC).map(p -> (FieldInsnNode) p)
|
.filter(node -> node instanceof FieldInsnNode && node.getOpcode() == Opcodes.PUTSTATIC).map(p -> (FieldInsnNode) p)
|
||||||
.filter(node -> node.owner.equals(classNode.name) && node.name.equals(field.name) && node.desc.equals(field.desc)).toList();
|
.filter(node -> node.owner.equals(classNode.name) && node.name.equals(field.name) && node.desc.equals(field.desc)).collect(Collectors.toList());
|
||||||
InsnList setter = serializeValue(value);
|
InsnList setter = serializeValue(value);
|
||||||
if (putStaticNodes.isEmpty()) {
|
if (putStaticNodes.isEmpty()) {
|
||||||
setter.add(new FieldInsnNode(Opcodes.PUTSTATIC, classNode.name, field.name, field.desc));
|
setter.add(new FieldInsnNode(Opcodes.PUTSTATIC, classNode.name, field.name, field.desc));
|
||||||
|
@ -130,7 +130,7 @@ public void visit(final String name, final Object value) {
|
||||||
}
|
}
|
||||||
List<FieldInsnNode> putFieldNodes = Arrays.stream(initMethod.instructions.toArray())
|
List<FieldInsnNode> putFieldNodes = Arrays.stream(initMethod.instructions.toArray())
|
||||||
.filter(node -> node instanceof FieldInsnNode && node.getOpcode() == Opcodes.PUTFIELD).map(p -> (FieldInsnNode) p)
|
.filter(node -> node instanceof FieldInsnNode && node.getOpcode() == Opcodes.PUTFIELD).map(p -> (FieldInsnNode) p)
|
||||||
.filter(node -> node.owner.equals(classNode.name) && node.name.equals(field.name) && node.desc.equals(field.desc)).toList();
|
.filter(node -> node.owner.equals(classNode.name) && node.name.equals(field.name) && node.desc.equals(field.desc)).collect(Collectors.toList());
|
||||||
InsnList setter = serializeValue(value);
|
InsnList setter = serializeValue(value);
|
||||||
if (putFieldNodes.isEmpty()) {
|
if (putFieldNodes.isEmpty()) {
|
||||||
setter.insert(new VarInsnNode(Opcodes.ALOAD, 0));
|
setter.insert(new VarInsnNode(Opcodes.ALOAD, 0));
|
||||||
|
|
|
@ -3,12 +3,10 @@
|
||||||
import pro.gravit.launcher.events.request.AuthRequestEvent;
|
import pro.gravit.launcher.events.request.AuthRequestEvent;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Serial;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public final class AuthException extends IOException {
|
public final class AuthException extends IOException {
|
||||||
@Serial
|
|
||||||
private static final long serialVersionUID = -2586107832847245863L;
|
private static final long serialVersionUID = -2586107832847245863L;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
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.core.MySQLCoreProvider;
|
||||||
|
import pro.gravit.launchserver.auth.core.PostgresSQLCoreProvider;
|
||||||
import pro.gravit.launchserver.auth.texture.TextureProvider;
|
import pro.gravit.launchserver.auth.texture.TextureProvider;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -21,6 +23,7 @@ public final class AuthProviderPair {
|
||||||
public transient Set<String> features;
|
public transient Set<String> features;
|
||||||
public String displayName;
|
public String displayName;
|
||||||
public boolean visible = true;
|
public boolean visible = true;
|
||||||
|
private transient boolean warnOAuthShow = false;
|
||||||
|
|
||||||
public AuthProviderPair() {
|
public AuthProviderPair() {
|
||||||
}
|
}
|
||||||
|
@ -53,6 +56,15 @@ public static void getFeatures(Class<?> clazz, Set<String> list) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void internalShowOAuthWarnMessage() {
|
||||||
|
if (!warnOAuthShow) {
|
||||||
|
if (!(core instanceof MySQLCoreProvider) && !(core instanceof PostgresSQLCoreProvider)) { // MySQL and PostgreSQL upgraded later
|
||||||
|
logger.warn("AuthCoreProvider {} ({}) not supported OAuth. Legacy session system may be removed in next release", name, core.getClass().getName());
|
||||||
|
}
|
||||||
|
warnOAuthShow = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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 = null;
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public abstract class AbstractSQLCoreProvider extends AuthCoreProvider {
|
public abstract class AbstractSQLCoreProvider extends AuthCoreProvider {
|
||||||
public final transient Logger logger = LogManager.getLogger();
|
public transient Logger logger = LogManager.getLogger();
|
||||||
public int expireSeconds = 3600;
|
public int expireSeconds = 3600;
|
||||||
public String uuidColumn;
|
public String uuidColumn;
|
||||||
public String usernameColumn;
|
public String usernameColumn;
|
||||||
|
@ -208,7 +208,7 @@ protected String makeUserCols() {
|
||||||
return String.format("%s, %s, %s, %s, %s", uuidColumn, usernameColumn, accessTokenColumn, serverIDColumn, passwordColumn);
|
return String.format("%s, %s, %s, %s, %s", uuidColumn, usernameColumn, accessTokenColumn, serverIDColumn, passwordColumn);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void updateAuth(User user, String accessToken) throws IOException {
|
protected boolean updateAuth(User user, String accessToken) throws IOException {
|
||||||
try (Connection c = getSQLConfig().getConnection()) {
|
try (Connection c = getSQLConfig().getConnection()) {
|
||||||
SQLUser SQLUser = (SQLUser) user;
|
SQLUser SQLUser = (SQLUser) user;
|
||||||
SQLUser.accessToken = accessToken;
|
SQLUser.accessToken = accessToken;
|
||||||
|
@ -216,7 +216,7 @@ protected void updateAuth(User user, String accessToken) throws IOException {
|
||||||
s.setString(1, accessToken);
|
s.setString(1, accessToken);
|
||||||
s.setString(2, user.getUUID().toString());
|
s.setString(2, user.getUUID().toString());
|
||||||
s.setQueryTimeout(MySQLSourceConfig.TIMEOUT);
|
s.setQueryTimeout(MySQLSourceConfig.TIMEOUT);
|
||||||
s.executeUpdate();
|
return s.executeUpdate() > 0;
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new IOException(e);
|
throw new IOException(e);
|
||||||
}
|
}
|
||||||
|
@ -238,7 +238,7 @@ protected boolean updateServerID(User user, String serverID) throws IOException
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() throws IOException {
|
||||||
getSQLConfig().close();
|
getSQLConfig().close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,12 +299,12 @@ private List<String> queryRolesNames(String sql, String value) throws SQLExcepti
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class SQLUser implements User {
|
public static class SQLUser implements User {
|
||||||
protected final UUID uuid;
|
protected UUID uuid;
|
||||||
protected final String username;
|
protected String username;
|
||||||
protected String accessToken;
|
protected String accessToken;
|
||||||
protected String serverId;
|
protected String serverId;
|
||||||
protected final String password;
|
protected String password;
|
||||||
protected final ClientPermissions permissions;
|
protected ClientPermissions permissions;
|
||||||
|
|
||||||
public SQLUser(UUID uuid, String username, String accessToken, String serverId, String password, ClientPermissions permissions) {
|
public SQLUser(UUID uuid, String username, String accessToken, String serverId, String password, ClientPermissions permissions) {
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
|
|
|
@ -140,7 +140,7 @@ public void invoke(String... args) throws Exception {
|
||||||
if (instance != null) {
|
if (instance != null) {
|
||||||
map.put("getallusers", new SubCommand("(limit)", "print all users information") {
|
map.put("getallusers", new SubCommand("(limit)", "print all users information") {
|
||||||
@Override
|
@Override
|
||||||
public void invoke(String... args) {
|
public void invoke(String... args) throws Exception {
|
||||||
int max = Integer.MAX_VALUE;
|
int max = Integer.MAX_VALUE;
|
||||||
if (args.length > 0) max = Integer.parseInt(args[0]);
|
if (args.length > 0) max = Integer.parseInt(args[0]);
|
||||||
Iterable<User> users = instance.getAllUsers();
|
Iterable<User> users = instance.getAllUsers();
|
||||||
|
@ -316,7 +316,7 @@ public <T> T isSupport(Class<T> clazz) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public abstract void close();
|
public abstract void close() throws IOException;
|
||||||
|
|
||||||
public static class PasswordVerifyReport {
|
public static class PasswordVerifyReport {
|
||||||
public static final PasswordVerifyReport REQUIRED_2FA = new PasswordVerifyReport(-1);
|
public static final PasswordVerifyReport REQUIRED_2FA = new PasswordVerifyReport(-1);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package pro.gravit.launchserver.auth.core;
|
package pro.gravit.launchserver.auth.core;
|
||||||
|
|
||||||
|
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.ClientPermissions;
|
import pro.gravit.launcher.ClientPermissions;
|
||||||
|
@ -317,7 +318,7 @@ public void init(LaunchServer server) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() throws IOException {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,6 +525,10 @@ public class HttpUser implements User, UserSupportTextures, UserSupportPropertie
|
||||||
private String serverId;
|
private String serverId;
|
||||||
private String accessToken;
|
private String accessToken;
|
||||||
private ClientPermissions permissions;
|
private ClientPermissions permissions;
|
||||||
|
@Deprecated
|
||||||
|
private Texture skin;
|
||||||
|
@Deprecated
|
||||||
|
private Texture cloak;
|
||||||
private Map<String, Texture> assets;
|
private Map<String, Texture> assets;
|
||||||
private Map<String, String> properties;
|
private Map<String, String> properties;
|
||||||
private long hwidId;
|
private long hwidId;
|
||||||
|
@ -547,6 +552,8 @@ public HttpUser(String username, UUID uuid, String serverId, String accessToken,
|
||||||
this.serverId = serverId;
|
this.serverId = serverId;
|
||||||
this.accessToken = accessToken;
|
this.accessToken = accessToken;
|
||||||
this.permissions = permissions;
|
this.permissions = permissions;
|
||||||
|
this.skin = skin;
|
||||||
|
this.cloak = cloak;
|
||||||
this.hwidId = hwidId;
|
this.hwidId = hwidId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -556,6 +563,8 @@ public HttpUser(String username, UUID uuid, String serverId, String accessToken,
|
||||||
this.serverId = serverId;
|
this.serverId = serverId;
|
||||||
this.accessToken = accessToken;
|
this.accessToken = accessToken;
|
||||||
this.permissions = permissions;
|
this.permissions = permissions;
|
||||||
|
this.skin = skin;
|
||||||
|
this.cloak = cloak;
|
||||||
this.properties = properties;
|
this.properties = properties;
|
||||||
this.hwidId = hwidId;
|
this.hwidId = hwidId;
|
||||||
}
|
}
|
||||||
|
@ -598,17 +607,30 @@ public ClientPermissions getPermissions() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Texture getSkinTexture() {
|
public Texture getSkinTexture() {
|
||||||
|
if (assets == null) {
|
||||||
|
return skin;
|
||||||
|
}
|
||||||
return assets.get("SKIN");
|
return assets.get("SKIN");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Texture getCloakTexture() {
|
public Texture getCloakTexture() {
|
||||||
|
if (assets == null) {
|
||||||
|
return cloak;
|
||||||
|
}
|
||||||
return assets.get("CAPE");
|
return assets.get("CAPE");
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Texture> getAssets() {
|
public Map<String, Texture> getAssets() {
|
||||||
if (assets == null) {
|
if (assets == null) {
|
||||||
return new HashMap<>();
|
Map<String, Texture> map = new HashMap<>();
|
||||||
|
if (skin != null) {
|
||||||
|
map.put("SKIN", skin);
|
||||||
|
}
|
||||||
|
if (cloak != null) {
|
||||||
|
map.put("CAPE", cloak);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
}
|
}
|
||||||
return assets;
|
return assets;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ public User getUserByUUID(UUID uuid) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserSession getUserSessionByOAuthAccessToken(String accessToken) {
|
public UserSession getUserSessionByOAuthAccessToken(String accessToken) throws OAuthAccessTokenExpired {
|
||||||
synchronized (memory) {
|
synchronized (memory) {
|
||||||
for (MemoryUser u : memory) {
|
for (MemoryUser u : memory) {
|
||||||
if (u.accessToken.equals(accessToken)) {
|
if (u.accessToken.equals(accessToken)) {
|
||||||
|
@ -95,14 +95,14 @@ public AuthManager.AuthReport authorize(String login, AuthResponse.AuthContext c
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean updateServerID(User user, String serverID) {
|
protected boolean updateServerID(User user, String serverID) throws IOException {
|
||||||
MemoryUser memoryUser = (MemoryUser) user;
|
MemoryUser memoryUser = (MemoryUser) user;
|
||||||
memoryUser.serverId = serverID;
|
memoryUser.serverId = serverID;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public User checkServer(Client client, String username, String serverID) {
|
public User checkServer(Client client, String username, String serverID) throws IOException {
|
||||||
synchronized (memory) {
|
synchronized (memory) {
|
||||||
for (MemoryUser u : memory) {
|
for (MemoryUser u : memory) {
|
||||||
if (u.username.equals(username)) {
|
if (u.username.equals(username)) {
|
||||||
|
@ -116,7 +116,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, String accessToken, String serverID) throws IOException {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,16 +126,16 @@ public void init(LaunchServer server) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() throws IOException {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class MemoryUser implements User {
|
public static class MemoryUser implements User {
|
||||||
private final String username;
|
private String username;
|
||||||
private final UUID uuid;
|
private UUID uuid;
|
||||||
private String serverId;
|
private String serverId;
|
||||||
private final String accessToken;
|
private String accessToken;
|
||||||
private final ClientPermissions permissions;
|
private ClientPermissions permissions;
|
||||||
|
|
||||||
public MemoryUser(String username) {
|
public MemoryUser(String username) {
|
||||||
this.username = username;
|
this.username = username;
|
||||||
|
@ -188,9 +188,9 @@ public int hashCode() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class MemoryUserSession implements UserSession {
|
public static class MemoryUserSession implements UserSession {
|
||||||
private final String id;
|
private String id;
|
||||||
private final MemoryUser user;
|
private MemoryUser user;
|
||||||
private final long expireIn;
|
private long expireIn;
|
||||||
|
|
||||||
public MemoryUserSession(MemoryUser user) {
|
public MemoryUserSession(MemoryUser user) {
|
||||||
this.id = SecurityHelper.randomStringToken();
|
this.id = SecurityHelper.randomStringToken();
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
public class MergeAuthCoreProvider extends AuthCoreProvider {
|
public class MergeAuthCoreProvider extends AuthCoreProvider {
|
||||||
private transient final Logger logger = LogManager.getLogger(MergeAuthCoreProvider.class);
|
private transient final Logger logger = LogManager.getLogger(MergeAuthCoreProvider.class);
|
||||||
public List<String> list = new ArrayList<>();
|
public List<String> list = new ArrayList<>();
|
||||||
private final transient List<AuthCoreProvider> providers = new ArrayList<>();
|
private transient List<AuthCoreProvider> providers = new ArrayList<>();
|
||||||
@Override
|
@Override
|
||||||
public User getUserByUsername(String username) {
|
public User getUserByUsername(String username) {
|
||||||
for(var core : providers) {
|
for(var core : providers) {
|
||||||
|
@ -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, String accessToken, String serverID) throws IOException {
|
||||||
return false; // Authorization not supported
|
return false; // Authorization not supported
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ public void init(LaunchServer server) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() throws IOException {
|
||||||
// Providers closed automatically
|
// Providers closed automatically
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ public User getUserByUUID(UUID uuid) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserSession getUserSessionByOAuthAccessToken(String accessToken) {
|
public UserSession getUserSessionByOAuthAccessToken(String accessToken) throws OAuthAccessTokenExpired {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,12 +46,12 @@ public void init(LaunchServer server) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean updateServerID(User user, String serverID) {
|
protected boolean updateServerID(User user, String serverID) throws IOException {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() throws IOException {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
import pro.gravit.launchserver.auth.core.UserSession;
|
import pro.gravit.launchserver.auth.core.UserSession;
|
||||||
|
|
||||||
public interface AuthSupportExit extends AuthSupport {
|
public interface AuthSupportExit extends AuthSupport {
|
||||||
void deleteSession(UserSession session);
|
boolean deleteSession(UserSession session);
|
||||||
|
|
||||||
void exitUser(User user);
|
boolean exitUser(User user);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
|
||||||
public class JsonPasswordVerifier extends PasswordVerifier {
|
public class JsonPasswordVerifier extends PasswordVerifier {
|
||||||
private static final Logger logger = LogManager.getLogger();
|
private static transient final Logger logger = LogManager.getLogger();
|
||||||
private transient final HttpClient client = HttpClient.newBuilder().build();
|
private transient final HttpClient client = HttpClient.newBuilder().build();
|
||||||
public String url;
|
public String url;
|
||||||
public String bearerToken;
|
public String bearerToken;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
import pro.gravit.launchserver.auth.protect.interfaces.JoinServerProtectHandler;
|
import pro.gravit.launchserver.auth.protect.interfaces.JoinServerProtectHandler;
|
||||||
import pro.gravit.launchserver.auth.protect.interfaces.SecureProtectHandler;
|
import pro.gravit.launchserver.auth.protect.interfaces.SecureProtectHandler;
|
||||||
import pro.gravit.launchserver.socket.Client;
|
import pro.gravit.launchserver.socket.Client;
|
||||||
|
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
|
||||||
import pro.gravit.launchserver.socket.response.auth.RestoreResponse;
|
import pro.gravit.launchserver.socket.response.auth.RestoreResponse;
|
||||||
import pro.gravit.launchserver.socket.response.secure.HardwareReportResponse;
|
import pro.gravit.launchserver.socket.response.secure.HardwareReportResponse;
|
||||||
|
|
||||||
|
@ -26,6 +27,16 @@ public class AdvancedProtectHandler extends StdProtectHandler implements SecureP
|
||||||
public boolean enableHardwareFeature;
|
public boolean enableHardwareFeature;
|
||||||
private transient LaunchServer server;
|
private transient LaunchServer server;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean allowGetAccessToken(AuthResponse.AuthContext context) {
|
||||||
|
return (context.authType == AuthResponse.ConnectTypes.CLIENT) && context.client.checkSign;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkLaunchServerLicense() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GetSecureLevelInfoRequestEvent onGetSecureLevelInfo(GetSecureLevelInfoRequestEvent event) {
|
public GetSecureLevelInfoRequestEvent onGetSecureLevelInfo(GetSecureLevelInfoRequestEvent event) {
|
||||||
return event;
|
return event;
|
||||||
|
@ -62,9 +73,11 @@ public void onHardwareReport(HardwareReportResponse response, Client client) {
|
||||||
}
|
}
|
||||||
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)));
|
||||||
|
return;
|
||||||
} 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");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,6 +113,10 @@ public void init(LaunchServer server) {
|
||||||
this.server = server;
|
this.server = server;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
}
|
||||||
|
|
||||||
public String createHardwareToken(String username, UserHardware hardware) {
|
public String createHardwareToken(String username, UserHardware hardware) {
|
||||||
return Jwts.builder()
|
return Jwts.builder()
|
||||||
.setIssuer("LaunchServer")
|
.setIssuer("LaunchServer")
|
||||||
|
@ -121,10 +138,12 @@ public String createPublicKeyToken(String username, byte[] publicKey) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class HardwareInfoTokenVerifier implements RestoreResponse.ExtendedTokenProvider {
|
public static class HardwareInfoTokenVerifier implements RestoreResponse.ExtendedTokenProvider {
|
||||||
|
private transient final LaunchServer server;
|
||||||
private transient final Logger logger = LogManager.getLogger();
|
private transient final Logger logger = LogManager.getLogger();
|
||||||
private final JwtParser parser;
|
private final JwtParser parser;
|
||||||
|
|
||||||
public HardwareInfoTokenVerifier(LaunchServer server) {
|
public HardwareInfoTokenVerifier(LaunchServer server) {
|
||||||
|
this.server = server;
|
||||||
this.parser = Jwts.parserBuilder()
|
this.parser = Jwts.parserBuilder()
|
||||||
.requireIssuer("LaunchServer")
|
.requireIssuer("LaunchServer")
|
||||||
.setSigningKey(server.keyAgreementManager.ecdsaPublicKey)
|
.setSigningKey(server.keyAgreementManager.ecdsaPublicKey)
|
||||||
|
@ -153,10 +172,12 @@ public boolean accept(Client client, AuthProviderPair pair, String extendedToken
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class PublicKeyTokenVerifier implements RestoreResponse.ExtendedTokenProvider {
|
public static class PublicKeyTokenVerifier implements RestoreResponse.ExtendedTokenProvider {
|
||||||
|
private transient final LaunchServer server;
|
||||||
private transient final Logger logger = LogManager.getLogger();
|
private transient final Logger logger = LogManager.getLogger();
|
||||||
private final JwtParser parser;
|
private final JwtParser parser;
|
||||||
|
|
||||||
public PublicKeyTokenVerifier(LaunchServer server) {
|
public PublicKeyTokenVerifier(LaunchServer server) {
|
||||||
|
this.server = server;
|
||||||
this.parser = Jwts.parserBuilder()
|
this.parser = Jwts.parserBuilder()
|
||||||
.requireIssuer("LaunchServer")
|
.requireIssuer("LaunchServer")
|
||||||
.setSigningKey(server.keyAgreementManager.ecdsaPublicKey)
|
.setSigningKey(server.keyAgreementManager.ecdsaPublicKey)
|
||||||
|
|
|
@ -9,4 +9,8 @@ public boolean allowGetAccessToken(AuthResponse.AuthContext context) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkLaunchServerLicense() {
|
||||||
|
// None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ public static void registerHandlers() {
|
||||||
|
|
||||||
public abstract boolean allowGetAccessToken(AuthResponse.AuthContext context);
|
public abstract boolean allowGetAccessToken(AuthResponse.AuthContext context);
|
||||||
|
|
||||||
|
public abstract void checkLaunchServerLicense(); //Выдает SecurityException при ошибке проверки лицензии
|
||||||
|
|
||||||
public void init(LaunchServer server) {
|
public void init(LaunchServer server) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,11 @@ public boolean allowGetAccessToken(AuthResponse.AuthContext context) {
|
||||||
return (context.authType == AuthResponse.ConnectTypes.CLIENT) && context.client.checkSign;
|
return (context.authType == AuthResponse.ConnectTypes.CLIENT) && context.client.checkSign;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkLaunchServerLicense() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(LaunchServer server) {
|
public void init(LaunchServer server) {
|
||||||
if (profileWhitelist != null && profileWhitelist.size() > 0) {
|
if (profileWhitelist != null && profileWhitelist.size() > 0) {
|
||||||
|
@ -54,6 +59,7 @@ private boolean isWhitelisted(String property, ClientProfile profile, Client cli
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
List<String> allowedUsername = profileWhitelist.get(profile.getTitle());
|
List<String> allowedUsername = profileWhitelist.get(profile.getTitle());
|
||||||
return allowedUsername != null && allowedUsername.contains(client.username);
|
if (allowedUsername != null && allowedUsername.contains(client.username)) return true;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,24 +15,24 @@
|
||||||
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 transient static final Type MAP_TYPE = new TypeToken<Map<String, Texture>>() {
|
||||||
}.getType();
|
}.getType();
|
||||||
private transient final Logger logger = LogManager.getLogger();
|
private transient final Logger logger = LogManager.getLogger();
|
||||||
public String url;
|
public String url;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() throws IOException {
|
||||||
//None
|
//None
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Texture getCloakTexture(UUID uuid, String username, String client) {
|
public Texture getCloakTexture(UUID uuid, String username, String client) throws IOException {
|
||||||
logger.warn("Ineffective get cloak texture for {}", username);
|
logger.warn("Ineffective get cloak texture for {}", username);
|
||||||
return getAssets(uuid, username, client).get("CAPE");
|
return getAssets(uuid, username, client).get("CAPE");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Texture getSkinTexture(UUID uuid, String username, String client) {
|
public Texture getSkinTexture(UUID uuid, String username, String client) throws IOException {
|
||||||
logger.warn("Ineffective get skin texture for {}", username);
|
logger.warn("Ineffective get skin texture for {}", username);
|
||||||
return getAssets(uuid, username, client).get("SKIN");
|
return getAssets(uuid, username, client).get("SKIN");
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ public RequestTextureProvider(String skinURL, String cloakURL) {
|
||||||
|
|
||||||
private static Texture getTexture(String url, boolean cloak) throws IOException {
|
private static Texture getTexture(String url, boolean cloak) throws IOException {
|
||||||
try {
|
try {
|
||||||
return new Texture(url, cloak, null);
|
return new Texture(url, cloak);
|
||||||
} catch (FileNotFoundException ignored) {
|
} catch (FileNotFoundException ignored) {
|
||||||
return null; // Simply not found
|
return null; // Simply not found
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ private static Texture getTexture(String url, boolean cloak) throws IOException
|
||||||
|
|
||||||
private static Texture getTexture(String url, Path local, boolean cloak) throws IOException {
|
private static Texture getTexture(String url, Path local, boolean cloak) throws IOException {
|
||||||
try {
|
try {
|
||||||
return new Texture(url, local, cloak, null);
|
return new Texture(url, local, cloak);
|
||||||
} catch (FileNotFoundException ignored) {
|
} catch (FileNotFoundException ignored) {
|
||||||
return null; // Simply not found
|
return null; // Simply not found
|
||||||
}
|
}
|
||||||
|
@ -60,8 +60,7 @@ public Texture getCloakTexture(UUID uuid, String username, String client) throws
|
||||||
if (cloakLocalPath == null) {
|
if (cloakLocalPath == null) {
|
||||||
return getTexture(textureUrl, true);
|
return getTexture(textureUrl, true);
|
||||||
} else {
|
} else {
|
||||||
String path = getTextureURL(cloakLocalPath, uuid, username, client);
|
return getTexture(textureUrl, Paths.get(cloakLocalPath), true);
|
||||||
return getTexture(textureUrl, Paths.get(path), true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,8 +70,7 @@ public Texture getSkinTexture(UUID uuid, String username, String client) throws
|
||||||
if (skinLocalPath == null) {
|
if (skinLocalPath == null) {
|
||||||
return getTexture(textureUrl, false);
|
return getTexture(textureUrl, false);
|
||||||
} else {
|
} else {
|
||||||
String path = getTextureURL(skinLocalPath, uuid, username, client);
|
return getTexture(textureUrl, Paths.get(skinLocalPath), false);
|
||||||
return getTexture(textureUrl, Paths.get(path), false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,7 @@ 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);
|
if (isNeedDelete && deleteTempFiles) Files.deleteIfExists(oldPath);
|
||||||
isNeedDelete = task.allowDelete();
|
isNeedDelete = task.allowDelete();
|
||||||
logger.info("Task {} processed from {} millis", task.getName(), time_task);
|
logger.info("Task {} processed from {} millis", task.getName(), time_task);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
public final class JARLauncherBinary extends LauncherBinary {
|
public final class JARLauncherBinary extends LauncherBinary {
|
||||||
public final AtomicLong count;
|
public final AtomicLong count;
|
||||||
public final Path runtimeDir;
|
public final Path runtimeDir;
|
||||||
|
public final Path guardDir;
|
||||||
public final Path buildDir;
|
public final Path buildDir;
|
||||||
public final List<Path> coreLibs;
|
public final List<Path> coreLibs;
|
||||||
public final List<Path> addonLibs;
|
public final List<Path> addonLibs;
|
||||||
|
@ -26,6 +27,7 @@ public JARLauncherBinary(LaunchServer server) throws IOException {
|
||||||
super(server, resolve(server, ".jar"), "Launcher-%s-%d.jar");
|
super(server, resolve(server, ".jar"), "Launcher-%s-%d.jar");
|
||||||
count = new AtomicLong(0);
|
count = new AtomicLong(0);
|
||||||
runtimeDir = server.dir.resolve(Launcher.RUNTIME_DIR);
|
runtimeDir = server.dir.resolve(Launcher.RUNTIME_DIR);
|
||||||
|
guardDir = server.dir.resolve(Launcher.GUARD_DIR);
|
||||||
buildDir = server.dir.resolve("build");
|
buildDir = server.dir.resolve("build");
|
||||||
coreLibs = new ArrayList<>();
|
coreLibs = new ArrayList<>();
|
||||||
addonLibs = new ArrayList<>();
|
addonLibs = new ArrayList<>();
|
||||||
|
|
|
@ -4,9 +4,12 @@
|
||||||
import pro.gravit.utils.helper.IOHelper;
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipInputStream;
|
import java.util.zip.ZipInputStream;
|
||||||
import java.util.zip.ZipOutputStream;
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
|
@ -72,6 +72,7 @@ public Path process(Path inputJar) throws IOException {
|
||||||
} else {
|
} else {
|
||||||
context.pushDir(server.launcherBinary.runtimeDir, Launcher.RUNTIME_DIR, runtime, false);
|
context.pushDir(server.launcherBinary.runtimeDir, Launcher.RUNTIME_DIR, runtime, false);
|
||||||
}
|
}
|
||||||
|
context.pushDir(server.launcherBinary.guardDir, Launcher.GUARD_DIR, runtime, false);
|
||||||
|
|
||||||
LauncherConfig launcherConfig = new LauncherConfig(server.config.netty.address, server.keyAgreementManager.ecdsaPublicKey, server.keyAgreementManager.rsaPublicKey, runtime, server.config.projectName);
|
LauncherConfig launcherConfig = new LauncherConfig(server.config.netty.address, server.keyAgreementManager.ecdsaPublicKey, server.keyAgreementManager.rsaPublicKey, runtime, server.config.projectName);
|
||||||
context.pushFile(Launcher.CONFIG_FILE, launcherConfig);
|
context.pushFile(Launcher.CONFIG_FILE, launcherConfig);
|
||||||
|
@ -107,6 +108,7 @@ protected void initProps() {
|
||||||
properties.put("launcher.projectName", server.config.projectName);
|
properties.put("launcher.projectName", server.config.projectName);
|
||||||
properties.put("runtimeconfig.secretKeyClient", SecurityHelper.randomStringAESKey());
|
properties.put("runtimeconfig.secretKeyClient", SecurityHelper.randomStringAESKey());
|
||||||
properties.put("launcher.port", 32148 + SecurityHelper.newRandom().nextInt(512));
|
properties.put("launcher.port", 32148 + SecurityHelper.newRandom().nextInt(512));
|
||||||
|
properties.put("launcher.guardType", server.config.launcher.guardType);
|
||||||
properties.put("launchercore.env", server.config.env);
|
properties.put("launchercore.env", server.config.env);
|
||||||
properties.put("launcher.memory", server.config.launcher.memoryLimit);
|
properties.put("launcher.memory", server.config.launcher.memoryLimit);
|
||||||
properties.put("launcher.customJvmOptions", server.config.launcher.customJvmOptions);
|
properties.put("launcher.customJvmOptions", server.config.launcher.customJvmOptions);
|
||||||
|
@ -124,8 +126,7 @@ protected void initProps() {
|
||||||
properties.put("runtimeconfig.secureCheckSalt", launcherSalt);
|
properties.put("runtimeconfig.secureCheckSalt", launcherSalt);
|
||||||
if (server.runtime.unlockSecret == null) server.runtime.unlockSecret = SecurityHelper.randomStringToken();
|
if (server.runtime.unlockSecret == null) server.runtime.unlockSecret = SecurityHelper.randomStringToken();
|
||||||
properties.put("runtimeconfig.unlockSecret", server.runtime.unlockSecret);
|
properties.put("runtimeconfig.unlockSecret", server.runtime.unlockSecret);
|
||||||
server.runtime.buildNumber++;
|
|
||||||
properties.put("runtimeconfig.buildNumber", server.runtime.buildNumber);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] transformClass(byte[] bytes, String classname, BuildContext context) {
|
public byte[] transformClass(byte[] bytes, String classname, BuildContext context) {
|
||||||
|
|
|
@ -45,7 +45,7 @@ public Path process(Path inputFile) throws IOException {
|
||||||
throw new RuntimeException(ex);
|
throw new RuntimeException(ex);
|
||||||
}
|
}
|
||||||
})) {
|
})) {
|
||||||
var map = stream.collect(Collectors.toMap(k -> server.launcherPack.relativize(k).toString().replace("\\", "/"), (v) -> v));
|
var map = stream.collect(Collectors.toMap(k -> server.launcherPack.relativize(k).toString(), (v) -> v));
|
||||||
server.launcherBinary.files.putAll(map);
|
server.launcherBinary.files.putAll(map);
|
||||||
}
|
}
|
||||||
UnpackHelper.unpack(IOHelper.getResourceURL("Launcher.jar"), result);
|
UnpackHelper.unpack(IOHelper.getResourceURL("Launcher.jar"), result);
|
||||||
|
@ -60,6 +60,7 @@ public boolean allowDelete() {
|
||||||
|
|
||||||
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("guard.zip", server.launcherBinary.guardDir);
|
||||||
UnpackHelper.unpackZipNoCheck("runtime.zip", server.launcherBinary.runtimeDir);
|
UnpackHelper.unpackZipNoCheck("runtime.zip", server.launcherBinary.runtimeDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
public class SignJarTask implements LauncherBuildTask {
|
public class SignJarTask implements LauncherBuildTask {
|
||||||
|
|
||||||
private static final Logger logger = LogManager.getLogger();
|
private transient static final Logger logger = LogManager.getLogger();
|
||||||
private final LaunchServerConfig.JarSignerConf config;
|
private final LaunchServerConfig.JarSignerConf config;
|
||||||
private final LaunchServer srv;
|
private final LaunchServer srv;
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,8 @@
|
||||||
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.AsyncDownloader;
|
||||||
import pro.gravit.launcher.Launcher;
|
|
||||||
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.Downloader;
|
||||||
import pro.gravit.utils.command.CommandException;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
@ -32,13 +29,6 @@ public Command(Map<String, pro.gravit.utils.command.Command> childCommands, Laun
|
||||||
this.server = server;
|
this.server = server;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ClientProfile.Version parseClientVersion(String arg) throws CommandException {
|
|
||||||
if(arg.isEmpty()) {
|
|
||||||
throw new CommandException("ClientVersion can't be empty");
|
|
||||||
}
|
|
||||||
return Launcher.gsonManager.gson.fromJson(arg, ClientProfile.Version.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean showApplyDialog(String text) throws IOException {
|
protected boolean showApplyDialog(String text) throws IOException {
|
||||||
System.out.printf("%s [Y/N]:", text);
|
System.out.printf("%s [Y/N]:", text);
|
||||||
String response = server.commandHandler.readLine().toLowerCase(Locale.ROOT);
|
String response = server.commandHandler.readLine().toLowerCase(Locale.ROOT);
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
import pro.gravit.launchserver.command.Command;
|
import pro.gravit.launchserver.command.Command;
|
||||||
|
|
||||||
public class DebugCommand extends Command {
|
public class DebugCommand extends Command {
|
||||||
private final transient Logger logger = LogManager.getLogger();
|
private transient Logger logger = LogManager.getLogger();
|
||||||
|
|
||||||
public DebugCommand(LaunchServer server) {
|
public DebugCommand(LaunchServer server) {
|
||||||
super(server);
|
super(server);
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
import pro.gravit.utils.command.basic.HelpCommand;
|
import pro.gravit.utils.command.basic.HelpCommand;
|
||||||
|
|
||||||
public abstract class CommandHandler extends pro.gravit.utils.command.CommandHandler {
|
public abstract class CommandHandler extends pro.gravit.utils.command.CommandHandler {
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public static void registerCommands(pro.gravit.utils.command.CommandHandler handler, LaunchServer server) {
|
public static void registerCommands(pro.gravit.utils.command.CommandHandler handler, LaunchServer server) {
|
||||||
BaseCommandCategory basic = new BaseCommandCategory();
|
BaseCommandCategory basic = new BaseCommandCategory();
|
||||||
// Register basic commands
|
// Register basic commands
|
||||||
|
|
|
@ -43,7 +43,7 @@ public void invoke(String... args) throws Exception {
|
||||||
verifyArgs(args, 1);
|
verifyArgs(args, 1);
|
||||||
//Version version = Version.byName(args[0]);
|
//Version version = Version.byName(args[0]);
|
||||||
String versionName = args[0];
|
String versionName = args[0];
|
||||||
String dirName = IOHelper.verifyFileName(args.length > 1 ? args[1] : "assets");
|
String dirName = IOHelper.verifyFileName(args[1] != null ? args[1] : "assets");
|
||||||
String type = args.length > 2 ? args[2] : "mojang";
|
String type = args.length > 2 ? args[2] : "mojang";
|
||||||
Path assetDir = server.updatesDir.resolve(dirName);
|
Path assetDir = server.updatesDir.resolve(dirName);
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,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.profiles.ClientProfile;
|
import pro.gravit.launcher.profiles.ClientProfile;
|
||||||
import pro.gravit.launcher.profiles.ClientProfileVersions;
|
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
import pro.gravit.launchserver.command.Command;
|
import pro.gravit.launchserver.command.Command;
|
||||||
import pro.gravit.launchserver.helper.MakeProfileHelper;
|
import pro.gravit.launchserver.helper.MakeProfileHelper;
|
||||||
|
@ -82,9 +81,9 @@ public void invoke(String... args) throws IOException, CommandException {
|
||||||
if (internalVersion.contains("-")) {
|
if (internalVersion.contains("-")) {
|
||||||
internalVersion = internalVersion.substring(0, versionName.indexOf('-'));
|
internalVersion = internalVersion.substring(0, versionName.indexOf('-'));
|
||||||
}
|
}
|
||||||
ClientProfile.Version version = ClientProfile.Version.of(internalVersion);
|
ClientProfile.Version version = ClientProfile.Version.byName(internalVersion);
|
||||||
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_7_10) <= 0) {
|
if (version.compareTo(ClientProfile.Version.MC164) <= 0) {
|
||||||
logger.warn("Minecraft 1.7.9 and below not supported. Use at your own risk");
|
logger.warn("Minecraft 1.6.4 and below not supported. Use at your own risk");
|
||||||
}
|
}
|
||||||
MakeProfileHelper.MakeProfileOption[] options = MakeProfileHelper.getMakeProfileOptionsFromDir(clientDir, version, Files.exists(server.updatesDir.resolve("assets")));
|
MakeProfileHelper.MakeProfileOption[] options = MakeProfileHelper.getMakeProfileOptionsFromDir(clientDir, version, Files.exists(server.updatesDir.resolve("assets")));
|
||||||
for (MakeProfileHelper.MakeProfileOption option : options) {
|
for (MakeProfileHelper.MakeProfileOption option : options) {
|
||||||
|
|
|
@ -32,12 +32,12 @@ public String getUsageDescription() {
|
||||||
@Override
|
@Override
|
||||||
public void invoke(String... args) throws Exception {
|
public void invoke(String... args) throws Exception {
|
||||||
verifyArgs(args, 3);
|
verifyArgs(args, 3);
|
||||||
ClientProfile.Version version = parseClientVersion(args[1]);
|
ClientProfile.Version version = ClientProfile.Version.byName(args[1]);
|
||||||
MakeProfileHelper.MakeProfileOption[] options = MakeProfileHelper.getMakeProfileOptionsFromDir(server.updatesDir.resolve(args[2]), version, Files.exists(server.updatesDir.resolve("assets")));
|
MakeProfileHelper.MakeProfileOption[] options = MakeProfileHelper.getMakeProfileOptionsFromDir(server.updatesDir.resolve(args[2]), version, Files.exists(server.updatesDir.resolve("assets")));
|
||||||
for (MakeProfileHelper.MakeProfileOption option : options) {
|
for (MakeProfileHelper.MakeProfileOption option : options) {
|
||||||
logger.info("Detected option {}", option);
|
logger.info("Detected option {}", option);
|
||||||
}
|
}
|
||||||
ClientProfile profile = MakeProfileHelper.makeProfile(version, args[0], options);
|
ClientProfile profile = MakeProfileHelper.makeProfile(ClientProfile.Version.byName(args[1]), args[0], options);
|
||||||
try (Writer writer = IOHelper.newWriter(server.profilesDir.resolve(args[0].concat(".json")))) {
|
try (Writer writer = IOHelper.newWriter(server.profilesDir.resolve(args[0].concat(".json")))) {
|
||||||
Launcher.gsonManager.configGson.toJson(profile, writer);
|
Launcher.gsonManager.configGson.toJson(profile, writer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class SecurityCheckCommand extends Command {
|
public class SecurityCheckCommand extends Command {
|
||||||
private static final Logger logger = LogManager.getLogger();
|
private static transient final Logger logger = LogManager.getLogger();
|
||||||
|
|
||||||
public SecurityCheckCommand(LaunchServer server) {
|
public SecurityCheckCommand(LaunchServer server) {
|
||||||
super(server);
|
super(server);
|
||||||
|
@ -110,7 +110,7 @@ public void invoke(String... args) {
|
||||||
try {
|
try {
|
||||||
KeyStore keyStore = SignHelper.getStore(new File(config.sign.keyStore).toPath(), config.sign.keyStorePass, config.sign.keyStoreType);
|
KeyStore keyStore = SignHelper.getStore(new File(config.sign.keyStore).toPath(), config.sign.keyStorePass, config.sign.keyStoreType);
|
||||||
Certificate[] certChainPlain = keyStore.getCertificateChain(config.sign.keyAlias);
|
Certificate[] certChainPlain = keyStore.getCertificateChain(config.sign.keyAlias);
|
||||||
List<X509Certificate> certChain = Arrays.stream(certChainPlain).map(e -> (X509Certificate) e).toList();
|
List<X509Certificate> certChain = Arrays.stream(certChainPlain).map(e -> (X509Certificate) e).collect(Collectors.toList());
|
||||||
X509Certificate cert = certChain.get(0);
|
X509Certificate cert = certChain.get(0);
|
||||||
cert.checkValidity();
|
cert.checkValidity();
|
||||||
if (certChain.size() <= 1) {
|
if (certChain.size() <= 1) {
|
||||||
|
@ -169,7 +169,7 @@ public void invoke(String... args) {
|
||||||
bad = true;
|
bad = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (nextToken.equals("memory_repo") || nextToken.equals(profile.getVersion().toString())) {
|
if (nextToken.equals("memory_repo") || nextToken.equals(profile.getVersion().name)) {
|
||||||
printCheckResult(profileModuleName, String.format("updateExclusions %s not safe. Cheats may be injected very easy!", exc), false);
|
printCheckResult(profileModuleName, String.format("updateExclusions %s not safe. Cheats may be injected very easy!", exc), false);
|
||||||
bad = true;
|
bad = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ public void invoke(String... args) throws Exception {
|
||||||
Optional<SignJarTask> task = server.launcherBinary.getTaskByClass(SignJarTask.class);
|
Optional<SignJarTask> task = server.launcherBinary.getTaskByClass(SignJarTask.class);
|
||||||
if (task.isEmpty()) throw new IllegalStateException("SignJarTask not found");
|
if (task.isEmpty()) throw new IllegalStateException("SignJarTask not found");
|
||||||
task.get().sign(server.config.sign, target, tmpSign);
|
task.get().sign(server.config.sign, target, tmpSign);
|
||||||
if (args.length == 1) {
|
if (args.length <= 1) {
|
||||||
logger.info("Move temp jar {} to {}", tmpSign.toString(), target.toString());
|
logger.info("Move temp jar {} to {}", tmpSign.toString(), target.toString());
|
||||||
Files.deleteIfExists(target);
|
Files.deleteIfExists(target);
|
||||||
Files.move(tmpSign, target);
|
Files.move(tmpSign, target);
|
||||||
|
|
|
@ -25,7 +25,7 @@ public void invoke(String... args) throws Exception {
|
||||||
});
|
});
|
||||||
this.childCommands.put("server", new SubCommand("[profileName] (authId)", "generate new server token") {
|
this.childCommands.put("server", new SubCommand("[profileName] (authId)", "generate new server token") {
|
||||||
@Override
|
@Override
|
||||||
public void invoke(String... args) {
|
public void invoke(String... args) throws Exception {
|
||||||
AuthProviderPair pair = args.length > 1 ? server.config.getAuthProviderPair(args[1]) : server.config.getAuthProviderPair();
|
AuthProviderPair pair = args.length > 1 ? server.config.getAuthProviderPair(args[1]) : server.config.getAuthProviderPair();
|
||||||
ClientProfile profile = null;
|
ClientProfile profile = null;
|
||||||
for (ClientProfile p : server.getProfiles()) {
|
for (ClientProfile p : server.getProfiles()) {
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class ProGuardComponent extends Component implements AutoCloseable, Reconfigurable {
|
public class ProGuardComponent extends Component implements AutoCloseable, Reconfigurable {
|
||||||
private static final Logger logger = LogManager.getLogger();
|
private transient static final Logger logger = LogManager.getLogger();
|
||||||
public String modeAfter = "MainBuild";
|
public String modeAfter = "MainBuild";
|
||||||
public String dir = "proguard";
|
public String dir = "proguard";
|
||||||
public boolean enabled = true;
|
public boolean enabled = true;
|
||||||
|
@ -79,7 +79,7 @@ public void init(LaunchServer launchServer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() throws Exception {
|
||||||
if (launchServer != null && buildTask != null) {
|
if (launchServer != null && buildTask != null) {
|
||||||
launchServer.launcherBinary.tasks.remove(buildTask);
|
launchServer.launcherBinary.tasks.remove(buildTask);
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ public boolean hookJoin(JoinServerResponse response, Client client) throws HookE
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() throws Exception {
|
||||||
this.server.authHookManager.preHook.unregisterHook(this::hookAuth);
|
this.server.authHookManager.preHook.unregisterHook(this::hookAuth);
|
||||||
this.server.authHookManager.joinServerHook.unregisterHook(this::hookJoin);
|
this.server.authHookManager.joinServerHook.unregisterHook(this::hookJoin);
|
||||||
}
|
}
|
||||||
|
@ -82,14 +82,14 @@ public void invoke(String... args) throws Exception {
|
||||||
});
|
});
|
||||||
commands.put("disable", new SubCommand() {
|
commands.put("disable", new SubCommand() {
|
||||||
@Override
|
@Override
|
||||||
public void invoke(String... args) {
|
public void invoke(String... args) throws Exception {
|
||||||
enabled = false;
|
enabled = false;
|
||||||
logger.info("Whitelist disabled");
|
logger.info("Whitelist disabled");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
commands.put("enable", new SubCommand() {
|
commands.put("enable", new SubCommand() {
|
||||||
@Override
|
@Override
|
||||||
public void invoke(String... args) {
|
public void invoke(String... args) throws Exception {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
logger.info("Whitelist enabled");
|
logger.info("Whitelist enabled");
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
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 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;
|
||||||
|
@ -46,7 +45,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.3.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";
|
||||||
|
@ -85,6 +84,7 @@ public static LaunchServerConfig getDefault(LaunchServer.LaunchServerEnv env) {
|
||||||
newConfig.netty.performance.schedulerThread = 2;
|
newConfig.netty.performance.schedulerThread = 2;
|
||||||
|
|
||||||
newConfig.launcher = new LauncherConf();
|
newConfig.launcher = new LauncherConf();
|
||||||
|
newConfig.launcher.guardType = "no";
|
||||||
newConfig.launcher.compress = true;
|
newConfig.launcher.compress = true;
|
||||||
newConfig.launcher.deleteTempFiles = true;
|
newConfig.launcher.deleteTempFiles = true;
|
||||||
newConfig.launcher.stripLineNumbers = true;
|
newConfig.launcher.stripLineNumbers = true;
|
||||||
|
@ -107,8 +107,9 @@ public static LaunchServerConfig getDefault(LaunchServer.LaunchServerEnv env) {
|
||||||
return newConfig;
|
return newConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLaunchServer(LaunchServer server) {
|
public LaunchServerConfig setLaunchServer(LaunchServer server) {
|
||||||
this.server = server;
|
this.server = server;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuthProviderPair getAuthProviderPair(String name) {
|
public AuthProviderPair getAuthProviderPair(String name) {
|
||||||
|
@ -167,9 +168,12 @@ public void verify() {
|
||||||
boolean updateMirror = Boolean.getBoolean("launchserver.config.disableUpdateMirror");
|
boolean updateMirror = Boolean.getBoolean("launchserver.config.disableUpdateMirror");
|
||||||
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 ("https://mirror.gravit.pro/5.2.x/".equals(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 'https://mirror.gravit.pro/5.2.x/' to 'https://mirror.gravitlauncher.com/5.3.x/'. If you really need to use original url, use '-Dlaunchserver.config.disableUpdateMirror=true'");
|
||||||
mirrors[i] = "https://mirror.gravitlauncher.com/5.4.x/";
|
mirrors[i] = "https://mirror.gravitlauncher.com/5.3.x/";
|
||||||
|
} else if ("https://mirror.gravit.pro/5.3.x/".equals(mirrors[i])) {
|
||||||
|
logger.warn("Replace mirror 'https://mirror.gravit.pro/5.3.x/' to 'https://mirror.gravitlauncher.com/5.3.x/'. If you really need to use original url, use '-Dlaunchserver.config.disableUpdateMirror=true'");
|
||||||
|
mirrors[i] = "https://mirror.gravitlauncher.com/5.3.x/";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,6 +188,7 @@ public void init(LaunchServer.ReloadType type) {
|
||||||
if (protectHandler != null) {
|
if (protectHandler != null) {
|
||||||
server.registerObject("protectHandler", protectHandler);
|
server.registerObject("protectHandler", protectHandler);
|
||||||
protectHandler.init(server);
|
protectHandler.init(server);
|
||||||
|
protectHandler.checkLaunchServerLicense();
|
||||||
}
|
}
|
||||||
if (components != null) {
|
if (components != null) {
|
||||||
components.forEach((k, v) -> server.registerObject("component.".concat(k), v));
|
components.forEach((k, v) -> server.registerObject("component.".concat(k), v));
|
||||||
|
@ -264,6 +269,7 @@ public static class NettyUpdatesBind {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class LauncherConf {
|
public static class LauncherConf {
|
||||||
|
public String guardType;
|
||||||
public boolean compress;
|
public boolean compress;
|
||||||
public boolean stripLineNumbers;
|
public boolean stripLineNumbers;
|
||||||
public boolean deleteTempFiles;
|
public boolean deleteTempFiles;
|
||||||
|
|
|
@ -11,7 +11,6 @@ public class LaunchServerRuntimeConfig {
|
||||||
public String unlockSecret;
|
public String unlockSecret;
|
||||||
public String registerApiKey;
|
public String registerApiKey;
|
||||||
public String clientCheckSecret;
|
public String clientCheckSecret;
|
||||||
public long buildNumber;
|
|
||||||
|
|
||||||
public void verify() {
|
public void verify() {
|
||||||
if (passwordEncryptKey == null) logger.error("[RuntimeConfig] passwordEncryptKey must not be null");
|
if (passwordEncryptKey == null) logger.error("[RuntimeConfig] passwordEncryptKey must not be null");
|
||||||
|
@ -26,6 +25,5 @@ public void reset() {
|
||||||
runtimeEncryptKey = SecurityHelper.randomStringAESKey();
|
runtimeEncryptKey = SecurityHelper.randomStringAESKey();
|
||||||
registerApiKey = SecurityHelper.randomStringToken();
|
registerApiKey = SecurityHelper.randomStringToken();
|
||||||
clientCheckSecret = SecurityHelper.randomStringToken();
|
clientCheckSecret = SecurityHelper.randomStringToken();
|
||||||
buildNumber = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public final class HttpHelper {
|
public final class HttpHelper {
|
||||||
private static final Logger logger = LogManager.getLogger();
|
private static transient final Logger logger = LogManager.getLogger();
|
||||||
|
|
||||||
private HttpHelper() {
|
private HttpHelper() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
|
@ -37,7 +37,7 @@ public static <T, E> HttpOptional<T, E> send(HttpClient client, HttpRequest requ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T, E> CompletableFuture<HttpOptional<T, E>> sendAsync(HttpClient client, HttpRequest request, HttpErrorHandler<T, E> handler) {
|
public static <T, E> CompletableFuture<HttpOptional<T, E>> sendAsync(HttpClient client, HttpRequest request, HttpErrorHandler<T, E> handler) throws IOException {
|
||||||
return client.sendAsync(request, HttpResponse.BodyHandlers.ofInputStream()).thenApply(handler::apply);
|
return client.sendAsync(request, HttpResponse.BodyHandlers.ofInputStream()).thenApply(handler::apply);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import pro.gravit.launcher.profiles.ClientProfile;
|
import pro.gravit.launcher.profiles.ClientProfile;
|
||||||
import pro.gravit.launcher.profiles.ClientProfileBuilder;
|
import pro.gravit.launcher.profiles.ClientProfileBuilder;
|
||||||
import pro.gravit.launcher.profiles.ClientProfileVersions;
|
|
||||||
import pro.gravit.launcher.profiles.optional.OptionalFile;
|
import pro.gravit.launcher.profiles.optional.OptionalFile;
|
||||||
import pro.gravit.launcher.profiles.optional.actions.OptionalActionFile;
|
import pro.gravit.launcher.profiles.optional.actions.OptionalActionFile;
|
||||||
import pro.gravit.launcher.profiles.optional.actions.OptionalActionJvmArgs;
|
import pro.gravit.launcher.profiles.optional.actions.OptionalActionJvmArgs;
|
||||||
|
@ -17,14 +16,14 @@
|
||||||
public class MakeProfileHelper {
|
public class MakeProfileHelper {
|
||||||
public static ClientProfile makeProfile(ClientProfile.Version version, String title, MakeProfileOption... options) {
|
public static ClientProfile makeProfile(ClientProfile.Version version, String title, MakeProfileOption... options) {
|
||||||
ClientProfileBuilder builder = new ClientProfileBuilder();
|
ClientProfileBuilder builder = new ClientProfileBuilder();
|
||||||
builder.setVersion(version);
|
builder.setVersion(version.name);
|
||||||
builder.setDir(title);
|
builder.setDir(title);
|
||||||
if (findOption(options, MakeProfileOptionGlobalAssets.class).isPresent()) {
|
if (findOption(options, MakeProfileOptionGlobalAssets.class).isPresent()) {
|
||||||
builder.setAssetDir("assets");
|
builder.setAssetDir("assets");
|
||||||
} else {
|
} else {
|
||||||
builder.setAssetDir("asset" + version.toCleanString());
|
builder.setAssetDir("asset" + version.name);
|
||||||
}
|
}
|
||||||
builder.setAssetIndex(version.toString());
|
builder.setAssetIndex(version.name);
|
||||||
builder.setInfo("Информация о сервере");
|
builder.setInfo("Информация о сервере");
|
||||||
builder.setTitle(title);
|
builder.setTitle(title);
|
||||||
builder.setUuid(UUID.randomUUID());
|
builder.setUuid(UUID.randomUUID());
|
||||||
|
@ -36,7 +35,7 @@ public static ClientProfile makeProfile(ClientProfile.Version version, String ti
|
||||||
List<String> classPath = new ArrayList<>(5);
|
List<String> classPath = new ArrayList<>(5);
|
||||||
classPath.add("libraries");
|
classPath.add("libraries");
|
||||||
classPath.add("minecraft.jar");
|
classPath.add("minecraft.jar");
|
||||||
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_12_2) <= 0) {
|
if (version.compareTo(ClientProfile.Version.MC1122) <= 0) {
|
||||||
findOption(options, MakeProfileOptionForge.class).ifPresent(e -> classPath.add("forge.jar"));
|
findOption(options, MakeProfileOptionForge.class).ifPresent(e -> classPath.add("forge.jar"));
|
||||||
findOption(options, MakeProfileOptionLiteLoader.class).ifPresent(e -> classPath.add("liteloader.jar"));
|
findOption(options, MakeProfileOptionLiteLoader.class).ifPresent(e -> classPath.add("liteloader.jar"));
|
||||||
}
|
}
|
||||||
|
@ -47,21 +46,20 @@ public static ClientProfile makeProfile(ClientProfile.Version version, String ti
|
||||||
Set<OptionalFile> optionals = new HashSet<>();
|
Set<OptionalFile> optionals = new HashSet<>();
|
||||||
jvmArgs.add("-XX:+DisableAttachMechanism");
|
jvmArgs.add("-XX:+DisableAttachMechanism");
|
||||||
// Official Mojang launcher java arguments
|
// Official Mojang launcher java arguments
|
||||||
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_12_2) <= 0) {
|
if (version.compareTo(ClientProfile.Version.MC112) <= 0) {
|
||||||
jvmArgs.add("-XX:+UseConcMarkSweepGC");
|
jvmArgs.add("-XX:+UseConcMarkSweepGC");
|
||||||
jvmArgs.add("-XX:+CMSIncrementalMode");
|
jvmArgs.add("-XX:+CMSIncrementalMode");
|
||||||
} else if (version.compareTo(ClientProfileVersions.MINECRAFT_1_18) <= 0) { // 1.13 - 1.16.5
|
} else if (version.compareTo(ClientProfile.Version.MC118) <= 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 { // 1.18+
|
||||||
//jvmArgs.add("-XX:+UseShenandoahGC");
|
jvmArgs.add("-XX:+UseShenandoahGC");
|
||||||
//jvmArgs.add("-XX:+UnlockExperimentalVMOptions");
|
jvmArgs.add("-XX:+UnlockExperimentalVMOptions");
|
||||||
}
|
}
|
||||||
// -----------
|
// -----------
|
||||||
Optional<MakeProfileOptionForge> forge = findOption(options, MakeProfileOptionForge.class);
|
Optional<MakeProfileOptionForge> forge = findOption(options, MakeProfileOptionForge.class);
|
||||||
Optional<MakeProfileOptionFabric> fabric = findOption(options, MakeProfileOptionFabric.class);
|
Optional<MakeProfileOptionFabric> fabric = findOption(options, MakeProfileOptionFabric.class);
|
||||||
Optional<MakeProfilesOptionsQuilt> quilt = findOption(options, MakeProfilesOptionsQuilt.class);
|
if (version.compareTo(ClientProfile.Version.MC1122) > 0) {
|
||||||
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_12_2) > 0) {
|
|
||||||
jvmArgs.add("-Djava.library.path=natives");
|
jvmArgs.add("-Djava.library.path=natives");
|
||||||
OptionalFile optionalMacOs = new OptionalFile();
|
OptionalFile optionalMacOs = new OptionalFile();
|
||||||
optionalMacOs.name = "MacOSArgs";
|
optionalMacOs.name = "MacOSArgs";
|
||||||
|
@ -74,9 +72,6 @@ public static ClientProfile makeProfile(ClientProfile.Version version, String ti
|
||||||
if (fabric.isPresent()) {
|
if (fabric.isPresent()) {
|
||||||
builder.setAltClassPath(fabric.orElseThrow().getAltClassPath());
|
builder.setAltClassPath(fabric.orElseThrow().getAltClassPath());
|
||||||
}
|
}
|
||||||
if(quilt.isPresent()) {
|
|
||||||
builder.setClassLoaderConfig(ClientProfile.ClassLoaderConfig.SYSTEM_ARGS);
|
|
||||||
}
|
|
||||||
if (findOption(options, MakeProfileOptionLwjgl.class).isPresent()) {
|
if (findOption(options, MakeProfileOptionLwjgl.class).isPresent()) {
|
||||||
OptionalFile optionalMac = new OptionalFile();
|
OptionalFile optionalMac = new OptionalFile();
|
||||||
optionalMac.name = "MacLwjgl";
|
optionalMac.name = "MacLwjgl";
|
||||||
|
@ -117,16 +112,16 @@ public static ClientProfile makeProfile(ClientProfile.Version version, String ti
|
||||||
if (log4jOption.logFile != null) {
|
if (log4jOption.logFile != null) {
|
||||||
jvmArgs.add("-Dlog4j.configurationFile=".concat(logFile.get().logFile));
|
jvmArgs.add("-Dlog4j.configurationFile=".concat(logFile.get().logFile));
|
||||||
} else if (log4jOption.affected) {
|
} else if (log4jOption.affected) {
|
||||||
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_17) >= 0 && version.compareTo(ClientProfileVersions.MINECRAFT_1_18) < 0) {
|
if (version.compareTo(ClientProfile.Version.MC117) >= 0 && version.compareTo(ClientProfile.Version.MC118) < 0) {
|
||||||
jvmArgs.add("-Dlog4j2.formatMsgNoLookups=true");
|
jvmArgs.add("-Dlog4j2.formatMsgNoLookups=true");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_17) >= 0 && version.compareTo(ClientProfileVersions.MINECRAFT_1_18) < 0) {
|
if (version.compareTo(ClientProfile.Version.MC117) >= 0 && version.compareTo(ClientProfile.Version.MC118) < 0) {
|
||||||
builder.setMinJavaVersion(16);
|
builder.setMinJavaVersion(16);
|
||||||
builder.setRecommendJavaVersion(16);
|
builder.setRecommendJavaVersion(16);
|
||||||
}
|
}
|
||||||
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_18) >= 0) {
|
if (version.compareTo(ClientProfile.Version.MC118) >= 0) {
|
||||||
builder.setMinJavaVersion(17);
|
builder.setMinJavaVersion(17);
|
||||||
builder.setRecommendJavaVersion(17);
|
builder.setRecommendJavaVersion(17);
|
||||||
}
|
}
|
||||||
|
@ -142,22 +137,22 @@ public static ClientProfile makeProfile(ClientProfile.Version version, String ti
|
||||||
}
|
}
|
||||||
if (forge.isPresent()) {
|
if (forge.isPresent()) {
|
||||||
clientArgs.add("--tweakClass");
|
clientArgs.add("--tweakClass");
|
||||||
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_7_10) > 0) {
|
if (version.compareTo(ClientProfile.Version.MC1710) > 0) {
|
||||||
clientArgs.add("net.minecraftforge.fml.common.launcher.FMLTweaker");
|
clientArgs.add("net.minecraftforge.fml.common.launcher.FMLTweaker");
|
||||||
} else {
|
} else {
|
||||||
clientArgs.add("cpw.mods.fml.common.launcher.FMLTweaker");
|
clientArgs.add("cpw.mods.fml.common.launcher.FMLTweaker");
|
||||||
}
|
}
|
||||||
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_12_2) <= 0) {
|
if (version.compareTo(ClientProfile.Version.MC1122) <= 0) {
|
||||||
builder.setMinJavaVersion(8);
|
builder.setMinJavaVersion(8);
|
||||||
builder.setRecommendJavaVersion(8);
|
builder.setRecommendJavaVersion(8);
|
||||||
builder.setMaxJavaVersion(8);
|
builder.setMaxJavaVersion(8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (version.compareTo(ClientProfileVersions.MINECRAFT_1_12_2) > 0) {
|
} else if (version.compareTo(ClientProfile.Version.MC1122) > 0) {
|
||||||
if (forge.isPresent()) {
|
if (forge.isPresent()) {
|
||||||
clientArgs.addAll(forge.get().makeClientArgs());
|
clientArgs.addAll(forge.get().makeClientArgs());
|
||||||
builder.setClassLoaderConfig(ClientProfile.ClassLoaderConfig.SYSTEM_ARGS);
|
builder.setClassLoaderConfig(ClientProfile.ClassLoaderConfig.AGENT);
|
||||||
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_16_5) <= 0) {
|
if (version.compareTo(ClientProfile.Version.MC1165) <= 0) {
|
||||||
builder.setMaxJavaVersion(15);
|
builder.setMaxJavaVersion(15);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,15 +171,12 @@ public static String getMainClassByVersion(ClientProfile.Version version, MakePr
|
||||||
if (findOption(options, MakeProfileOptionLaunchWrapper.class).isPresent()) {
|
if (findOption(options, MakeProfileOptionLaunchWrapper.class).isPresent()) {
|
||||||
return "net.minecraft.launchwrapper.Launch";
|
return "net.minecraft.launchwrapper.Launch";
|
||||||
}
|
}
|
||||||
if (findOption(options, MakeProfileOptionForge.class).isPresent() && version.compareTo(ClientProfileVersions.MINECRAFT_1_12_2) > 0) {
|
if (findOption(options, MakeProfileOptionForge.class).isPresent() && version.compareTo(ClientProfile.Version.MC1122) > 0) {
|
||||||
return "cpw.mods.modlauncher.Launcher";
|
return "cpw.mods.modlauncher.Launcher";
|
||||||
}
|
}
|
||||||
if (findOption(options, MakeProfileOptionFabric.class).isPresent()) {
|
if (findOption(options, MakeProfileOptionFabric.class).isPresent()) {
|
||||||
return "net.fabricmc.loader.launch.knot.KnotClient";
|
return "net.fabricmc.loader.launch.knot.KnotClient";
|
||||||
}
|
}
|
||||||
if(findOption(options, MakeProfilesOptionsQuilt.class).isPresent()) {
|
|
||||||
return "org.quiltmc.loader.impl.launch.knot.KnotClient";
|
|
||||||
}
|
|
||||||
return "net.minecraft.client.main.Main";
|
return "net.minecraft.client.main.Main";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,7 +206,7 @@ public static MakeProfileOption[] getMakeProfileOptionsFromDir(Path dir, ClientP
|
||||||
if (Files.exists(dir.resolve("forge.jar"))) {
|
if (Files.exists(dir.resolve("forge.jar"))) {
|
||||||
options.add(new MakeProfileOptionForge());
|
options.add(new MakeProfileOptionForge());
|
||||||
} else if (Files.exists(dir.resolve("libraries/net/minecraftforge/forge"))) {
|
} else if (Files.exists(dir.resolve("libraries/net/minecraftforge/forge"))) {
|
||||||
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_12_2) > 0) {
|
if (version.compareTo(ClientProfile.Version.MC1122) > 0) {
|
||||||
options.add(new MakeProfileOptionForge(dir));
|
options.add(new MakeProfileOptionForge(dir));
|
||||||
} else {
|
} else {
|
||||||
options.add(new MakeProfileOptionForge());
|
options.add(new MakeProfileOptionForge());
|
||||||
|
@ -223,9 +215,6 @@ public static MakeProfileOption[] getMakeProfileOptionsFromDir(Path dir, ClientP
|
||||||
if (Files.exists(dir.resolve("libraries/net/fabricmc/fabric-loader"))) {
|
if (Files.exists(dir.resolve("libraries/net/fabricmc/fabric-loader"))) {
|
||||||
options.add(new MakeProfileOptionFabric(dir));
|
options.add(new MakeProfileOptionFabric(dir));
|
||||||
}
|
}
|
||||||
if (Files.exists(dir.resolve("libraries/org/quiltmc/quilt-loader"))) {
|
|
||||||
options.add(new MakeProfilesOptionsQuilt());
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
String log4jVersion = getLog4jVersion(dir);
|
String log4jVersion = getLog4jVersion(dir);
|
||||||
if (log4jVersion != null) {
|
if (log4jVersion != null) {
|
||||||
|
@ -354,10 +343,6 @@ public List<String> getAltClassPath() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class MakeProfilesOptionsQuilt implements MakeProfileOption {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class MakeProfileOptionLiteLoader implements MakeProfileOption {
|
public static class MakeProfileOptionLiteLoader implements MakeProfileOption {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,6 +119,17 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
|
||||||
ModuleEntity entity = new ModuleEntity();
|
ModuleEntity entity = new ModuleEntity();
|
||||||
entity.path = file;
|
entity.path = file;
|
||||||
entity.moduleMainClass = mainClass;
|
entity.moduleMainClass = mainClass;
|
||||||
|
try {
|
||||||
|
Class<? extends LauncherModule> mainClazz = (Class<? extends LauncherModule>) classLoader.loadClass(entity.moduleMainClass);
|
||||||
|
entity.checkResult = server.modulesManager.checkModuleClass(mainClazz);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
if (e instanceof ClassNotFoundException || e instanceof NoClassDefFoundError) {
|
||||||
|
logger.error("Module-MainClass in module {} incorrect", file.toString());
|
||||||
|
} else {
|
||||||
|
logger.error(e);
|
||||||
|
}
|
||||||
|
return super.visitFile(file, attrs);
|
||||||
|
}
|
||||||
entity.moduleConfigClass = attributes.getValue("Module-Config-Class");
|
entity.moduleConfigClass = attributes.getValue("Module-Config-Class");
|
||||||
if (entity.moduleConfigClass != null) {
|
if (entity.moduleConfigClass != null) {
|
||||||
entity.moduleConfigName = attributes.getValue("Module-Config-Name");
|
entity.moduleConfigName = attributes.getValue("Module-Config-Name");
|
||||||
|
|
|
@ -7,9 +7,11 @@
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class FeaturesManager {
|
public class FeaturesManager {
|
||||||
|
private final transient LaunchServer server;
|
||||||
private final Map<String, String> map;
|
private final Map<String, String> map;
|
||||||
|
|
||||||
public FeaturesManager(LaunchServer server) {
|
public FeaturesManager(LaunchServer server) {
|
||||||
|
this.server = server;
|
||||||
map = new HashMap<>();
|
map = new HashMap<>();
|
||||||
addFeatureInfo("version", Version.getVersion().getVersionString());
|
addFeatureInfo("version", Version.getVersion().getVersionString());
|
||||||
addFeatureInfo("projectName", server.config.projectName);
|
addFeatureInfo("projectName", server.config.projectName);
|
||||||
|
@ -23,8 +25,8 @@ public String getFeatureInfo(String name) {
|
||||||
return map.get(name);
|
return map.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addFeatureInfo(String name, String featureInfo) {
|
public String addFeatureInfo(String name, String featureInfo) {
|
||||||
map.put(name, featureInfo);
|
return map.put(name, featureInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String removeFeatureInfo(String name) {
|
public String removeFeatureInfo(String name) {
|
||||||
|
|
|
@ -22,6 +22,7 @@ public class KeyAgreementManager {
|
||||||
public final RSAPublicKey rsaPublicKey;
|
public final RSAPublicKey rsaPublicKey;
|
||||||
public final RSAPrivateKey rsaPrivateKey;
|
public final RSAPrivateKey rsaPrivateKey;
|
||||||
public final String legacySalt;
|
public final String legacySalt;
|
||||||
|
private transient final Logger logger = LogManager.getLogger();
|
||||||
|
|
||||||
public KeyAgreementManager(ECPublicKey ecdsaPublicKey, ECPrivateKey ecdsaPrivateKey, RSAPublicKey rsaPublicKey, RSAPrivateKey rsaPrivateKey, String legacySalt) {
|
public KeyAgreementManager(ECPublicKey ecdsaPublicKey, ECPrivateKey ecdsaPrivateKey, RSAPublicKey rsaPublicKey, RSAPrivateKey rsaPrivateKey, String legacySalt) {
|
||||||
this.ecdsaPublicKey = ecdsaPublicKey;
|
this.ecdsaPublicKey = ecdsaPublicKey;
|
||||||
|
@ -33,7 +34,6 @@ public KeyAgreementManager(ECPublicKey ecdsaPublicKey, ECPrivateKey ecdsaPrivate
|
||||||
|
|
||||||
public KeyAgreementManager(Path keyDirectory) throws IOException, InvalidKeySpecException {
|
public KeyAgreementManager(Path keyDirectory) throws IOException, InvalidKeySpecException {
|
||||||
Path ecdsaPublicKeyPath = keyDirectory.resolve("ecdsa_id.pub"), ecdsaPrivateKeyPath = keyDirectory.resolve("ecdsa_id");
|
Path ecdsaPublicKeyPath = keyDirectory.resolve("ecdsa_id.pub"), ecdsaPrivateKeyPath = keyDirectory.resolve("ecdsa_id");
|
||||||
Logger logger = LogManager.getLogger();
|
|
||||||
if (IOHelper.isFile(ecdsaPublicKeyPath) && IOHelper.isFile(ecdsaPrivateKeyPath)) {
|
if (IOHelper.isFile(ecdsaPublicKeyPath) && IOHelper.isFile(ecdsaPrivateKeyPath)) {
|
||||||
logger.info("Reading ECDSA keypair");
|
logger.info("Reading ECDSA keypair");
|
||||||
ecdsaPublicKey = SecurityHelper.toPublicECDSAKey(IOHelper.read(ecdsaPublicKeyPath));
|
ecdsaPublicKey = SecurityHelper.toPublicECDSAKey(IOHelper.read(ecdsaPublicKeyPath));
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
import pro.gravit.launcher.events.request.GetAvailabilityAuthRequestEvent;
|
import pro.gravit.launcher.events.request.GetAvailabilityAuthRequestEvent;
|
||||||
import pro.gravit.launcher.managers.GsonManager;
|
import pro.gravit.launcher.managers.GsonManager;
|
||||||
import pro.gravit.launcher.modules.events.PreGsonPhase;
|
import pro.gravit.launcher.modules.events.PreGsonPhase;
|
||||||
import pro.gravit.launcher.profiles.ClientProfile;
|
|
||||||
import pro.gravit.launcher.profiles.optional.actions.OptionalAction;
|
import pro.gravit.launcher.profiles.optional.actions.OptionalAction;
|
||||||
import pro.gravit.launcher.profiles.optional.triggers.OptionalTrigger;
|
import pro.gravit.launcher.profiles.optional.triggers.OptionalTrigger;
|
||||||
import pro.gravit.launcher.request.JsonResultSerializeAdapter;
|
import pro.gravit.launcher.request.JsonResultSerializeAdapter;
|
||||||
|
@ -36,7 +35,6 @@ public void registerAdapters(GsonBuilder builder) {
|
||||||
builder.registerTypeAdapterFactory(RecordTypeAdapterFactory.builder()
|
builder.registerTypeAdapterFactory(RecordTypeAdapterFactory.builder()
|
||||||
.allowMissingComponentValues()
|
.allowMissingComponentValues()
|
||||||
.create());
|
.create());
|
||||||
builder.registerTypeAdapter(ClientProfile.Version.class, new ClientProfile.Version.GsonSerializer());
|
|
||||||
builder.registerTypeAdapter(TextureProvider.class, new UniversalJsonAdapter<>(TextureProvider.providers));
|
builder.registerTypeAdapter(TextureProvider.class, new UniversalJsonAdapter<>(TextureProvider.providers));
|
||||||
builder.registerTypeAdapter(AuthCoreProvider.class, new UniversalJsonAdapter<>(AuthCoreProvider.providers));
|
builder.registerTypeAdapter(AuthCoreProvider.class, new UniversalJsonAdapter<>(AuthCoreProvider.providers));
|
||||||
builder.registerTypeAdapter(PasswordVerifier.class, new UniversalJsonAdapter<>(PasswordVerifier.providers));
|
builder.registerTypeAdapter(PasswordVerifier.class, new UniversalJsonAdapter<>(PasswordVerifier.providers));
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
package pro.gravit.launchserver.modules.events;
|
|
||||||
|
|
||||||
import pro.gravit.launcher.modules.LauncherModule;
|
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
|
||||||
|
|
||||||
public class LaunchServerNettyFullInitEvent extends LauncherModule.Event {
|
|
||||||
public final LaunchServer server;
|
|
||||||
|
|
||||||
public LaunchServerNettyFullInitEvent(LaunchServer server) {
|
|
||||||
this.server = server;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,7 @@
|
||||||
package pro.gravit.launchserver.socket;
|
package pro.gravit.launchserver.socket;
|
||||||
|
|
||||||
import io.netty.bootstrap.ServerBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelInitializer;
|
import io.netty.channel.ChannelInitializer;
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelPipeline;
|
||||||
import io.netty.channel.EventLoopGroup;
|
import io.netty.channel.EventLoopGroup;
|
||||||
|
@ -33,11 +34,11 @@ public class LauncherNettyServer implements AutoCloseable {
|
||||||
public final EventLoopGroup workerGroup;
|
public final EventLoopGroup workerGroup;
|
||||||
public final WebSocketService service;
|
public final WebSocketService service;
|
||||||
public final BiHookSet<NettyConnectContext, SocketChannel> pipelineHook = new BiHookSet<>();
|
public final BiHookSet<NettyConnectContext, SocketChannel> pipelineHook = new BiHookSet<>();
|
||||||
|
private transient final Logger logger = LogManager.getLogger();
|
||||||
|
|
||||||
public LauncherNettyServer(LaunchServer server) {
|
public LauncherNettyServer(LaunchServer server) {
|
||||||
LaunchServerConfig.NettyConfig config = server.config.netty;
|
LaunchServerConfig.NettyConfig config = server.config.netty;
|
||||||
NettyObjectFactory.setUsingEpoll(config.performance.usingEpoll);
|
NettyObjectFactory.setUsingEpoll(config.performance.usingEpoll);
|
||||||
Logger logger = LogManager.getLogger();
|
|
||||||
if (config.performance.usingEpoll) {
|
if (config.performance.usingEpoll) {
|
||||||
logger.debug("Netty: Epoll enabled");
|
logger.debug("Netty: Epoll enabled");
|
||||||
}
|
}
|
||||||
|
@ -73,8 +74,8 @@ public void initChannel(SocketChannel ch) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void bind(InetSocketAddress address) {
|
public ChannelFuture bind(InetSocketAddress address) {
|
||||||
serverBootstrap.bind(address);
|
return serverBootstrap.bind(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
import io.netty.channel.ChannelFutureListener;
|
import io.netty.channel.ChannelFutureListener;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.group.ChannelGroup;
|
import io.netty.channel.group.ChannelGroup;
|
||||||
|
import io.netty.channel.group.ChannelMatchers;
|
||||||
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
|
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
@ -20,6 +21,7 @@
|
||||||
import pro.gravit.launchserver.socket.response.auth.*;
|
import pro.gravit.launchserver.socket.response.auth.*;
|
||||||
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.management.ServerStatusResponse;
|
||||||
import pro.gravit.launchserver.socket.response.profile.BatchProfileByUsername;
|
import pro.gravit.launchserver.socket.response.profile.BatchProfileByUsername;
|
||||||
import pro.gravit.launchserver.socket.response.profile.ProfileByUUIDResponse;
|
import pro.gravit.launchserver.socket.response.profile.ProfileByUUIDResponse;
|
||||||
import pro.gravit.launchserver.socket.response.profile.ProfileByUsername;
|
import pro.gravit.launchserver.socket.response.profile.ProfileByUsername;
|
||||||
|
@ -31,21 +33,26 @@
|
||||||
import pro.gravit.launchserver.socket.response.update.UpdateListResponse;
|
import pro.gravit.launchserver.socket.response.update.UpdateListResponse;
|
||||||
import pro.gravit.launchserver.socket.response.update.UpdateResponse;
|
import pro.gravit.launchserver.socket.response.update.UpdateResponse;
|
||||||
import pro.gravit.utils.BiHookSet;
|
import pro.gravit.utils.BiHookSet;
|
||||||
import pro.gravit.utils.HookSet;
|
|
||||||
import pro.gravit.utils.ProviderMap;
|
import pro.gravit.utils.ProviderMap;
|
||||||
import pro.gravit.utils.helper.IOHelper;
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
public class WebSocketService {
|
public class WebSocketService {
|
||||||
public static final ProviderMap<WebSocketServerResponse> providers = new ProviderMap<>();
|
public static final ProviderMap<WebSocketServerResponse> providers = new ProviderMap<>();
|
||||||
public final ChannelGroup channels;
|
public final ChannelGroup channels;
|
||||||
public final HookSet<WebSocketRequestContext> hookBeforeParsing = new HookSet<>();
|
public final BiHookSet<WebSocketRequestContext, ChannelHandlerContext> hook = new BiHookSet<>();
|
||||||
public final HookSet<WebSocketRequestContext> hookBeforeExecute = new HookSet<>();
|
//Statistic data
|
||||||
public final HookSet<WebSocketRequestContext> hookComplete = new HookSet<>();
|
public final AtomicLong shortRequestLatency = new AtomicLong();
|
||||||
public final BiHookSet<Channel, Object> hookSend = new BiHookSet<>();
|
public final AtomicLong shortRequestCounter = new AtomicLong();
|
||||||
|
public final AtomicLong middleRequestLatency = new AtomicLong();
|
||||||
|
public final AtomicLong middleRequestCounter = new AtomicLong();
|
||||||
|
public final AtomicLong longRequestLatency = new AtomicLong();
|
||||||
|
public final AtomicLong longRequestCounter = new AtomicLong();
|
||||||
|
public final AtomicLong lastRequestTime = new AtomicLong();
|
||||||
private final LaunchServer server;
|
private final LaunchServer server;
|
||||||
private final Gson gson;
|
private final Gson gson;
|
||||||
private transient final Logger logger = LogManager.getLogger();
|
private transient final Logger logger = LogManager.getLogger();
|
||||||
|
@ -56,6 +63,7 @@ public WebSocketService(ChannelGroup channels, LaunchServer server) {
|
||||||
this.gson = Launcher.gsonManager.gson;
|
this.gson = Launcher.gsonManager.gson;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public static void registerResponses() {
|
public static void registerResponses() {
|
||||||
providers.register("auth", AuthResponse.class);
|
providers.register("auth", AuthResponse.class);
|
||||||
providers.register("checkServer", CheckServerResponse.class);
|
providers.register("checkServer", CheckServerResponse.class);
|
||||||
|
@ -75,6 +83,7 @@ public static void registerResponses() {
|
||||||
providers.register("verifySecureLevelKey", VerifySecureLevelKeyResponse.class);
|
providers.register("verifySecureLevelKey", VerifySecureLevelKeyResponse.class);
|
||||||
providers.register("securityReport", SecurityReportResponse.class);
|
providers.register("securityReport", SecurityReportResponse.class);
|
||||||
providers.register("hardwareReport", HardwareReportResponse.class);
|
providers.register("hardwareReport", HardwareReportResponse.class);
|
||||||
|
providers.register("serverStatus", ServerStatusResponse.class);
|
||||||
providers.register("currentUser", CurrentUserResponse.class);
|
providers.register("currentUser", CurrentUserResponse.class);
|
||||||
providers.register("features", FeaturesResponse.class);
|
providers.register("features", FeaturesResponse.class);
|
||||||
providers.register("refreshToken", RefreshTokenResponse.class);
|
providers.register("refreshToken", RefreshTokenResponse.class);
|
||||||
|
@ -110,27 +119,55 @@ public void forEachActiveChannels(BiConsumer<Channel, WebSocketFrameHandler> cal
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process(ChannelHandlerContext ctx, TextWebSocketFrame frame, Client client, String ip) {
|
public void process(ChannelHandlerContext ctx, TextWebSocketFrame frame, Client client, String ip) {
|
||||||
|
long startTimeNanos = System.nanoTime();
|
||||||
String request = frame.text();
|
String request = frame.text();
|
||||||
WebSocketRequestContext context = new WebSocketRequestContext(ctx, request, client, ip);
|
|
||||||
if(hookBeforeParsing.hook(context)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
WebSocketServerResponse response = gson.fromJson(request, WebSocketServerResponse.class);
|
WebSocketServerResponse response = gson.fromJson(request, WebSocketServerResponse.class);
|
||||||
context.response = response;
|
|
||||||
if (response == null) {
|
if (response == null) {
|
||||||
RequestEvent event = new ErrorRequestEvent("This type of request is not supported");
|
RequestEvent event = new ErrorRequestEvent("This type of request is not supported");
|
||||||
hookComplete.hook(context);
|
sendObject(ctx, event);
|
||||||
sendObject(ctx.channel(), event, WebSocketEvent.class);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
process(context, response, client, ip);
|
process(ctx, response, client, ip);
|
||||||
|
long executeTime = System.nanoTime() - startTimeNanos;
|
||||||
|
if (executeTime > 0) {
|
||||||
|
addRequestTimeToStats(executeTime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void process(WebSocketRequestContext context, WebSocketServerResponse response, Client client, String ip) {
|
public void addRequestTimeToStats(long nanos) {
|
||||||
if (hookBeforeExecute.hook(context)) {
|
if (nanos < 100_000_000L) // < 100 millis
|
||||||
|
{
|
||||||
|
shortRequestCounter.getAndIncrement();
|
||||||
|
shortRequestLatency.getAndAdd(nanos);
|
||||||
|
} else if (nanos < 1_000_000_000L) // > 100 millis and < 1 second
|
||||||
|
{
|
||||||
|
middleRequestCounter.getAndIncrement();
|
||||||
|
middleRequestLatency.getAndAdd(nanos);
|
||||||
|
} else // > 1 second
|
||||||
|
{
|
||||||
|
longRequestCounter.getAndIncrement();
|
||||||
|
longRequestLatency.getAndAdd(nanos);
|
||||||
|
}
|
||||||
|
long lastTime = lastRequestTime.get();
|
||||||
|
long currentTime = System.currentTimeMillis();
|
||||||
|
if (currentTime - lastTime > 60 * 1000) //1 minute
|
||||||
|
{
|
||||||
|
lastRequestTime.set(currentTime);
|
||||||
|
shortRequestLatency.set(0);
|
||||||
|
shortRequestCounter.set(0);
|
||||||
|
middleRequestCounter.set(0);
|
||||||
|
middleRequestLatency.set(0);
|
||||||
|
longRequestCounter.set(0);
|
||||||
|
longRequestLatency.set(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void process(ChannelHandlerContext ctx, WebSocketServerResponse response, Client client, String ip) {
|
||||||
|
WebSocketRequestContext context = new WebSocketRequestContext(response, client, ip);
|
||||||
|
if (hook.hook(context, ctx)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ChannelHandlerContext ctx = context.context;
|
|
||||||
if (response instanceof SimpleResponse simpleResponse) {
|
if (response instanceof SimpleResponse simpleResponse) {
|
||||||
simpleResponse.server = server;
|
simpleResponse.server = server;
|
||||||
simpleResponse.service = this;
|
simpleResponse.service = this;
|
||||||
|
@ -140,27 +177,38 @@ void process(WebSocketRequestContext context, WebSocketServerResponse response,
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
response.execute(ctx, client);
|
response.execute(ctx, client);
|
||||||
} catch (Throwable e) {
|
} catch (Exception e) {
|
||||||
context.exception = e;
|
|
||||||
logger.error("WebSocket request processing failed", e);
|
logger.error("WebSocket request processing failed", e);
|
||||||
RequestEvent event;
|
RequestEvent event;
|
||||||
event = new ErrorRequestEvent("Fatal server error. Contact administrator");
|
event = new ErrorRequestEvent("Fatal server error. Contact administrator");
|
||||||
if (response instanceof SimpleResponse) {
|
if (response instanceof SimpleResponse) {
|
||||||
event.requestUUID = ((SimpleResponse) response).requestUUID;
|
event.requestUUID = ((SimpleResponse) response).requestUUID;
|
||||||
}
|
}
|
||||||
sendObject(ctx.channel(), event);
|
sendObject(ctx, event);
|
||||||
}
|
}
|
||||||
hookComplete.hook(context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerClient(Channel channel) {
|
public void registerClient(Channel channel) {
|
||||||
channels.add(channel);
|
channels.add(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendObject(Channel channel, Object obj) {
|
public void sendObject(ChannelHandlerContext ctx, Object obj) {
|
||||||
if(hookSend.hook(channel, obj)) {
|
String msg = gson.toJson(obj, WebSocketEvent.class);
|
||||||
return;
|
if (logger.isTraceEnabled()) {
|
||||||
|
logger.trace("Send to {}: {}", getIPFromContext(ctx), msg);
|
||||||
}
|
}
|
||||||
|
ctx.writeAndFlush(new TextWebSocketFrame(msg), ctx.voidPromise());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendObject(ChannelHandlerContext ctx, Object obj, Type type) {
|
||||||
|
String msg = gson.toJson(obj, type);
|
||||||
|
if (logger.isTraceEnabled()) {
|
||||||
|
logger.trace("Send to {}: {}", getIPFromContext(ctx), msg);
|
||||||
|
}
|
||||||
|
ctx.writeAndFlush(new TextWebSocketFrame(msg), ctx.voidPromise());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendObject(Channel channel, Object obj) {
|
||||||
String msg = gson.toJson(obj, WebSocketEvent.class);
|
String msg = gson.toJson(obj, WebSocketEvent.class);
|
||||||
if (logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
logger.trace("Send to channel {}: {}", getIPFromChannel(channel), msg);
|
logger.trace("Send to channel {}: {}", getIPFromChannel(channel), msg);
|
||||||
|
@ -169,9 +217,6 @@ public void sendObject(Channel channel, Object obj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendObject(Channel channel, Object obj, Type type) {
|
public void sendObject(Channel channel, Object obj, Type type) {
|
||||||
if(hookSend.hook(channel, obj)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String msg = gson.toJson(obj, type);
|
String msg = gson.toJson(obj, type);
|
||||||
if (logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
logger.trace("Send to channel {}: {}", getIPFromChannel(channel), msg);
|
logger.trace("Send to channel {}: {}", getIPFromChannel(channel), msg);
|
||||||
|
@ -179,9 +224,23 @@ public void sendObject(Channel channel, Object obj, Type type) {
|
||||||
channel.writeAndFlush(new TextWebSocketFrame(msg), channel.voidPromise());
|
channel.writeAndFlush(new TextWebSocketFrame(msg), channel.voidPromise());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendObjectAll(Object obj, Type type) {
|
public void sendObjectAll(Object obj) {
|
||||||
|
String msg = gson.toJson(obj, WebSocketEvent.class);
|
||||||
|
if (logger.isTraceEnabled()) {
|
||||||
|
logger.trace("Send to all: {}", msg);
|
||||||
|
}
|
||||||
for (Channel ch : channels) {
|
for (Channel ch : channels) {
|
||||||
sendObject(ch, obj, type);
|
ch.writeAndFlush(new TextWebSocketFrame(msg), ch.voidPromise());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendObjectAll(Object obj, Type type) {
|
||||||
|
String msg = gson.toJson(obj, type);
|
||||||
|
if (logger.isTraceEnabled()) {
|
||||||
|
logger.trace("Send to all: {}", msg);
|
||||||
|
}
|
||||||
|
for (Channel ch : channels) {
|
||||||
|
ch.writeAndFlush(new TextWebSocketFrame(msg), ch.voidPromise());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,9 +251,6 @@ public void sendObjectToUUID(UUID userUuid, Object obj, Type type) {
|
||||||
if (wsHandler == null) continue;
|
if (wsHandler == null) continue;
|
||||||
Client client = wsHandler.getClient();
|
Client client = wsHandler.getClient();
|
||||||
if (client == null || !userUuid.equals(client.uuid)) continue;
|
if (client == null || !userUuid.equals(client.uuid)) continue;
|
||||||
if(hookSend.hook(ch, obj)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
String msg = gson.toJson(obj, type);
|
String msg = gson.toJson(obj, type);
|
||||||
if (logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
logger.trace("Send to {}({}): {}", getIPFromChannel(ch), userUuid, msg);
|
logger.trace("Send to {}({}): {}", getIPFromChannel(ch), userUuid, msg);
|
||||||
|
@ -263,9 +319,6 @@ public boolean kickByIP(String ip, boolean isClose) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendObjectAndClose(ChannelHandlerContext ctx, Object obj) {
|
public void sendObjectAndClose(ChannelHandlerContext ctx, Object obj) {
|
||||||
if(hookSend.hook(ctx.channel(), obj)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String msg = gson.toJson(obj, WebSocketEvent.class);
|
String msg = gson.toJson(obj, WebSocketEvent.class);
|
||||||
if (logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
logger.trace("Send and close {}: {}", getIPFromContext(ctx), msg);
|
logger.trace("Send and close {}: {}", getIPFromContext(ctx), msg);
|
||||||
|
@ -274,9 +327,6 @@ public void sendObjectAndClose(ChannelHandlerContext ctx, Object obj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendObjectAndClose(ChannelHandlerContext ctx, Object obj, Type type) {
|
public void sendObjectAndClose(ChannelHandlerContext ctx, Object obj, Type type) {
|
||||||
if(hookSend.hook(ctx.channel(), obj)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String msg = gson.toJson(obj, type);
|
String msg = gson.toJson(obj, type);
|
||||||
if (logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
logger.trace("Send and close {}: {}", getIPFromContext(ctx), msg);
|
logger.trace("Send and close {}: {}", getIPFromContext(ctx), msg);
|
||||||
|
@ -284,17 +334,22 @@ public void sendObjectAndClose(ChannelHandlerContext ctx, Object obj, Type type)
|
||||||
ctx.writeAndFlush(new TextWebSocketFrame(msg)).addListener(ChannelFutureListener.CLOSE);
|
ctx.writeAndFlush(new TextWebSocketFrame(msg)).addListener(ChannelFutureListener.CLOSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public void sendEvent(EventResult obj) {
|
||||||
|
String msg = gson.toJson(obj, WebSocketEvent.class);
|
||||||
|
if (logger.isTraceEnabled()) {
|
||||||
|
logger.trace("Send event: {}", msg);
|
||||||
|
}
|
||||||
|
channels.writeAndFlush(new TextWebSocketFrame(msg), ChannelMatchers.all(), true);
|
||||||
|
}
|
||||||
|
|
||||||
public static class WebSocketRequestContext {
|
public static class WebSocketRequestContext {
|
||||||
public final ChannelHandlerContext context;
|
public final WebSocketServerResponse response;
|
||||||
public final String text;
|
|
||||||
public final Client client;
|
public final Client client;
|
||||||
public final String ip;
|
public final String ip;
|
||||||
public WebSocketServerResponse response;
|
|
||||||
public Throwable exception;
|
|
||||||
|
|
||||||
public WebSocketRequestContext(ChannelHandlerContext context, String text, Client client, String ip) {
|
public WebSocketRequestContext(WebSocketServerResponse response, Client client, String ip) {
|
||||||
this.context = context;
|
this.response = response;
|
||||||
this.text = text;
|
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.ip = ip;
|
this.ip = ip;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
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.config.LaunchServerConfig;
|
import pro.gravit.launchserver.config.LaunchServerConfig;
|
||||||
import pro.gravit.launchserver.modules.events.LaunchServerNettyFullInitEvent;
|
|
||||||
import pro.gravit.launchserver.socket.LauncherNettyServer;
|
import pro.gravit.launchserver.socket.LauncherNettyServer;
|
||||||
|
|
||||||
import javax.net.ssl.SSLServerSocketFactory;
|
import javax.net.ssl.SSLServerSocketFactory;
|
||||||
|
@ -35,6 +34,5 @@ public void run() {
|
||||||
for (LaunchServerConfig.NettyBindAddress address : server.config.netty.binds) {
|
for (LaunchServerConfig.NettyBindAddress address : server.config.netty.binds) {
|
||||||
nettyServer.bind(new InetSocketAddress(address.address, address.port));
|
nettyServer.bind(new InetSocketAddress(address.address, address.port));
|
||||||
}
|
}
|
||||||
server.modulesManager.invokeEvent(new LaunchServerNettyFullInitEvent(server));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,9 +36,10 @@ public NettyWebAPIHandler(NettyConnectContext context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addNewSeverlet(String path, SimpleSeverletHandler callback) {
|
public static SeverletPathPair addNewSeverlet(String path, SimpleSeverletHandler callback) {
|
||||||
SeverletPathPair pair = new SeverletPathPair("/webapi/".concat(path), callback);
|
SeverletPathPair pair = new SeverletPathPair("/webapi/".concat(path), callback);
|
||||||
severletList.add(pair);
|
severletList.add(pair);
|
||||||
|
return pair;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SeverletPathPair addUnsafeSeverlet(String path, SimpleSeverletHandler callback) {
|
public static SeverletPathPair addUnsafeSeverlet(String path, SimpleSeverletHandler callback) {
|
||||||
|
@ -52,7 +53,7 @@ public static void removeSeverlet(SeverletPathPair pair) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) {
|
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception {
|
||||||
boolean isNext = true;
|
boolean isNext = true;
|
||||||
for (SeverletPathPair pair : severletList) {
|
for (SeverletPathPair pair : severletList) {
|
||||||
if (msg.uri().startsWith(pair.key)) {
|
if (msg.uri().startsWith(pair.key)) {
|
||||||
|
@ -74,7 +75,7 @@ protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) {
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface SimpleSeverletHandler {
|
public interface SimpleSeverletHandler {
|
||||||
void handle(ChannelHandlerContext ctx, FullHttpRequest msg, NettyConnectContext context);
|
void handle(ChannelHandlerContext ctx, FullHttpRequest msg, NettyConnectContext context) throws Exception;
|
||||||
|
|
||||||
default Map<String, String> getParamsFromUri(String uri) {
|
default Map<String, String> getParamsFromUri(String uri) {
|
||||||
int ind = uri.indexOf("?");
|
int ind = uri.indexOf("?");
|
||||||
|
|
|
@ -17,7 +17,7 @@ public abstract class SimpleResponse implements WebSocketServerResponse {
|
||||||
|
|
||||||
public void sendResult(RequestEvent result) {
|
public void sendResult(RequestEvent result) {
|
||||||
result.requestUUID = requestUUID;
|
result.requestUUID = requestUUID;
|
||||||
service.sendObject(ctx.channel(), result);
|
service.sendObject(ctx, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendResultAndClose(RequestEvent result) {
|
public void sendResultAndClose(RequestEvent result) {
|
||||||
|
@ -28,6 +28,6 @@ public void sendResultAndClose(RequestEvent result) {
|
||||||
public void sendError(String errorMessage) {
|
public void sendError(String errorMessage) {
|
||||||
ErrorRequestEvent event = new ErrorRequestEvent(errorMessage);
|
ErrorRequestEvent event = new ErrorRequestEvent(errorMessage);
|
||||||
event.requestUUID = requestUUID;
|
event.requestUUID = requestUUID;
|
||||||
service.sendObject(ctx.channel(), event);
|
service.sendObject(ctx, event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public class AdditionalDataResponse extends SimpleResponse {
|
public class AdditionalDataResponse extends SimpleResponse {
|
||||||
public String username;
|
public String username;
|
||||||
public UUID uuid;
|
public UUID uuid;
|
||||||
|
@ -21,7 +22,7 @@ public String getType() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(ChannelHandlerContext ctx, Client client) {
|
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||||
if (!client.isAuth) {
|
if (!client.isAuth) {
|
||||||
sendError("Access denied");
|
sendError("Access denied");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -28,7 +28,7 @@ public String getType() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(ChannelHandlerContext ctx, Client clientData) {
|
public void execute(ChannelHandlerContext ctx, Client clientData) throws Exception {
|
||||||
try {
|
try {
|
||||||
AuthRequestEvent result = new AuthRequestEvent();
|
AuthRequestEvent result = new AuthRequestEvent();
|
||||||
AuthProviderPair pair;
|
AuthProviderPair pair;
|
||||||
|
|
|
@ -6,9 +6,11 @@
|
||||||
import pro.gravit.launchserver.socket.Client;
|
import pro.gravit.launchserver.socket.Client;
|
||||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
public class CurrentUserResponse extends SimpleResponse {
|
public class CurrentUserResponse extends SimpleResponse {
|
||||||
|
|
||||||
public static CurrentUserRequestEvent.UserInfo collectUserInfoFromClient(LaunchServer server, Client client) {
|
public static CurrentUserRequestEvent.UserInfo collectUserInfoFromClient(LaunchServer server, Client client) throws IOException {
|
||||||
CurrentUserRequestEvent.UserInfo result = new CurrentUserRequestEvent.UserInfo();
|
CurrentUserRequestEvent.UserInfo result = new CurrentUserRequestEvent.UserInfo();
|
||||||
if (client.auth != null && client.isAuth && client.username != null) {
|
if (client.auth != null && client.isAuth && client.username != null) {
|
||||||
result.playerProfile = server.authManager.getPlayerProfile(client);
|
result.playerProfile = server.authManager.getPlayerProfile(client);
|
||||||
|
|
|
@ -14,7 +14,7 @@ public String getType() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(ChannelHandlerContext ctx, Client client) {
|
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||||
if (!client.isAuth || client.type != AuthResponse.ConnectTypes.CLIENT) {
|
if (!client.isAuth || client.type != AuthResponse.ConnectTypes.CLIENT) {
|
||||||
sendError("Permissions denied");
|
sendError("Permissions denied");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -18,7 +18,7 @@ public String getType() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(ChannelHandlerContext ctx, Client client) {
|
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||||
if (refreshToken == null) {
|
if (refreshToken == null) {
|
||||||
sendError("Invalid request");
|
sendError("Invalid request");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -76,10 +76,6 @@ public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
User user = session.getUser();
|
User user = session.getUser();
|
||||||
if(user == null) {
|
|
||||||
sendError("Internal Auth error: UserSession is broken");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
client.coreObject = user;
|
client.coreObject = user;
|
||||||
client.sessionObject = session;
|
client.sessionObject = session;
|
||||||
server.authManager.internalAuth(client, client.type == null ? AuthResponse.ConnectTypes.API : client.type, pair, user.getUsername(), user.getUUID(), user.getPermissions(), true);
|
server.authManager.internalAuth(client, client.type == null ? AuthResponse.ConnectTypes.API : client.type, pair, user.getUsername(), user.getUUID(), user.getPermissions(), true);
|
||||||
|
|
|
@ -18,7 +18,7 @@ public String getType() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(ChannelHandlerContext ctx, Client client) {
|
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||||
sendError("Legacy session system removed");
|
sendError("Legacy session system removed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ public String getType() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(ChannelHandlerContext ctx, Client client) {
|
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||||
sendResult(new GetPublicKeyRequestEvent(server.keyAgreementManager.rsaPublicKey, server.keyAgreementManager.ecdsaPublicKey));
|
sendResult(new GetPublicKeyRequestEvent(server.keyAgreementManager.rsaPublicKey, server.keyAgreementManager.ecdsaPublicKey));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
package pro.gravit.launchserver.socket.response.management;
|
||||||
|
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import pro.gravit.launcher.events.request.ServerStatusRequestEvent;
|
||||||
|
import pro.gravit.launchserver.socket.Client;
|
||||||
|
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||||
|
import pro.gravit.utils.helper.JVMHelper;
|
||||||
|
|
||||||
|
public class ServerStatusResponse extends SimpleResponse {
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "serverStatus";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(ChannelHandlerContext ctx, Client client) {
|
||||||
|
ServerStatusRequestEvent event = new ServerStatusRequestEvent(server.config.projectName);
|
||||||
|
event.totalJavaMemory = JVMHelper.RUNTIME.totalMemory();
|
||||||
|
event.freeJavaMemory = JVMHelper.RUNTIME.freeMemory();
|
||||||
|
event.shortLatency = (service.shortRequestLatency.get() / service.shortRequestCounter.get()) / 1_000_000;
|
||||||
|
event.middleLatency = (service.middleRequestLatency.get() / service.middleRequestCounter.get()) / 1_000_000;
|
||||||
|
event.longLatency = (service.longRequestLatency.get() / service.longRequestCounter.get()) / 1_000_000;
|
||||||
|
event.latency = ((service.shortRequestLatency.get() + service.middleRequestLatency.get() + service.longRequestLatency.get()) /
|
||||||
|
(service.shortRequestCounter.get() + service.middleRequestCounter.get() + service.longRequestCounter.get())) / 1_000_000;
|
||||||
|
sendResult(event);
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,7 +16,7 @@ public String getType() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(ChannelHandlerContext ctx, Client client) {
|
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||||
BatchProfileByUsernameRequestEvent result = new BatchProfileByUsernameRequestEvent();
|
BatchProfileByUsernameRequestEvent result = new BatchProfileByUsernameRequestEvent();
|
||||||
if (list == null) {
|
if (list == null) {
|
||||||
sendError("Invalid request");
|
sendError("Invalid request");
|
||||||
|
|
|
@ -19,7 +19,7 @@ public String getType() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(ChannelHandlerContext ctx, Client client) {
|
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||||
AuthProviderPair pair;
|
AuthProviderPair pair;
|
||||||
if (client.auth == null) {
|
if (client.auth == null) {
|
||||||
pair = server.config.getAuthProviderPair();
|
pair = server.config.getAuthProviderPair();
|
||||||
|
|
|
@ -17,7 +17,7 @@ public String getType() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(ChannelHandlerContext ctx, Client client) {
|
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||||
AuthProviderPair pair = client.auth;
|
AuthProviderPair pair = client.auth;
|
||||||
if (pair == null) pair = server.config.getAuthProviderPair();
|
if (pair == null) pair = server.config.getAuthProviderPair();
|
||||||
PlayerProfile profile = server.authManager.getPlayerProfile(pair, username);
|
PlayerProfile profile = server.authManager.getPlayerProfile(pair, username);
|
||||||
|
|
|
@ -85,10 +85,12 @@ private boolean checkSecure(String hash, String salt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class LauncherTokenVerifier implements RestoreResponse.ExtendedTokenProvider {
|
public static class LauncherTokenVerifier implements RestoreResponse.ExtendedTokenProvider {
|
||||||
|
private final LaunchServer server;
|
||||||
private final JwtParser parser;
|
private final JwtParser parser;
|
||||||
private final Logger logger = LogManager.getLogger();
|
private final Logger logger = LogManager.getLogger();
|
||||||
|
|
||||||
public LauncherTokenVerifier(LaunchServer server) {
|
public LauncherTokenVerifier(LaunchServer server) {
|
||||||
|
this.server = server;
|
||||||
parser = Jwts.parserBuilder()
|
parser = Jwts.parserBuilder()
|
||||||
.setSigningKey(server.keyAgreementManager.ecdsaPublicKey)
|
.setSigningKey(server.keyAgreementManager.ecdsaPublicKey)
|
||||||
.requireIssuer("LaunchServer")
|
.requireIssuer("LaunchServer")
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
{
|
||||||
|
"version": "1.10.2",
|
||||||
|
"assetIndex": "1.10.2",
|
||||||
|
"assetDir": "asset1.10",
|
||||||
|
"dir": "HiTech",
|
||||||
|
"info": "Информация о сервере",
|
||||||
|
"sortIndex": 0,
|
||||||
|
"title": "xxxxxxxx",
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"name": "----",
|
||||||
|
"serverAddress": "localhost",
|
||||||
|
"serverPort": 25565,
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"update": ["servers.dat"],
|
||||||
|
"updateExclusions": [],
|
||||||
|
"updateShared": [],
|
||||||
|
"updateVerify": [
|
||||||
|
"libraries", "natives", "mods",
|
||||||
|
"minecraft.jar", "forge.jar", "liteloader.jar"
|
||||||
|
],
|
||||||
|
"updateOptional": [
|
||||||
|
],
|
||||||
|
"updateFastCheck": true,
|
||||||
|
"useWhitelist": false,
|
||||||
|
"mainClass": "net.minecraft.launchwrapper.Launch",
|
||||||
|
"jvmArgs": [
|
||||||
|
"-Dfml.ignorePatchDiscrepancies=true",
|
||||||
|
"-Dfml.ignoreInvalidMinecraftCertificates=true",
|
||||||
|
"-XX:+UseConcMarkSweepGC",
|
||||||
|
"-XX:+CMSIncrementalMode",
|
||||||
|
"-XX:-UseAdaptiveSizePolicy",
|
||||||
|
"-Xmn128M",
|
||||||
|
"-XX:+DisableAttachMechanism"
|
||||||
|
],
|
||||||
|
"classPath": ["forge.jar", "liteloader.jar", "minecraft.jar", "libraries"],
|
||||||
|
"clientArgs": [
|
||||||
|
"--tweakClass", "net.minecraftforge.fml.common.launcher.FMLTweaker",
|
||||||
|
"--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker"
|
||||||
|
],
|
||||||
|
"optionalJVMArgs": [],
|
||||||
|
"optionalClientArgs": [],
|
||||||
|
"optionalClassPath": [],
|
||||||
|
"whitelist": []
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
{
|
||||||
|
"version": "1.11.2",
|
||||||
|
"assetIndex": "1.11.2",
|
||||||
|
"assetDir": "asset1.11",
|
||||||
|
"dir": "HiTech",
|
||||||
|
"info": "Информация о сервере",
|
||||||
|
"sortIndex": 0,
|
||||||
|
"title": "xxxxxxxx",
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"name": "----",
|
||||||
|
"serverAddress": "localhost",
|
||||||
|
"serverPort": 25565,
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"update": ["servers.dat"],
|
||||||
|
"updateExclusions": [],
|
||||||
|
"updateShared": [],
|
||||||
|
"updateVerify": [
|
||||||
|
"libraries", "natives", "mods",
|
||||||
|
"minecraft.jar", "forge.jar", "liteloader.jar"
|
||||||
|
],
|
||||||
|
"updateOptional": [
|
||||||
|
],
|
||||||
|
"updateFastCheck": true,
|
||||||
|
"useWhitelist": false,
|
||||||
|
"mainClass": "net.minecraft.launchwrapper.Launch",
|
||||||
|
"jvmArgs": [
|
||||||
|
"-Dfml.ignorePatchDiscrepancies=true",
|
||||||
|
"-Dfml.ignoreInvalidMinecraftCertificates=true",
|
||||||
|
"-XX:+UseConcMarkSweepGC",
|
||||||
|
"-XX:+CMSIncrementalMode",
|
||||||
|
"-XX:-UseAdaptiveSizePolicy",
|
||||||
|
"-Xmn128M",
|
||||||
|
"-XX:+DisableAttachMechanism"
|
||||||
|
],
|
||||||
|
"classPath": ["forge.jar", "liteloader.jar", "minecraft.jar", "libraries"],
|
||||||
|
"clientArgs": [
|
||||||
|
"--tweakClass", "net.minecraftforge.fml.common.launcher.FMLTweaker",
|
||||||
|
"--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker"
|
||||||
|
],
|
||||||
|
"optionalJVMArgs": [],
|
||||||
|
"optionalClientArgs": [],
|
||||||
|
"optionalClassPath": [],
|
||||||
|
"whitelist": []
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
{
|
||||||
|
"version": "1.12.2",
|
||||||
|
"assetIndex": "1.12.2",
|
||||||
|
"assetDir": "asset1.12",
|
||||||
|
"dir": "HiTech",
|
||||||
|
"info": "Информация о сервере",
|
||||||
|
"sortIndex": 0,
|
||||||
|
"title": "xxxxxxxx",
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"name": "----",
|
||||||
|
"serverAddress": "localhost",
|
||||||
|
"serverPort": 25565,
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"update": ["servers.dat"],
|
||||||
|
"updateExclusions": [],
|
||||||
|
"updateShared": [],
|
||||||
|
"updateVerify": [
|
||||||
|
"libraries", "natives", "mods",
|
||||||
|
"minecraft.jar", "forge.jar", "liteloader.jar"
|
||||||
|
],
|
||||||
|
"updateOptional": [
|
||||||
|
],
|
||||||
|
"updateFastCheck": true,
|
||||||
|
"useWhitelist": false,
|
||||||
|
"mainClass": "net.minecraft.launchwrapper.Launch",
|
||||||
|
"jvmArgs": [
|
||||||
|
"-Dfml.ignorePatchDiscrepancies=true",
|
||||||
|
"-Dfml.ignoreInvalidMinecraftCertificates=true",
|
||||||
|
"-XX:+UseConcMarkSweepGC",
|
||||||
|
"-XX:+CMSIncrementalMode",
|
||||||
|
"-XX:-UseAdaptiveSizePolicy",
|
||||||
|
"-Xmn128M",
|
||||||
|
"-XX:+DisableAttachMechanism"
|
||||||
|
],
|
||||||
|
"classPath": ["forge.jar", "liteloader.jar", "minecraft.jar", "libraries"],
|
||||||
|
"clientArgs": [
|
||||||
|
"--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker",
|
||||||
|
"--tweakClass", "net.minecraftforge.fml.common.launcher.FMLTweaker"
|
||||||
|
],
|
||||||
|
"optionalJVMArgs": [],
|
||||||
|
"optionalClientArgs": [],
|
||||||
|
"optionalClassPath": [],
|
||||||
|
"whitelist": []
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
"version": "1.13.1",
|
||||||
|
"assetIndex": "1.13.1",
|
||||||
|
"assetDir": "asset1.13.1",
|
||||||
|
"dir": "HiTech",
|
||||||
|
"info": "Информация о сервере",
|
||||||
|
"sortIndex": 0,
|
||||||
|
"title": "xxxxxxxx",
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"name": "----",
|
||||||
|
"serverAddress": "localhost",
|
||||||
|
"serverPort": 25565,
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"update": ["servers.dat"],
|
||||||
|
"updateExclusions": [],
|
||||||
|
"updateShared": [],
|
||||||
|
"updateVerify": [
|
||||||
|
"libraries", "natives", "mods",
|
||||||
|
"minecraft.jar", "forge.jar", "liteloader.jar"
|
||||||
|
],
|
||||||
|
"updateOptional": [
|
||||||
|
],
|
||||||
|
"updateFastCheck": true,
|
||||||
|
"useWhitelist": false,
|
||||||
|
"mainClass": "net.minecraft.client.main.Main",
|
||||||
|
"jvmArgs": [
|
||||||
|
"-Dfml.ignorePatchDiscrepancies=true",
|
||||||
|
"-Dfml.ignoreInvalidMinecraftCertificates=true",
|
||||||
|
"-XX:+UseConcMarkSweepGC",
|
||||||
|
"-XX:+CMSIncrementalMode",
|
||||||
|
"-XX:-UseAdaptiveSizePolicy",
|
||||||
|
"-Xmn128M",
|
||||||
|
"-XX:+DisableAttachMechanism"
|
||||||
|
],
|
||||||
|
"classPath": ["forge.jar", "liteloader.jar", "minecraft.jar", "libraries"],
|
||||||
|
"clientArgs": [
|
||||||
|
],
|
||||||
|
"optionalJVMArgs": [],
|
||||||
|
"optionalClientArgs": [],
|
||||||
|
"optionalClassPath": [],
|
||||||
|
"whitelist": []
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
"version": "1.13",
|
||||||
|
"assetIndex": "1.13",
|
||||||
|
"assetDir": "asset1.13",
|
||||||
|
"dir": "HiTech",
|
||||||
|
"info": "Информация о сервере",
|
||||||
|
"sortIndex": 0,
|
||||||
|
"title": "xxxxxxxx",
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"name": "----",
|
||||||
|
"serverAddress": "localhost",
|
||||||
|
"serverPort": 25565,
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"update": ["servers.dat"],
|
||||||
|
"updateExclusions": [],
|
||||||
|
"updateShared": [],
|
||||||
|
"updateVerify": [
|
||||||
|
"libraries", "natives", "mods",
|
||||||
|
"minecraft.jar", "forge.jar", "liteloader.jar"
|
||||||
|
],
|
||||||
|
"updateOptional": [
|
||||||
|
],
|
||||||
|
"updateFastCheck": true,
|
||||||
|
"useWhitelist": false,
|
||||||
|
"mainClass": "net.minecraft.client.main.Main",
|
||||||
|
"jvmArgs": [
|
||||||
|
"-Dfml.ignorePatchDiscrepancies=true",
|
||||||
|
"-Dfml.ignoreInvalidMinecraftCertificates=true",
|
||||||
|
"-XX:+UseConcMarkSweepGC",
|
||||||
|
"-XX:+CMSIncrementalMode",
|
||||||
|
"-XX:-UseAdaptiveSizePolicy",
|
||||||
|
"-Xmn128M",
|
||||||
|
"-XX:+DisableAttachMechanism"
|
||||||
|
],
|
||||||
|
"classPath": ["forge.jar", "liteloader.jar", "minecraft.jar", "libraries"],
|
||||||
|
"clientArgs": [
|
||||||
|
],
|
||||||
|
"optionalJVMArgs": [],
|
||||||
|
"optionalClientArgs": [],
|
||||||
|
"optionalClassPath": [],
|
||||||
|
"whitelist": []
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
{
|
||||||
|
"version": "1.14.4",
|
||||||
|
"assetIndex": "1.14.4",
|
||||||
|
"assetDir": "asset1.14.4",
|
||||||
|
"dir": "HiTech",
|
||||||
|
"info": "Информация о сервере",
|
||||||
|
"sortIndex": 0,
|
||||||
|
"title": "xxxxxxxx",
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"name": "----",
|
||||||
|
"serverAddress": "localhost",
|
||||||
|
"serverPort": 25565,
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"update": [
|
||||||
|
"servers.dat"
|
||||||
|
],
|
||||||
|
"updateExclusions": [],
|
||||||
|
"updateShared": [],
|
||||||
|
"updateVerify": [
|
||||||
|
"libraries",
|
||||||
|
"natives",
|
||||||
|
"minecraft.jar"
|
||||||
|
],
|
||||||
|
"updateOptional": [],
|
||||||
|
"updateFastCheck": true,
|
||||||
|
"useWhitelist": false,
|
||||||
|
"mainClass": "net.minecraft.client.main.Main",
|
||||||
|
"jvmArgs": [
|
||||||
|
"-XX:+UseConcMarkSweepGC",
|
||||||
|
"-XX:+CMSIncrementalMode",
|
||||||
|
"-XX:-UseAdaptiveSizePolicy",
|
||||||
|
"-Xmn128M",
|
||||||
|
"-XX:+DisableAttachMechanism"
|
||||||
|
],
|
||||||
|
"classPath": [
|
||||||
|
"minecraft.jar",
|
||||||
|
"libraries"
|
||||||
|
],
|
||||||
|
"clientArgs": [],
|
||||||
|
"whitelist": []
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
{
|
||||||
|
"version": "1.15.1",
|
||||||
|
"assetIndex": "1.15.1",
|
||||||
|
"assetDir": "asset1.15.1",
|
||||||
|
"dir": "HiTech",
|
||||||
|
"info": "Информация о сервере",
|
||||||
|
"sortIndex": 0,
|
||||||
|
"title": "xxxxxxxx",
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"name": "----",
|
||||||
|
"serverAddress": "localhost",
|
||||||
|
"serverPort": 25565,
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"update": [
|
||||||
|
"servers.dat"
|
||||||
|
],
|
||||||
|
"updateExclusions": [],
|
||||||
|
"updateShared": [],
|
||||||
|
"updateVerify": [
|
||||||
|
"libraries",
|
||||||
|
"natives",
|
||||||
|
"minecraft.jar"
|
||||||
|
],
|
||||||
|
"updateOptional": [],
|
||||||
|
"updateFastCheck": true,
|
||||||
|
"useWhitelist": false,
|
||||||
|
"mainClass": "net.minecraft.client.main.Main",
|
||||||
|
"jvmArgs": [
|
||||||
|
"-XX:+UseConcMarkSweepGC",
|
||||||
|
"-XX:+CMSIncrementalMode",
|
||||||
|
"-XX:-UseAdaptiveSizePolicy",
|
||||||
|
"-Xmn128M",
|
||||||
|
"-XX:+DisableAttachMechanism"
|
||||||
|
],
|
||||||
|
"classPath": [
|
||||||
|
"minecraft.jar",
|
||||||
|
"libraries"
|
||||||
|
],
|
||||||
|
"clientArgs": [],
|
||||||
|
"whitelist": []
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
{
|
||||||
|
"version": "1.15.2",
|
||||||
|
"assetIndex": "1.15.2",
|
||||||
|
"assetDir": "asset1.15.2",
|
||||||
|
"dir": "HiTech",
|
||||||
|
"info": "Информация о сервере",
|
||||||
|
"sortIndex": 0,
|
||||||
|
"title": "xxxxxxxx",
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"name": "----",
|
||||||
|
"serverAddress": "localhost",
|
||||||
|
"serverPort": 25565,
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"update": [
|
||||||
|
"servers.dat"
|
||||||
|
],
|
||||||
|
"updateExclusions": [],
|
||||||
|
"updateShared": [],
|
||||||
|
"updateVerify": [
|
||||||
|
"libraries",
|
||||||
|
"natives",
|
||||||
|
"minecraft.jar"
|
||||||
|
],
|
||||||
|
"updateOptional": [],
|
||||||
|
"updateFastCheck": true,
|
||||||
|
"useWhitelist": false,
|
||||||
|
"mainClass": "net.minecraft.client.main.Main",
|
||||||
|
"jvmArgs": [
|
||||||
|
"-XX:+UseConcMarkSweepGC",
|
||||||
|
"-XX:+CMSIncrementalMode",
|
||||||
|
"-XX:-UseAdaptiveSizePolicy",
|
||||||
|
"-Xmn128M",
|
||||||
|
"-XX:+DisableAttachMechanism"
|
||||||
|
],
|
||||||
|
"classPath": [
|
||||||
|
"minecraft.jar",
|
||||||
|
"libraries"
|
||||||
|
],
|
||||||
|
"clientArgs": [],
|
||||||
|
"whitelist": []
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
{
|
||||||
|
"version": "1.16.1",
|
||||||
|
"assetIndex": "1.16.1",
|
||||||
|
"assetDir": "asset1.16.1",
|
||||||
|
"dir": "HiTech",
|
||||||
|
"info": "Информация о сервере",
|
||||||
|
"sortIndex": 0,
|
||||||
|
"title": "xxxxxxxx",
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"name": "----",
|
||||||
|
"serverAddress": "localhost",
|
||||||
|
"serverPort": 25565,
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"update": [
|
||||||
|
"servers.dat"
|
||||||
|
],
|
||||||
|
"updateExclusions": [],
|
||||||
|
"updateShared": [],
|
||||||
|
"updateVerify": [
|
||||||
|
"libraries",
|
||||||
|
"natives",
|
||||||
|
"minecraft.jar"
|
||||||
|
],
|
||||||
|
"updateOptional": [],
|
||||||
|
"updateFastCheck": true,
|
||||||
|
"useWhitelist": false,
|
||||||
|
"mainClass": "net.minecraft.client.main.Main",
|
||||||
|
"jvmArgs": [
|
||||||
|
"-XX:+UseConcMarkSweepGC",
|
||||||
|
"-XX:+CMSIncrementalMode",
|
||||||
|
"-XX:-UseAdaptiveSizePolicy",
|
||||||
|
"-Xmn128M",
|
||||||
|
"-XX:+DisableAttachMechanism"
|
||||||
|
],
|
||||||
|
"classPath": [
|
||||||
|
"minecraft.jar",
|
||||||
|
"libraries"
|
||||||
|
],
|
||||||
|
"clientArgs": [],
|
||||||
|
"whitelist": []
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
{
|
||||||
|
"version": "1.4.7",
|
||||||
|
"assetIndex": "---",
|
||||||
|
"assetDir": "asset1.4.7",
|
||||||
|
"dir": "xxxxxxx",
|
||||||
|
"info": "Информация о сервере",
|
||||||
|
"sortIndex": 0,
|
||||||
|
"title": "Test1.4.7",
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"name": "----",
|
||||||
|
"serverAddress": "localhost",
|
||||||
|
"serverPort": 25565,
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"update": ["servers.dat"],
|
||||||
|
"updateExclusions": [],
|
||||||
|
"updateShared": [],
|
||||||
|
"updateVerify": [
|
||||||
|
"libraries", "natives", "mods",
|
||||||
|
"minecraft.jar"
|
||||||
|
],
|
||||||
|
"updateOptional": [
|
||||||
|
],
|
||||||
|
"updateFastCheck": true,
|
||||||
|
"useWhitelist": false,
|
||||||
|
"mainClass": "net.minecraft.launchwrapper.Launch",
|
||||||
|
"jvmArgs": [
|
||||||
|
"-XX:+UseConcMarkSweepGC",
|
||||||
|
"-XX:+CMSIncrementalMode",
|
||||||
|
"-XX:-UseAdaptiveSizePolicy",
|
||||||
|
"-Xmn128M",
|
||||||
|
"-XX:+DisableAttachMechanism",
|
||||||
|
"-Dlauncher.legacy.skinsURL=http://skins.minecraft.net/MinecraftSkins/%username%.png",
|
||||||
|
"-Dlauncher.legacy.cloaksURL=http://skins.minecraft.net/MinecraftCloaks/%username%.png"
|
||||||
|
],
|
||||||
|
"classPath": ["minecraft.jar", "libraries"],
|
||||||
|
"clientArgs": [],
|
||||||
|
"optionalJVMArgs": [],
|
||||||
|
"optionalClientArgs": [],
|
||||||
|
"optionalClassPath": [],
|
||||||
|
"whitelist": []
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
{
|
||||||
|
"version": "1.5.2",
|
||||||
|
"assetIndex": "---",
|
||||||
|
"assetDir": "asset1.5.2",
|
||||||
|
"dir": "xxxxxxx",
|
||||||
|
"info": "Информация о сервере",
|
||||||
|
"sortIndex": 0,
|
||||||
|
"title": "Test1.5.2",
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"name": "----",
|
||||||
|
"serverAddress": "localhost",
|
||||||
|
"serverPort": 25565,
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"update": ["servers.dat"],
|
||||||
|
"updateExclusions": [],
|
||||||
|
"updateShared": [],
|
||||||
|
"updateVerify": [
|
||||||
|
"libraries", "natives", "mods",
|
||||||
|
"minecraft.jar"
|
||||||
|
],
|
||||||
|
"updateOptional": [
|
||||||
|
],
|
||||||
|
"updateFastCheck": true,
|
||||||
|
"useWhitelist": false,
|
||||||
|
"mainClass": "net.minecraft.launchwrapper.Launch",
|
||||||
|
"jvmArgs": [
|
||||||
|
"-XX:+UseConcMarkSweepGC",
|
||||||
|
"-XX:+CMSIncrementalMode",
|
||||||
|
"-XX:-UseAdaptiveSizePolicy",
|
||||||
|
"-Xmn128M",
|
||||||
|
"-XX:+DisableAttachMechanism",
|
||||||
|
"-Dlauncher.legacy.skinsURL=http://skins.minecraft.net/MinecraftSkins/%username%.png",
|
||||||
|
"-Dlauncher.legacy.cloaksURL=http://skins.minecraft.net/MinecraftCloaks/%username%.png"
|
||||||
|
],
|
||||||
|
"classPath": ["minecraft.jar", "libraries"],
|
||||||
|
"clientArgs": [],
|
||||||
|
"optionalJVMArgs": [],
|
||||||
|
"optionalClientArgs": [],
|
||||||
|
"optionalClassPath": [],
|
||||||
|
"whitelist": []
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
{
|
||||||
|
"version": "1.6.4",
|
||||||
|
"assetIndex": "---",
|
||||||
|
"assetDir": "asset1.6.4",
|
||||||
|
"dir": "xxxxxxx",
|
||||||
|
"info": "Информация о сервере",
|
||||||
|
"sortIndex": 0,
|
||||||
|
"title": "Test1.6.4",
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"name": "----",
|
||||||
|
"serverAddress": "localhost",
|
||||||
|
"serverPort": 25565,
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"update": ["servers.dat"],
|
||||||
|
"updateExclusions": [],
|
||||||
|
"updateShared": [],
|
||||||
|
"updateVerify": [
|
||||||
|
"libraries", "natives", "mods",
|
||||||
|
"minecraft.jar", "forge.jar", "liteloader.jar"
|
||||||
|
],
|
||||||
|
"updateOptional": [
|
||||||
|
],
|
||||||
|
"updateFastCheck": true,
|
||||||
|
"useWhitelist": false,
|
||||||
|
"mainClass": "net.minecraft.launchwrapper.Launch",
|
||||||
|
"jvmArgs": [
|
||||||
|
"-Dfml.ignorePatchDiscrepancies=true",
|
||||||
|
"-Dfml.ignoreInvalidMinecraftCertificates=true",
|
||||||
|
"-XX:+UseConcMarkSweepGC",
|
||||||
|
"-XX:+CMSIncrementalMode",
|
||||||
|
"-XX:-UseAdaptiveSizePolicy",
|
||||||
|
"-Xmn128M",
|
||||||
|
"-XX:+DisableAttachMechanism",
|
||||||
|
"-Dlauncher.legacy.skinsURL=http://skins.minecraft.net/MinecraftSkins/%username%.png",
|
||||||
|
"-Dlauncher.legacy.cloaksURL=http://skins.minecraft.net/MinecraftCloaks/%username%.png"
|
||||||
|
],
|
||||||
|
"classPath": ["forge.jar", "liteloader.jar", "minecraft.jar", "libraries"],
|
||||||
|
"clientArgs": [
|
||||||
|
"--tweakClass", "cpw.mods.fml.common.launcher.FMLTweaker",
|
||||||
|
"--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker"
|
||||||
|
],
|
||||||
|
"optionalJVMArgs": [],
|
||||||
|
"optionalClientArgs": [],
|
||||||
|
"optionalClassPath": [],
|
||||||
|
"whitelist": []
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
{
|
||||||
|
"version": "1.7.10",
|
||||||
|
"assetIndex": "1.7.10",
|
||||||
|
"assetDir": "asset1.7.10",
|
||||||
|
"dir": "xxxxxxx",
|
||||||
|
"info": "Информация о сервере",
|
||||||
|
"sortIndex": 0,
|
||||||
|
"title": "Test1.7.10",
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"name": "----",
|
||||||
|
"serverAddress": "localhost",
|
||||||
|
"serverPort": 25565,
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"update": ["servers.dat"],
|
||||||
|
"updateExclusions": [],
|
||||||
|
"updateShared": [],
|
||||||
|
"updateVerify": [
|
||||||
|
"libraries", "natives", "mods",
|
||||||
|
"minecraft.jar", "forge.jar", "liteloader.jar"
|
||||||
|
],
|
||||||
|
"updateOptional": [
|
||||||
|
],
|
||||||
|
"updateFastCheck": true,
|
||||||
|
"useWhitelist": false,
|
||||||
|
"mainClass": "net.minecraft.launchwrapper.Launch",
|
||||||
|
"jvmArgs": [
|
||||||
|
"-Dfml.ignorePatchDiscrepancies=true",
|
||||||
|
"-Dfml.ignoreInvalidMinecraftCertificates=true",
|
||||||
|
"-XX:+UseConcMarkSweepGC",
|
||||||
|
"-XX:+CMSIncrementalMode",
|
||||||
|
"-XX:-UseAdaptiveSizePolicy",
|
||||||
|
"-Xmn128M",
|
||||||
|
"-XX:+DisableAttachMechanism"
|
||||||
|
],
|
||||||
|
"classPath": ["forge.jar", "liteloader.jar", "minecraft.jar", "libraries"],
|
||||||
|
"clientArgs": [
|
||||||
|
"--tweakClass", "cpw.mods.fml.common.launcher.FMLTweaker",
|
||||||
|
"--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker"
|
||||||
|
],
|
||||||
|
"optionalJVMArgs": [],
|
||||||
|
"optionalClientArgs": [],
|
||||||
|
"optionalClassPath": [],
|
||||||
|
"whitelist": []
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
{
|
||||||
|
"version": "1.7.2",
|
||||||
|
"assetIndex": "1.7.2",
|
||||||
|
"assetDir": "asset1.7.2",
|
||||||
|
"dir": "xxxxxxx",
|
||||||
|
"info": "Информация о сервере",
|
||||||
|
"sortIndex": 0,
|
||||||
|
"title": "Test1.7.2",
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"name": "----",
|
||||||
|
"serverAddress": "localhost",
|
||||||
|
"serverPort": 25565,
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"update": ["servers.dat"],
|
||||||
|
"updateExclusions": [],
|
||||||
|
"updateShared": [],
|
||||||
|
"updateVerify": [
|
||||||
|
"libraries", "natives", "mods",
|
||||||
|
"minecraft.jar", "forge.jar", "liteloader.jar"
|
||||||
|
],
|
||||||
|
"updateOptional": [
|
||||||
|
],
|
||||||
|
"updateFastCheck": true,
|
||||||
|
"useWhitelist": false,
|
||||||
|
"mainClass": "net.minecraft.launchwrapper.Launch",
|
||||||
|
"jvmArgs": [
|
||||||
|
"-Dfml.ignorePatchDiscrepancies=true",
|
||||||
|
"-Dfml.ignoreInvalidMinecraftCertificates=true",
|
||||||
|
"-XX:+UseConcMarkSweepGC",
|
||||||
|
"-XX:+CMSIncrementalMode",
|
||||||
|
"-XX:-UseAdaptiveSizePolicy",
|
||||||
|
"-Xmn128M",
|
||||||
|
"-XX:+DisableAttachMechanism"
|
||||||
|
],
|
||||||
|
"classPath": ["forge.jar", "liteloader.jar", "minecraft.jar", "libraries"],
|
||||||
|
"clientArgs": [
|
||||||
|
"--tweakClass", "cpw.mods.fml.common.launcher.FMLTweaker",
|
||||||
|
"--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker"
|
||||||
|
],
|
||||||
|
"optionalJVMArgs": [],
|
||||||
|
"optionalClientArgs": [],
|
||||||
|
"optionalClassPath": [],
|
||||||
|
"whitelist": []
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
{
|
||||||
|
"version": "1.8.9",
|
||||||
|
"assetIndex": "1.8.9",
|
||||||
|
"assetDir": "asset1.8.9",
|
||||||
|
"dir": "xxxxxxx",
|
||||||
|
"info": "Информация о сервере",
|
||||||
|
"sortIndex": 0,
|
||||||
|
"title": "Test1.8.9",
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"name": "----",
|
||||||
|
"serverAddress": "localhost",
|
||||||
|
"serverPort": 25565,
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"update": ["servers.dat"],
|
||||||
|
"updateExclusions": [],
|
||||||
|
"updateShared": [],
|
||||||
|
"updateVerify": [
|
||||||
|
"libraries", "natives", "mods",
|
||||||
|
"minecraft.jar", "forge.jar", "liteloader.jar"
|
||||||
|
],
|
||||||
|
"updateOptional": [
|
||||||
|
],
|
||||||
|
"updateFastCheck": true,
|
||||||
|
"useWhitelist": false,
|
||||||
|
"mainClass": "net.minecraft.launchwrapper.Launch",
|
||||||
|
"jvmArgs": [
|
||||||
|
"-Dfml.ignorePatchDiscrepancies=true",
|
||||||
|
"-Dfml.ignoreInvalidMinecraftCertificates=true",
|
||||||
|
"-XX:+UseConcMarkSweepGC",
|
||||||
|
"-XX:+CMSIncrementalMode",
|
||||||
|
"-XX:-UseAdaptiveSizePolicy",
|
||||||
|
"-Xmn128M",
|
||||||
|
"-XX:+DisableAttachMechanism"
|
||||||
|
],
|
||||||
|
"classPath": ["forge.jar", "liteloader.jar", "minecraft.jar", "libraries"],
|
||||||
|
"clientArgs": [
|
||||||
|
"--tweakClass", "net.minecraftforge.fml.common.launcher.FMLTweaker",
|
||||||
|
"--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker"
|
||||||
|
],
|
||||||
|
"optionalJVMArgs": [],
|
||||||
|
"optionalClientArgs": [],
|
||||||
|
"optionalClassPath": [],
|
||||||
|
"whitelist": []
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
{
|
||||||
|
"version": "1.9.4",
|
||||||
|
"assetIndex": "1.9.4",
|
||||||
|
"assetDir": "asset1.9.4",
|
||||||
|
"dir": "xxxxxxx",
|
||||||
|
"info": "Информация о сервере",
|
||||||
|
"sortIndex": 0,
|
||||||
|
"title": "Test1.9.4",
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"name": "----",
|
||||||
|
"serverAddress": "localhost",
|
||||||
|
"serverPort": 25565,
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"update": ["servers.dat"],
|
||||||
|
"updateExclusions": [],
|
||||||
|
"updateShared": [],
|
||||||
|
"updateVerify": [
|
||||||
|
"libraries", "natives", "mods",
|
||||||
|
"minecraft.jar", "forge.jar", "liteloader.jar"
|
||||||
|
],
|
||||||
|
"updateOptional": [
|
||||||
|
],
|
||||||
|
"updateFastCheck": true,
|
||||||
|
"useWhitelist": false,
|
||||||
|
"mainClass": "net.minecraft.launchwrapper.Launch",
|
||||||
|
"jvmArgs": [
|
||||||
|
"-Dfml.ignorePatchDiscrepancies=true",
|
||||||
|
"-Dfml.ignoreInvalidMinecraftCertificates=true",
|
||||||
|
"-XX:+UseConcMarkSweepGC",
|
||||||
|
"-XX:+CMSIncrementalMode",
|
||||||
|
"-XX:-UseAdaptiveSizePolicy",
|
||||||
|
"-Xmn128M",
|
||||||
|
"-XX:+DisableAttachMechanism"
|
||||||
|
],
|
||||||
|
"classPath": ["forge.jar", "liteloader.jar", "minecraft.jar", "libraries"],
|
||||||
|
"clientArgs": [
|
||||||
|
"--tweakClass", "net.minecraftforge.fml.common.launcher.FMLTweaker",
|
||||||
|
"--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker"
|
||||||
|
],
|
||||||
|
"optionalJVMArgs": [],
|
||||||
|
"optionalClientArgs": [],
|
||||||
|
"optionalClassPath": [],
|
||||||
|
"whitelist": []
|
||||||
|
}
|
|
@ -21,7 +21,7 @@ public class ASMTransformersTest {
|
||||||
public static ASMClassLoader classLoader;
|
public static ASMClassLoader classLoader;
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
public static void prepare() {
|
public static void prepare() throws Throwable {
|
||||||
classLoader = new ASMClassLoader(ASMTransformersTest.class.getClassLoader());
|
classLoader = new ASMClassLoader(ASMTransformersTest.class.getClassLoader());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.jupiter.api.io.TempDir;
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
import pro.gravit.launcher.Launcher;
|
import pro.gravit.launcher.Launcher;
|
||||||
import pro.gravit.launchserver.config.LaunchServerConfig;
|
import pro.gravit.launchserver.config.LaunchServerConfig;
|
||||||
|
@ -46,9 +45,4 @@ public static void prepare() throws Throwable {
|
||||||
.setCommandHandler(new StdCommandHandler(false));
|
.setCommandHandler(new StdCommandHandler(false));
|
||||||
launchServer = builder.build();
|
launchServer = builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void test() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
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 java.io.IOException;
|
||||||
|
|
||||||
public class TestLaunchServerConfigManager implements LaunchServer.LaunchServerConfigManager {
|
public class TestLaunchServerConfigManager implements LaunchServer.LaunchServerConfigManager {
|
||||||
public LaunchServerConfig config;
|
public LaunchServerConfig config;
|
||||||
public LaunchServerRuntimeConfig runtimeConfig;
|
public LaunchServerRuntimeConfig runtimeConfig;
|
||||||
|
@ -15,22 +17,22 @@ public TestLaunchServerConfigManager() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LaunchServerConfig readConfig() {
|
public LaunchServerConfig readConfig() throws IOException {
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LaunchServerRuntimeConfig readRuntimeConfig() {
|
public LaunchServerRuntimeConfig readRuntimeConfig() throws IOException {
|
||||||
return runtimeConfig;
|
return runtimeConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeConfig(LaunchServerConfig config) {
|
public void writeConfig(LaunchServerConfig config) throws IOException {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeRuntimeConfig(LaunchServerRuntimeConfig config) {
|
public void writeRuntimeConfig(LaunchServerRuntimeConfig config) throws IOException {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,12 +29,12 @@
|
||||||
"Multi-Release": "true")
|
"Multi-Release": "true")
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register('sourcesJar', Jar) {
|
task sourcesJar(type: Jar) {
|
||||||
from sourceSets.main.allJava
|
from sourceSets.main.allJava
|
||||||
archiveClassifier.set('sources')
|
archiveClassifier.set('sources')
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register('javadocJar', Jar) {
|
task javadocJar(type: Jar) {
|
||||||
from javadoc
|
from javadoc
|
||||||
archiveClassifier.set('javadoc')
|
archiveClassifier.set('javadoc')
|
||||||
}
|
}
|
||||||
|
@ -53,14 +53,14 @@ pack project(':LauncherAPI')
|
||||||
pack group: 'io.netty', name: 'netty-codec-http', version: rootProject['verNetty']
|
pack group: 'io.netty', name: 'netty-codec-http', version: rootProject['verNetty']
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register('genRuntimeJS', Zip) {
|
task genRuntimeJS(type: Zip) {
|
||||||
duplicatesStrategy = 'EXCLUDE'
|
duplicatesStrategy = 'EXCLUDE'
|
||||||
archiveFileName = "runtime.zip"
|
archiveFileName = "runtime.zip"
|
||||||
destinationDirectory = file("${buildDir}/tmp")
|
destinationDirectory = file("${buildDir}/tmp")
|
||||||
from "runtime/"
|
from "runtime/"
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register('dumpLibs', Copy) {
|
task dumpLibs(type: Copy) {
|
||||||
duplicatesStrategy = 'EXCLUDE'
|
duplicatesStrategy = 'EXCLUDE'
|
||||||
into "$buildDir/libs/libraries"
|
into "$buildDir/libs/libraries"
|
||||||
from configurations.bundle
|
from configurations.bundle
|
||||||
|
|
|
@ -83,6 +83,8 @@ public static void main(String[] arguments) throws IOException, InterruptedExcep
|
||||||
}
|
}
|
||||||
|
|
||||||
context.executePath = IOHelper.resolveJavaBin(context.javaVersion.jvmDir);
|
context.executePath = IOHelper.resolveJavaBin(context.javaVersion.jvmDir);
|
||||||
|
//List<String> args = new LinkedList<>();
|
||||||
|
//args.add(javaBin.toString());
|
||||||
String pathLauncher = IOHelper.getCodeSource(LauncherEngine.class).toString();
|
String pathLauncher = IOHelper.getCodeSource(LauncherEngine.class).toString();
|
||||||
context.mainClass = LauncherEngine.class.getName();
|
context.mainClass = LauncherEngine.class.getName();
|
||||||
context.memoryLimit = launcherMemoryLimit;
|
context.memoryLimit = launcherMemoryLimit;
|
||||||
|
@ -141,12 +143,8 @@ public static void main(String[] arguments) throws IOException, InterruptedExcep
|
||||||
if (customJvmOptions != null) {
|
if (customJvmOptions != null) {
|
||||||
args.addAll(customJvmOptions);
|
args.addAll(customJvmOptions);
|
||||||
}
|
}
|
||||||
if(context.useLegacyClasspathProperty) {
|
|
||||||
args.add(String.format("-Djava.class.path=%s", String.join(IOHelper.PLATFORM_SEPARATOR, context.classpath)));
|
|
||||||
} else {
|
|
||||||
args.add("-cp");
|
args.add("-cp");
|
||||||
args.add(String.join(IOHelper.PLATFORM_SEPARATOR, context.classpath));
|
args.add(String.join(IOHelper.PLATFORM_SEPARATOR, context.classpath));
|
||||||
}
|
|
||||||
args.add(context.mainClass);
|
args.add(context.mainClass);
|
||||||
args.addAll(context.clientArgs);
|
args.addAll(context.clientArgs);
|
||||||
LogHelper.debug("Commandline: " + args);
|
LogHelper.debug("Commandline: " + args);
|
||||||
|
@ -174,7 +172,6 @@ public static class ClientLauncherWrapperContext {
|
||||||
public Path executePath;
|
public Path executePath;
|
||||||
public String mainClass;
|
public String mainClass;
|
||||||
public int memoryLimit;
|
public int memoryLimit;
|
||||||
public boolean useLegacyClasspathProperty;
|
|
||||||
public ProcessBuilder processBuilder;
|
public ProcessBuilder processBuilder;
|
||||||
public List<String> args = new ArrayList<>(8);
|
public List<String> args = new ArrayList<>(8);
|
||||||
public Map<String, String> jvmProperties = new HashMap<>();
|
public Map<String, String> jvmProperties = new HashMap<>();
|
||||||
|
|
|
@ -8,6 +8,9 @@
|
||||||
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.events.request.*;
|
||||||
|
import pro.gravit.launcher.guard.LauncherGuard;
|
||||||
|
import pro.gravit.launcher.guard.LauncherNoGuard;
|
||||||
|
import pro.gravit.launcher.guard.LauncherWrapperGuard;
|
||||||
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.ClientGsonManager;
|
||||||
|
@ -46,6 +49,7 @@
|
||||||
|
|
||||||
public class LauncherEngine {
|
public class LauncherEngine {
|
||||||
public static ClientLauncherProcess.ClientParams clientParams;
|
public static ClientLauncherProcess.ClientParams clientParams;
|
||||||
|
public static LauncherGuard guard;
|
||||||
public static ClientModuleManager modulesManager;
|
public static ClientModuleManager modulesManager;
|
||||||
public final boolean clientInstance;
|
public final boolean clientInstance;
|
||||||
// Instance
|
// Instance
|
||||||
|
@ -130,6 +134,8 @@ public static void main(String... args) throws Throwable {
|
||||||
}
|
}
|
||||||
long endTime = System.currentTimeMillis();
|
long endTime = System.currentTimeMillis();
|
||||||
LogHelper.debug("Launcher started in %dms", endTime - startTime);
|
LogHelper.debug("Launcher started in %dms", endTime - startTime);
|
||||||
|
//Request.service.close();
|
||||||
|
//FunctionalBridge.close();
|
||||||
LauncherEngine.exitLauncher(0);
|
LauncherEngine.exitLauncher(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,6 +153,16 @@ public static void verifyNoAgent() {
|
||||||
throw new SecurityException("JavaAgent found");
|
throw new SecurityException("JavaAgent found");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static LauncherGuard tryGetStdGuard() {
|
||||||
|
switch (Launcher.getConfig().guardType) {
|
||||||
|
case "no":
|
||||||
|
return new LauncherNoGuard();
|
||||||
|
case "wrapper":
|
||||||
|
return new LauncherWrapperGuard();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public static RequestService initOffline() {
|
public static RequestService initOffline() {
|
||||||
OfflineRequestService service = new OfflineRequestService();
|
OfflineRequestService service = new OfflineRequestService();
|
||||||
applyBasicOfflineProcessors(service);
|
applyBasicOfflineProcessors(service);
|
||||||
|
@ -216,6 +232,7 @@ public void readKeys() throws IOException, InvalidKeySpecException {
|
||||||
|
|
||||||
public void start(String... args) throws Throwable {
|
public void start(String... args) throws Throwable {
|
||||||
//Launcher.modulesManager = new ClientModuleManager(this);
|
//Launcher.modulesManager = new ClientModuleManager(this);
|
||||||
|
LauncherEngine.guard = tryGetStdGuard();
|
||||||
ClientPreGuiPhase event = new ClientPreGuiPhase(null);
|
ClientPreGuiPhase event = new ClientPreGuiPhase(null);
|
||||||
LauncherEngine.modulesManager.invokeEvent(event);
|
LauncherEngine.modulesManager.invokeEvent(event);
|
||||||
runtimeProvider = event.runtimeProvider;
|
runtimeProvider = event.runtimeProvider;
|
||||||
|
|
|
@ -5,15 +5,10 @@
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class ClientClassLoader extends URLClassLoader {
|
public class ClientClassLoader extends URLClassLoader {
|
||||||
private static final ClassLoader SYSTEM_CLASS_LOADER = ClassLoader.getSystemClassLoader();
|
|
||||||
public String nativePath;
|
public String nativePath;
|
||||||
|
|
||||||
private final List<String> packages = new ArrayList<>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new URLClassLoader for the specified URLs using the
|
* Constructs a new URLClassLoader for the specified URLs using the
|
||||||
* default delegation parent {@code ClassLoader}. The URLs will
|
* default delegation parent {@code ClassLoader}. The URLs will
|
||||||
|
@ -32,11 +27,10 @@ public class ClientClassLoader extends URLClassLoader {
|
||||||
* {@code checkCreateClassLoader} method doesn't allow
|
* {@code checkCreateClassLoader} method doesn't allow
|
||||||
* creation of a class loader.
|
* creation of a class loader.
|
||||||
* @throws NullPointerException if {@code urls} is {@code null}.
|
* @throws NullPointerException if {@code urls} is {@code null}.
|
||||||
|
* @see SecurityManager#checkCreateClassLoader
|
||||||
*/
|
*/
|
||||||
public ClientClassLoader(URL[] urls) {
|
public ClientClassLoader(URL[] urls) {
|
||||||
super(urls);
|
super(urls);
|
||||||
packages.add("pro.gravit.launcher.");
|
|
||||||
packages.add("pro.gravit.utils.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -58,23 +52,12 @@ public ClientClassLoader(URL[] urls) {
|
||||||
* {@code checkCreateClassLoader} method doesn't allow
|
* {@code checkCreateClassLoader} method doesn't allow
|
||||||
* creation of a class loader.
|
* creation of a class loader.
|
||||||
* @throws NullPointerException if {@code urls} is {@code null}.
|
* @throws NullPointerException if {@code urls} is {@code null}.
|
||||||
|
* @see SecurityManager#checkCreateClassLoader
|
||||||
*/
|
*/
|
||||||
public ClientClassLoader(URL[] urls, ClassLoader parent) {
|
public ClientClassLoader(URL[] urls, ClassLoader parent) {
|
||||||
super(urls, parent);
|
super(urls, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
|
|
||||||
if(name != null) {
|
|
||||||
for(String pkg : packages) {
|
|
||||||
if(name.startsWith(pkg)) {
|
|
||||||
return SYSTEM_CLASS_LOADER.loadClass(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return super.loadClass(name, resolve);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String findLibrary(String name) {
|
public String findLibrary(String name) {
|
||||||
return nativePath.concat(IOHelper.PLATFORM_SEPARATOR).concat(getNativePrefix()).concat(name).concat(getNativeEx());
|
return nativePath.concat(IOHelper.PLATFORM_SEPARATOR).concat(getNativePrefix()).concat(name).concat(getNativeEx());
|
||||||
|
@ -98,10 +81,6 @@ else if (JVMHelper.OS_TYPE == JVMHelper.OS.MACOSX)
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAllowedPackage(String pkg) {
|
|
||||||
packages.add(pkg);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addURL(URL url) {
|
public void addURL(URL url) {
|
||||||
super.addURL(url);
|
super.addURL(url);
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
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;
|
||||||
import pro.gravit.launcher.profiles.ClientProfile;
|
import pro.gravit.launcher.profiles.ClientProfile;
|
||||||
import pro.gravit.launcher.profiles.ClientProfileVersions;
|
|
||||||
import pro.gravit.launcher.profiles.optional.actions.OptionalAction;
|
import pro.gravit.launcher.profiles.optional.actions.OptionalAction;
|
||||||
import pro.gravit.launcher.profiles.optional.actions.OptionalActionClassPath;
|
import pro.gravit.launcher.profiles.optional.actions.OptionalActionClassPath;
|
||||||
import pro.gravit.launcher.profiles.optional.actions.OptionalActionClientArgs;
|
import pro.gravit.launcher.profiles.optional.actions.OptionalActionClientArgs;
|
||||||
|
@ -34,6 +33,7 @@
|
||||||
import pro.gravit.launcher.utils.DirWatcher;
|
import pro.gravit.launcher.utils.DirWatcher;
|
||||||
import pro.gravit.utils.helper.*;
|
import pro.gravit.utils.helper.*;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
|
@ -46,7 +46,6 @@
|
||||||
import java.nio.file.SimpleFileVisitor;
|
import java.nio.file.SimpleFileVisitor;
|
||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
@ -108,6 +107,7 @@ public static void main(String[] args) throws Throwable {
|
||||||
} else if (params.session != null) {
|
} else if (params.session != null) {
|
||||||
throw new UnsupportedOperationException("Legacy session not supported");
|
throw new UnsupportedOperationException("Legacy session not supported");
|
||||||
}
|
}
|
||||||
|
checkJVMBitsAndVersion(params.profile.getMinJavaVersion(), params.profile.getRecommendJavaVersion(), params.profile.getMaxJavaVersion(), params.profile.isWarnMissJavaVersion());
|
||||||
LauncherEngine.modulesManager.invokeEvent(new ClientProcessInitPhase(engine, params));
|
LauncherEngine.modulesManager.invokeEvent(new ClientProcessInitPhase(engine, params));
|
||||||
|
|
||||||
Path clientDir = Paths.get(params.clientDir);
|
Path clientDir = Paths.get(params.clientDir);
|
||||||
|
@ -144,7 +144,7 @@ public static void main(String[] args) throws Throwable {
|
||||||
LogHelper.debug("Natives dir %s", params.nativesDir);
|
LogHelper.debug("Natives dir %s", params.nativesDir);
|
||||||
ClientProfile.ClassLoaderConfig classLoaderConfig = profile.getClassLoaderConfig();
|
ClientProfile.ClassLoaderConfig classLoaderConfig = profile.getClassLoaderConfig();
|
||||||
if (classLoaderConfig == ClientProfile.ClassLoaderConfig.LAUNCHER) {
|
if (classLoaderConfig == ClientProfile.ClassLoaderConfig.LAUNCHER) {
|
||||||
ClientClassLoader classLoader = new ClientClassLoader(classpathURLs.toArray(new URL[0]), ClientLauncherEntryPoint.class.getClassLoader());
|
ClientClassLoader classLoader = new ClientClassLoader(classpathURLs.toArray(new URL[0]), ClassLoader.getSystemClassLoader());
|
||||||
System.setProperty("java.class.path", classpath.stream().map(Path::toString).collect(Collectors.joining(File.pathSeparator)));
|
System.setProperty("java.class.path", classpath.stream().map(Path::toString).collect(Collectors.joining(File.pathSeparator)));
|
||||||
ClientLauncherEntryPoint.classLoader = classLoader;
|
ClientLauncherEntryPoint.classLoader = classLoader;
|
||||||
Thread.currentThread().setContextClassLoader(classLoader);
|
Thread.currentThread().setContextClassLoader(classLoader);
|
||||||
|
@ -174,6 +174,15 @@ public static void main(String[] args) throws Throwable {
|
||||||
AuthService.username = params.playerProfile.username;
|
AuthService.username = params.playerProfile.username;
|
||||||
AuthService.uuid = params.playerProfile.uuid;
|
AuthService.uuid = params.playerProfile.uuid;
|
||||||
KeyService.serverRsaPublicKey = Launcher.getConfig().rsaPublicKey;
|
KeyService.serverRsaPublicKey = Launcher.getConfig().rsaPublicKey;
|
||||||
|
if (params.profile.getRuntimeInClientConfig() != ClientProfile.RuntimeInClientConfig.NONE) {
|
||||||
|
CommonHelper.newThread("Client Launcher Thread", true, () -> {
|
||||||
|
try {
|
||||||
|
engine.start(args);
|
||||||
|
} catch (Throwable throwable) {
|
||||||
|
LogHelper.error(throwable);
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
LauncherEngine.modulesManager.invokeEvent(new ClientProcessReadyEvent(engine, params));
|
LauncherEngine.modulesManager.invokeEvent(new ClientProcessReadyEvent(engine, params));
|
||||||
LogHelper.debug("Starting JVM and client WatchService");
|
LogHelper.debug("Starting JVM and client WatchService");
|
||||||
FileNameMatcher assetMatcher = profile.getAssetUpdateMatcher();
|
FileNameMatcher assetMatcher = profile.getAssetUpdateMatcher();
|
||||||
|
@ -242,26 +251,45 @@ public static void verifyHDir(Path dir, HashedDir hdir, FileNameMatcher matcher,
|
||||||
// Hash directory and compare (ignore update-only matcher entries, it will break offline-mode)
|
// Hash directory and compare (ignore update-only matcher entries, it will break offline-mode)
|
||||||
HashedDir currentHDir = new HashedDir(dir, matcher, true, digest);
|
HashedDir currentHDir = new HashedDir(dir, matcher, true, digest);
|
||||||
HashedDir.Diff diff = hdir.diff(currentHDir, matcher);
|
HashedDir.Diff diff = hdir.diff(currentHDir, matcher);
|
||||||
AtomicReference<String> latestPath = new AtomicReference<>("unknown");
|
|
||||||
if (!diff.mismatch.isEmpty() || (checkExtra && !diff.extra.isEmpty())) {
|
if (!diff.mismatch.isEmpty() || (checkExtra && !diff.extra.isEmpty())) {
|
||||||
diff.extra.walk(File.separator, (e, k, v) -> {
|
diff.extra.walk(File.separator, (e, k, v) -> {
|
||||||
if (v.getType().equals(HashedEntry.Type.FILE)) {
|
if (v.getType().equals(HashedEntry.Type.FILE)) {
|
||||||
LogHelper.error("Extra file %s", e);
|
LogHelper.error("Extra file %s", e);
|
||||||
latestPath.set(e);
|
|
||||||
} else LogHelper.error("Extra %s", e);
|
} else LogHelper.error("Extra %s", e);
|
||||||
return HashedDir.WalkAction.CONTINUE;
|
return HashedDir.WalkAction.CONTINUE;
|
||||||
});
|
});
|
||||||
diff.mismatch.walk(File.separator, (e, k, v) -> {
|
diff.mismatch.walk(File.separator, (e, k, v) -> {
|
||||||
if (v.getType().equals(HashedEntry.Type.FILE)) {
|
if (v.getType().equals(HashedEntry.Type.FILE)) {
|
||||||
LogHelper.error("Mismatch file %s", e);
|
LogHelper.error("Mismatch file %s", e);
|
||||||
latestPath.set(e);
|
|
||||||
} else LogHelper.error("Mismatch %s", e);
|
} else LogHelper.error("Mismatch %s", e);
|
||||||
return HashedDir.WalkAction.CONTINUE;
|
return HashedDir.WalkAction.CONTINUE;
|
||||||
});
|
});
|
||||||
throw new SecurityException(String.format("Forbidden modification: '%s' file '%s'", IOHelper.getFileName(dir), latestPath.get()));
|
throw new SecurityException(String.format("Forbidden modification: '%s'", IOHelper.getFileName(dir)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean checkJVMBitsAndVersion(int minVersion, int recommendVersion, int maxVersion, boolean showMessage) {
|
||||||
|
boolean ok = true;
|
||||||
|
if (JVMHelper.JVM_BITS == 64 && JVMHelper.ARCH_TYPE == JVMHelper.ARCH.X86) {
|
||||||
|
String error = "У Вас установлена Java x64, но Ваша система определена как x32. Установите Java правильной разрядности";
|
||||||
|
LogHelper.error(error);
|
||||||
|
if (showMessage)
|
||||||
|
JOptionPane.showMessageDialog(null, error);
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
String jvmVersion = JVMHelper.RUNTIME_MXBEAN.getVmVersion();
|
||||||
|
LogHelper.info(jvmVersion);
|
||||||
|
int version = JVMHelper.getVersion();
|
||||||
|
if (version < minVersion || version > maxVersion) {
|
||||||
|
String error = String.format("У Вас установлена Java %d, но этот клиент требует Java %d", JVMHelper.getVersion(), recommendVersion);
|
||||||
|
LogHelper.error(error);
|
||||||
|
if (showMessage)
|
||||||
|
JOptionPane.showMessageDialog(null, error);
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
private static LinkedList<Path> resolveClassPathList(Path clientDir, String... classPath) throws IOException {
|
private static LinkedList<Path> resolveClassPathList(Path clientDir, String... classPath) throws IOException {
|
||||||
return resolveClassPathStream(clientDir, classPath).collect(Collectors.toCollection(LinkedList::new));
|
return resolveClassPathStream(clientDir, classPath).collect(Collectors.toCollection(LinkedList::new));
|
||||||
}
|
}
|
||||||
|
@ -291,7 +319,7 @@ public static Stream<Path> resolveClassPath(Path clientDir, Set<OptionalAction>
|
||||||
private static void launch(ClientProfile profile, ClientLauncherProcess.ClientParams params) throws Throwable {
|
private static void launch(ClientProfile profile, ClientLauncherProcess.ClientParams params) throws Throwable {
|
||||||
// Add client args
|
// Add client args
|
||||||
Collection<String> args = new LinkedList<>();
|
Collection<String> args = new LinkedList<>();
|
||||||
if (profile.getVersion().compareTo(ClientProfileVersions.MINECRAFT_1_6_4) >= 0)
|
if (profile.getVersion().compareTo(ClientProfile.Version.MC164) >= 0)
|
||||||
params.addClientArgs(args);
|
params.addClientArgs(args);
|
||||||
else {
|
else {
|
||||||
params.addClientLegacyArgs(args);
|
params.addClientLegacyArgs(args);
|
||||||
|
@ -325,7 +353,7 @@ private static void launch(ClientProfile profile, ClientLauncherProcess.ClientPa
|
||||||
List<String> compatClasses = profile.getCompatClasses();
|
List<String> compatClasses = profile.getCompatClasses();
|
||||||
for (String e : compatClasses) {
|
for (String e : compatClasses) {
|
||||||
Class<?> clazz = classLoader.loadClass(e);
|
Class<?> clazz = classLoader.loadClass(e);
|
||||||
MethodHandle runMethod = MethodHandles.lookup().findStatic(clazz, "run", MethodType.methodType(void.class));
|
MethodHandle runMethod = MethodHandles.publicLookup().findStatic(clazz, "run", MethodType.methodType(void.class));
|
||||||
runMethod.invoke();
|
runMethod.invoke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
import pro.gravit.launcher.events.request.AuthRequestEvent;
|
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;
|
||||||
|
@ -32,8 +31,6 @@
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class ClientLauncherProcess {
|
public class ClientLauncherProcess {
|
||||||
|
|
||||||
public final List<String> pre = new LinkedList<>();
|
|
||||||
public final ClientParams params = new ClientParams();
|
public final ClientParams params = new ClientParams();
|
||||||
public final List<String> jvmArgs = new LinkedList<>();
|
public final List<String> jvmArgs = new LinkedList<>();
|
||||||
public final List<String> jvmModules = new LinkedList<>();
|
public final List<String> jvmModules = new LinkedList<>();
|
||||||
|
@ -79,14 +76,9 @@ public ClientLauncherProcess(Path clientDir, Path assetDir, JavaHelper.JavaVersi
|
||||||
this.params.clientDir = this.workDir.toString();
|
this.params.clientDir = this.workDir.toString();
|
||||||
this.params.resourcePackDir = resourcePackDir.toAbsolutePath().toString();
|
this.params.resourcePackDir = resourcePackDir.toAbsolutePath().toString();
|
||||||
this.params.assetDir = assetDir.toAbsolutePath().toString();
|
this.params.assetDir = assetDir.toAbsolutePath().toString();
|
||||||
Path nativesPath;
|
Path nativesPath = workDir.resolve("natives").resolve(JVMHelper.OS_TYPE.name).resolve(javaVersion.arch.name);
|
||||||
if(profile.hasFlag(ClientProfile.CompatibilityFlags.LEGACY_NATIVES_DIR)) {
|
|
||||||
nativesPath = workDir.resolve("natives");
|
|
||||||
} else {
|
|
||||||
nativesPath = workDir.resolve("natives").resolve(JVMHelper.OS_TYPE.name).resolve(javaVersion.arch.name);
|
|
||||||
}
|
|
||||||
if (!Files.isDirectory(nativesPath)) {
|
if (!Files.isDirectory(nativesPath)) {
|
||||||
throw new RuntimeException(String.format("Natives dir %s not exist! Your operating system or architecture not supported", nativesPath.toAbsolutePath()));
|
nativesPath = workDir.resolve("natives");
|
||||||
}
|
}
|
||||||
this.params.nativesDir = nativesPath.toString();
|
this.params.nativesDir = nativesPath.toString();
|
||||||
this.params.profile = profile;
|
this.params.profile = profile;
|
||||||
|
@ -131,13 +123,24 @@ private void applyClientProfile() {
|
||||||
}
|
}
|
||||||
this.jvmModules.addAll(this.params.profile.getModules());
|
this.jvmModules.addAll(this.params.profile.getModules());
|
||||||
this.jvmModulesPaths.addAll(this.params.profile.getModulePath());
|
this.jvmModulesPaths.addAll(this.params.profile.getModulePath());
|
||||||
|
if (this.params.profile.getRuntimeInClientConfig() != ClientProfile.RuntimeInClientConfig.NONE) {
|
||||||
|
jvmModules.add("javafx.base");
|
||||||
|
jvmModules.add("javafx.graphics");
|
||||||
|
jvmModules.add("javafx.fxml");
|
||||||
|
jvmModules.add("javafx.controls");
|
||||||
|
jvmModules.add("javafx.swing");
|
||||||
|
jvmModules.add("javafx.media");
|
||||||
|
jvmModules.add("javafx.web");
|
||||||
|
}
|
||||||
|
|
||||||
LauncherEngine.modulesManager.invokeEvent(new ClientProcessBuilderCreateEvent(this));
|
LauncherEngine.modulesManager.invokeEvent(new ClientProcessBuilderCreateEvent(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start(boolean pipeOutput) throws IOException, InterruptedException {
|
public void start(boolean pipeOutput) throws IOException, InterruptedException {
|
||||||
if (isStarted) throw new IllegalStateException("Process already started");
|
if (isStarted) throw new IllegalStateException("Process already started");
|
||||||
|
if (LauncherEngine.guard != null) LauncherEngine.guard.applyGuardParams(this);
|
||||||
LauncherEngine.modulesManager.invokeEvent(new ClientProcessBuilderPreLaunchEvent(this));
|
LauncherEngine.modulesManager.invokeEvent(new ClientProcessBuilderPreLaunchEvent(this));
|
||||||
List<String> processArgs = new LinkedList<>(pre);
|
List<String> processArgs = new LinkedList<>();
|
||||||
processArgs.add(executeFile.toString());
|
processArgs.add(executeFile.toString());
|
||||||
processArgs.addAll(jvmArgs);
|
processArgs.addAll(jvmArgs);
|
||||||
if (javaVersion.version >= 9) {
|
if (javaVersion.version >= 9) {
|
||||||
|
@ -189,10 +192,20 @@ public void start(boolean pipeOutput) throws IOException, InterruptedException {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyJava9Params(List<String> processArgs) {
|
private void applyJava9Params(List<String> processArgs) {
|
||||||
// TODO: fix runtime in client
|
/*jvmModulesPaths.add(javaVersion.jvmDir);
|
||||||
|
jvmModulesPaths.add(javaVersion.jvmDir.resolve("jre"));
|
||||||
|
Path openjfxPath = JavaHelper.tryGetOpenJFXPath(javaVersion.jvmDir);
|
||||||
|
if (openjfxPath != null) {
|
||||||
|
jvmModulesPaths.add(openjfxPath);
|
||||||
|
}*/ // TODO: fix runtime in client
|
||||||
StringBuilder modulesPath = new StringBuilder();
|
StringBuilder modulesPath = new StringBuilder();
|
||||||
StringBuilder modulesAdd = new StringBuilder();
|
StringBuilder modulesAdd = new StringBuilder();
|
||||||
for (String moduleName : jvmModules) {
|
for (String moduleName : jvmModules) {
|
||||||
|
/*boolean success = JavaHelper.tryAddModule(jvmModulesPaths, moduleName, modulesPath);
|
||||||
|
if (success) {
|
||||||
|
if (modulesAdd.length() > 0) modulesAdd.append(",");
|
||||||
|
modulesAdd.append(moduleName);
|
||||||
|
}*/
|
||||||
if (modulesAdd.length() > 0) modulesAdd.append(",");
|
if (modulesAdd.length() > 0) modulesAdd.append(",");
|
||||||
modulesAdd.append(moduleName);
|
modulesAdd.append(moduleName);
|
||||||
}
|
}
|
||||||
|
@ -290,7 +303,7 @@ public static class ClientParams {
|
||||||
public transient HashedDir javaHDir;
|
public transient HashedDir javaHDir;
|
||||||
|
|
||||||
public void addClientArgs(Collection<String> args) {
|
public void addClientArgs(Collection<String> args) {
|
||||||
if (profile.getVersion().compareTo(ClientProfileVersions.MINECRAFT_1_6_4) >= 0)
|
if (profile.getVersion().compareTo(ClientProfile.Version.MC164) >= 0)
|
||||||
addModernClientArgs(args);
|
addModernClientArgs(args);
|
||||||
else
|
else
|
||||||
addClientLegacyArgs(args);
|
addClientLegacyArgs(args);
|
||||||
|
@ -301,7 +314,7 @@ public void addClientLegacyArgs(Collection<String> args) {
|
||||||
args.add(accessToken);
|
args.add(accessToken);
|
||||||
|
|
||||||
// Add args for tweaker
|
// Add args for tweaker
|
||||||
Collections.addAll(args, "--version", profile.getVersion().toString());
|
Collections.addAll(args, "--version", profile.getVersion().name);
|
||||||
Collections.addAll(args, "--gameDir", clientDir);
|
Collections.addAll(args, "--gameDir", clientDir);
|
||||||
Collections.addAll(args, "--assetsDir", assetDir);
|
Collections.addAll(args, "--assetsDir", assetDir);
|
||||||
}
|
}
|
||||||
|
@ -311,12 +324,12 @@ private void addModernClientArgs(Collection<String> args) {
|
||||||
// Add version-dependent args
|
// Add version-dependent args
|
||||||
ClientProfile.Version version = profile.getVersion();
|
ClientProfile.Version version = profile.getVersion();
|
||||||
Collections.addAll(args, "--username", playerProfile.username);
|
Collections.addAll(args, "--username", playerProfile.username);
|
||||||
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_7_2) >= 0) {
|
if (version.compareTo(ClientProfile.Version.MC172) >= 0) {
|
||||||
Collections.addAll(args, "--uuid", Launcher.toHash(playerProfile.uuid));
|
Collections.addAll(args, "--uuid", Launcher.toHash(playerProfile.uuid));
|
||||||
Collections.addAll(args, "--accessToken", accessToken);
|
Collections.addAll(args, "--accessToken", accessToken);
|
||||||
|
|
||||||
// Add 1.7.10+ args (user properties, asset index)
|
// Add 1.7.10+ args (user properties, asset index)
|
||||||
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_7_10) >= 0) {
|
if (version.compareTo(ClientProfile.Version.MC1710) >= 0) {
|
||||||
// Add user properties
|
// Add user properties
|
||||||
Collections.addAll(args, "--userType", "mojang");
|
Collections.addAll(args, "--userType", "mojang");
|
||||||
Collections.addAll(args, "--userProperties", "{}");
|
Collections.addAll(args, "--userProperties", "{}");
|
||||||
|
@ -328,11 +341,11 @@ private void addModernClientArgs(Collection<String> args) {
|
||||||
Collections.addAll(args, "--session", accessToken);
|
Collections.addAll(args, "--session", accessToken);
|
||||||
|
|
||||||
// Add version and dirs args
|
// Add version and dirs args
|
||||||
Collections.addAll(args, "--version", profile.getVersion().toString());
|
Collections.addAll(args, "--version", profile.getVersion().name);
|
||||||
Collections.addAll(args, "--gameDir", clientDir);
|
Collections.addAll(args, "--gameDir", clientDir);
|
||||||
Collections.addAll(args, "--assetsDir", assetDir);
|
Collections.addAll(args, "--assetsDir", assetDir);
|
||||||
Collections.addAll(args, "--resourcePackDir", resourcePackDir);
|
Collections.addAll(args, "--resourcePackDir", resourcePackDir);
|
||||||
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_9_4) >= 0)
|
if (version.compareTo(ClientProfile.Version.MC194) >= 0)
|
||||||
Collections.addAll(args, "--versionType", "Launcher v" + Version.getVersion().getVersionString());
|
Collections.addAll(args, "--versionType", "Launcher v" + Version.getVersion().getVersionString());
|
||||||
|
|
||||||
// Add server args
|
// Add server args
|
||||||
|
|
|
@ -112,17 +112,6 @@ public static Path getGuardDir() {
|
||||||
return dir.resolve("guard");
|
return dir.resolve("guard");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Path getGuardDir(JVMHelper.ARCH arch, JVMHelper.OS os) {
|
|
||||||
Path dir = getGuardDir().resolve(Launcher.makeSpecialGuardDirName(arch, os));
|
|
||||||
try {
|
|
||||||
IOHelper.createParentDirs(dir);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
return dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static Path getLegacyLauncherDir(String projectname) {
|
public static Path getLegacyLauncherDir(String projectname) {
|
||||||
return IOHelper.HOME_DIR.resolve(projectname);
|
return IOHelper.HOME_DIR.resolve(projectname);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
import pro.gravit.launcher.profiles.ClientProfile;
|
import pro.gravit.launcher.profiles.ClientProfile;
|
||||||
import pro.gravit.launcher.profiles.ClientProfileVersions;
|
|
||||||
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.utils.helper.IOHelper;
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
|
@ -30,7 +29,6 @@ public final class ServerPinger {
|
||||||
private static final int PACKET_LENGTH = 65535;
|
private static final int PACKET_LENGTH = 65535;
|
||||||
// Instance
|
// Instance
|
||||||
private final InetSocketAddress address;
|
private final InetSocketAddress address;
|
||||||
private final int protocol;
|
|
||||||
private final ClientProfile.Version version;
|
private final ClientProfile.Version version;
|
||||||
// Cache
|
// Cache
|
||||||
private final Object cacheLock = new Object();
|
private final Object cacheLock = new Object();
|
||||||
|
@ -48,7 +46,6 @@ public ServerPinger(ClientProfile.ServerProfile profile, ClientProfile.Version v
|
||||||
}
|
}
|
||||||
this.address = profile.toSocketAddress();
|
this.address = profile.toSocketAddress();
|
||||||
this.version = Objects.requireNonNull(version, "version");
|
this.version = Objects.requireNonNull(version, "version");
|
||||||
this.protocol = profile.protocol;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String readUTF16String(HInput input) throws IOException {
|
private static String readUTF16String(HInput input) throws IOException {
|
||||||
|
@ -67,7 +64,7 @@ private Result doPing() throws IOException {
|
||||||
socket.connect(IOHelper.resolve(address), IOHelper.SOCKET_TIMEOUT);
|
socket.connect(IOHelper.resolve(address), IOHelper.SOCKET_TIMEOUT);
|
||||||
try (HInput input = new HInput(socket.getInputStream());
|
try (HInput input = new HInput(socket.getInputStream());
|
||||||
HOutput output = new HOutput(socket.getOutputStream())) {
|
HOutput output = new HOutput(socket.getOutputStream())) {
|
||||||
return version.compareTo(ClientProfileVersions.MINECRAFT_1_7_2) >= 0 ? modernPing(input, output, protocol) : legacyPing(input, output, version.compareTo(ClientProfileVersions.MINECRAFT_1_6_4) >= 0);
|
return version.compareTo(ClientProfile.Version.MC172) >= 0 ? modernPing(input, output) : legacyPing(input, output, version.compareTo(ClientProfile.Version.MC164) >= 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,7 +80,7 @@ private Result legacyPing(HInput input, HOutput output, boolean mc16) throws IOE
|
||||||
byte[] customPayloadPacket;
|
byte[] customPayloadPacket;
|
||||||
try (ByteArrayOutputStream packetArray = IOHelper.newByteArrayOutput()) {
|
try (ByteArrayOutputStream packetArray = IOHelper.newByteArrayOutput()) {
|
||||||
try (HOutput packetOutput = new HOutput(packetArray)) {
|
try (HOutput packetOutput = new HOutput(packetArray)) {
|
||||||
packetOutput.writeUnsignedByte(0x4a); // Protocol version
|
packetOutput.writeUnsignedByte(version.protocol); // Protocol version
|
||||||
writeUTF16String(packetOutput, address.getHostString()); // Server address
|
writeUTF16String(packetOutput, address.getHostString()); // Server address
|
||||||
packetOutput.writeInt(address.getPort()); // Server port
|
packetOutput.writeInt(address.getPort()); // Server port
|
||||||
}
|
}
|
||||||
|
@ -113,7 +110,11 @@ private Result legacyPing(HInput input, HOutput output, boolean mc16) throws IOE
|
||||||
if (!magic.equals(LEGACY_PING_HOST_MAGIC))
|
if (!magic.equals(LEGACY_PING_HOST_MAGIC))
|
||||||
throw new IOException("Magic file mismatch: " + magic);
|
throw new IOException("Magic file mismatch: " + magic);
|
||||||
int protocol = Integer.parseInt(splitted[1]);
|
int protocol = Integer.parseInt(splitted[1]);
|
||||||
|
if (protocol != version.protocol)
|
||||||
|
throw new IOException("Protocol mismatch: " + protocol);
|
||||||
String clientVersion = splitted[2];
|
String clientVersion = splitted[2];
|
||||||
|
if (!clientVersion.equals(version.name))
|
||||||
|
throw new IOException(String.format("Version mismatch: '%s'", clientVersion));
|
||||||
int onlinePlayers = VerifyHelper.verifyInt(Integer.parseInt(splitted[4]),
|
int onlinePlayers = VerifyHelper.verifyInt(Integer.parseInt(splitted[4]),
|
||||||
VerifyHelper.NOT_NEGATIVE, "onlinePlayers can't be < 0");
|
VerifyHelper.NOT_NEGATIVE, "onlinePlayers can't be < 0");
|
||||||
int maxPlayers = VerifyHelper.verifyInt(Integer.parseInt(splitted[5]),
|
int maxPlayers = VerifyHelper.verifyInt(Integer.parseInt(splitted[5]),
|
||||||
|
@ -123,13 +124,13 @@ private Result legacyPing(HInput input, HOutput output, boolean mc16) throws IOE
|
||||||
return new Result(onlinePlayers, maxPlayers, response);
|
return new Result(onlinePlayers, maxPlayers, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Result modernPing(HInput input, HOutput output, int protocol) throws IOException {
|
private Result modernPing(HInput input, HOutput output) throws IOException {
|
||||||
// Prepare handshake packet
|
// Prepare handshake packet
|
||||||
byte[] handshakePacket;
|
byte[] handshakePacket;
|
||||||
try (ByteArrayOutputStream packetArray = IOHelper.newByteArrayOutput()) {
|
try (ByteArrayOutputStream packetArray = IOHelper.newByteArrayOutput()) {
|
||||||
try (HOutput packetOutput = new HOutput(packetArray)) {
|
try (HOutput packetOutput = new HOutput(packetArray)) {
|
||||||
packetOutput.writeVarInt(0x0); // Handshake packet ID
|
packetOutput.writeVarInt(0x0); // Handshake packet ID
|
||||||
packetOutput.writeVarInt(protocol > 0 ? protocol : 0x4); // Protocol version
|
packetOutput.writeVarInt(version.protocol); // Protocol version
|
||||||
packetOutput.writeString(address.getHostString(), 0); // Server address
|
packetOutput.writeString(address.getHostString(), 0); // Server address
|
||||||
packetOutput.writeShort((short) address.getPort()); // Server port
|
packetOutput.writeShort((short) address.getPort()); // Server port
|
||||||
packetOutput.writeVarInt(0x1); // Next state - status
|
packetOutput.writeVarInt(0x1); // Next state - status
|
||||||
|
|
|
@ -24,7 +24,7 @@ public String getUsageDescription() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void invoke(String... args) {
|
public void invoke(String... args) throws Exception {
|
||||||
LogHelper.info("PublicKey: %s", Base64.getEncoder().encodeToString(engine.getClientPublicKey().getEncoded()));
|
LogHelper.info("PublicKey: %s", Base64.getEncoder().encodeToString(engine.getClientPublicKey().getEncoded()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ public String getUsageDescription() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void invoke(String... args) {
|
public void invoke(String... args) throws Exception {
|
||||||
for (LauncherModule module : LauncherEngine.modulesManager.getModules()) {
|
for (LauncherModule module : LauncherEngine.modulesManager.getModules()) {
|
||||||
LauncherModuleInfo info = module.getModuleInfo();
|
LauncherModuleInfo info = module.getModuleInfo();
|
||||||
LauncherTrustManager.CheckClassResult checkStatus = module.getCheckResult();
|
LauncherTrustManager.CheckClassResult checkStatus = module.getCheckResult();
|
||||||
|
|
|
@ -16,7 +16,7 @@ public String getUsageDescription() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void invoke(String... args) {
|
public void invoke(String... args) throws Exception {
|
||||||
LogHelper.info("Your Hardware ID:");
|
LogHelper.info("Your Hardware ID:");
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
long currentTime;
|
long currentTime;
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package pro.gravit.launcher.guard;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.client.ClientLauncherProcess;
|
||||||
|
|
||||||
|
public interface LauncherGuard {
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
void applyGuardParams(ClientLauncherProcess process);
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package pro.gravit.launcher.guard;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.client.ClientLauncherProcess;
|
||||||
|
|
||||||
|
public class LauncherNoGuard implements LauncherGuard {
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "noGuard";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyGuardParams(ClientLauncherProcess process) {
|
||||||
|
//IGNORED
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package pro.gravit.launcher.guard;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.Launcher;
|
||||||
|
import pro.gravit.launcher.client.ClientLauncherProcess;
|
||||||
|
import pro.gravit.launcher.client.DirBridge;
|
||||||
|
import pro.gravit.utils.helper.JVMHelper;
|
||||||
|
import pro.gravit.utils.helper.UnpackHelper;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class LauncherWrapperGuard implements LauncherGuard {
|
||||||
|
|
||||||
|
public LauncherWrapperGuard() {
|
||||||
|
try {
|
||||||
|
String wrapperName = JVMHelper.JVM_BITS == 64 ? "wrapper64.exe" : "wrapper32.exe";
|
||||||
|
String projectName = Launcher.getConfig().projectName;
|
||||||
|
String wrapperUnpackName = JVMHelper.JVM_BITS == 64 ? projectName.concat("64.exe") : projectName.concat("32.exe");
|
||||||
|
String antiInjectName = JVMHelper.JVM_BITS == 64 ? "AntiInject64.dll" : "AntiInject32.dll";
|
||||||
|
UnpackHelper.unpack(Launcher.getResourceURL(wrapperName, "guard"), DirBridge.getGuardDir().resolve(wrapperUnpackName));
|
||||||
|
UnpackHelper.unpack(Launcher.getResourceURL(antiInjectName, "guard"), DirBridge.getGuardDir().resolve(antiInjectName));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new SecurityException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "wrapper";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyGuardParams(ClientLauncherProcess process) {
|
||||||
|
if (JVMHelper.OS_TYPE == JVMHelper.OS.MUSTDIE) {
|
||||||
|
String projectName = Launcher.getConfig().projectName;
|
||||||
|
String wrapperUnpackName = JVMHelper.JVM_BITS == 64 ? projectName.concat("64.exe") : projectName.concat("32.exe");
|
||||||
|
process.executeFile = DirBridge.getGuardDir().resolve(wrapperUnpackName);
|
||||||
|
process.useLegacyJavaClassPathProperty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,12 +4,12 @@
|
||||||
|
|
||||||
public class NoRuntimeProvider implements RuntimeProvider {
|
public class NoRuntimeProvider implements RuntimeProvider {
|
||||||
@Override
|
@Override
|
||||||
public void run(String[] args) {
|
public void run(String[] args) throws Exception {
|
||||||
JOptionPane.showMessageDialog(null, "GUI часть лаунчера не найдена.\nС 5.1.0 вам необходимо самостоятельно установить модуль, отвечающий за GUI. Рантайм на JS более не поддерживается");
|
JOptionPane.showMessageDialog(null, "GUI часть лаунчера не найдена.\nС 5.1.0 вам необходимо самостоятельно установить модуль, отвечающий за GUI. Рантайм на JS более не поддерживается");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void preLoad() {
|
public void preLoad() throws Exception {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package pro.gravit.launcher.gui;
|
package pro.gravit.launcher.gui;
|
||||||
|
|
||||||
public interface RuntimeProvider {
|
public interface RuntimeProvider {
|
||||||
void run(String[] args);
|
void run(String[] args) throws Exception;
|
||||||
|
|
||||||
void preLoad();
|
void preLoad() throws Exception;
|
||||||
|
|
||||||
void init(boolean clientInstance);
|
void init(boolean clientInstance);
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,6 +115,10 @@ private final class RegisterFileVisitor extends SimpleFileVisitor<Path> {
|
||||||
@Override
|
@Override
|
||||||
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
|
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
|
||||||
FileVisitResult result = super.preVisitDirectory(dir, attrs);
|
FileVisitResult result = super.preVisitDirectory(dir, attrs);
|
||||||
|
if (DirWatcher.this.dir.equals(dir)) {
|
||||||
|
dir.register(service, KINDS);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// Maybe it's unnecessary to go deeper
|
// Maybe it's unnecessary to go deeper
|
||||||
//if (matcher != null && !matcher.shouldVerify(path)) {
|
//if (matcher != null && !matcher.shouldVerify(path)) {
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue