pub mod backup;
pub mod collisions;
pub mod deploy;
pub mod detect;
pub mod diagnostics;
pub mod export;
pub mod fomod;
pub mod import;
pub mod install;
pub mod instance;
pub mod loot;
pub mod nexus;
pub mod nxm;
pub mod play;
pub mod profile;
pub mod rollback;
pub mod save;
pub mod scan;
pub mod stock;
pub mod tool;
pub mod uninstall;
pub mod update;
pub mod verify;
use std::path::PathBuf;
use anyhow::Result;
use modde_core::profile::{Profile, ProfileManager};
use modde_core::save::SaveFingerprint;
pub fn resolve_save_dir(game_id: &str) -> Option<PathBuf> {
modde_games::resolve_game_plugin(game_id).and_then(|p| p.save_directory())
}
pub fn require_save_dir(game_id: &str) -> Result<PathBuf> {
if modde_games::resolve_game_plugin(game_id).is_none() {
anyhow::bail!(
"unknown game '{}'. Supported games: {}",
game_id,
modde_games::SUPPORTED_GAME_IDS.join(", ")
);
}
resolve_save_dir(game_id)
.ok_or_else(|| anyhow::anyhow!(
"save directory not found for game '{game_id}'. \
The game may not be installed, or save tracking is not supported for this title."
))
}
pub fn compute_fingerprint(pm: &ProfileManager, name: &str, game_id: &str) -> Option<SaveFingerprint> {
let profile = pm.load(name, Some(game_id)).ok()?;
let game_plugin = modde_games::resolve_game_plugin(game_id)?;
let staging_dir = ProfileManager::staging_dir(&profile.name);
Some(SaveFingerprint::compute(&profile.mods, |mod_id| {
let mod_path = staging_dir.join(mod_id);
game_plugin.classify_mod(&mod_path).affects_saves()
}))
}
pub fn load_profile_or_default(
pm: &ProfileManager,
name: Option<&str>,
game_id: Option<&str>,
) -> Result<Profile> {
match name {
Some(name) => Ok(pm.load(name, game_id)?),
None => {
let profiles = pm.list()?;
let first = profiles
.first()
.ok_or_else(|| anyhow::anyhow!(
"no profiles found. Create one with: modde profile create <name> --game <id>"
))?;
Ok(pm.load(&first.name, Some(&first.game_id))?)
}
}
}