From 6515ea9cf6922dc431090fba3457400d95f74a57 Mon Sep 17 00:00:00 2001 From: GeckoEidechse <40122905+GeckoEidechse@users.noreply.github.com> Date: Thu, 10 Nov 2022 00:21:41 +0100 Subject: feat: Parse actually installed mods (#38) * feat: Parse actually installed mods Instead of using solely `enabledmods.json` parse the `mod.json` of found mods in `mods` folder. * refactor: Remove leftover print statements * refactor: Move logic into dedicated module * fix: Load mods despite `enabledmods.json` missing Previously we would error out early if `enabledmods.json` was missing despite not actually needing it for mod list. * style: Autoformat --- src-tauri/src/lib.rs | 24 --------- src-tauri/src/main.rs | 4 +- src-tauri/src/mod_management/mod.rs | 97 +++++++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 26 deletions(-) (limited to 'src-tauri') diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index e4f67108..79c5165e 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -448,27 +448,3 @@ pub fn get_enabled_mods(game_install: GameInstall) -> Result Result, String> { - // Get enabled mods as JSON - let res: serde_json::Value = get_enabled_mods(game_install)?; - - let mut installed_mods = Vec::new(); - - for (key, value) in res.as_object().unwrap() { - - let current_mod: NorthstarMod = NorthstarMod { - name: key.to_string(), - enabled: value.as_bool().unwrap(), - }; - installed_mods.push(current_mod); - } - - dbg!(&res); - dbg!(installed_mods.clone()); - - Ok(installed_mods) -} diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 26f138ba..0210cabb 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -12,7 +12,7 @@ use std::{ use app::{ check_is_flightcore_outdated, check_is_valid_game_path, check_northstar_running, check_origin_running, convert_release_candidate_number, find_game_install_location, - get_enabled_mods, get_host_os, get_installed_mods_and_properties, get_log_list, get_northstar_version_number, + get_enabled_mods, get_host_os, get_log_list, get_northstar_version_number, install_northstar, launch_northstar, linux_checks_librs, GameInstall, NorthstarMod, }; @@ -23,7 +23,7 @@ mod repair_and_verify; use repair_and_verify::{verify_game_files, disable_all_but_core}; mod mod_management; -use mod_management::set_mod_enabled_status; +use mod_management::{set_mod_enabled_status, get_installed_mods_and_properties}; use tauri::Manager; use tauri_plugin_store::PluginBuilder; diff --git a/src-tauri/src/mod_management/mod.rs b/src-tauri/src/mod_management/mod.rs index dfc05c4a..e3034903 100644 --- a/src-tauri/src/mod_management/mod.rs +++ b/src-tauri/src/mod_management/mod.rs @@ -1,5 +1,9 @@ // This file contains various mod management functions +use anyhow::{anyhow, Result}; +use app::NorthstarMod; +use std::path::PathBuf; + use app::GameInstall; use app::get_enabled_mods; @@ -31,3 +35,96 @@ pub fn set_mod_enabled_status( Ok(()) } + + +/// Parses `mod.json` for mod name +// TODO: Maybe pass PathBuf or serde json object +fn parse_mod_json_for_mod_name(mod_json_path: String) -> Result { + // Read file into string and parse it + let data = std::fs::read_to_string(mod_json_path)?; + let parsed_json: serde_json::Value = serde_json::from_str(&data)?; + + // Extract mod name + let mod_name = match parsed_json.get("Name").and_then(|value| value.as_str()) { + Some(name) => name, + None => return Err(anyhow!("No name found")), + }; + + Ok(mod_name.to_string()) +} + +/// Parse `mods` folder for installed mods. +fn get_installed_mods(game_install: GameInstall) -> Result, String> { + let ns_mods_folder = format!("{}/R2Northstar/mods/", game_install.game_path); + + let paths = std::fs::read_dir(ns_mods_folder).unwrap(); + + let mut directories: Vec = Vec::new(); + let mut mod_names: Vec = Vec::new(); + + // Get list of folders in `mods` directory + for path in paths { + let my_path = path.unwrap().path(); + + let md = std::fs::metadata(my_path.clone()).unwrap(); + if md.is_dir() { + directories.push(my_path); + } + } + + // Iterate over folders and check if they are Northstar mods + for directory in directories { + // Check if mod.json exists + let mod_json_path = format!("{}/mod.json", directory.to_str().unwrap()); + if !std::path::Path::new(&mod_json_path).exists() { + continue; + } + + // Parse mod.json and get mod name + let mod_name = match parse_mod_json_for_mod_name(mod_json_path.clone()) { + Ok(mod_name) => mod_name, + Err(err) => { + println!("Failed parsing {} with {}", mod_json_path, err.to_string()); + continue; + } + }; + mod_names.push(mod_name); + } + + // Return found mod names + Ok(mod_names) +} + +/// Gets list of installed mods and their properties +/// - name +/// - is enabled? +pub fn get_installed_mods_and_properties( + game_install: GameInstall, +) -> Result, String> { + // Get actually installed mods + let found_installed_mods = get_installed_mods(game_install.clone())?; + + // Get enabled mods as JSON + let enabled_mods: serde_json::Value = match get_enabled_mods(game_install) { + Ok(enabled_mods) => enabled_mods, + Err(_) => serde_json::from_str("{}").unwrap(), // `enabledmods.json` not found, create empty object + }; + + let mut installed_mods = Vec::new(); + let mapping = enabled_mods.as_object().unwrap(); + + // Use list of installed mods and set enabled based on `enabledmods.json` + for name in found_installed_mods { + let current_mod_enabled = match mapping.get(&name) { + Some(enabled) => enabled.as_bool().unwrap(), + None => true, // Northstar considers mods not in mapping as enabled. + }; + let current_mod: NorthstarMod = NorthstarMod { + name: name, + enabled: current_mod_enabled, + }; + installed_mods.push(current_mod); + } + + Ok(installed_mods) +} -- cgit v1.2.3