diff options
| author | 2025-01-05 04:39:18 -0600 | |
|---|---|---|
| committer | 2025-01-05 04:39:18 -0600 | |
| commit | a757414560aba4247eb0bd93cf954968fd006f7c (patch) | |
| tree | 7523186408e3ad85706e9c1e1ca2070e9660ee20 /src/launcher.rs | |
| parent | moo (diff) | |
idr what I changed
Diffstat (limited to 'src/launcher.rs')
| -rw-r--r-- | src/launcher.rs | 146 |
1 files changed, 141 insertions, 5 deletions
diff --git a/src/launcher.rs b/src/launcher.rs index 0e1639d..4c4f762 100644 --- a/src/launcher.rs +++ b/src/launcher.rs @@ -3,12 +3,19 @@ mod version; mod profile; mod strsub; +use std::borrow::Cow; use std::collections::HashMap; +use std::env::consts::{ARCH, OS}; use std::error::Error; +use std::fmt::{Display, Formatter}; use std::path::{Path, PathBuf}; use serde::{Deserialize, Serialize}; +use sha1_smol::Digest; +use sysinfo::System; use version::VersionList; -use crate::launcher::profile::{Instance, Profile}; +use profile::{Instance, Profile}; +use crate::launcher::version::{VersionResolveError, VersionResult}; +use crate::version::{Library, OSRestriction, OperatingSystem}; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Settings { @@ -16,6 +23,17 @@ pub struct Settings { instances: HashMap<String, Instance> } +struct SystemInfo { + os: OperatingSystem, + os_version: String, + arch: String, + arch_bits: usize +} + +struct LibraryRepository { + home: PathBuf +} + pub struct Launcher { online: bool, home: PathBuf, @@ -23,18 +41,42 @@ pub struct Launcher { settings_path: PathBuf, // maybe redundant but idc >:3 settings: Settings, + + system_info: SystemInfo, + + libraries: LibraryRepository +} + +#[derive(Debug)] +pub enum LaunchError { + UnknownVersion(String), + LoadVersion(Box<dyn Error>), + ResolveVersion(VersionResolveError) +} + +impl Display for LaunchError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match &self { + LaunchError::UnknownVersion(id) => write!(f, "Unknown version ID: {id}"), + LaunchError::LoadVersion(e) => write!(f, "error loading remote version: {e}"), + LaunchError::ResolveVersion(e) => write!(f, "error resolving remote version: {e}") + } + } } +impl Error for LaunchError {} + impl Launcher { // FIXME: more descriptive error type por favor pub async fn new(home: &Path, online: bool) -> Result<Launcher, Box<dyn Error>> { let home = home.to_owned(); + let versions_home = home.join("versions"); let versions; if online { - versions = VersionList::online(home.join("versions").as_ref()).await?; + versions = VersionList::online(versions_home.as_ref()).await?; } else { - versions = VersionList::offline(home.join("versions").as_ref()).await?; + versions = VersionList::offline(versions_home.as_ref()).await?; } let settings_path = home.join("ozone.json"); @@ -45,11 +87,13 @@ impl Launcher { home: home.to_owned(), versions, settings_path, - settings + settings, + system_info: SystemInfo::new(), + libraries: LibraryRepository { home: home.join("libraries") } }) } - pub async fn launch(profile: &Profile) -> Result<(), Box<dyn Error>> { + pub async fn prepare_launch(&self, profile: &Profile) -> Result<(), LaunchError> { /* tasks 2 l;aunch the gayme!!!! :3 * - java runtime * - normal process (good research, past figboot :3) @@ -74,9 +118,101 @@ impl Launcher { * - launch the game * - build argument list and whatnot also */ + let ver_res = self.versions.get_version_lazy(&profile.version_id); + let ver = match ver_res { + VersionResult::Remote(mv) => Cow::Owned(self.versions.load_remote_version(mv).await.map_err(|e| LaunchError::LoadVersion(e))?), + VersionResult::Complete(cv) => Cow::Borrowed(cv), + VersionResult::None => { + return Err(LaunchError::UnknownVersion(profile.version_id.clone()).into()) + } + }; + + let ver = self.versions.resolve_version(ver.as_ref()).await.map_err(|e| LaunchError::ResolveVersion(e))?; + todo!() + } +} +impl LibraryRepository { + fn get_artifact_base_dir(name: &str) -> Option<PathBuf> { + let end_of_gid = name.find(':')?; + + Some(name[..end_of_gid].split('.').chain(name.split(':').skip(1).take(2)).collect()) + } + + fn get_artifact_filename(name: &str, classifier: Option<&str>) -> Option<PathBuf> { + let n: Vec<&str> = name.splitn(4, ':').skip(1).collect(); + + if let Some(classifier) = classifier { + match n.len() { + 3 => Some(PathBuf::from(format!("{}-{}-{}.jar", n[1], n[2], classifier))), + 4 => Some(PathBuf::from(format!("{}-{}-{}-{}.jar", n[1], n[2], classifier, n[3]))), + _ => None + } + } else { + match n.len() { + 3 => Some(PathBuf::from(format!("{}-{}.jar", n[1], n[2]))), + 4 => Some(PathBuf::from(format!("{}-{}-{}.jar", n[1], n[2], n[3]))), + _ => None + } + } + } + + fn get_artifact_path(name: &str, classifier: Option<&str>) -> Option<PathBuf> { + let Some(mut p) = Self::get_artifact_base_dir(name) else { + return None; + }; + + p.push(Self::get_artifact_filename(name, classifier)?); + Some(p) + } + + async fn should_redownload(&self, lib: &Library, classifier: Option<&str>) -> Result<bool, Box<dyn Error>> { + let path = Self::get_artifact_path(lib.name.as_str(), classifier); todo!() } +} + +impl SystemInfo { + fn new() -> SystemInfo { + let os = match OS { + "windows" => OperatingSystem::Windows, + "macos" => OperatingSystem::MacOS, + "linux" => OperatingSystem::Linux, + _ => OperatingSystem::Unknown // could probably consider "hurd" and "*bsd" to be linux... + }; + + let mut os_version = System::os_version().unwrap_or_default(); + if os == OperatingSystem::Windows && (os_version.starts_with("10") || os_version.starts_with("11")) { + os_version.replace_range(..2, "10.0"); // java expects this funny business... + } + + let mut arch = ARCH.to_owned(); + if arch == "x86_64" { + // this nomenclature is preferred, since some versions expect the arch containing "x86" to mean 32-bit. + arch.replace_range(.., "amd64"); + } + + SystemInfo { + os, + os_version, + arch, + arch_bits: size_of::<*const i32>() * 8 + } + } + + fn is_our_os(&self, os: OperatingSystem) -> bool { + if self.os == OperatingSystem::Unknown { + return false; + } + + self.os == os + } + + fn applies(&self, restriction: &OSRestriction) -> bool { + restriction.os.is_none_or(|os| self.is_our_os(os)) + && restriction.version.as_deref().is_none_or(|pat| pat.is_match(&self.os_version)) + && restriction.arch.as_deref().is_none_or(|pat| pat.is_match(&self.arch)) + } }
\ No newline at end of file |
