diff --git a/Cargo.lock b/Cargo.lock index 9be4ce7..8f00e10 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,47 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "array-init" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" + +[[package]] +name = "binrw" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d4bca59c20d6f40c2cc0802afbe1e788b89096f61bdf7aeea6bf00f10c2909b" +dependencies = [ + "array-init", + "binrw_derive", + "bytemuck", +] + +[[package]] +name = "binrw_derive" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8ba42866ce5bced2645bfa15e97eef2c62d2bdb530510538de8dd3d04efff3c" +dependencies = [ + "either", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bytemuck" +version = "1.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9134a6ef01ce4b366b50689c94f82c14bc72bc5d0386829828a2e2752ef7958c" + [[package]] name = "cfg-expr" version = "0.17.2" @@ -12,12 +53,40 @@ dependencies = [ "target-lexicon", ] +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "crunchy" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "half" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +dependencies = [ + "cfg-if", + "crunchy", +] + [[package]] name = "hashbrown" version = "0.15.2" @@ -40,6 +109,15 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "libz-rs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6489ca9bd760fe9642d7644e827b0c9add07df89857b0416ee15c1cc1a3b8c5a" +dependencies = [ + "zlib-rs", +] + [[package]] name = "memchr" version = "2.7.4" @@ -50,9 +128,34 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" name = "miscel" version = "0.1.0" dependencies = [ + "physis", "system-deps", ] +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "physis" +version = "0.4.0" +source = "git+https://github.com/redstrate/Physis#62b13f557ab141bd28fcce29036b83a229f5e249" +dependencies = [ + "binrw", + "bitflags", + "half", + "libz-rs-sys", + "tracing", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + [[package]] name = "pkg-config" version = "0.3.32" @@ -94,7 +197,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.101", ] [[package]] @@ -112,6 +215,17 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.101" @@ -176,6 +290,25 @@ dependencies = [ "winnow", ] +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", +] + [[package]] name = "unicode-ident" version = "1.0.18" @@ -196,3 +329,9 @@ checksum = "6cb8234a863ea0e8cd7284fcdd4f145233eb00fee02bbdd9861aec44e6477bc5" dependencies = [ "memchr", ] + +[[package]] +name = "zlib-rs" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "868b928d7949e09af2f6086dfc1e01936064cc7a819253bce650d4e2a2d63ba8" diff --git a/Cargo.toml b/Cargo.toml index 4719c7d..7560086 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,3 +17,4 @@ default = [] game_install = [] [dependencies] +physis = { git = "https://github.com/redstrate/Physis" } diff --git a/src/existing_dirs.rs b/src/existing_dirs.rs index 8aeacab..af73882 100644 --- a/src/existing_dirs.rs +++ b/src/existing_dirs.rs @@ -9,6 +9,9 @@ use std::fs; use std::fs::read_dir; use std::path::PathBuf; +use physis::common::Platform; +use physis::gamedata::GameData; + /// Where the existing installation came from #[derive(Clone, Copy)] #[repr(C)] @@ -31,6 +34,22 @@ pub struct ExistingGameDirectory { pub install_type: ExistingInstallType, /// The path to the "main folder" where "game" and "boot" sits pub path: String, + /// The latest expansion and game version in this directory. + pub version: String, +} + +fn read_version(path: &str) -> String { + let mut path = PathBuf::from(path); + path.push("game"); + let path = path.to_str().unwrap().to_string(); + + let game_data = GameData::from_existing(Platform::Win32, &path); + + if let Some(latest_repository) = game_data.repositories.last() { + return latest_repository.version.clone().unwrap_or_default(); + } + + String::default() } /// Finds existing installations on disk. Will only return locations that actually have files in them, and a really basic check to see if the data is valid. @@ -39,25 +58,27 @@ pub fn find_existing_game_dirs() -> Vec { match std::env::consts::OS { "linux" => { - // Official install (Wine) - install_dirs.push(ExistingGameDirectory { - install_type: ExistingInstallType::OfficialLauncher, - path: from_home_dir(".wine/drive_c/Program Files (x86)/SquareEnix/FINAL FANTASY XIV - A Realm Reborn") - }); - // Official install (Steam) - install_dirs.push(ExistingGameDirectory { - install_type: ExistingInstallType::OfficialLauncher, - path: from_home_dir( + { + let path = from_home_dir( ".steam/steam/steamapps/common/FINAL FANTASY XIV - A Realm Reborn", - ), - }); + ); + install_dirs.push(ExistingGameDirectory { + install_type: ExistingInstallType::OfficialLauncher, + path: path.clone(), + version: read_version(&path), + }); + } // XIVLauncherCore location - install_dirs.push(ExistingGameDirectory { - install_type: ExistingInstallType::XIVLauncherCore, - path: from_home_dir(".xlcore/ffxiv"), - }); + { + let path = from_home_dir(".xlcore/ffxiv"); + install_dirs.push(ExistingGameDirectory { + install_type: ExistingInstallType::XIVLauncherCore, + path: path.clone(), + version: read_version(&path), + }); + } // Astra location. But we have to iterate through each UUID. if let Ok(entries) = read_dir(from_home_dir(".local/share/astra/game/")) { @@ -73,30 +94,44 @@ pub fn find_existing_game_dirs() -> Vec { vec![] }) .for_each(|path| { + let path = path.to_str().unwrap().to_string(); + let version = read_version(&path); + install_dirs.push(ExistingGameDirectory { install_type: ExistingInstallType::Astra, - path: path.into_os_string().into_string().unwrap(), + path, + version, }) }); } } "macos" => { // Official Launcher (macOS) - install_dirs.push(ExistingGameDirectory { - install_type: ExistingInstallType::OfficialLauncher, - path: from_home_dir("Library/Application Support/FINAL FANTASY XIV ONLINE/Bottles/published_Final_Fantasy/drive_c/Program Files (x86)/SquareEnix/FINAL FANTASY XIV - A Realm Reborn") - }); + { + let path = from_home_dir( + "Library/Application Support/FINAL FANTASY XIV ONLINE/Bottles/published_Final_Fantasy/drive_c/Program Files (x86)/SquareEnix/FINAL FANTASY XIV - A Realm Reborn", + ); + install_dirs.push(ExistingGameDirectory { + install_type: ExistingInstallType::OfficialLauncher, + path: path.clone(), + version: read_version(&path), + }); + } // TODO: add XIV on Mac } "windows" => { // Official install (Wine) - install_dirs.push(ExistingGameDirectory { - install_type: ExistingInstallType::OfficialLauncher, - path: "C:\\Program Files (x86)\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn" - .parse() - .unwrap(), - }); + { + let path = + "C:\\Program Files (x86)\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn" + .to_string(); + install_dirs.push(ExistingGameDirectory { + install_type: ExistingInstallType::OfficialLauncher, + path: path.clone(), + version: read_version(&path), + }); + } // TODO: Add Astra } @@ -106,6 +141,7 @@ pub fn find_existing_game_dirs() -> Vec { install_dirs .into_iter() .filter(|dir| is_valid_game_dir(&dir.path)) + .filter(|dir| !dir.version.is_empty()) .collect() }