From 288adf356ba39a15a150ab885980e610dd2ad598 Mon Sep 17 00:00:00 2001 From: Lucas Schwiderski Date: Mon, 27 Mar 2023 15:31:29 +0200 Subject: [PATCH] feat(dtmm): Implement resetting dtkit-patch installations Closes #88. --- CHANGELOG.adoc | 1 + crates/dtmm/src/controller/game.rs | 67 +++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index c9e4e70..2409280 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -14,6 +14,7 @@ - dtmt: add mod dependencies to config - dtmm: match mods to Nexus and check for updates - dtmt: add utility to migrate mod projects +- dtmm: reset dtkit-patch installations === Fixed diff --git a/crates/dtmm/src/controller/game.rs b/crates/dtmm/src/controller/game.rs index 45ed27e..6f5da47 100644 --- a/crates/dtmm/src/controller/game.rs +++ b/crates/dtmm/src/controller/game.rs @@ -526,11 +526,27 @@ where pub(crate) async fn deploy_mods(state: ActionState) -> Result<()> { let state = Arc::new(state); let bundle_dir = state.game_dir.join("bundle"); + let boot_bundle_path = format!("{:016x}", Murmur64::hash(BOOT_BUNDLE_NAME.as_bytes())); + + if fs::metadata(bundle_dir.join(format!("{boot_bundle_path}.patch_999"))) + .await + .is_ok() + { + let err = eyre::eyre!("Found dtkit-patch-based mod installation."); + return Err(err) + .with_suggestion(|| { + "If you're a mod author and saved projects directly in 'mods/', \ + use DTMT to migrate them to the new project structure." + .to_string() + }) + .with_suggestion(|| { + "Click 'Reset Game' to remove the previous mod installation.".to_string() + }); + } let (_, game_info, deployment_info) = tokio::try_join!( async { - let path = state.game_dir.join("bundle"); - fs::metadata(&path) + fs::metadata(&bundle_dir) .await .wrap_err("Failed to open game bundle directory") .with_suggestion(|| "Double-check 'Game Directory' in the Settings tab.") @@ -668,6 +684,45 @@ pub(crate) async fn deploy_mods(state: ActionState) -> Result<()> { Ok(()) } +#[tracing::instrument(skip_all)] +async fn reset_dtkit_patch(state: ActionState) -> Result<()> { + let bundle_dir = state.game_dir.join("bundle"); + + { + let path = bundle_dir.join(BUNDLE_DATABASE_NAME); + let backup_path = path.with_extension("data.bak"); + fs::rename(&backup_path, &path).await.wrap_err_with(|| { + format!( + "Failed to move bundle datbase backup '{}' -> '{}'", + backup_path.display(), + path.display() + ) + })?; + tracing::trace!("Reverted bundle database from backup"); + } + + for path in [ + bundle_dir.join(format!( + "{:016x}.patch_999", + Murmur64::hash(BOOT_BUNDLE_NAME.as_bytes()) + )), + state.game_dir.join("binaries/mod_loader"), + state.game_dir.join("toggle_darktide_mods.bat"), + state.game_dir.join("README.md"), + ] { + let _ = fs::remove_file(&path).await; + tracing::trace!("Removed file '{}'", path.display()); + } + + for path in [state.game_dir.join("mods"), state.game_dir.join("tools")] { + let _ = fs::remove_dir_all(&path).await; + tracing::trace!("Removed directory '{}'", path.display()); + } + + tracing::info!("Removed dtkit-patch-based mod installation."); + Ok(()) +} + #[tracing::instrument(skip(state))] pub(crate) async fn reset_mod_deployment(state: ActionState) -> Result<()> { let boot_bundle_path = format!("{:016x}", Murmur64::hash(BOOT_BUNDLE_NAME.as_bytes())); @@ -676,6 +731,14 @@ pub(crate) async fn reset_mod_deployment(state: ActionState) -> Result<()> { tracing::info!("Resetting mod deployment in {}", bundle_dir.display()); + if fs::metadata(bundle_dir.join(format!("{boot_bundle_path}.patch_999"))) + .await + .is_ok() + { + tracing::info!("Found dtkit-patch-based mod installation. Removing."); + return reset_dtkit_patch(state).await; + } + tracing::debug!("Reading mod deployment"); let info: DeploymentData = {