Compare commits
3 Commits
a1256064fa
...
f2042be088
| Author | SHA1 | Date | |
|---|---|---|---|
|
f2042be088
|
|||
|
d84db4b0c1
|
|||
|
50f16cd7a0
|
@@ -44,7 +44,7 @@ impl RootConfig {
|
||||
|
||||
#[inline]
|
||||
pub fn get_mod_location(&self, mod_config: &ModConfig) -> PathBuf {
|
||||
self.mod_location.join(mod_config.source.clone())
|
||||
self.mod_location.join(mod_config.path.clone())
|
||||
}
|
||||
|
||||
pub fn get_mod_by_id(&self, id: &str) -> Option<ModConfig> {
|
||||
@@ -83,14 +83,14 @@ pub struct ModConfig {
|
||||
pub id: String,
|
||||
|
||||
/// Relative to the mod_location from root config
|
||||
pub source: PathBuf,
|
||||
pub path: PathBuf,
|
||||
}
|
||||
|
||||
impl ModConfig {
|
||||
pub fn new(id: &str, source: impl AsRef<Path>) -> Self {
|
||||
Self {
|
||||
id: id.to_owned(),
|
||||
source: source.as_ref().to_owned(),
|
||||
path: source.as_ref().to_owned(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
90
src/main.rs
90
src/main.rs
@@ -1,15 +1,18 @@
|
||||
use clap::Parser;
|
||||
use log::debug;
|
||||
use std::{error::Error, path::Path};
|
||||
use std::{
|
||||
error::Error,
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
basic_types::{ModConfig, ModFile, ModdedInstance, RootConfig},
|
||||
cli::Args,
|
||||
fomod::Config,
|
||||
linker::{create_plugins_txt, link_game_to_target, link_instance_to_target},
|
||||
load_order::LoadOrder,
|
||||
mod_config_installer::FomodInstaller,
|
||||
utils::resolve_case_insensitive,
|
||||
utils::{resolve_case_insensitive, walk_files_recursive},
|
||||
};
|
||||
|
||||
mod basic_types;
|
||||
@@ -22,31 +25,92 @@ mod load_order;
|
||||
mod mod_config_installer;
|
||||
mod utils;
|
||||
|
||||
pub fn load_mod_config(mod_root: impl AsRef<Path>) -> Result<fomod::Config, Box<dyn Error>> {
|
||||
let path = resolve_case_insensitive(&mod_root, "fomod/ModuleConfig.xml")?;
|
||||
let mod_config = Config::load_from_file(path)?;
|
||||
Ok(mod_config)
|
||||
}
|
||||
|
||||
pub fn gen_filelist_for_mod(
|
||||
root_config: &RootConfig,
|
||||
instance: &ModdedInstance,
|
||||
mod_config: &ModConfig,
|
||||
) -> Result<Vec<ModFile>, Box<dyn Error>> {
|
||||
let mod_location = root_config.get_mod_location(mod_config);
|
||||
let module_config = load_mod_config(&mod_location)?;
|
||||
|
||||
let module_config_path = resolve_case_insensitive(&mod_location, "fomod/ModuleConfig.xml")?;
|
||||
|
||||
let files: Vec<ModFile> = match module_config_path {
|
||||
Some(path) => {
|
||||
debug!("Found a ModuleConfig.xml");
|
||||
gen_filelist_from_fomod(instance, path, &mod_location)?
|
||||
}
|
||||
None => {
|
||||
debug!("Did not find a ModuleConfig.xml");
|
||||
gen_filelist_from_mod_dir(&mod_location)?
|
||||
}
|
||||
};
|
||||
|
||||
Ok(files)
|
||||
}
|
||||
|
||||
pub fn gen_filelist_from_mod_dir(
|
||||
mod_location: impl AsRef<Path>,
|
||||
) -> Result<Vec<ModFile>, Box<dyn Error>> {
|
||||
// Check for Data dir in root
|
||||
let files = match resolve_case_insensitive(&mod_location, "data")? {
|
||||
Some(data_path) => gen_filelist_from_dir(data_path),
|
||||
None => gen_filelist_from_dir(&mod_location),
|
||||
}?;
|
||||
|
||||
let mod_files: Vec<_> = files
|
||||
.iter()
|
||||
.filter(|e| should_be_included(e))
|
||||
.map(|e| ModFile::new(e, PathBuf::from("Data").join(e), 0))
|
||||
.collect();
|
||||
|
||||
Ok(mod_files)
|
||||
}
|
||||
|
||||
fn should_be_included(path: impl AsRef<Path>) -> bool {
|
||||
matches!(
|
||||
path.as_ref().extension().and_then(|e| e.to_str()),
|
||||
Some(
|
||||
"esp"
|
||||
| "esm"
|
||||
| "esl"
|
||||
| "bsa"
|
||||
| "ba2"
|
||||
| "bsl"
|
||||
| "ini"
|
||||
| "pex"
|
||||
| "psc"
|
||||
| "strings"
|
||||
| "ilstrings"
|
||||
| "dlstrings"
|
||||
| "dll"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn gen_filelist_from_dir(path: impl AsRef<Path>) -> Result<Vec<PathBuf>, Box<dyn Error>> {
|
||||
let files: Vec<_> = walk_files_recursive(&path)?
|
||||
.map(|file| file.path().strip_prefix(&path).unwrap().to_owned())
|
||||
.collect();
|
||||
|
||||
Ok(files)
|
||||
}
|
||||
|
||||
pub fn gen_filelist_from_fomod(
|
||||
instance: &ModdedInstance,
|
||||
xml_path: impl AsRef<Path>,
|
||||
mod_location: impl AsRef<Path>,
|
||||
) -> Result<Vec<ModFile>, Box<dyn Error>> {
|
||||
let module_config = fomod::Config::load_from_file(xml_path)?;
|
||||
// TODO: add active plugins from instance config
|
||||
let installer = FomodInstaller::new(module_config, vec![], install_prompt::prompt);
|
||||
|
||||
let files = installer.run();
|
||||
|
||||
let converted_files: Vec<_> = files
|
||||
let mod_files: Vec<_> = files
|
||||
.iter()
|
||||
.flat_map(|f| ModFile::from_installer(f.clone(), &mod_location).unwrap())
|
||||
.collect();
|
||||
|
||||
Ok(converted_files)
|
||||
Ok(mod_files)
|
||||
}
|
||||
|
||||
pub fn activate_instance(
|
||||
|
||||
@@ -34,7 +34,7 @@ pub fn path_to_lowercase(path: impl AsRef<Path>) -> PathBuf {
|
||||
pub fn resolve_case_insensitive(
|
||||
base: impl AsRef<Path>,
|
||||
rel: impl AsRef<Path>,
|
||||
) -> io::Result<PathBuf> {
|
||||
) -> io::Result<Option<PathBuf>> {
|
||||
let mut current = base.as_ref().to_path_buf();
|
||||
|
||||
for part in rel.as_ref().iter() {
|
||||
@@ -56,13 +56,10 @@ pub fn resolve_case_insensitive(
|
||||
match found {
|
||||
Some(path) => current = path,
|
||||
None => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::NotFound,
|
||||
format!("Path component not found: {}", target),
|
||||
));
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(current)
|
||||
Ok(Some(current))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user