[FEATURE][EXPERIMENTAL] separate branch

This commit is contained in:
Gravita 2023-07-27 20:03:49 +07:00
parent 4d1fd23e84
commit 9de81095b1
46 changed files with 638 additions and 324 deletions

View file

@ -1,4 +1,4 @@
{ {
"features": [], "features": ["separate"],
"info": [] "info": []
} }

View file

@ -17,7 +17,7 @@
-keeppackagenames com.mojang.**,net.minecraftforge.fml.**,cpw.mods.fml.**,com.google.gson.**,pro.gravit.repackage.**,org.fusesource.**, pro.gravit.launcher.api.**, pro.gravit.utils.**, pro.gravit.launcher.request.**, pro.gravit.launcher.events.**, pro.gravit.launcher.profiles.** -keeppackagenames com.mojang.**,net.minecraftforge.fml.**,cpw.mods.fml.**,com.google.gson.**,pro.gravit.repackage.**,org.fusesource.**, pro.gravit.launcher.api.**, pro.gravit.utils.**, pro.gravit.launcher.request.**, pro.gravit.launcher.events.**, pro.gravit.launcher.profiles.**
-keep class com.mojang.**,net.minecraftforge.fml.**,cpw.mods.fml.**,com.google.gson.**,pro.gravit.repackage.**,org.fusesource.**, pro.gravit.launcher.api.**, pro.gravit.utils.**, pro.gravit.launcher.request.**, pro.gravit.launcher.events.**, pro.gravit.launcher.profiles.** { -keep class com.mojang.**,net.minecraftforge.fml.**,cpw.mods.fml.**,com.google.gson.**,pro.gravit.repackage.**,org.fusesource.**, pro.gravit.launcher.api.**, pro.gravit.utils.**, pro.gravit.launcher.request.**, pro.gravit.launcher.events.**, pro.gravit.launcher.profiles.**, pro.gravit.launcher.LauncherEngineWrapper {
*; *;
} }

View file

@ -49,6 +49,8 @@
dependencies { dependencies {
pack project(':LauncherAPI') pack project(':LauncherAPI')
pack project(':LauncherClient')
pack project(':LauncherStart')
bundle group: 'com.github.oshi', name: 'oshi-core', version: rootProject['verOshiCore'] bundle group: 'com.github.oshi', name: 'oshi-core', version: rootProject['verOshiCore']
pack group: 'io.netty', name: 'netty-codec-http', version: rootProject['verNetty'] pack group: 'io.netty', name: 'netty-codec-http', version: rootProject['verNetty']
} }

View file

