OneLauncher-Cracked/packages/oneclient_core/src/state.rs
2026-07-14 18:06:23 +02:00

124 lines
3.6 KiB
Rust

use std::collections::HashMap;
use std::sync::Arc;
use oneclient_db::DbPool;
use tokio::sync::{Mutex, OnceCell};
use crate::auth::{CredentialsStore, PendingBrowserLogin};
use crate::bundles::BundlesManager;
use crate::http::RequestClient;
use crate::images::ImageCacheStore;
use crate::java::JavaManager;
use crate::notification::NotificationService;
use crate::metadata::MetadataStore;
use crate::packages::provider::PackageProviderRegistry;
use crate::paths;
use crate::settings::{store, LauncherSettings};
use crate::versions::VersionsManager;
use crate::{LauncherError, LauncherResult};
static STATE: OnceCell<Arc<LauncherState>> = OnceCell::const_new();
#[derive(Clone)]
pub struct LauncherServices {
pub notifier: NotificationService,
pub requester: RequestClient,
pub db: DbPool,
pub packages: PackageProviderRegistry,
}
pub struct LauncherState {
pub services: LauncherServices,
pub settings: parking_lot::RwLock<LauncherSettings>,
pub auth: Mutex<CredentialsStore>,
pub microsoft_logins: Mutex<HashMap<String, PendingBrowserLogin>>,
pub java: JavaManager,
pub metadata: Mutex<MetadataStore>,
pub bundles: Arc<BundlesManager>,
pub versions: Arc<VersionsManager>,
pub images: ImageCacheStore,
pub games: crate::game::GameProcessManager,
}
impl LauncherState {
#[tracing::instrument(skip(notifier))]
pub async fn initialize(
notifier: NotificationService,
) -> LauncherResult<Arc<Self>> {
if let Some(state) = STATE.get() {
return Ok(Arc::clone(state));
}
let services = LauncherServices {
notifier,
db: oneclient_db::connect(paths::database_file()?).await?,
requester: RequestClient::new()?,
packages: PackageProviderRegistry::new(),
};
let settings = store::load_settings(Some(&services.notifier)).await;
let auth = CredentialsStore::load().await?;
let java = JavaManager;
let state = Arc::new(Self {
services,
settings: parking_lot::RwLock::new(settings),
auth: Mutex::new(auth),
microsoft_logins: Mutex::new(HashMap::new()),
java,
metadata: Mutex::new(MetadataStore::new()),
bundles: Arc::new(BundlesManager::new()),
versions: Arc::new(VersionsManager::new()),
images: ImageCacheStore::new(),
games: crate::game::GameProcessManager::new(),
});
STATE
.set(Arc::clone(&state))
.map_err(|_| LauncherError::AlreadyInitialized)?;
let background = Arc::clone(&state);
tokio::spawn(async move {
let recovery = match crate::recovery::reconstruct_from_disk(&background).await {
Ok(report) => report,
Err(err) => {
tracing::error!("disk recovery failed: {err:#}");
crate::recovery::RecoveryReport::default()
}
};
let (versions_res, bundles_res) = tokio::join!(
background.versions.sync(&background.services),
background.bundles.sync(&background.services),
);
if let Err(err) = versions_res {
tracing::error!("versions manifest sync failed: {err:#}");
}
if let Err(err) = bundles_res {
tracing::error!("bundle catalog sync failed: {err:#}");
}
if recovery.did_recover()
&& let Err(err) = crate::recovery::restore_bundle_tracking(&background).await
{
tracing::warn!("bundle tracking restore failed: {err:#}");
}
if let Err(err) = crate::clusters::ensure_from_versions(&background).await {
tracing::error!("versions cluster provisioning failed: {err:#}");
} else {
background.services.notifier.invalidate_clusters();
}
background.services.notifier.sync_complete();
});
Ok(state)
}
pub fn get() -> LauncherResult<Arc<Self>> {
STATE
.get()
.cloned()
.ok_or(LauncherError::NotInitialized)
}
}