93 lines
2.6 KiB
Rust
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),
|
|
}
|