@ -10,7 +10,7 @@
import pro.gravit.launcher.events.request.*; import pro.gravit.launcher.events.request.*;
import pro.gravit.launcher.gui.NoRuntimeProvider; import pro.gravit.launcher.gui.NoRuntimeProvider;
import pro.gravit.launcher.gui.RuntimeProvider; import pro.gravit.launcher.gui.RuntimeProvider;
import pro.gravit.launcher.managers.ClientGsonManager; import pro.gravit.launcher.client.RuntimeGsonManager;
import pro.gravit.launcher.managers.ConsoleManager; import pro.gravit.launcher.managers.ConsoleManager;
import pro.gravit.launcher.modules.events.OfflineModeEvent; import pro.gravit.launcher.modules.events.OfflineModeEvent;
import pro.gravit.launcher.modules.events.PreConfigPhase; import pro.gravit.launcher.modules.events.PreConfigPhase;
@ -45,8 +45,8 @@
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
public class LauncherEngine { public class LauncherEngine {
public static ClientLauncherProcess.ClientParams clientParams; public static ClientParams clientParams;
public static ClientModuleManager modulesManager; public static RuntimeModuleManager modulesManager;
public final boolean clientInstance; public final boolean clientInstance;
// Instance // Instance
private final AtomicBoolean started = new AtomicBoolean(false); private final AtomicBoolean started = new AtomicBoolean(false);
@ -102,18 +102,19 @@ public static void exitLauncher(int code) {
} }
public static void main(String... args) throws Throwable { public static void main(String... args) throws Throwable {
JVMHelper.checkStackTrace(LauncherEngine.class); JVMHelper.checkStackTrace(LauncherEngineWrapper.class);
JVMHelper.verifySystemProperties(Launcher.class, true); JVMHelper.verifySystemProperties(Launcher.class, true);
EnvHelper.checkDangerousParams(); EnvHelper.checkDangerousParams();
//if(!LauncherAgent.isStarted()) throw new SecurityException("JavaAgent not set"); //if(!LauncherAgent.isStarted()) throw new SecurityException("JavaAgent not set");
verifyNoAgent(); verifyNoAgent();
LogHelper.printVersion("Launcher"); LogHelper.printVersion("Launcher");
LogHelper.printLicense("Launcher"); LogHelper.printLicense("Launcher");
LauncherEngine.checkClass(LauncherEngineWrapper.class);
LauncherEngine.checkClass(LauncherEngine.class); LauncherEngine.checkClass(LauncherEngine.class);
LauncherEngine.checkClass(LauncherAgent.class); LauncherEngine.checkClass(LauncherAgent.class);
LauncherEngine.checkClass(ClientLauncherEntryPoint.class); LauncherEngine.checkClass(ClientLauncherEntryPoint.class);
LauncherEngine.modulesManager = new ClientModuleManager(); LauncherEngine.modulesManager = new RuntimeModuleManager();
LauncherEngine.modulesManager.loadModule(new ClientLauncherCoreModule()); LauncherEngine.modulesManager.loadModule(new RuntimeLauncherCoreModule());
LauncherConfig.initModules(LauncherEngine.modulesManager); LauncherConfig.initModules(LauncherEngine.modulesManager);
LauncherEngine.modulesManager.initModules(null); LauncherEngine.modulesManager.initModules(null);
// Start Launcher // Start Launcher
@ -133,12 +134,12 @@ public static void main(String... args) throws Throwable {
LauncherEngine.exitLauncher(0); LauncherEngine.exitLauncher(0);
} }
public static void initGson(ClientModuleManager modulesManager) { public static void initGson(RuntimeModuleManager modulesManager) {
AuthRequest.registerProviders(); AuthRequest.registerProviders();
GetAvailabilityAuthRequest.registerProviders(); GetAvailabilityAuthRequest.registerProviders();
OptionalAction.registerProviders(); OptionalAction.registerProviders();
OptionalTrigger.registerProviders(); OptionalTrigger.registerProviders();
Launcher.gsonManager = new ClientGsonManager(modulesManager); Launcher.gsonManager = new RuntimeGsonManager(modulesManager);
Launcher.gsonManager.initGson(); Launcher.gsonManager.initGson();
} }
@ -149,37 +150,12 @@ public static void verifyNoAgent() {
public static RequestService initOffline() { public static RequestService initOffline() {
OfflineRequestService service = new OfflineRequestService(); OfflineRequestService service = new OfflineRequestService();
applyBasicOfflineProcessors(service); ClientLauncherMethods.applyBasicOfflineProcessors(service);
OfflineModeEvent event = new OfflineModeEvent(service); OfflineModeEvent event = new OfflineModeEvent(service);
modulesManager.invokeEvent(event); modulesManager.invokeEvent(event);
return event.service; return event.service;
} }
public static void applyBasicOfflineProcessors(OfflineRequestService service) {
service.registerRequestProcessor(LauncherRequest.class, (r) -> new LauncherRequestEvent(false, (String) null));
service.registerRequestProcessor(CheckServerRequest.class, (r) -> {
throw new RequestException("CheckServer disabled in offline mode");
});
service.registerRequestProcessor(GetAvailabilityAuthRequest.class, (r) -> {
List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> details = new ArrayList<>();
details.add(new AuthLoginOnlyDetails());
GetAvailabilityAuthRequestEvent.AuthAvailability authAvailability = new GetAvailabilityAuthRequestEvent.AuthAvailability("offline", "Offline Mode", true, details);
List<GetAvailabilityAuthRequestEvent.AuthAvailability> list = new ArrayList<>(1);
list.add(authAvailability);
return new GetAvailabilityAuthRequestEvent(list);
});
service.registerRequestProcessor(JoinServerRequest.class, (r) -> new JoinServerRequestEvent(false));
service.registerRequestProcessor(ExitRequest.class, (r) -> new ExitRequestEvent(ExitRequestEvent.ExitReason.CLIENT));
service.registerRequestProcessor(SetProfileRequest.class, (r) -> new SetProfileRequestEvent(null));
service.registerRequestProcessor(FeaturesRequest.class, (r) -> new FeaturesRequestEvent());
service.registerRequestProcessor(GetSecureLevelInfoRequest.class, (r) -> new GetSecureLevelInfoRequestEvent(null, false));
service.registerRequestProcessor(SecurityReportRequest.class, (r) -> new SecurityReportRequestEvent(SecurityReportRequestEvent.ReportAction.NONE));
}
public static LauncherEngine clientInstance() {
return new LauncherEngine(true);
}
public static LauncherEngine newInstance(boolean clientInstance) { public static LauncherEngine newInstance(boolean clientInstance) {
return new LauncherEngine(clientInstance); return new LauncherEngine(clientInstance);
} }

View file

@ -0,0 +1,8 @@
package pro.gravit.launcher;
@LauncherNetworkAPI
public class LauncherEngineWrapper {
public static void main(String[] args) throws Throwable {
LauncherEngine.main(args);
}
}

View file

@ -7,18 +7,14 @@
import pro.gravit.launcher.client.events.client.ClientProcessBuilderLaunchedEvent; import pro.gravit.launcher.client.events.client.ClientProcessBuilderLaunchedEvent;
import pro.gravit.launcher.client.events.client.ClientProcessBuilderParamsWrittedEvent; import pro.gravit.launcher.client.events.client.ClientProcessBuilderParamsWrittedEvent;
import pro.gravit.launcher.client.events.client.ClientProcessBuilderPreLaunchEvent; import pro.gravit.launcher.client.events.client.ClientProcessBuilderPreLaunchEvent;
import pro.gravit.launcher.events.request.AuthRequestEvent;
import pro.gravit.launcher.hasher.HashedDir; import pro.gravit.launcher.hasher.HashedDir;
import pro.gravit.launcher.profiles.ClientProfile; import pro.gravit.launcher.profiles.ClientProfile;
import pro.gravit.launcher.profiles.ClientProfileVersions;
import pro.gravit.launcher.profiles.PlayerProfile; import pro.gravit.launcher.profiles.PlayerProfile;
import pro.gravit.launcher.profiles.optional.OptionalView; import pro.gravit.launcher.profiles.optional.OptionalView;
import pro.gravit.launcher.profiles.optional.actions.OptionalAction; import pro.gravit.launcher.profiles.optional.actions.OptionalAction;
import pro.gravit.launcher.profiles.optional.actions.OptionalActionClientArgs;
import pro.gravit.launcher.profiles.optional.actions.OptionalActionJvmArgs; import pro.gravit.launcher.profiles.optional.actions.OptionalActionJvmArgs;
import pro.gravit.launcher.request.Request; import pro.gravit.launcher.request.Request;
import pro.gravit.launcher.serialize.HOutput; import pro.gravit.launcher.serialize.HOutput;
import pro.gravit.utils.Version;
import pro.gravit.utils.helper.*; import pro.gravit.utils.helper.*;
import java.io.File; import java.io.File;
@ -238,120 +234,4 @@ public Process getProcess() {
return process; return process;
} }
public static class ClientParams {
public String assetDir;
public String clientDir;
public String resourcePackDir;
public String nativesDir;
// Client params
public PlayerProfile playerProfile;
public ClientProfile profile;
public String accessToken;
//==Minecraft params==
public boolean autoEnter;
public boolean fullScreen;
public int ram;
public int width;
public int height;
public Set<OptionalAction> actions = new HashSet<>();
//========
public UUID session;
public AuthRequestEvent.OAuthRequestEvent oauth;
public String authId;
public long oauthExpiredTime;
public Map<String, String> extendedTokens;
public boolean offlineMode;
public transient HashedDir assetHDir;
public transient HashedDir clientHDir;
public transient HashedDir javaHDir;
public void addClientArgs(Collection<String> args) {
if (profile.getVersion().compareTo(ClientProfileVersions.MINECRAFT_1_6_4) >= 0)
addModernClientArgs(args);
else
addClientLegacyArgs(args);
}
public void addClientLegacyArgs(Collection<String> args) {
args.add(playerProfile.username);
args.add(accessToken);
// Add args for tweaker
Collections.addAll(args, "--version", profile.getVersion().toString());
Collections.addAll(args, "--gameDir", clientDir);
Collections.addAll(args, "--assetsDir", assetDir);
}
private void addModernClientArgs(Collection<String> args) {
// Add version-dependent args
ClientProfile.Version version = profile.getVersion();
Collections.addAll(args, "--username", playerProfile.username);
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_7_2) >= 0) {
Collections.addAll(args, "--uuid", Launcher.toHash(playerProfile.uuid));
Collections.addAll(args, "--accessToken", accessToken);
// Add 1.7.10+ args (user properties, asset index)
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_7_10) >= 0) {
// Add user properties
Collections.addAll(args, "--userType", "mojang");
Collections.addAll(args, "--userProperties", "{}");
// Add asset index
Collections.addAll(args, "--assetIndex", profile.getAssetIndex());
}
} else
Collections.addAll(args, "--session", accessToken);
// Add version and dirs args
Collections.addAll(args, "--version", profile.getVersion().toString());
Collections.addAll(args, "--gameDir", clientDir);
Collections.addAll(args, "--assetsDir", assetDir);
Collections.addAll(args, "--resourcePackDir", resourcePackDir);
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_9_4) >= 0)
Collections.addAll(args, "--versionType", "Launcher v" + Version.getVersion().getVersionString());
// Add server args
if (autoEnter) {
Collections.addAll(args, "--server", profile.getServerAddress());
Collections.addAll(args, "--port", Integer.toString(profile.getServerPort()));
}
for (OptionalAction a : actions) {
if (a instanceof OptionalActionClientArgs) {
args.addAll(((OptionalActionClientArgs) a).args);
}
}
// Add window size args
if (fullScreen)
Collections.addAll(args, "--fullscreen", Boolean.toString(true));
if (width > 0 && height > 0) {
Collections.addAll(args, "--width", Integer.toString(width));
Collections.addAll(args, "--height", Integer.toString(height));
}
}
}
} }

View file

@ -0,0 +1,23 @@
package pro.gravit.launcher.client;
import com.google.gson.GsonBuilder;
import pro.gravit.launcher.managers.GsonManager;
import pro.gravit.launcher.modules.events.PreGsonPhase;
import pro.gravit.launcher.request.websockets.ClientWebSocketService;
import pro.gravit.utils.UniversalJsonAdapter;
public class RuntimeGsonManager extends GsonManager {
private final RuntimeModuleManager moduleManager;
public RuntimeGsonManager(RuntimeModuleManager moduleManager) {
this.moduleManager = moduleManager;
}
@Override
public void registerAdapters(GsonBuilder builder) {
super.registerAdapters(builder);
builder.registerTypeAdapter(UserSettings.class, new UniversalJsonAdapter<>(UserSettings.providers));
ClientWebSocketService.appendTypeAdapters(builder);
moduleManager.invokeEvent(new PreGsonPhase(builder));
}
}

View file

@ -0,0 +1,17 @@
package pro.gravit.launcher.client;
import pro.gravit.launcher.modules.LauncherInitContext;
import pro.gravit.launcher.modules.LauncherModule;
import pro.gravit.launcher.modules.LauncherModuleInfo;
import pro.gravit.utils.Version;
public class RuntimeLauncherCoreModule extends LauncherModule {
public RuntimeLauncherCoreModule() {
super(new LauncherModuleInfo("ClientLauncherCore", Version.getVersion()));
}
@Override
public void init(LauncherInitContext initContext) {
}
}

View file

@ -1,15 +0,0 @@
package pro.gravit.launcher.client.events.client;
import pro.gravit.launcher.LauncherEngine;
import pro.gravit.launcher.client.ClientLauncherProcess;
import pro.gravit.launcher.modules.events.InitPhase;
public class ClientProcessInitPhase extends InitPhase {
public final LauncherEngine clientInstance;
public final ClientLauncherProcess.ClientParams params;
public ClientProcessInitPhase(LauncherEngine clientInstance, ClientLauncherProcess.ClientParams params) {
this.clientInstance = clientInstance;
this.params = params;
}
}

View file

