diff --git a/docs/mod_installer.mp4 b/docs/mod_installer.mp4 index 2b8b0fd..d462b26 100644 Binary files a/docs/mod_installer.mp4 and b/docs/mod_installer.mp4 differ diff --git a/src/main.rs b/src/main.rs index 355223d..53c6ab9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use args::Args; use clap::Parser; use env_logger::Env; @@ -5,8 +7,8 @@ use env_logger::Env; use crate::{ mod_component::parse_weidu_log, utils::{ - copy_mod_folder, create_weidu_log_if_not_exists, find_mod_folder, - mod_folder_present_in_game_directory, + copy_mod_folder, create_weidu_log_if_not_exists, mod_folder_present_in_game_directory, + search_mod_folders, }, weidu::{generate_args, install}, }; @@ -30,29 +32,24 @@ fn main() { create_weidu_log_if_not_exists(&args.game_directory); + let mut mod_folder_cache = HashMap::new(); for weidu_mod in parse_weidu_log(args.log_file) { - let mod_folder_locations = args - .mod_directories - .iter() - .find_map(|mod_folder| find_mod_folder(&weidu_mod, mod_folder)); - - let mod_folder = if let Some(mod_folder) = mod_folder_locations { - mod_folder - } else { - log::error!("Could not find {:#?} mod folder ", weidu_mod); - panic!(); - }; - log::info!("Found mod folder {:?}, for mod {:?}", mod_folder, weidu_mod); + let mod_folder = mod_folder_cache + .entry(weidu_mod.tp_file.clone()) + .or_insert_with(|| search_mod_folders(&args.mod_directories, &weidu_mod.clone())); + + log::debug!("Found mod folder {:?}, for mod {:?}", mod_folder, weidu_mod); if !mod_folder_present_in_game_directory(&args.game_directory, &weidu_mod.name) { - log::info!( + log::debug!( "Copying mod directory, from {:?} to, {:?}", mod_folder, - args.game_directory.clone().join(weidu_mod.name.clone()) + args.game_directory.join(&weidu_mod.name) ); - copy_mod_folder(&args.game_directory, &mod_folder) + copy_mod_folder(&args.game_directory, mod_folder) } let weidu_args = generate_args(&weidu_mod, &args.language); install(&args.weidu_binary, &args.game_directory, weidu_args); + log::info!("Installed mod {:?}", &weidu_mod); } } diff --git a/src/mod_component.rs b/src/mod_component.rs index 8fa50dc..96caacf 100644 --- a/src/mod_component.rs +++ b/src/mod_component.rs @@ -4,7 +4,7 @@ use std::{ path::PathBuf, }; -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct ModComponent { pub tp_file: String, pub name: String, diff --git a/src/utils.rs b/src/utils.rs index 336ff25..04f9250 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -28,7 +28,20 @@ pub fn copy_mod_folder(game_directory: &Path, mod_folder: &Path) { } } -pub fn find_mod_folder(mod_component: &ModComponent, mod_dir: &Path) -> Option { +pub fn search_mod_folders(folder_directories: &[PathBuf], weidu_mod: &ModComponent) -> PathBuf { + let mod_folder_locations = folder_directories + .iter() + .find_map(|mod_folder| find_mod_folder(weidu_mod, mod_folder)); + + if let Some(mod_folder) = mod_folder_locations { + mod_folder + } else { + log::error!("Could not find {:#?} mod folder ", weidu_mod); + panic!() + } +} + +fn find_mod_folder(mod_component: &ModComponent, mod_dir: &Path) -> Option { WalkDir::new(mod_dir) .follow_links(true) .max_depth(4) diff --git a/src/weidu.rs b/src/weidu.rs index 956c744..73a76a1 100644 --- a/src/weidu.rs +++ b/src/weidu.rs @@ -22,7 +22,7 @@ pub fn generate_args(weidu_mod: &ModComponent, language: &str) -> Vec { pub fn install(weidu_binary: &PathBuf, game_directory: &PathBuf, weidu_args: Vec) { log::trace!("{:#?}", weidu_args); let mut command = Command::new(weidu_binary); - let weidu_process = command.current_dir(game_directory).args(weidu_args); + let weidu_process = command.current_dir(game_directory).args(weidu_args.clone()); let mut child = weidu_process .stdin(Stdio::piped()) @@ -33,17 +33,29 @@ pub fn install(weidu_binary: &PathBuf, game_directory: &PathBuf, weidu_args: Vec let mut reader = BufReader::new(child.stdout.as_mut().unwrap()); let stdin = &mut child.stdin.take().expect("Failed to open stdin"); - let mut choice_flag = 0; + let mut choice_flag = false; + let mut failure_flag = false; while child.stderr.is_none() { let mut text = String::new(); if reader.read_line(&mut text).is_ok() { - if !text.is_empty() { + if !text.is_empty() && !failure_flag { log::trace!("{}", text); + } else { + log::error!("{}", text); + } + + if text.to_ascii_lowercase().contains("failure") { + failure_flag = true; + } + + if text.contains("Stopping installation because of error.") { + log::error!("Weidu process failed with args: {:?}", weidu_args); + panic!(); } match text { // Choice - _ if choice_flag == 1 => { + _ if choice_flag => { if !text.chars().nth(1).unwrap_or_default().is_numeric() { stdin .write_all(get_user_input().as_bytes()) @@ -63,7 +75,7 @@ pub fn install(weidu_binary: &PathBuf, game_directory: &PathBuf, weidu_args: Vec && !x.to_ascii_lowercase().starts_with("[r]e-install") => { log::trace!("Choice found"); - choice_flag = 1; + choice_flag = true; } // Success