OneLauncher-Cracked/packages/oneclient_common/src/paths.rs
2026-08-08 11:33:24 +07:00

152 lines
3.9 KiB
Rust

use directories::ProjectDirs;
use std::path::{Path, PathBuf};
use std::sync::OnceLock;
use crate::domain::{ContentType, ProviderId};
use crate::error::{PathsError, PathsResult};
const QUALIFIER: &str = "org";
const ORGANIZATION: &str = "Polyfrost";
#[cfg(not(debug_assertions))]
const APPLICATION: &str = "OneClient";
// Separate dir so a running dev environment never touches prod data
#[cfg(debug_assertions)]
const APPLICATION: &str = "OneClient-dev";
static PROJECT_DIRS: OnceLock<ProjectDirs> = OnceLock::new();
static LAUNCHER_DIR_OVERRIDE: OnceLock<PathBuf> = OnceLock::new();
pub fn set_launcher_dir(dir: PathBuf) {
let _ = LAUNCHER_DIR_OVERRIDE.set(dir);
}
fn project_dirs() -> PathsResult<&'static ProjectDirs> {
if let Some(dirs) = PROJECT_DIRS.get() {
return Ok(dirs);
}
let dirs = ProjectDirs::from(QUALIFIER, ORGANIZATION, APPLICATION)
.ok_or(PathsError::DataDirUnavailable)?;
let _ = PROJECT_DIRS.set(dirs);
PROJECT_DIRS.get().ok_or(PathsError::DataDirUnavailable)
}
pub fn launcher_dir() -> PathsResult<&'static Path> {
if let Some(dir) = LAUNCHER_DIR_OVERRIDE.get() {
return Ok(dir);
}
Ok(project_dirs()?.data_local_dir())
}
pub fn database_file() -> PathsResult<PathBuf> {
Ok(launcher_dir()?.join("user_data.db"))
}
pub fn settings_file() -> PathsResult<PathBuf> {
Ok(launcher_dir()?.join("settings.json"))
}
pub fn auth_file() -> PathsResult<PathBuf> {
Ok(launcher_dir()?.join("auth.json"))
}
pub fn logs_dir() -> PathsResult<PathBuf> {
Ok(launcher_dir()?.join("logs"))
}
pub fn java_dir() -> PathsResult<PathBuf> {
Ok(launcher_dir()?.join("metadata").join("java"))
}
pub fn clusters_dir() -> PathsResult<PathBuf> {
Ok(launcher_dir()?.join("clusters"))
}
pub fn shared_minecraft_dir() -> PathsResult<PathBuf> {
Ok(launcher_dir()?.join(".minecraft"))
}
/// Presence marks a cluster folder as its own game dir instead of the shared `.minecraft`
pub const DEDICATED_MARKER: &str = ".dedicated_directory";
pub fn cluster_dir(folder_name: &str) -> PathsResult<PathBuf> {
Ok(clusters_dir()?.join(folder_name))
}
pub fn cluster_uses_dedicated_dir(folder_name: &str) -> bool {
cluster_dir(folder_name).is_ok_and(|dir| dir.join(DEDICATED_MARKER).exists())
}
/// Lives here not on `Cluster` so the content layer can resolve it from a bare
/// `ClusterRow` without duplicating the marker-file rule
pub fn cluster_game_dir(folder_name: &str) -> PathsResult<PathBuf> {
if cluster_uses_dedicated_dir(folder_name) {
cluster_dir(folder_name)
} else {
shared_minecraft_dir()
}
}
pub fn packages_cache_dir() -> PathsResult<PathBuf> {
Ok(launcher_dir()?.join("metadata").join("packages"))
}
pub fn caches_dir() -> PathsResult<PathBuf> {
Ok(launcher_dir()?.join("metadata").join("caches"))
}
pub fn bundles_dir() -> PathsResult<PathBuf> {
Ok(caches_dir()?.join("bundles"))
}
pub fn images_cache_dir() -> PathsResult<PathBuf> {
Ok(caches_dir()?.join("images"))
}
pub fn profiles_cache_dir() -> PathsResult<PathBuf> {
Ok(caches_dir()?.join("profiles"))
}
pub fn versions_dir() -> PathsResult<PathBuf> {
Ok(launcher_dir()?.join("metadata").join("versions"))
}
pub fn libraries_dir() -> PathsResult<PathBuf> {
Ok(launcher_dir()?.join("metadata").join("libraries"))
}
pub fn natives_dir() -> PathsResult<PathBuf> {
Ok(launcher_dir()?.join("metadata").join("natives"))
}
pub fn assets_dir() -> PathsResult<PathBuf> {
Ok(launcher_dir()?.join("metadata").join("assets"))
}
pub fn assets_index_dir() -> PathsResult<PathBuf> {
Ok(assets_dir()?.join("indexes"))
}
pub fn assets_object_dir() -> PathsResult<PathBuf> {
Ok(assets_dir()?.join("objects"))
}
pub fn legacy_assets_dir() -> PathsResult<PathBuf> {
Ok(launcher_dir()?.join("metadata").join("resources"))
}
pub fn package_version_dir(
content_type: ContentType,
provider: ProviderId,
project_id: &str,
version_id: &str,
) -> PathsResult<PathBuf> {
Ok(packages_cache_dir()?
.join(content_type.folder_name())
.join(provider.dir_name())
.join(project_id)
.join(version_id))
}