From 3a85fdeb16463c3204fdc37b44b079897d703fed Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Sun, 5 Mar 2023 20:27:39 +0100 Subject: [PATCH] feat(dtmm): Locate Steam installation --- .gitmodules | 3 + Cargo.lock | 230 ++++++++++++++++++++++++++++++++++++- crates/dtmm/src/main.rs | 4 +- lib/dtmt-shared/Cargo.toml | 2 + lib/dtmt-shared/src/lib.rs | 41 ++++++- lib/steamlocate-rs | 1 + 6 files changed, 276 insertions(+), 5 deletions(-) create mode 160000 lib/steamlocate-rs diff --git a/.gitmodules b/.gitmodules index a56154d..5741e15 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "lib/serde_sjson"] path = lib/serde_sjson url = git@git.sclu1034.dev:lucas/serde_sjson.git +[submodule "lib/steamlocate-rs"] + path = lib/steamlocate-rs + url = git@github.com:sclu1034/steamlocate-rs.git diff --git a/Cargo.lock b/Cargo.lock index 60358e3..69eeed1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -483,6 +483,21 @@ dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484" + [[package]] name = "crc32fast" version = "1.3.2" @@ -557,6 +572,15 @@ dependencies = [ "dirs-sys", ] +[[package]] +name = "dirs" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" +dependencies = [ + "dirs-sys", +] + [[package]] name = "dirs-next" version = "2.0.0" @@ -726,7 +750,9 @@ dependencies = [ name = "dtmt-shared" version = "0.1.0" dependencies = [ + "color-eyre", "serde", + "steamlocate", "time", "tracing", "tracing-error", @@ -751,6 +777,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" +[[package]] +name = "enum_primitive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" +dependencies = [ + "num-traits 0.1.43", +] + [[package]] name = "errno" version = "0.2.8" @@ -1373,6 +1408,17 @@ dependencies = [ "bitflags", ] +[[package]] +name = "keyvalues-parser" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d990301996c856ea07a84bc291e76f1273db52683663efc05c8d355976897e5" +dependencies = [ + "pest", + "pest_derive", + "thiserror", +] + [[package]] name = "kurbo" version = "0.9.1" @@ -1534,6 +1580,12 @@ dependencies = [ "memoffset 0.6.5", ] +[[package]] +name = "nom" +version = "1.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce" + [[package]] name = "nom" version = "7.1.3" @@ -1552,7 +1604,7 @@ checksum = "b1e299bf5ea7b212e811e71174c5d1a5d065c4c0ad0c8691ecb1f97e3e66025e" dependencies = [ "bytecount", "memchr", - "nom", + "nom 7.1.3", ] [[package]] @@ -1565,6 +1617,91 @@ dependencies = [ "winapi", ] +[[package]] +name = "num" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits 0.2.15", +] + +[[package]] +name = "num-bigint" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" +dependencies = [ + "autocfg", + "num-integer", + "num-traits 0.2.15", +] + +[[package]] +name = "num-complex" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5" +dependencies = [ + "num-traits 0.2.15", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits 0.2.15", +] + +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits 0.2.15", +] + +[[package]] +name = "num-rational" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits 0.2.15", +] + +[[package]] +name = "num-traits" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" +dependencies = [ + "num-traits 0.2.15", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + [[package]] name = "num_cpus" version = "1.15.0" @@ -1729,6 +1866,50 @@ dependencies = [ "sha2", ] +[[package]] +name = "pest" +version = "2.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cbd939b234e95d72bc393d51788aec68aeeb5d51e748ca08ff3aad58cb722f7" +dependencies = [ + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a81186863f3d0a27340815be8f2078dd8050b14cd71913db9fbda795e5f707d7" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75a1ef20bf3193c15ac345acb32e26b3dc3223aff4d77ae4fc5359567683796b" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pest_meta" +version = "2.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e3b284b1f13a20dc5ebc90aff59a51b8d7137c221131b52a7260c08cbc1cc80" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + [[package]] name = "piet" version = "0.6.2" @@ -2099,7 +2280,7 @@ dependencies = [ name = "serde_sjson" version = "0.2.4" dependencies = [ - "nom", + "nom 7.1.3", "nom_locate", "serde", ] @@ -2169,6 +2350,42 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +[[package]] +name = "steamid-ng" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb049f8faa2cba570c5366dbaf88ee5849725b16edb771848639fac92e33673" +dependencies = [ + "enum_primitive", + "lazy_static", + "num", + "regex", + "serde", + "serde_derive", + "thiserror", +] + +[[package]] +name = "steamlocate" +version = "1.1.1" +dependencies = [ + "crc", + "dirs", + "keyvalues-parser", + "steamid-ng", + "steamy-vdf", + "winreg", +] + +[[package]] +name = "steamy-vdf" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "533127ad49314bfe71c3d3fd36b3ebac3d24f40618092e70e1cfe8362c7fac79" +dependencies = [ + "nom 1.2.4", +] + [[package]] name = "str-buf" version = "1.0.6" @@ -2792,6 +3009,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + [[package]] name = "wio" version = "0.2.2" diff --git a/crates/dtmm/src/main.rs b/crates/dtmm/src/main.rs index b1d87b9..667fc07 100644 --- a/crates/dtmm/src/main.rs +++ b/crates/dtmm/src/main.rs @@ -64,10 +64,12 @@ fn main() -> Result<()> { let config = util::config::read_config(&default_config_path, &matches) .wrap_err("failed to read config file")?; + let game_info = dtmt_shared::collect_game_info()?; + let initial_state = { let mut state = State::new( config.path, - config.game_dir.unwrap_or_default(), + config.game_dir.unwrap_or(game_info.path), config.data_dir.unwrap_or_default(), ); state.mods = load_mods(state.get_mod_dir(), config.mod_order.iter()) diff --git a/lib/dtmt-shared/Cargo.toml b/lib/dtmt-shared/Cargo.toml index 0f8ed63..eb9591d 100644 --- a/lib/dtmt-shared/Cargo.toml +++ b/lib/dtmt-shared/Cargo.toml @@ -6,7 +6,9 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +color-eyre = "0.6.2" serde = "1.0.152" +steamlocate = { path = "../../lib/steamlocate-rs", version = "*" } time = { version = "0.3.19", features = ["formatting", "local-offset", "macros"] } tracing = "0.1.37" tracing-error = "0.2.0" diff --git a/lib/dtmt-shared/src/lib.rs b/lib/dtmt-shared/src/lib.rs index 3c8690d..46e7950 100644 --- a/lib/dtmt-shared/src/lib.rs +++ b/lib/dtmt-shared/src/lib.rs @@ -1,8 +1,13 @@ -mod log; - use std::path::PathBuf; +use color_eyre::eyre; +use color_eyre::Result; + +mod log; + pub use log::*; +use steamlocate::SteamDir; +use time::OffsetDateTime; #[derive(Clone, Debug, Default, serde::Deserialize)] pub struct ModConfigResources { @@ -26,3 +31,35 @@ pub struct ModConfig { #[serde(default)] pub depends: Vec, } + +pub const STEAMAPP_ID: u32 = 1361210; + +pub struct GameInfo { + pub path: PathBuf, + pub last_updated: OffsetDateTime, +} + +pub fn collect_game_info() -> Result { + let mut dir = if let Some(dir) = SteamDir::locate() { + dir + } else { + eyre::bail!("Failed to locate Steam installation") + }; + + let found = dir + .app(&STEAMAPP_ID) + .and_then(|app| app.vdf.get("LastUpdated").map(|v| (app.path.clone(), v))); + + let Some((path, last_updated)) = found else { + eyre::bail!("Failed to find game installation"); + }; + + let Some(last_updated) = last_updated + .as_value() + .and_then(|v| v.to::()) + .and_then(|v| OffsetDateTime::from_unix_timestamp(v).ok()) else { + eyre::bail!("Couldn't read 'LastUpdate'."); + }; + + Ok(GameInfo { path, last_updated }) +} diff --git a/lib/steamlocate-rs b/lib/steamlocate-rs new file mode 160000 index 0000000..4d6898f --- /dev/null +++ b/lib/steamlocate-rs @@ -0,0 +1 @@ +Subproject commit 4d6898f632e20ea15d47b0b071daa4f3fa6c9574