make discord rpc more stable
This commit is contained in:
parent
d6aba6ab45
commit
6190411635
6 changed files with 75 additions and 24 deletions
|
|
@ -313,13 +313,8 @@ export type VersionType =
|
|||
*/
|
||||
"old_beta"
|
||||
|
||||
const ARGS_MAP = { 'debug':'{"getBuildTimestamp":[],"getPackageVersion":[],"getPlatform":[],"isInDev":[],"getArch":[],"getFamily":[],"openDevTools":[],"getGitCommitHash":[],"getType":[],"getLocale":[],"getOsVersion":[]}', 'folders':'{"fromCluster":["folder_name"],"openCluster":["folder_name"]}', 'events':'{"process":["event"],"ingress":["event"],"message":["event"]}', 'oneclient':'{"getVersions":[],"getBundlesFor":["cluster_id"],"extractBundleOverrides":["bundle_path","cluster_id"],"installUpdate":[],"updateBundlePackages":["cluster_id"],"isBundleSyncing":[],"refreshArt":["path"],"cacheArt":["path"],"checkForUpdate":[],"getClustersGroupedByMajor":[],"downloadPackageFromBundle":["package","cluster_id","bundle_name","skip_compatibility"]}', 'core':'{"createSettingsProfile":["name"],"getPackageBody":["provider","body"],"getUsers":[],"launchCluster":["id","uuid","search_for_java"],"getUsersFromAuthor":["provider","author"],"syncCluster":["cluster_id"],"getLinkedPackages":["cluster_id"],"changeSkin":["access_token","skin_url","skin_variant"],"getMultiplePackages":["provider","slugs"],"removeCluster":["id"],"togglePackage":["cluster_id","package_hash"],"installModpack":["modpack","cluster_id"],"uploadSkinBytes":["access_token","skin_data","image_format","skin_variant"],"fetchMinecraftProfile":["uuid"],"getScreenshots":["id"],"updateClusterProfile":["name","profile"],"getRunningProcessesByClusterId":["cluster_id"],"getProfileOrDefault":["name"],"getPackageVersions":["provider","slug","mc_version","loader","offset","limit"],"getProcessLogTail":["id","max_lines"],"getClusterById":["id"],"isClusterRunning":["cluster_id"],"open":["input"],"killProcess":["pid"],"fetchLoggedInProfile":["access_token"],"openMsaLogin":[],"writeSettings":["setting"],"changeCape":["access_token","cape_uuid"],"createCluster":["options"],"setClusterStage":["id","stage"],"searchPackages":["provider","query"],"setDiscordRPCMessage":["message"],"downloadPackage":["provider","package_id","version_id","cluster_id","skip_compatibility"],"removePackage":["cluster_id","package_hash"],"getClusters":[],"getWorlds":["id"],"getDefaultUser":["fallback"],"getPackage":["provider","slug"],"setDefaultUser":["uuid"],"getRunningProcesses":[],"getGlobalProfile":[],"updateClusterById":["id","request"],"refreshAccounts":[],"getGameVersions":[],"getUser":["uuid"],"convertUsernameUUID":["username_uuid"],"refreshAccount":["uuid"],"removeCape":["access_token"],"downloadExternalPackage":["package","cluster_id","force","skip_compatibility"],"removeUser":["uuid"],"getLogs":["id"],"getLogByName":["id","name"],"getLoadersForVersion":["mc_version"],"readSettings":[]}' }
|
||||
export type Router = { 'events': { ingress: (event: IngressPayload) => Promise<void>,
|
||||
message: (event: MessagePayload) => Promise<void>,
|
||||
process: (event: ProcessPayload) => Promise<void> },
|
||||
'folders': { fromCluster: (folderName: string) => Promise<string>,
|
||||
openCluster: (folderName: string) => Promise<null> },
|
||||
'debug': { openDevTools: () => Promise<void>,
|
||||
const ARGS_MAP = { 'oneclient':'{"checkForUpdate":[],"installUpdate":[],"downloadPackageFromBundle":["package","cluster_id","bundle_name","skip_compatibility"],"getClustersGroupedByMajor":[],"getBundlesFor":["cluster_id"],"getVersions":[],"isBundleSyncing":[],"cacheArt":["path"],"updateBundlePackages":["cluster_id"],"refreshArt":["path"],"extractBundleOverrides":["bundle_path","cluster_id"]}', 'events':'{"message":["event"],"ingress":["event"],"process":["event"]}', 'debug':'{"getBuildTimestamp":[],"getLocale":[],"openDevTools":[],"isInDev":[],"getFamily":[],"getArch":[],"getOsVersion":[],"getPlatform":[],"getGitCommitHash":[],"getPackageVersion":[],"getType":[]}', 'folders':'{"fromCluster":["folder_name"],"openCluster":["folder_name"]}', 'core':'{"getDefaultUser":["fallback"],"getUser":["uuid"],"removeCluster":["id"],"launchCluster":["id","uuid","search_for_java"],"searchPackages":["provider","query"],"getPackageBody":["provider","body"],"getRunningProcessesByClusterId":["cluster_id"],"setDefaultUser":["uuid"],"getProfileOrDefault":["name"],"refreshAccount":["uuid"],"readSettings":[],"getPackageVersions":["provider","slug","mc_version","loader","offset","limit"],"getUsersFromAuthor":["provider","author"],"removePackage":["cluster_id","package_hash"],"installModpack":["modpack","cluster_id"],"getLoadersForVersion":["mc_version"],"changeSkin":["access_token","skin_url","skin_variant"],"open":["input"],"downloadExternalPackage":["package","cluster_id","force","skip_compatibility"],"getClusterById":["id"],"uploadSkinBytes":["access_token","skin_data","image_format","skin_variant"],"getUsers":[],"fetchMinecraftProfile":["uuid"],"setClusterStage":["id","stage"],"changeCape":["access_token","cape_uuid"],"getMultiplePackages":["provider","slugs"],"isClusterRunning":["cluster_id"],"openMsaLogin":[],"getClusters":[],"getLogByName":["id","name"],"killProcess":["pid"],"getScreenshots":["id"],"getLinkedPackages":["cluster_id"],"updateClusterProfile":["name","profile"],"getPackage":["provider","slug"],"fetchLoggedInProfile":["access_token"],"removeUser":["uuid"],"getProcessLogTail":["id","max_lines"],"downloadPackage":["provider","package_id","version_id","cluster_id","skip_compatibility"],"createCluster":["options"],"createSettingsProfile":["name"],"getRunningProcesses":[],"updateClusterById":["id","request"],"setDiscordRPCMessage":["message"],"togglePackage":["cluster_id","package_hash"],"refreshAccounts":[],"getWorlds":["id"],"writeSettings":["setting"],"getLogs":["id"],"removeCape":["access_token"],"convertUsernameUUID":["username_uuid"],"getGameVersions":[],"syncCluster":["cluster_id"],"getGlobalProfile":[]}' }
|
||||
export type Router = { 'debug': { openDevTools: () => Promise<void>,
|
||||
isInDev: () => Promise<boolean>,
|
||||
getArch: () => Promise<string>,
|
||||
getFamily: () => Promise<string>,
|
||||
|
|
@ -330,6 +325,11 @@ getOsVersion: () => Promise<string>,
|
|||
getGitCommitHash: () => Promise<string>,
|
||||
getBuildTimestamp: () => Promise<string>,
|
||||
getPackageVersion: () => Promise<string> },
|
||||
'events': { ingress: (event: IngressPayload) => Promise<void>,
|
||||
message: (event: MessagePayload) => Promise<void>,
|
||||
process: (event: ProcessPayload) => Promise<void> },
|
||||
'folders': { fromCluster: (folderName: string) => Promise<string>,
|
||||
openCluster: (folderName: string) => Promise<null> },
|
||||
'oneclient': { getClustersGroupedByMajor: () => Promise<Partial<{ [key in number]: ClusterModel[] }>>,
|
||||
getBundlesFor: (clusterId: number) => Promise<ModpackArchive[]>,
|
||||
getVersions: () => Promise<OnlineClusterManifest>,
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ const ResolvedPathNames: Record<URLPath, string> = {
|
|||
'/app': 'Viewing Homepage',
|
||||
'/app/account': 'Viewing Account',
|
||||
'/app/account/skins': 'Viewing Skin Manager',
|
||||
'/app/cluster': 'Viewing Clusters',
|
||||
'/app/cluster': 'Viewing Versions',
|
||||
'/app/cluster/browser': 'Viewing {clusterName}\'s mods',
|
||||
'/app/cluster/browser/package': 'Browsing {packageName}',
|
||||
'/app/cluster/logs': 'Viewing {clusterName}\'s logs',
|
||||
|
|
@ -51,7 +51,7 @@ const ResolvedPathNames: Record<URLPath, string> = {
|
|||
'/app/settings/minecraft': 'Viewing Settings',
|
||||
'/app/settings/changelog': 'Viewing Settings',
|
||||
'/app/accounts': 'Viewing Accounts',
|
||||
'/app/clusters': 'Viewing Clusters',
|
||||
'/app/clusters': 'Viewing Versions',
|
||||
'/onboarding': 'Preparing OneClient',
|
||||
'/onboarding/account': 'Preparing OneClient',
|
||||
'/onboarding/finished': 'Preparing OneClient',
|
||||
|
|
|
|||
|
|
@ -196,13 +196,16 @@ pub async fn launch_minecraft(
|
|||
|
||||
let censors = log::create_censors(&creds);
|
||||
|
||||
if let Some(discord) = &state.rpc {
|
||||
discord
|
||||
.set_message(
|
||||
&format!("Playing {}", cluster.name),
|
||||
Some(Timestamps::new().start(Utc::now().timestamp())),
|
||||
)
|
||||
.await;
|
||||
if state.ensure_rpc().await {
|
||||
let rpc = state.rpc.read().await;
|
||||
if let Some(discord) = rpc.as_ref() {
|
||||
discord
|
||||
.set_message(
|
||||
&format!("Playing {}", cluster.name),
|
||||
Some(Timestamps::new().start(Utc::now().timestamp())),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
state
|
||||
|
|
|
|||
|
|
@ -945,12 +945,15 @@ impl TauriLauncherApi for TauriLauncherApiImpl {
|
|||
// region: discord RPC
|
||||
async fn set_discord_rpc_message(self, message: String) -> LauncherResult<()> {
|
||||
let state = State::get().await?;
|
||||
if let Some(discord) = &state.rpc {
|
||||
if !state.settings.read().await.discord_enabled {
|
||||
discord.clear_activity().await;
|
||||
return Ok(());
|
||||
if state.ensure_rpc().await {
|
||||
let rpc = state.rpc.read().await;
|
||||
if let Some(discord) = rpc.as_ref() {
|
||||
if !state.settings.read().await.discord_enabled {
|
||||
discord.clear_activity().await;
|
||||
return Ok(());
|
||||
}
|
||||
discord.set_message(&message, None).await;
|
||||
}
|
||||
discord.set_message(&message, None).await;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -27,6 +27,12 @@ impl DiscordRPC {
|
|||
|
||||
let connected = client.connect().is_ok();
|
||||
|
||||
if connected {
|
||||
tracing::info!("Discord RPC connected successfully");
|
||||
} else {
|
||||
tracing::warn!("Discord RPC failed to connect (Discord may not be running)");
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
started_at: chrono::Utc::now().timestamp(),
|
||||
client: Arc::new(RwLock::new(client)),
|
||||
|
|
@ -50,13 +56,17 @@ impl DiscordRPC {
|
|||
}
|
||||
|
||||
pub async fn set_activity(&self, activity: Activity<'_>) -> bool {
|
||||
if !self.is_connected() {
|
||||
// If we know we're disconnected, try to reconnect first
|
||||
if !self.is_connected() && !self.reconnect().await {
|
||||
return false;
|
||||
}
|
||||
|
||||
let mut client = self.client.write().await;
|
||||
|
||||
if client.set_activity(activity).is_err() {
|
||||
// Connection dropped — mark as disconnected so next call will reconnect
|
||||
self.set_connected(false);
|
||||
tracing::warn!("Discord RPC set_activity failed; connection may have dropped");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -71,6 +81,7 @@ impl DiscordRPC {
|
|||
let mut client = self.client.write().await;
|
||||
|
||||
if client.clear_activity().is_err() {
|
||||
self.set_connected(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -78,11 +89,19 @@ impl DiscordRPC {
|
|||
}
|
||||
|
||||
pub async fn reconnect(&self) -> bool {
|
||||
tracing::info!("Attempting Discord RPC reconnect...");
|
||||
let mut client = self.client.write().await;
|
||||
|
||||
let connected = client.reconnect().is_ok();
|
||||
|
||||
self.set_connected(connected);
|
||||
|
||||
if connected {
|
||||
tracing::info!("Discord RPC reconnected successfully");
|
||||
} else {
|
||||
tracing::warn!("Discord RPC reconnect failed");
|
||||
}
|
||||
|
||||
connected
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,9 @@ pub struct State {
|
|||
pub credentials: RwLock<CredentialsStore>,
|
||||
pub metadata: RwLock<Metadata>,
|
||||
pub processes: ProcessStore,
|
||||
pub rpc: Option<DiscordRPC>,
|
||||
/// Discord RPC client. Wrapped in `RwLock` so it can be lazily initialized
|
||||
/// after startup if Discord wasn't running when the launcher launched.
|
||||
pub rpc: RwLock<Option<DiscordRPC>>,
|
||||
}
|
||||
|
||||
impl State {
|
||||
|
|
@ -64,7 +66,31 @@ impl State {
|
|||
credentials: RwLock::new(credentials),
|
||||
metadata: RwLock::new(metadata),
|
||||
processes,
|
||||
rpc,
|
||||
rpc: RwLock::new(rpc),
|
||||
}))
|
||||
}
|
||||
|
||||
/// Get or lazily initialize the Discord RPC.
|
||||
///
|
||||
/// If RPC was `None` at startup (Discord wasn't running), this will attempt
|
||||
/// to initialize it now. Returns `true` if RPC is available after the call.
|
||||
pub async fn ensure_rpc(&self) -> bool {
|
||||
// Fast path: already have a client
|
||||
if self.rpc.read().await.is_some() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to initialize for the first time
|
||||
match DiscordRPC::initialize() {
|
||||
Ok(rpc) => {
|
||||
*self.rpc.write().await = Some(rpc);
|
||||
tracing::info!("Discord RPC lazily initialized");
|
||||
true
|
||||
}
|
||||
Err(err) => {
|
||||
tracing::debug!("Discord RPC lazy init failed: {err}");
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue