use libloot::{ Game, GameType, error::{GameHandleCreationError, LoadPluginsError, SortPluginsError}, }; use log::trace; use std::{ io, path::{Path, PathBuf}, }; use thiserror::Error; use walkdir::WalkDir; use crate::{types::{self, ModdedInstance, RootConfig}, utils::is_plugin_file}; pub fn create_loadorder( root_config: &RootConfig, game: &types::Game, instance: &ModdedInstance, ) -> Result, LoadOrderError> { let mut loot_game = Game::with_local_path( GameType::SkyrimSE, game.install_location(), &game.install_location().join(PathBuf::from("appdata")), )?; // Add plugins files from the game install let install_plugins: Vec = WalkDir::new(game.install_location().join("Data")) .into_iter() .map(|entry| { let entry = entry?; let path = entry.path(); if is_plugin_file(path) { Ok(Some(path.to_path_buf())) } else { Ok(None) } }) .filter_map(|r| r.transpose()) .collect::>()?; // The loaded_plugins function requires &[&Path] let refs: Vec<&Path> = install_plugins.iter().map(|e| e.as_path()).collect(); trace!("Loading {} plugins to game", refs.len()); loot_game.load_plugins(&refs)?; // Add plugins from the instance let instance_plugins: Vec<_> = instance .mods() .iter() .flat_map(|installed_mod| { let mod_config = root_config.mod_by_id(installed_mod.mod_id()).unwrap(); let mod_source_root = root_config.mod_location().join(mod_config.path()); installed_mod .files() .iter() .filter(|f| is_plugin_file(f.dst())) .map(move |link| mod_source_root.join(link.src())) }) .collect(); let refs: Vec<_> = instance_plugins.iter().map(|e| e.as_path()).collect(); trace!("Loading {} plugins to game", refs.len()); loot_game.load_plugins(&refs)?; // Genrate load order let all_plugins = loot_game.loaded_plugins(); let plugins_names: Vec<&str> = all_plugins.iter().map(|e| e.name()).collect(); let sorted = loot_game.sort_plugins(&plugins_names)?; Ok(sorted) } #[derive(Error, Debug)] pub enum LoadOrderError { #[error("Failed to read game directory")] Io(#[from] io::Error), #[error("Failed to create libloot game")] Creating(#[from] GameHandleCreationError), #[error("Failed to add plugins to libloot")] Loading(#[from] LoadPluginsError), #[error("libloot failed to sort plugins")] Sorting(#[from] SortPluginsError), }