From 6b168bad6b120a0d64f2b51dba202da9f170e29a Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Thu, 9 Mar 2023 11:34:54 +0100 Subject: [PATCH] fix(dtmm): Fix game directory check when there is no Steam Fixes #60. --- crates/dtmm/src/controller/game.rs | 25 ++++++++++++++--------- crates/dtmm/src/main.rs | 31 ++++++++++++++++++++--------- crates/dtmm/src/ui/window/dialog.rs | 1 + lib/dtmt-shared/src/lib.rs | 16 +++++++-------- 4 files changed, 47 insertions(+), 26 deletions(-) diff --git a/crates/dtmm/src/controller/game.rs b/crates/dtmm/src/controller/game.rs index 9a95be6..c054688 100644 --- a/crates/dtmm/src/controller/game.rs +++ b/crates/dtmm/src/controller/game.rs @@ -533,7 +533,14 @@ pub(crate) async fn deploy_mods(state: ActionState) -> Result<()> { } } - let (game_info, deployment_info) = tokio::try_join!( + let (_, game_info, deployment_info) = tokio::try_join!( + async { + let path = state.game_dir.join("bundle"); + fs::metadata(&path) + .await + .wrap_err("Failed to open game bundle directory") + .with_suggestion(|| "Double-check 'Game Directory' in the Settings tab.") + }, async { tokio::task::spawn_blocking(dtmt_shared::collect_game_info) .await @@ -557,16 +564,16 @@ pub(crate) async fn deploy_mods(state: ActionState) -> Result<()> { ) .wrap_err("Failed to gather deployment information")?; - let game_info = game_info.wrap_err("Failed to collect Steam info")?; - tracing::debug!(?game_info, ?deployment_info); - if deployment_info - .as_ref() - .map(|i| game_info.last_updated > i.timestamp) - .unwrap_or(false) - { - eyre::bail!("Game was updated since last mod deployment. Please reset first."); + if let Some(game_info) = game_info { + if deployment_info + .as_ref() + .map(|i| game_info.last_updated > i.timestamp) + .unwrap_or(false) + { + eyre::bail!("Game was updated since last mod deployment. Please reset first."); + } } tracing::info!( diff --git a/crates/dtmm/src/main.rs b/crates/dtmm/src/main.rs index 4a6b153..c3b8cb5 100644 --- a/crates/dtmm/src/main.rs +++ b/crates/dtmm/src/main.rs @@ -8,13 +8,17 @@ use std::sync::Arc; use clap::command; use clap::value_parser; use clap::Arg; +use color_eyre::eyre; use color_eyre::eyre::Context; use color_eyre::{Report, Result}; use druid::AppLauncher; +use druid::SingleUse; +use druid::Target; use tokio::sync::RwLock; use crate::controller::app::load_mods; use crate::controller::worker::work_thread; +use crate::state::ACTION_SHOW_ERROR_DIALOG; use crate::state::{Delegate, State}; mod controller; @@ -57,17 +61,32 @@ fn main() -> Result<()> { oodle_sys::init(matches.get_one::("oodle")); } + let (action_tx, action_rx) = tokio::sync::mpsc::unbounded_channel(); + let delegate = Delegate::new(action_tx); + + let launcher = AppLauncher::with_window(ui::window::main::new()).delegate(delegate); + + let event_sink = launcher.get_external_handle(); + 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 game_info = dtmt_shared::collect_game_info(); tracing::debug!(?config, ?game_info); + let game_dir = config.game_dir.or_else(|| game_info.map(|i| i.path)); + if game_dir.is_none() { + let err = + eyre::eyre!("No Game Directory set. Head to the 'Settings' tab to set it manually",); + event_sink + .submit_command(ACTION_SHOW_ERROR_DIALOG, SingleUse::new(err), Target::Auto) + .expect("failed to send command"); + } + let initial_state = { let mut state = State::new( config.path, - config.game_dir.unwrap_or(game_info.path), + game_dir.unwrap_or_default(), config.data_dir.unwrap_or_default(), ); state.mods = load_mods(state.get_mod_dir(), config.mod_order.iter()) @@ -75,12 +94,6 @@ fn main() -> Result<()> { state }; - let (action_tx, action_rx) = tokio::sync::mpsc::unbounded_channel(); - let delegate = Delegate::new(action_tx); - - let launcher = AppLauncher::with_window(ui::window::main::new()).delegate(delegate); - - let event_sink = launcher.get_external_handle(); std::thread::spawn(move || { let event_sink = Arc::new(RwLock::new(event_sink)); let action_rx = Arc::new(RwLock::new(action_rx)); diff --git a/crates/dtmm/src/ui/window/dialog.rs b/crates/dtmm/src/ui/window/dialog.rs index 3b6802a..64ce88d 100644 --- a/crates/dtmm/src/ui/window/dialog.rs +++ b/crates/dtmm/src/ui/window/dialog.rs @@ -20,6 +20,7 @@ pub fn error(err: Report, parent: WindowHandle) -> WindowDesc { let widget = Flex::column() .main_axis_alignment(MainAxisAlignment::SpaceBetween) + .must_fill_main_axis(true) .cross_axis_alignment(CrossAxisAlignment::End) .with_child(text) .with_spacer(20.) diff --git a/lib/dtmt-shared/src/lib.rs b/lib/dtmt-shared/src/lib.rs index fa8c407..f15e4e7 100644 --- a/lib/dtmt-shared/src/lib.rs +++ b/lib/dtmt-shared/src/lib.rs @@ -1,8 +1,5 @@ use std::path::PathBuf; -use color_eyre::eyre; -use color_eyre::Result; - mod log; pub use log::*; @@ -40,11 +37,12 @@ pub struct GameInfo { pub last_updated: OffsetDateTime, } -pub fn collect_game_info() -> Result { +pub fn collect_game_info() -> Option { let mut dir = if let Some(dir) = SteamDir::locate() { dir } else { - eyre::bail!("Failed to locate Steam installation") + tracing::debug!("Failed to locate Steam installation"); + return None; }; let found = dir @@ -52,15 +50,17 @@ pub fn collect_game_info() -> Result { .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"); + tracing::debug!("Found Steam, but failed to find game installation"); + return None; }; 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'."); + tracing::error!("Found Steam game, but couldn't read 'LastUpdate'."); + return None; }; - Ok(GameInfo { path, last_updated }) + Some(GameInfo { path, last_updated }) }