From 8fc5480243993114f6ce9198f2c19ccda3472114 Mon Sep 17 00:00:00 2001 From: Niklas Kapelle Date: Sun, 1 Mar 2026 23:18:59 +0100 Subject: [PATCH] fixed load_order --- src/load_order.rs | 78 +++++++++++++++++++++++++++++++++++++ src/lootorder.rs | 98 ----------------------------------------------- 2 files changed, 78 insertions(+), 98 deletions(-) create mode 100644 src/load_order.rs delete mode 100644 src/lootorder.rs diff --git a/src/load_order.rs b/src/load_order.rs new file mode 100644 index 0000000..1adb71e --- /dev/null +++ b/src/load_order.rs @@ -0,0 +1,78 @@ +use std::{ + error::Error, + path::{Path, PathBuf}, +}; + +use libloot::{Game, GameType}; + +use crate::{ + basic_types::{ModdedInstance, RootConfig}, + utils::walk_files_recursive, +}; + +pub struct LoadOrder { + game: libloot::Game, + target: PathBuf, +} + +impl LoadOrder { + pub fn new(install_dir: impl AsRef, game_type: GameType) -> Result> { + Ok(Self { + game: Game::with_local_path( + game_type, + install_dir.as_ref(), + &install_dir.as_ref().join("appdata"), + )?, + target: install_dir.as_ref().to_owned(), + }) + } + + pub fn add_plugins_from_instance( + &mut self, + root_config: &RootConfig, + instance: &ModdedInstance, + ) -> Result<(), Box> { + for installed_mod in &instance.mods { + let mod_config = root_config.get_mod_by_id(&installed_mod.mod_id()).unwrap(); + let mod_source_root = root_config.get_mod_location(&mod_config); + + let mod_plugins: Vec = installed_mod + .files() + .iter() + .filter(|f| Self::is_plugin_file(&f.0)) + .map(|(from, _)| mod_source_root.join(from)) + .collect(); + + let refs: Vec<_> = mod_plugins.iter().map(|e| e.as_path()).collect(); + self.game.load_plugins(&refs)?; + } + Ok(()) + } + + pub fn add_plugins_from_install(&mut self) -> Result<(), Box> { + let plugins: Vec<_> = walk_files_recursive(self.target.join("Data"))? + .filter(|f| Self::is_plugin_file(f.path())) + .map(|f| f.path()) + .collect(); + let refs: Vec<_> = plugins.iter().map(|e| e.as_path()).collect(); + dbg!(&refs); + self.game.load_plugins(&refs)?; + Ok(()) + } + + fn is_plugin_file(filename: impl AsRef) -> bool { + filename + .as_ref() + .extension() + .is_some_and(|ext| ext == "esp" || ext == "esm" || ext == "esl") + } + + pub fn load_order(&self) -> Result, Box> { + let all_plugins = self.game.loaded_plugins(); + let plugins_names: Vec<&str> = all_plugins.iter().map(|e| e.name()).collect(); + + let sorted = self.game.sort_plugins(&plugins_names)?; + + Ok(sorted) + } +} diff --git a/src/lootorder.rs b/src/lootorder.rs deleted file mode 100644 index 9a406aa..0000000 --- a/src/lootorder.rs +++ /dev/null @@ -1,98 +0,0 @@ -use std::{ - fmt::Display, - fs, - path::{Path, PathBuf}, -}; - -use libloot::{ - Game, GameType, - error::{GameHandleCreationError, LoadPluginsError, SortPluginsError}, -}; - -use crate::{Mod, ModFile}; - -pub struct LootOrder { - game: libloot::Game, - target: PathBuf, -} - -impl LootOrder { - pub fn new(install_dir: &Path, game_type: GameType) -> Result { - Ok(Self { - game: Game::with_local_path(game_type, install_dir, &install_dir.join("appdata"))?, - target: install_dir.to_owned(), - }) - } - - pub fn add_plugin(&mut self, file: &ModFile) -> Result<(), LootOrderError> { - if !Self::is_plugin_file(file.dest.to_str().unwrap_or_default()) { - return Ok(()); - } - - let rel_path = self.target.join(&file.dest); - let absolute_path = fs::canonicalize(rel_path).unwrap(); - - self.game.load_plugins(&[&absolute_path])?; - Ok(()) - } - - fn is_plugin_file(filename: &str) -> bool { - filename.ends_with(".esp") || filename.ends_with(".esm") || filename.ends_with(".esl") - } - - pub fn load_order(&self) -> Result<(), LootOrderError> { - let all_plugins = self.game.loaded_plugins(); - let plugins_names: Vec<&str> = all_plugins.iter().map(|e| e.name()).collect(); - - let sorted = self.game.sort_plugins(&plugins_names)?; - - dbg!(sorted); - - todo!() - } -} - -#[derive(Debug)] -pub enum LootOrderError { - Create(GameHandleCreationError), - Load(LoadPluginsError), - Sort(SortPluginsError), -} - -impl std::error::Error for LootOrderError {} - -impl Display for LootOrderError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - LootOrderError::Create(game_handle_creation_error) => write!( - f, - "Failed to create LootOrder: {}", - game_handle_creation_error - ), - LootOrderError::Load(load_plugins_error) => { - write!(f, "Failed to load plugin: {}", load_plugins_error) - } - LootOrderError::Sort(sort_plugins_error) => { - write!(f, "Failed to sort: {}", sort_plugins_error) - } - } - } -} - -impl From for LootOrderError { - fn from(e: GameHandleCreationError) -> Self { - Self::Create(e) - } -} - -impl From for LootOrderError { - fn from(e: LoadPluginsError) -> Self { - Self::Load(e) - } -} - -impl From for LootOrderError { - fn from(e: SortPluginsError) -> Self { - Self::Sort(e) - } -}