diff options
| author | 2025-01-05 04:39:18 -0600 | |
|---|---|---|
| committer | 2025-01-05 04:39:18 -0600 | |
| commit | a757414560aba4247eb0bd93cf954968fd006f7c (patch) | |
| tree | 7523186408e3ad85706e9c1e1ca2070e9660ee20 | |
| parent | moo (diff) | |
idr what I changed
| -rw-r--r-- | .idea/o3launcher.iml | 1 | ||||
| -rw-r--r-- | Cargo.lock | 94 | ||||
| -rw-r--r-- | Cargo.toml | 3 | ||||
| -rw-r--r-- | ozone-cli/Cargo.toml | 7 | ||||
| -rw-r--r-- | ozone-cli/src/main.rs | 8 | ||||
| -rw-r--r-- | src/launcher.rs | 146 | ||||
| -rw-r--r-- | src/launcher/version.rs | 25 | ||||
| -rw-r--r-- | src/version.rs | 5 |
8 files changed, 275 insertions, 14 deletions
diff --git a/.idea/o3launcher.iml b/.idea/o3launcher.iml index 34c821f..18d6207 100644 --- a/.idea/o3launcher.iml +++ b/.idea/o3launcher.iml @@ -4,6 +4,7 @@ <content url="file://$MODULE_DIR$"> <sourceFolder url="file://$MODULE_DIR$/ozone-ui/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> + <sourceFolder url="file://$MODULE_DIR$/ozone-cli/src" isTestSource="false" /> <excludeFolder url="file://$MODULE_DIR$/target" /> </content> <orderEntry type="inheritedJdk" /> @@ -1358,7 +1358,7 @@ dependencies = [ "presser", "thiserror", "winapi", - "windows", + "windows 0.52.0", ] [[package]] @@ -1607,7 +1607,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows-core 0.52.0", ] [[package]] @@ -2284,6 +2284,15 @@ dependencies = [ ] [[package]] +name = "ntapi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +dependencies = [ + "winapi", +] + +[[package]] name = "num-traits" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2334,6 +2343,7 @@ dependencies = [ "serde", "serde_json", "sha1_smol", + "sysinfo", "tokio", ] @@ -2657,6 +2667,13 @@ dependencies = [ ] [[package]] +name = "ozone-cli" +version = "0.1.0" +dependencies = [ + "sysinfo", +] + +[[package]] name = "ozone-ui" version = "0.1.0" dependencies = [ @@ -3651,6 +3668,20 @@ dependencies = [ ] [[package]] +name = "sysinfo" +version = "0.33.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fc858248ea01b66f19d8e8a6d55f41deaf91e9d495246fd01368d99935c6c01" +dependencies = [ + "core-foundation-sys", + "libc", + "memchr", + "ntapi", + "rayon", + "windows 0.57.0", +] + +[[package]] name = "system-configuration" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4442,7 +4473,17 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ - "windows-core", + "windows-core 0.52.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +dependencies = [ + "windows-core 0.57.0", "windows-targets 0.52.6", ] @@ -4456,18 +4497,61 @@ dependencies = [ ] [[package]] +name = "windows-core" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result 0.1.2", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.93", +] + +[[package]] +name = "windows-interface" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.93", +] + +[[package]] name = "windows-registry" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" dependencies = [ - "windows-result", + "windows-result 0.2.0", "windows-strings", "windows-targets 0.52.6", ] [[package]] name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" @@ -4481,7 +4565,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" dependencies = [ - "windows-result", + "windows-result 0.2.0", "windows-targets 0.52.6", ] @@ -11,9 +11,10 @@ reqwest = "0.12.9" serde = { version = "1.0.216", features = ["derive"] } serde_json = "1.0.133" sha1_smol = { version = "1.0.1", features = ["alloc", "std", "serde"] } +sysinfo = { version = "0.33.1", features = ["system", "multithread"] } tokio = { version = "1.42.0", features = ["fs"] } [workspace] -members = [ +members = [ "ozone-cli", "ozone-ui" ] diff --git a/ozone-cli/Cargo.toml b/ozone-cli/Cargo.toml new file mode 100644 index 0000000..c4b3dd0 --- /dev/null +++ b/ozone-cli/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "ozone-cli" +version = "0.1.0" +edition = "2021" + +[dependencies] +sysinfo = { version = "0.33.1", features = ["system", "multithread"] }
\ No newline at end of file diff --git a/ozone-cli/src/main.rs b/ozone-cli/src/main.rs new file mode 100644 index 0000000..b3f91f1 --- /dev/null +++ b/ozone-cli/src/main.rs @@ -0,0 +1,8 @@ +use std::env::consts::{ARCH, OS}; +use sysinfo::System; + +fn main() { + println!("Hello, world!"); + println!("stuff: {:?} {:?} {:?} {:?} {:?}", System::name(), System::os_version(), System::long_os_version(), System::kernel_version(), System::cpu_arch()); + println!("stuff: {:?} {:?} {:?} {}", System::distribution_id(), OS, ARCH, size_of::<*const i32>()); +} 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 diff --git a/src/launcher/version.rs b/src/launcher/version.rs index 08c3bb5..f4cdd6c 100644 --- a/src/launcher/version.rs +++ b/src/launcher/version.rs @@ -190,12 +190,31 @@ impl<'a, T: Into<VersionResult<'a>>> From<Option<T>> for VersionResult<'a> { } } +#[derive(Debug)] pub enum VersionResolveError { - InheritanceLoop, + InheritanceLoop(String), MissingVersion(String), Unknown(Box<dyn Error>) } +impl Display for VersionResolveError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + VersionResolveError::InheritanceLoop(s) => { + write!(f, "inheritance loop (saw {s} twice)") + }, + VersionResolveError::MissingVersion(s) => { + write!(f, "unknown version {s}") + }, + VersionResolveError::Unknown(err) => { + write!(f, "unknown error: {err}") + } + } + } +} + +impl Error for VersionResolveError {} + impl VersionList { pub async fn online(home: &Path) -> Result<VersionList, Box<dyn Error>> { let remote = RemoteVersionList::new().await?; @@ -262,6 +281,10 @@ impl VersionList { let mut inherit = inherit.clone(); loop { + if seen.insert(inherit.clone()) { + return Err(VersionResolveError::InheritanceLoop(inherit)); + } + let inherited_ver = match self.get_version_lazy(inherit.as_str()) { VersionResult::Complete(v) => Cow::Borrowed(v), VersionResult::Remote(v) => diff --git a/src/version.rs b/src/version.rs index 188b88a..078927d 100644 --- a/src/version.rs +++ b/src/version.rs @@ -32,7 +32,7 @@ pub enum OperatingSystem { } #[derive(Debug, Clone)] -struct WrappedRegex(Regex); +pub struct WrappedRegex(Regex); impl Deref for WrappedRegex { type Target = Regex; @@ -67,7 +67,8 @@ impl<'de> Deserialize<'de> for WrappedRegex { #[derive(Deserialize, Debug, Clone)] pub struct OSRestriction { - pub name: Option<OperatingSystem>, + #[serde(rename = "name")] + pub os: Option<OperatingSystem>, pub version: Option<WrappedRegex>, pub arch: Option<WrappedRegex> |
