Files
fomod-manager/src/load_order.rs

93 lines
2.6 KiB
Rust

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<Vec<String>, 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<PathBuf> = 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::<Result<_, io::Error>>()?;
// 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),
}