@ -1,15 +0,0 @@
package pro.gravit.launcher.client.events.client;
import pro.gravit.launcher.LauncherEngine;
import pro.gravit.launcher.client.ClientLauncherProcess;
import pro.gravit.launcher.modules.LauncherModule;
public class ClientProcessLaunchEvent extends LauncherModule.Event {
public final LauncherEngine clientInstance;
public final ClientLauncherProcess.ClientParams params;
public ClientProcessLaunchEvent(LauncherEngine clientInstance, ClientLauncherProcess.ClientParams params) {
this.clientInstance = clientInstance;
this.params = params;
}
}

View file

@ -1,15 +0,0 @@
package pro.gravit.launcher.client.events.client;
import pro.gravit.launcher.LauncherEngine;
import pro.gravit.launcher.client.ClientLauncherProcess;
import pro.gravit.launcher.modules.events.PostInitPhase;
public class ClientProcessReadyEvent extends PostInitPhase {
public final LauncherEngine clientInstance;
public final ClientLauncherProcess.ClientParams params;
public ClientProcessReadyEvent(LauncherEngine clientInstance, ClientLauncherProcess.ClientParams params) {
this.clientInstance = clientInstance;
this.params = params;
}
}

View file

@ -1,10 +1,11 @@
package pro.gravit.launcher.debug; package pro.gravit.launcher.debug;
import pro.gravit.launcher.ClientLauncherMethods;
import pro.gravit.launcher.Launcher; import pro.gravit.launcher.Launcher;
import pro.gravit.launcher.LauncherConfig; import pro.gravit.launcher.LauncherConfig;
import pro.gravit.launcher.LauncherEngine; import pro.gravit.launcher.LauncherEngine;
import pro.gravit.launcher.client.ClientLauncherCoreModule; import pro.gravit.launcher.client.RuntimeLauncherCoreModule;
import pro.gravit.launcher.client.ClientModuleManager; import pro.gravit.launcher.client.RuntimeModuleManager;
import pro.gravit.launcher.managers.ConsoleManager; import pro.gravit.launcher.managers.ConsoleManager;
import pro.gravit.launcher.modules.LauncherModule; import pro.gravit.launcher.modules.LauncherModule;
import pro.gravit.launcher.modules.events.OfflineModeEvent; import pro.gravit.launcher.modules.events.OfflineModeEvent;
@ -42,8 +43,8 @@ public static void main(String[] args) throws Throwable {
config.unlockSecret = unlockSecret; config.unlockSecret = unlockSecret;
Launcher.setConfig(config); Launcher.setConfig(config);
Launcher.applyLauncherEnv(environment); Launcher.applyLauncherEnv(environment);
LauncherEngine.modulesManager = new ClientModuleManager(); LauncherEngine.modulesManager = new RuntimeModuleManager();
LauncherEngine.modulesManager.loadModule(new ClientLauncherCoreModule()); LauncherEngine.modulesManager.loadModule(new RuntimeLauncherCoreModule());
for (String moduleClassName : moduleClasses) { for (String moduleClassName : moduleClasses) {
if (moduleClassName.isEmpty()) continue; if (moduleClassName.isEmpty()) continue;
LauncherEngine.modulesManager.loadModule(newModule(moduleClassName)); LauncherEngine.modulesManager.loadModule(newModule(moduleClassName));
@ -59,7 +60,7 @@ public static void main(String[] args) throws Throwable {
RequestService service; RequestService service;
if (offlineMode) { if (offlineMode) {
OfflineRequestService offlineRequestService = new OfflineRequestService(); OfflineRequestService offlineRequestService = new OfflineRequestService();
LauncherEngine.applyBasicOfflineProcessors(offlineRequestService); ClientLauncherMethods.applyBasicOfflineProcessors(offlineRequestService);
OfflineModeEvent event = new OfflineModeEvent(offlineRequestService); OfflineModeEvent event = new OfflineModeEvent(offlineRequestService);
LauncherEngine.modulesManager.invokeEvent(event); LauncherEngine.modulesManager.invokeEvent(event);
service = event.service; service = event.service;

View file

@ -22,23 +22,9 @@ public final class Launcher {
// Authlib constants // Authlib constants
public static final String SKIN_URL_PROPERTY = "skinURL";
public static final String SKIN_DIGEST_PROPERTY = "skinDigest";
public static final String SKIN_METADATA_PROPERTY = "skinMetadata";
public static final String CLOAK_URL_PROPERTY = "cloakURL";
public static final String CLOAK_DIGEST_PROPERTY = "cloakDigest";
public static final String CLOAK_METADATA_PROPERTY = "cloakMetadata";
// Used to determine from clientside is launched from launcher // Used to determine from clientside is launched from launcher
public static final AtomicBoolean LAUNCHED = new AtomicBoolean(false); public static final AtomicBoolean LAUNCHED = new AtomicBoolean(false);
public static final int PROTOCOL_MAGIC_LEGACY = 0x724724_00 + 24;
public static final int PROTOCOL_MAGIC = 0xA205B064; // e = 2.718281828
public static final String RUNTIME_DIR = "runtime"; public static final String RUNTIME_DIR = "runtime";
// Constants // Constants

View file

@ -31,6 +31,7 @@ public enum ReportAction {
LOGOUT, LOGOUT,
TOKEN_EXPIRED, TOKEN_EXPIRED,
EXIT, EXIT,
@Deprecated
CRASH, CRASH,
OTHER OTHER
} }

View file

@ -0,0 +1,79 @@
apply plugin: 'org.openjfx.javafxplugin'
String mainClassName = "pro.gravit.launcher.ClientLauncherWrapper"
String mainAgentName = "pro.gravit.launcher.LauncherAgent"
repositories {
maven {
url "https://repo.spring.io/plugins-release/"
}
}
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
jar {
archiveClassifier.set('clean')
manifest.attributes("Main-Class": mainClassName,
"Premain-Class": mainAgentName,
"Multi-Release": "true")
}
tasks.register('sourcesJar', Jar) {
from sourceSets.main.allJava
archiveClassifier.set('sources')
}
tasks.register('javadocJar', Jar) {
from javadoc
archiveClassifier.set('javadoc')
}
dependencies {
implementation project(':LauncherAPI')
}
publishing {
publications {
launcherclientstarter(MavenPublication) {
artifactId = 'launcher-client-starter-api'
artifact(jar) {
classifier ""
}
artifact sourcesJar
artifact javadocJar
pom {
name = 'GravitLauncher Client API'
description = 'GravitLauncher Client Module API'
url = 'https://gravitlauncher.com'
licenses {
license {
name = 'GNU General Public License, Version 3.0'
url = 'https://www.gnu.org/licenses/gpl-3.0.html'
}
}
developers {
developer {
id = 'gravita'
name = 'Gravita'
email = 'gravita@gravit.pro'
}
developer {
id = 'zaxar163'
name = 'Zaxar163'
email = 'zahar.vcherachny@yandex.ru'
}
}
scm {
connection = 'scm:git:https://github.com/GravitLauncher/Launcher.git'
developerConnection = 'scm:git:ssh://git@github.com:GravitLauncher/Launcher.git'
url = 'https://gravitlauncher.com/'
}
}
}
}
}
signing {
sign publishing.publications.launcherclientapi
}

View file

@ -15,9 +15,7 @@ public class BasicLauncherEventHandler implements RequestService.EventHandler {
public <T extends WebSocketEvent> boolean eventHandle(T event) { public <T extends WebSocketEvent> boolean eventHandle(T event) {
if (event instanceof SecurityReportRequestEvent) { if (event instanceof SecurityReportRequestEvent) {
SecurityReportRequestEvent event1 = (SecurityReportRequestEvent) event; SecurityReportRequestEvent event1 = (SecurityReportRequestEvent) event;
if (event1.action == SecurityReportRequestEvent.ReportAction.CRASH) { if (event1.action == SecurityReportRequestEvent.ReportAction.TOKEN_EXPIRED) {
LauncherEngine.exitLauncher(80);
} else if (event1.action == SecurityReportRequestEvent.ReportAction.TOKEN_EXPIRED) {
try { try {
Request.restore(); Request.restore();
} catch (Exception e) { } catch (Exception e) {

View file

@ -0,0 +1,138 @@
package pro.gravit.launcher;
import pro.gravit.launcher.client.ClientGsonManager;
import pro.gravit.launcher.client.ClientLauncherEntryPoint;
import pro.gravit.launcher.client.ClientModuleManager;
import pro.gravit.launcher.client.ClientParams;
import pro.gravit.launcher.client.events.ClientExitPhase;
import pro.gravit.launcher.events.request.*;
import pro.gravit.launcher.modules.LauncherModulesManager;
import pro.gravit.launcher.modules.events.OfflineModeEvent;
import pro.gravit.launcher.profiles.optional.actions.OptionalAction;
import pro.gravit.launcher.profiles.optional.triggers.OptionalTrigger;
import pro.gravit.launcher.request.RequestException;
import pro.gravit.launcher.request.RequestService;
import pro.gravit.launcher.request.auth.*;
import pro.gravit.launcher.request.auth.details.AuthLoginOnlyDetails;
import pro.gravit.launcher.request.management.FeaturesRequest;
import pro.gravit.launcher.request.secure.GetSecureLevelInfoRequest;
import pro.gravit.launcher.request.secure.SecurityReportRequest;
import pro.gravit.launcher.request.update.LauncherRequest;
import pro.gravit.launcher.request.uuid.ProfileByUUIDRequest;
import pro.gravit.launcher.request.uuid.ProfileByUsernameRequest;
import pro.gravit.launcher.request.websockets.OfflineRequestService;
import pro.gravit.launcher.utils.NativeJVMHalt;
import pro.gravit.utils.helper.JVMHelper;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ClientLauncherMethods {
public static void verifyNoAgent() {
if (JVMHelper.RUNTIME_MXBEAN.getInputArguments().stream().filter(e -> e != null && !e.isEmpty()).anyMatch(e -> e.contains("javaagent")))
throw new SecurityException("JavaAgent found");
}
//JVMHelper.getCertificates
public static X509Certificate[] getCertificates(Class<?> clazz) {
Object[] signers = clazz.getSigners();
if (signers == null) return null;
return Arrays.stream(signers).filter((c) -> c instanceof X509Certificate).map((c) -> (X509Certificate) c).toArray(X509Certificate[]::new);
}
public static void beforeExit(int code) {
try {
ClientLauncherEntryPoint.modulesManager.invokeEvent(new ClientExitPhase(code));
} catch (Throwable ignored) {
}
}
public static void forceExit(int code) {
try {
System.exit(code);
} catch (Throwable e) //Forge Security Manager?
{
NativeJVMHalt.haltA(code);
}
}
public static void exitLauncher(int code) {
beforeExit(code);
forceExit(code);
}
public static void checkClass(Class<?> clazz) throws SecurityException {
LauncherTrustManager trustManager = Launcher.getConfig().trustManager;
if (trustManager == null) return;
X509Certificate[] certificates = getCertificates(clazz);
if (certificates == null) {
throw new SecurityException(String.format("Class %s not signed", clazz.getName()));
}
try {
trustManager.checkCertificatesSuccess(certificates, trustManager::stdCertificateChecker);
} catch (Exception e) {
throw new SecurityException(e);
}
}
public static void initGson(ClientModuleManager moduleManager) {
AuthRequest.registerProviders();
GetAvailabilityAuthRequest.registerProviders();
OptionalAction.registerProviders();
OptionalTrigger.registerProviders();
Launcher.gsonManager = new ClientGsonManager(moduleManager);
Launcher.gsonManager.initGson();
}
public static RequestService initOffline(LauncherModulesManager modulesManager, ClientParams params) {
OfflineRequestService service = new OfflineRequestService();
applyBasicOfflineProcessors(service);
applyClientOfflineProcessors(service, params);
OfflineModeEvent event = new OfflineModeEvent(service);
modulesManager.invokeEvent(event);
return event.service;
}
public static void applyClientOfflineProcessors(OfflineRequestService service, ClientParams params) {
service.registerRequestProcessor(ProfileByUsernameRequest.class, (r) -> {
if (params.playerProfile.username.equals(r.username)) {
return new ProfileByUsernameRequestEvent(params.playerProfile);
}
throw new RequestException("User not found");
});
service.registerRequestProcessor(ProfileByUUIDRequest.class, (r) -> {
if (params.playerProfile.uuid.equals(r.uuid)) {
return new ProfileByUUIDRequestEvent(params.playerProfile);
}
throw new RequestException("User not found");
});
}
public static void applyBasicOfflineProcessors(OfflineRequestService service) {
service.registerRequestProcessor(LauncherRequest.class, (r) -> new LauncherRequestEvent(false, (String) null));
service.registerRequestProcessor(CheckServerRequest.class, (r) -> {
throw new RequestException("CheckServer disabled in offline mode");
});
service.registerRequestProcessor(GetAvailabilityAuthRequest.class, (r) -> {
List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> details = new ArrayList<>();
details.add(new AuthLoginOnlyDetails());
GetAvailabilityAuthRequestEvent.AuthAvailability authAvailability = new GetAvailabilityAuthRequestEvent.AuthAvailability("offline", "Offline Mode", true, details);
List<GetAvailabilityAuthRequestEvent.AuthAvailability> list = new ArrayList<>(1);
list.add(authAvailability);
return new GetAvailabilityAuthRequestEvent(list);
});
service.registerRequestProcessor(JoinServerRequest.class, (r) -> new JoinServerRequestEvent(false));
service.registerRequestProcessor(ExitRequest.class, (r) -> new ExitRequestEvent(ExitRequestEvent.ExitReason.CLIENT));
service.registerRequestProcessor(SetProfileRequest.class, (r) -> new SetProfileRequestEvent(null));
service.registerRequestProcessor(FeaturesRequest.class, (r) -> new FeaturesRequestEvent());
service.registerRequestProcessor(GetSecureLevelInfoRequest.class, (r) -> new GetSecureLevelInfoRequestEvent(null, false));
service.registerRequestProcessor(SecurityReportRequest.class, (r) -> new SecurityReportRequestEvent(SecurityReportRequestEvent.ReportAction.NONE));
}
}

View file

@ -1,19 +1,19 @@
package pro.gravit.launcher.api; package pro.gravit.launcher.api;
import pro.gravit.launcher.ClientLauncherMethods;
import pro.gravit.launcher.LauncherTrustManager; import pro.gravit.launcher.LauncherTrustManager;
import pro.gravit.launcher.client.ClientLauncherEntryPoint;
import pro.gravit.launcher.utils.ApiBridgeService; import pro.gravit.launcher.utils.ApiBridgeService;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import static pro.gravit.launcher.LauncherEngine.getCertificates;
public class CertificateService { public class CertificateService {
private CertificateService() { private CertificateService() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
public static CheckClassResultApi checkClass(Class<?> clazz) throws SecurityException { public static CheckClassResultApi checkClass(Class<?> clazz) throws SecurityException {
X509Certificate[] certificates = getCertificates(clazz); X509Certificate[] certificates = ClientLauncherMethods.getCertificates(clazz);
if (certificates == null) { if (certificates == null) {
return new CheckClassResultApi(CheckClassResultTypeApi.NOT_SIGNED, null, null); return new CheckClassResultApi(CheckClassResultTypeApi.NOT_SIGNED, null, null);
} }
@ -25,7 +25,7 @@ public static CheckClassResultApi checkClass(Class<?> clazz) throws SecurityExce
} }
public static void checkClassSuccess(Class<?> clazz) { public static void checkClassSuccess(Class<?> clazz) {
X509Certificate[] certificates = getCertificates(clazz); X509Certificate[] certificates = ClientLauncherMethods.getCertificates(clazz);
if (certificates == null) { if (certificates == null) {
throw new SecurityException(String.format("Class %s not signed", clazz.getName())); throw new SecurityException(String.format("Class %s not signed", clazz.getName()));
} }

View file

@ -1,6 +1,6 @@
package pro.gravit.launcher.api; package pro.gravit.launcher.api;
import pro.gravit.launcher.LauncherEngine; import pro.gravit.launcher.ClientLauncherMethods;
public class SystemService { public class SystemService {
private SystemService() { private SystemService() {
@ -8,6 +8,6 @@ private SystemService() {
} }
public static void exit(int code) { public static void exit(int code) {
LauncherEngine.exitLauncher(code); ClientLauncherMethods.exitLauncher(code);
} }
} }

View file

@ -1,11 +1,9 @@
package pro.gravit.launcher.managers; package pro.gravit.launcher.client;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import pro.gravit.launcher.client.ClientModuleManager; import pro.gravit.launcher.managers.GsonManager;
import pro.gravit.launcher.client.UserSettings;
import pro.gravit.launcher.modules.events.PreGsonPhase; import pro.gravit.launcher.modules.events.PreGsonPhase;
import pro.gravit.launcher.request.websockets.ClientWebSocketService; import pro.gravit.launcher.request.websockets.ClientWebSocketService;
import pro.gravit.utils.UniversalJsonAdapter;
public class ClientGsonManager extends GsonManager { public class ClientGsonManager extends GsonManager {
private final ClientModuleManager moduleManager; private final ClientModuleManager moduleManager;
@ -17,7 +15,6 @@ public ClientGsonManager(ClientModuleManager moduleManager) {
@Override @Override
public void registerAdapters(GsonBuilder builder) { public void registerAdapters(GsonBuilder builder) {
super.registerAdapters(builder); super.registerAdapters(builder);
builder.registerTypeAdapter(UserSettings.class, new UniversalJsonAdapter<>(UserSettings.providers));
ClientWebSocketService.appendTypeAdapters(builder); ClientWebSocketService.appendTypeAdapters(builder);
moduleManager.invokeEvent(new PreGsonPhase(builder)); moduleManager.invokeEvent(new PreGsonPhase(builder));
} }

View file

@ -4,14 +4,13 @@
import pro.gravit.launcher.api.AuthService; import pro.gravit.launcher.api.AuthService;
import pro.gravit.launcher.api.ClientService; import pro.gravit.launcher.api.ClientService;
import pro.gravit.launcher.api.KeyService; import pro.gravit.launcher.api.KeyService;
import pro.gravit.launcher.client.events.ClientExitPhase;
import pro.gravit.launcher.client.events.client.*; import pro.gravit.launcher.client.events.client.*;
import pro.gravit.launcher.events.request.ProfileByUUIDRequestEvent; import pro.gravit.launcher.events.request.ProfileByUUIDRequestEvent;
import pro.gravit.launcher.events.request.ProfileByUsernameRequestEvent; import pro.gravit.launcher.events.request.ProfileByUsernameRequestEvent;
import pro.gravit.launcher.hasher.FileNameMatcher; import pro.gravit.launcher.hasher.FileNameMatcher;
import pro.gravit.launcher.hasher.HashedDir; import pro.gravit.launcher.hasher.HashedDir;
import pro.gravit.launcher.hasher.HashedEntry; import pro.gravit.launcher.hasher.HashedEntry;
import pro.gravit.launcher.managers.ClientGsonManager;
import pro.gravit.launcher.managers.ConsoleManager;
import pro.gravit.launcher.modules.LauncherModulesManager; import pro.gravit.launcher.modules.LauncherModulesManager;
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;
@ -32,6 +31,7 @@
import pro.gravit.launcher.request.websockets.StdWebSocketService; import pro.gravit.launcher.request.websockets.StdWebSocketService;
import pro.gravit.launcher.serialize.HInput; import pro.gravit.launcher.serialize.HInput;
import pro.gravit.launcher.utils.DirWatcher; import pro.gravit.launcher.utils.DirWatcher;
import pro.gravit.launcher.utils.NativeJVMHalt;
import pro.gravit.utils.helper.*; import pro.gravit.utils.helper.*;
import java.io.File; import java.io.File;
@ -45,6 +45,7 @@
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor; import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributes;
import java.security.cert.X509Certificate;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -52,13 +53,15 @@
public class ClientLauncherEntryPoint { public class ClientLauncherEntryPoint {
private static ClassLoader classLoader; private static ClassLoader classLoader;
public static ClientModuleManager modulesManager;
public static ClientParams clientParams;
private static ClientLauncherProcess.ClientParams readParams(SocketAddress address) throws IOException { private static ClientParams readParams(SocketAddress address) throws IOException {
try (Socket socket = IOHelper.newSocket()) { try (Socket socket = IOHelper.newSocket()) {
socket.connect(address); socket.connect(address);
try (HInput input = new HInput(socket.getInputStream())) { try (HInput input = new HInput(socket.getInputStream())) {
byte[] serialized = input.readByteArray(0); byte[] serialized = input.readByteArray(0);
ClientLauncherProcess.ClientParams params = Launcher.gsonManager.gson.fromJson(IOHelper.decode(serialized), ClientLauncherProcess.ClientParams.class); ClientParams params = Launcher.gsonManager.gson.fromJson(IOHelper.decode(serialized), ClientParams.class);
params.clientHDir = new HashedDir(input); params.clientHDir = new HashedDir(input);
params.assetHDir = new HashedDir(input); params.assetHDir = new HashedDir(input);
boolean isNeedReadJavaDir = input.readBoolean(); boolean isNeedReadJavaDir = input.readBoolean();
@ -70,31 +73,26 @@ private static ClientLauncherProcess.ClientParams readParams(SocketAddress addre
} }
public static void main(String[] args) throws Throwable { public static void main(String[] args) throws Throwable {
LauncherEngine engine = LauncherEngine.clientInstance();
JVMHelper.verifySystemProperties(ClientLauncherEntryPoint.class, true); JVMHelper.verifySystemProperties(ClientLauncherEntryPoint.class, true);
EnvHelper.checkDangerousParams(); EnvHelper.checkDangerousParams();
JVMHelper.checkStackTrace(ClientLauncherEntryPoint.class); JVMHelper.checkStackTrace(ClientLauncherEntryPoint.class);
LogHelper.printVersion("Client Launcher"); LogHelper.printVersion("Client Launcher");
LauncherEngine.checkClass(LauncherEngine.class); ClientLauncherMethods.checkClass(ClientLauncherEntryPoint.class);
LauncherEngine.checkClass(LauncherAgent.class); modulesManager = new ClientModuleManager();
LauncherEngine.checkClass(ClientLauncherEntryPoint.class); modulesManager.loadModule(new ClientLauncherCoreModule());
LauncherEngine.modulesManager = new ClientModuleManager(); LauncherConfig.initModules(modulesManager); //INIT
LauncherEngine.modulesManager.loadModule(new ClientLauncherCoreModule()); modulesManager.initModules(null);
LauncherConfig.initModules(LauncherEngine.modulesManager); //INIT ClientLauncherMethods.initGson(modulesManager);
LauncherEngine.modulesManager.initModules(null); modulesManager.invokeEvent(new PreConfigPhase());
initGson(LauncherEngine.modulesManager);
ConsoleManager.initConsole();
LauncherEngine.modulesManager.invokeEvent(new PreConfigPhase());
engine.readKeys();
LogHelper.debug("Reading ClientLauncher params"); LogHelper.debug("Reading ClientLauncher params");
ClientLauncherProcess.ClientParams params = readParams(new InetSocketAddress("127.0.0.1", Launcher.getConfig().clientPort)); ClientParams params = readParams(new InetSocketAddress("127.0.0.1", Launcher.getConfig().clientPort));
if (params.profile.getClassLoaderConfig() != ClientProfile.ClassLoaderConfig.AGENT) { if (params.profile.getClassLoaderConfig() != ClientProfile.ClassLoaderConfig.AGENT) {
LauncherEngine.verifyNoAgent(); ClientLauncherMethods.verifyNoAgent();
} }
ClientProfile profile = params.profile; ClientProfile profile = params.profile;
Launcher.profile = profile; Launcher.profile = profile;
AuthService.profile = profile; AuthService.profile = profile;
LauncherEngine.clientParams = params; clientParams = params;
if (params.oauth != null) { if (params.oauth != null) {
LogHelper.info("Using OAuth"); LogHelper.info("Using OAuth");
if (params.oauthExpiredTime != 0) { if (params.oauthExpiredTime != 0) {
@ -108,7 +106,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");
} }
LauncherEngine.modulesManager.invokeEvent(new ClientProcessInitPhase(engine, params)); modulesManager.invokeEvent(new ClientProcessInitPhase(params));
Path clientDir = Paths.get(params.clientDir); Path clientDir = Paths.get(params.clientDir);
Path assetDir = Paths.get(params.assetDir); Path assetDir = Paths.get(params.assetDir);
@ -122,7 +120,7 @@ public static void main(String[] args) throws Throwable {
// Start client with WatchService monitoring // Start client with WatchService monitoring
RequestService service; RequestService service;
if (params.offlineMode) { if (params.offlineMode) {
service = initOffline(LauncherEngine.modulesManager, params); service = ClientLauncherMethods.initOffline(modulesManager, params);
Request.setRequestService(service); Request.setRequestService(service);
} else { } else {
service = StdWebSocketService.initWebSockets(Launcher.getConfig().address).get(); service = StdWebSocketService.initWebSockets(Launcher.getConfig().address).get();
@ -149,7 +147,7 @@ public static void main(String[] args) throws Throwable {
ClientLauncherEntryPoint.classLoader = classLoader; ClientLauncherEntryPoint.classLoader = classLoader;
Thread.currentThread().setContextClassLoader(classLoader); Thread.currentThread().setContextClassLoader(classLoader);
classLoader.nativePath = params.nativesDir; classLoader.nativePath = params.nativesDir;
LauncherEngine.modulesManager.invokeEvent(new ClientProcessClassLoaderEvent(engine, classLoader, profile)); modulesManager.invokeEvent(new ClientProcessClassLoaderEvent(classLoader, profile));
ClientService.classLoader = classLoader; ClientService.classLoader = classLoader;
ClientService.nativePath = classLoader.nativePath; ClientService.nativePath = classLoader.nativePath;
classLoader.addURL(IOHelper.getCodeSource(ClientLauncherEntryPoint.class).toUri().toURL()); classLoader.addURL(IOHelper.getCodeSource(ClientLauncherEntryPoint.class).toUri().toURL());
@ -162,7 +160,7 @@ public static void main(String[] args) throws Throwable {
} }
ClientService.instrumentation = LauncherAgent.inst; ClientService.instrumentation = LauncherAgent.inst;
ClientService.nativePath = params.nativesDir; ClientService.nativePath = params.nativesDir;
LauncherEngine.modulesManager.invokeEvent(new ClientProcessClassLoaderEvent(engine, classLoader, profile)); modulesManager.invokeEvent(new ClientProcessClassLoaderEvent(classLoader, profile));
ClientService.classLoader = classLoader; ClientService.classLoader = classLoader;
ClientService.baseURLs = classpathURLs.toArray(new URL[0]); ClientService.baseURLs = classpathURLs.toArray(new URL[0]);
} else if (classLoaderConfig == ClientProfile.ClassLoaderConfig.SYSTEM_ARGS) { } else if (classLoaderConfig == ClientProfile.ClassLoaderConfig.SYSTEM_ARGS) {
@ -174,7 +172,7 @@ 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;
LauncherEngine.modulesManager.invokeEvent(new ClientProcessReadyEvent(engine, params)); modulesManager.invokeEvent(new ClientProcessReadyEvent(params));
LogHelper.debug("Starting JVM and client WatchService"); LogHelper.debug("Starting JVM and client WatchService");
FileNameMatcher assetMatcher = profile.getAssetUpdateMatcher(); FileNameMatcher assetMatcher = profile.getAssetUpdateMatcher();
FileNameMatcher clientMatcher = profile.getClientUpdateMatcher(); FileNameMatcher clientMatcher = profile.getClientUpdateMatcher();
@ -197,44 +195,11 @@ public static void main(String[] args) throws Throwable {
verifyHDir(clientDir, params.clientHDir, clientMatcher, false, true); verifyHDir(clientDir, params.clientHDir, clientMatcher, false, true);
if (javaWatcher != null) if (javaWatcher != null)
verifyHDir(javaDir, params.javaHDir, null, false, true); verifyHDir(javaDir, params.javaHDir, null, false, true);
LauncherEngine.modulesManager.invokeEvent(new ClientProcessLaunchEvent(engine, params)); modulesManager.invokeEvent(new ClientProcessLaunchEvent(params));
launch(profile, params); launch(profile, params);
} }
} }
private static void initGson(ClientModuleManager moduleManager) {
AuthRequest.registerProviders();
GetAvailabilityAuthRequest.registerProviders();
OptionalAction.registerProviders();
OptionalTrigger.registerProviders();
Launcher.gsonManager = new ClientGsonManager(moduleManager);
Launcher.gsonManager.initGson();
}
public static RequestService initOffline(LauncherModulesManager modulesManager, ClientLauncherProcess.ClientParams params) {
OfflineRequestService service = new OfflineRequestService();
LauncherEngine.applyBasicOfflineProcessors(service);
applyClientOfflineProcessors(service, params);
OfflineModeEvent event = new OfflineModeEvent(service);
modulesManager.invokeEvent(event);
return event.service;
}
public static void applyClientOfflineProcessors(OfflineRequestService service, ClientLauncherProcess.ClientParams params) {
service.registerRequestProcessor(ProfileByUsernameRequest.class, (r) -> {
if (params.playerProfile.username.equals(r.username)) {
return new ProfileByUsernameRequestEvent(params.playerProfile);
}
throw new RequestException("User not found");
});
service.registerRequestProcessor(ProfileByUUIDRequest.class, (r) -> {
if (params.playerProfile.uuid.equals(r.uuid)) {
return new ProfileByUUIDRequestEvent(params.playerProfile);
}
throw new RequestException("User not found");
});
}
public static void verifyHDir(Path dir, HashedDir hdir, FileNameMatcher matcher, boolean digest, boolean checkExtra) throws IOException { public static void verifyHDir(Path dir, HashedDir hdir, FileNameMatcher matcher, boolean digest, boolean checkExtra) throws IOException {
//if (matcher != null) //if (matcher != null)
// matcher = matcher.verifyOnly(); // matcher = matcher.verifyOnly();
@ -288,7 +253,7 @@ public static Stream<Path> resolveClassPath(Path clientDir, Set<OptionalAction>
return result; return result;
} }
private static void launch(ClientProfile profile, ClientLauncherProcess.ClientParams params) throws Throwable { private static void launch(ClientProfile profile, 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(ClientProfileVersions.MINECRAFT_1_6_4) >= 0)
@ -318,7 +283,7 @@ private static void launch(ClientProfile profile, ClientLauncherProcess.ClientPa
LogHelper.dev("ClassLoader URL: %s", u.toString()); LogHelper.dev("ClassLoader URL: %s", u.toString());
} }
} }
LauncherEngine.modulesManager.invokeEvent(new ClientProcessPreInvokeMainClassEvent(params, profile, args)); modulesManager.invokeEvent(new ClientProcessPreInvokeMainClassEvent(params, profile, args));
// Invoke main method // Invoke main method
try { try {
{ {
@ -338,7 +303,7 @@ private static void launch(ClientProfile profile, ClientLauncherProcess.ClientPa
LogHelper.error(e); LogHelper.error(e);
throw e; throw e;
} finally { } finally {
LauncherEngine.exitLauncher(0); ClientLauncherMethods.exitLauncher(0);
} }
} }

View file

@ -1,6 +1,5 @@
package pro.gravit.launcher.client; package pro.gravit.launcher.client;
import pro.gravit.launcher.ClientLauncherWrapper;
import pro.gravit.launcher.Launcher; import pro.gravit.launcher.Launcher;
import pro.gravit.launcher.LauncherTrustManager; import pro.gravit.launcher.LauncherTrustManager;
import pro.gravit.launcher.modules.LauncherModule; import pro.gravit.launcher.modules.LauncherModule;
@ -38,12 +37,4 @@ public List<LauncherModule> getModules() {
public final boolean verifyClassCheckResult(LauncherTrustManager.CheckClassResult result) { public final boolean verifyClassCheckResult(LauncherTrustManager.CheckClassResult result) {
return result.type == LauncherTrustManager.CheckClassResultType.SUCCESS; return result.type == LauncherTrustManager.CheckClassResultType.SUCCESS;
} }
public void callWrapper(ClientLauncherWrapper.ClientLauncherWrapperContext context) {
for (LauncherModule module : modules) {
if (module instanceof ClientWrapperModule) {
((ClientWrapperModule) module).wrapperPhase(context);
}
}
}
} }

View file

@ -0,0 +1,130 @@
package pro.gravit.launcher.client;
import pro.gravit.launcher.Launcher;
import pro.gravit.launcher.events.request.AuthRequestEvent;
import pro.gravit.launcher.hasher.HashedDir;
import pro.gravit.launcher.profiles.ClientProfile;
import pro.gravit.launcher.profiles.ClientProfileVersions;
import pro.gravit.launcher.profiles.PlayerProfile;
import pro.gravit.launcher.profiles.optional.actions.OptionalAction;
import pro.gravit.launcher.profiles.optional.actions.OptionalActionClientArgs;
import pro.gravit.utils.Version;
import java.util.*;
public class ClientParams {
public String assetDir;
public String clientDir;
public String resourcePackDir;
public String nativesDir;
// Client params
public PlayerProfile playerProfile;
public ClientProfile profile;
public String accessToken;
//==Minecraft params==
public boolean autoEnter;
public boolean fullScreen;
public int ram;
public int width;
public int height;
public Set<OptionalAction> actions = new HashSet<>();
//========
public UUID session;
public AuthRequestEvent.OAuthRequestEvent oauth;
public String authId;
public long oauthExpiredTime;
public Map<String, String> extendedTokens;
public boolean offlineMode;
public transient HashedDir assetHDir;
public transient HashedDir clientHDir;
public transient HashedDir javaHDir;
public void addClientArgs(Collection<String> args) {
if (profile.getVersion().compareTo(ClientProfileVersions.MINECRAFT_1_6_4) >= 0)
addModernClientArgs(args);
else
addClientLegacyArgs(args);
}
public void addClientLegacyArgs(Collection<String> args) {
args.add(playerProfile.username);
args.add(accessToken);
// Add args for tweaker
Collections.addAll(args, "--version", profile.getVersion().toString());
Collections.addAll(args, "--gameDir", clientDir);
Collections.addAll(args, "--assetsDir", assetDir);
}
private void addModernClientArgs(Collection<String> args) {
// Add version-dependent args
ClientProfile.Version version = profile.getVersion();
Collections.addAll(args, "--username", playerProfile.username);
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_7_2) >= 0) {
Collections.addAll(args, "--uuid", Launcher.toHash(playerProfile.uuid));
Collections.addAll(args, "--accessToken", accessToken);
// Add 1.7.10+ args (user properties, asset index)
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_7_10) >= 0) {
// Add user properties
Collections.addAll(args, "--userType", "mojang");
Collections.addAll(args, "--userProperties", "{}");
// Add asset index
Collections.addAll(args, "--assetIndex", profile.getAssetIndex());
}
} else
Collections.addAll(args, "--session", accessToken);
// Add version and dirs args
Collections.addAll(args, "--version", profile.getVersion().toString());
Collections.addAll(args, "--gameDir", clientDir);
Collections.addAll(args, "--assetsDir", assetDir);
Collections.addAll(args, "--resourcePackDir", resourcePackDir);
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_9_4) >= 0)
Collections.addAll(args, "--versionType", "Launcher v" + Version.getVersion().getVersionString());
// Add server args
if (autoEnter) {
Collections.addAll(args, "--server", profile.getServerAddress());
Collections.addAll(args, "--port", Integer.toString(profile.getServerPort()));
}
for (OptionalAction a : actions) {
if (a instanceof OptionalActionClientArgs) {
args.addAll(((OptionalActionClientArgs) a).args);
}
}
// Add window size args
if (fullScreen)
Collections.addAll(args, "--fullscreen", Boolean.toString(true));
if (width > 0 && height > 0) {
Collections.addAll(args, "--width", Integer.toString(width));
Collections.addAll(args, "--height", Integer.toString(height));
}
}
}

View file

@ -1,16 +1,13 @@
package pro.gravit.launcher.client.events.client; package pro.gravit.launcher.client.events.client;
import pro.gravit.launcher.LauncherEngine;
import pro.gravit.launcher.modules.LauncherModule; import pro.gravit.launcher.modules.LauncherModule;
import pro.gravit.launcher.profiles.ClientProfile; import pro.gravit.launcher.profiles.ClientProfile;
public class ClientProcessClassLoaderEvent extends LauncherModule.Event { public class ClientProcessClassLoaderEvent extends LauncherModule.Event {
public final LauncherEngine clientInstance;
public final ClassLoader clientClassLoader; public final ClassLoader clientClassLoader;
public final ClientProfile profile; public final ClientProfile profile;
public ClientProcessClassLoaderEvent(LauncherEngine clientInstance, ClassLoader clientClassLoader, ClientProfile profile) { public ClientProcessClassLoaderEvent(ClassLoader clientClassLoader, ClientProfile profile) {
this.clientInstance = clientInstance;
this.clientClassLoader = clientClassLoader; this.clientClassLoader = clientClassLoader;
this.profile = profile; this.profile = profile;
} }

View file

@ -0,0 +1,12 @@
package pro.gravit.launcher.client.events.client;
import pro.gravit.launcher.client.ClientParams;
import pro.gravit.launcher.modules.events.InitPhase;
public class ClientProcessInitPhase extends InitPhase {
public final ClientParams params;
public ClientProcessInitPhase(ClientParams params) {
this.params = params;
}
}

View file

@ -0,0 +1,12 @@
package pro.gravit.launcher.client.events.client;
import pro.gravit.launcher.client.ClientParams;
import pro.gravit.launcher.modules.LauncherModule;
public class ClientProcessLaunchEvent extends LauncherModule.Event {
public final ClientParams params;
public ClientProcessLaunchEvent(ClientParams params) {
this.params = params;
}
}

View file

@ -1,17 +1,17 @@
package pro.gravit.launcher.client.events.client; package pro.gravit.launcher.client.events.client;
import pro.gravit.launcher.client.ClientLauncherProcess; import pro.gravit.launcher.client.ClientParams;
import pro.gravit.launcher.modules.LauncherModule; import pro.gravit.launcher.modules.LauncherModule;
import pro.gravit.launcher.profiles.ClientProfile; import pro.gravit.launcher.profiles.ClientProfile;
import java.util.Collection; import java.util.Collection;
public class ClientProcessPreInvokeMainClassEvent extends LauncherModule.Event { public class ClientProcessPreInvokeMainClassEvent extends LauncherModule.Event {
public final ClientLauncherProcess.ClientParams params; public final ClientParams params;
public final ClientProfile profile; public final ClientProfile profile;
public final Collection<String> args; public final Collection<String> args;
public ClientProcessPreInvokeMainClassEvent(ClientLauncherProcess.ClientParams params, ClientProfile profile, Collection<String> args) { public ClientProcessPreInvokeMainClassEvent(ClientParams params, ClientProfile profile, Collection<String> args) {
this.params = params; this.params = params;
this.profile = profile; this.profile = profile;
this.args = args; this.args = args;

View file

@ -0,0 +1,12 @@
package pro.gravit.launcher.client.events.client;
import pro.gravit.launcher.client.ClientParams;
import pro.gravit.launcher.modules.events.PostInitPhase;
public class ClientProcessReadyEvent extends PostInitPhase {
public final ClientParams params;
public ClientProcessReadyEvent(ClientParams params) {
this.params = params;
}
}

View file

@ -1,6 +1,7 @@
package pro.gravit.launcher.utils; package pro.gravit.launcher.utils;
import pro.gravit.launcher.LauncherEngine; import pro.gravit.launcher.ClientLauncherMethods;
import pro.gravit.launcher.client.ClientLauncherEntryPoint;
import pro.gravit.launcher.hasher.FileNameMatcher; import pro.gravit.launcher.hasher.FileNameMatcher;
import pro.gravit.launcher.hasher.HashedDir; import pro.gravit.launcher.hasher.HashedDir;
import pro.gravit.launcher.hasher.HashedEntry; import pro.gravit.launcher.hasher.HashedEntry;
@ -47,7 +48,7 @@ public DirWatcher(Path dir, HashedDir hdir, FileNameMatcher matcher, boolean dig
private static void handleError(Throwable e) { private static void handleError(Throwable e) {
LogHelper.error(e); LogHelper.error(e);
LauncherEngine.exitLauncher(-123); ClientLauncherMethods.exitLauncher(-123);
} }
private static Deque<String> toPath(Iterable<Path> path) { private static Deque<String> toPath(Iterable<Path> path) {

View file

@ -5,10 +5,10 @@
public final class Version implements Comparable<Version> { public final class Version implements Comparable<Version> {
public static final int MAJOR = 5; public static final int MAJOR = 5;
public static final int MINOR = 4; public static final int MINOR = 5;
public static final int PATCH = 4; public static final int PATCH = 0;
public static final int BUILD = 1; public static final int BUILD = 1;
public static final Version.Type RELEASE = Type.STABLE; public static final Version.Type RELEASE = Type.EXPERIMENTAL;
public final int major; public final int major;
public final int minor; public final int minor;
public final int patch; public final int patch;

View file

@ -0,0 +1,80 @@
apply plugin: 'org.openjfx.javafxplugin'
String mainClassName = "pro.gravit.launcher.ClientLauncherWrapper"
String mainAgentName = "pro.gravit.launcher.LauncherAgent"
repositories {
maven {
url "https://repo.spring.io/plugins-release/"
}
}
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
jar {
archiveClassifier.set('clean')
manifest.attributes("Main-Class": mainClassName,
"Premain-Class": mainAgentName,
"Multi-Release": "true")
}
tasks.register('sourcesJar', Jar) {
from sourceSets.main.allJava
archiveClassifier.set('sources')
}
tasks.register('javadocJar', Jar) {
from javadoc
archiveClassifier.set('javadoc')
}
dependencies {
implementation project(':LauncherAPI')
implementation project(':LauncherClient')
}
publishing {
publications {
launcherclientstart(MavenPublication) {
artifactId = 'launcher-client-start-api'
artifact(jar) {
classifier ""
}
artifact sourcesJar
artifact javadocJar
pom {
name = 'GravitLauncher Client API'
description = 'GravitLauncher Client Module API'
url = 'https://gravitlauncher.com'
licenses {
license {
name = 'GNU General Public License, Version 3.0'
url = 'https://www.gnu.org/licenses/gpl-3.0.html'
}
}
developers {
developer {
id = 'gravita'
name = 'Gravita'
email = 'gravita@gravit.pro'
}
developer {
id = 'zaxar163'
name = 'Zaxar163'
email = 'zahar.vcherachny@yandex.ru'
}
}
scm {
connection = 'scm:git:https://github.com/GravitLauncher/Launcher.git'
developerConnection = 'scm:git:ssh://git@github.com:GravitLauncher/Launcher.git'
url = 'https://gravitlauncher.com/'
}
}
}
}
}
signing {
sign publishing.publications.launcherclientapi
}

View file

@ -1,6 +1,6 @@
package pro.gravit.launcher; package pro.gravit.launcher;
import pro.gravit.launcher.client.ClientModuleManager; import pro.gravit.launcher.client.RuntimeModuleManager;
import pro.gravit.launcher.client.DirBridge; import pro.gravit.launcher.client.DirBridge;
import pro.gravit.launcher.utils.DirWatcher; import pro.gravit.launcher.utils.DirWatcher;
import pro.gravit.utils.helper.*; import pro.gravit.utils.helper.*;
@ -22,6 +22,7 @@ public class ClientLauncherWrapper {
public static int launcherMemoryLimit; public static int launcherMemoryLimit;
@LauncherInject("launcher.customJvmOptions") @LauncherInject("launcher.customJvmOptions")
public static List<String> customJvmOptions; public static List<String> customJvmOptions;
public static RuntimeModuleManager modulesManager;
public static void main(String[] arguments) throws IOException, InterruptedException { public static void main(String[] arguments) throws IOException, InterruptedException {
LogHelper.printVersion("Launcher"); LogHelper.printVersion("Launcher");
@ -30,8 +31,8 @@ public static void main(String[] arguments) throws IOException, InterruptedExcep
JVMHelper.verifySystemProperties(Launcher.class, true); JVMHelper.verifySystemProperties(Launcher.class, true);
EnvHelper.checkDangerousParams(); EnvHelper.checkDangerousParams();
LauncherConfig config = Launcher.getConfig(); LauncherConfig config = Launcher.getConfig();
LauncherEngine.modulesManager = new ClientModuleManager(); modulesManager = new RuntimeModuleManager();
LauncherConfig.initModules(LauncherEngine.modulesManager); LauncherConfig.initModules(modulesManager);
LogHelper.info("Launcher for project %s", config.projectName); LogHelper.info("Launcher for project %s", config.projectName);
if (config.environment.equals(LauncherConfig.LauncherEnvironment.PROD)) { if (config.environment.equals(LauncherConfig.LauncherEnvironment.PROD)) {
@ -83,8 +84,8 @@ public static void main(String[] arguments) throws IOException, InterruptedExcep
} }
context.executePath = IOHelper.resolveJavaBin(context.javaVersion.jvmDir); context.executePath = IOHelper.resolveJavaBin(context.javaVersion.jvmDir);
String pathLauncher = IOHelper.getCodeSource(LauncherEngine.class).toString(); String pathLauncher = IOHelper.getCodeSource(ClientLauncherWrapper.class).toString();
context.mainClass = LauncherEngine.class.getName(); context.mainClass = "pro.gravit.launcher.LauncherEngineWrapper";
context.memoryLimit = launcherMemoryLimit; context.memoryLimit = launcherMemoryLimit;
context.classpath.add(pathLauncher); context.classpath.add(pathLauncher);
context.jvmProperties.put(LogHelper.DEBUG_PROPERTY, Boolean.toString(LogHelper.isDebugEnabled())); context.jvmProperties.put(LogHelper.DEBUG_PROPERTY, Boolean.toString(LogHelper.isDebugEnabled()));
@ -104,7 +105,7 @@ public static void main(String[] arguments) throws IOException, InterruptedExcep
context.args.add(MAGIC_ARG); context.args.add(MAGIC_ARG);
context.args.add("-XX:+DisableAttachMechanism"); context.args.add("-XX:+DisableAttachMechanism");
EnvHelper.addEnv(context.processBuilder); EnvHelper.addEnv(context.processBuilder);
LauncherEngine.modulesManager.callWrapper(context); modulesManager.callWrapper(context);
// --------- // ---------
List<String> args = new ArrayList<>(16); List<String> args = new ArrayList<>(16);
args.add(context.executePath.toAbsolutePath().toString()); args.add(context.executePath.toAbsolutePath().toString());

View file

@ -1,4 +1,4 @@
package pro.gravit.launcher.client; package pro.gravit.launcher;
import pro.gravit.launcher.ClientLauncherWrapper; import pro.gravit.launcher.ClientLauncherWrapper;

View file

@ -0,0 +1,50 @@
package pro.gravit.launcher.client;
import pro.gravit.launcher.ClientLauncherWrapper;
import pro.gravit.launcher.ClientWrapperModule;
import pro.gravit.launcher.Launcher;
import pro.gravit.launcher.LauncherTrustManager;
import pro.gravit.launcher.modules.LauncherModule;
import pro.gravit.launcher.modules.impl.SimpleModuleManager;
import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
public final class RuntimeModuleManager extends SimpleModuleManager {
public RuntimeModuleManager() {
super(null, null, Launcher.getConfig().trustManager);
}
@Override
public void autoload() {
throw new UnsupportedOperationException();
}
@Override
public void autoload(Path dir) {
throw new UnsupportedOperationException();
}
@Override
public LauncherModule loadModule(LauncherModule module) {
return super.loadModule(module);
}
public List<LauncherModule> getModules() {
return Collections.unmodifiableList(modules);
}
@Override
public final boolean verifyClassCheckResult(LauncherTrustManager.CheckClassResult result) {
return result.type == LauncherTrustManager.CheckClassResultType.SUCCESS;
}
public void callWrapper(ClientLauncherWrapper.ClientLauncherWrapperContext context) {
for (LauncherModule module : modules) {
if (module instanceof ClientWrapperModule) {
((ClientWrapperModule) module).wrapperPhase(context);
}
}
}
}

View file

@ -5,7 +5,7 @@
id 'org.openjfx.javafxplugin' version '0.0.10' apply false id 'org.openjfx.javafxplugin' version '0.0.10' apply false
} }
group = 'pro.gravit.launcher' group = 'pro.gravit.launcher'
version = '5.4.4' version = '5.5.0-SNAPSHOT'
apply from: 'props.gradle' apply from: 'props.gradle'

View file

@ -3,6 +3,8 @@
include 'Launcher' include 'Launcher'
include 'LauncherCore' include 'LauncherCore'
include 'LauncherAPI' include 'LauncherAPI'
include 'LauncherClient'
include 'LauncherStart'
include 'ServerWrapper' include 'ServerWrapper'
include 'LaunchServer' include 'LaunchServer'
include 'modules' include 'modules'