diff options
| author | GeckoEidechse <gecko.eidechse+git@pm.me> | 2023-01-29 15:19:18 +0100 |
|---|---|---|
| committer | GeckoEidechse <gecko.eidechse+git@pm.me> | 2023-01-29 15:19:18 +0100 |
| commit | 672201785222ce0905cda8b228b1390899c1d1e8 (patch) | |
| tree | c3d94ec262697b8024d89f39c1209791c2c72476 /src-tauri/src | |
| parent | b66410e8c19e89acd39628350c4fe70e0e85ff32 (diff) | |
| parent | 31b32c725ce4f47a6726cb0d8ef5f21ec6030580 (diff) | |
| download | FlightCore-fix/add-empty-dist-folder.tar.gz FlightCore-fix/add-empty-dist-folder.zip | |
Merge branch 'main' into fix/add-empty-dist-folderfix/add-empty-dist-folder
Diffstat (limited to 'src-tauri/src')
| -rw-r--r-- | src-tauri/src/constants.rs | 9 | ||||
| -rw-r--r-- | src-tauri/src/github/release_notes.rs | 65 | ||||
| -rw-r--r-- | src-tauri/src/lib.rs | 9 | ||||
| -rw-r--r-- | src-tauri/src/main.rs | 93 | ||||
| -rw-r--r-- | src-tauri/src/mod_management/mod.rs | 249 | ||||
| -rw-r--r-- | src-tauri/src/repair_and_verify/mod.rs | 10 |
6 files changed, 290 insertions, 145 deletions
diff --git a/src-tauri/src/constants.rs b/src-tauri/src/constants.rs new file mode 100644 index 00000000..4cc3c204 --- /dev/null +++ b/src-tauri/src/constants.rs @@ -0,0 +1,9 @@ +// This file stores various global constants values + +pub const APP_USER_AGENT: &str = "R2NorthstarTools/FlightCore"; + +// URL of the Northstar masterserver +pub const MASTER_SERVER_URL: &str = "https://northstar.tf"; + +// server list endpoint +pub const SERVER_BROWSER_ENDPOINT: &str = "/client/servers"; diff --git a/src-tauri/src/github/release_notes.rs b/src-tauri/src/github/release_notes.rs index f139ead5..758f7ace 100644 --- a/src-tauri/src/github/release_notes.rs +++ b/src-tauri/src/github/release_notes.rs @@ -1,3 +1,4 @@ +use crate::constants::APP_USER_AGENT; use serde::{Deserialize, Serialize}; use std::vec::Vec; @@ -8,15 +9,20 @@ pub struct ReleaseInfo { pub body: String, } +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct FlightCoreVersion { + tag_name: String, + published_at: String, +} + // Fetches repo release API and returns response as string async fn fetch_github_releases_api(url: &str) -> Result<String, String> { println!("Fetching releases notes from GitHub API"); - let user_agent = "R2NorthstarTools/FlightCore"; let client = reqwest::Client::new(); let res = client .get(url) - .header(reqwest::header::USER_AGENT, user_agent) + .header(reqwest::header::USER_AGENT, APP_USER_AGENT) .send() .await .unwrap() @@ -27,24 +33,26 @@ async fn fetch_github_releases_api(url: &str) -> Result<String, String> { Ok(res) } -/// Checks if installed FlightCore version is up-to-date -/// false -> FlightCore install is up-to-date -/// true -> FlightCore install is outdated -pub async fn check_is_flightcore_outdated() -> Result<bool, String> { +/// Gets newest FlighCore version from GitHub +#[tauri::command] +pub async fn get_newest_flightcore_version() -> Result<FlightCoreVersion, String> { // Get newest version number from GitHub API println!("Checking GitHub API"); let url = "https://api.github.com/repos/R2NorthstarTools/FlightCore/releases/latest"; let res = fetch_github_releases_api(url).await?; - let json_response: serde_json::Value = + let flightcore_version: FlightCoreVersion = serde_json::from_str(&res).expect("JSON was not well-formatted"); println!("Done checking GitHub API"); - // Extract version number from JSON - let newest_release_version = json_response - .get("tag_name") - .and_then(|value| value.as_str()) - .unwrap(); + Ok(flightcore_version) +} + +/// Checks if installed FlightCore version is up-to-date +/// false -> FlightCore install is up-to-date +/// true -> FlightCore install is outdated +pub async fn check_is_flightcore_outdated() -> Result<bool, String> { + let newest_flightcore_release = get_newest_flightcore_version().await?; // Get version of installed FlightCore... let version = env!("CARGO_PKG_VERSION"); @@ -52,16 +60,10 @@ pub async fn check_is_flightcore_outdated() -> Result<bool, String> { let version = format!("v{}", version); // TODO: This shouldn't be a string compare but promper semver compare - let is_outdated = version != newest_release_version; + let is_outdated = version != newest_flightcore_release.tag_name; // If outdated, check how new the update is if is_outdated { - // Extract release date from JSON - let release_date = json_response - .get("published_at") - .and_then(|value| value.as_str()) - .unwrap(); - // Time to wait (2h) h * m * s let threshold_seconds = 2 * 60 * 60; @@ -69,7 +71,7 @@ pub async fn check_is_flightcore_outdated() -> Result<bool, String> { let current_time = chrono::Utc::now(); // Get latest release time from GitHub API response - let result = chrono::DateTime::parse_from_rfc3339(release_date) + let result = chrono::DateTime::parse_from_rfc3339(&newest_flightcore_release.published_at) .unwrap() .with_timezone(&chrono::Utc); @@ -91,28 +93,9 @@ pub async fn get_northstar_release_notes() -> Result<Vec<ReleaseInfo>, String> { let url = "https://api.github.com/repos/R2Northstar/Northstar/releases"; let res = fetch_github_releases_api(url).await?; - let json_response: Vec<serde_json::Value> = + let release_info_vector: Vec<ReleaseInfo> = serde_json::from_str(&res).expect("JSON was not well-formatted"); println!("Done checking GitHub API"); - return Ok(json_response - .iter() - .map(|release| ReleaseInfo { - name: release - .get("name") - .and_then(|value| value.as_str()) - .unwrap() - .to_string(), - published_at: release - .get("published_at") - .and_then(|value| value.as_str()) - .unwrap() - .to_string(), - body: release - .get("body") - .and_then(|value| value.as_str()) - .unwrap() - .to_string(), - }) - .collect()); + return Ok(release_info_vector); } diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index f8ea6aba..67f42f85 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -4,6 +4,7 @@ use anyhow::{anyhow, Context, Result}; mod northstar; +pub mod constants; mod platform_specific; #[cfg(target_os = "windows")] use platform_specific::windows; @@ -38,6 +39,12 @@ pub struct NorthstarMod { pub directory: String, } +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct NorthstarServer { + #[serde(rename = "playerCount")] + pub player_count: i32, +} + /// Check version number of a mod pub fn check_mod_version_number(path_to_mod_folder: String) -> Result<String, anyhow::Error> { // println!("{}", format!("{}/mod.json", path_to_mod_folder)); @@ -183,7 +190,7 @@ async fn do_install(nmod: &thermite::model::ModVersion, game_path: &std::path::P let download_path = format!("{}/{}", download_directory.clone(), filename); println!("{}", download_path); - let nfile = thermite::core::actions::download_file(&nmod.url, download_path) + let nfile = thermite::core::manage::download_file(&nmod.url, download_path) .await .unwrap(); diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index e8912d60..4eab7a00 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -9,10 +9,15 @@ use std::{ time::Duration, }; -use app::*; +use app::{ + constants::{APP_USER_AGENT, MASTER_SERVER_URL, SERVER_BROWSER_ENDPOINT}, + *, +}; mod github; -use github::release_notes::{check_is_flightcore_outdated, get_northstar_release_notes}; +use github::release_notes::{ + check_is_flightcore_outdated, get_newest_flightcore_version, get_northstar_release_notes, +}; mod repair_and_verify; use repair_and_verify::{ @@ -21,7 +26,8 @@ use repair_and_verify::{ mod mod_management; use mod_management::{ - fc_download_mod_and_install, get_installed_mods_and_properties, set_mod_enabled_status, + delete_northstar_mod, delete_thunderstore_mod, fc_download_mod_and_install, + get_installed_mods_and_properties, set_mod_enabled_status, }; mod northstar; @@ -90,17 +96,20 @@ fn main() { update_northstar_caller, launch_northstar_caller, check_is_flightcore_outdated_caller, - get_log_list_caller, - verify_game_files_caller, - get_enabled_mods_caller, - set_mod_enabled_status_caller, - disable_all_but_core_caller, + get_log_list, + verify_game_files, + set_mod_enabled_status, + disable_all_but_core, is_debug_mode, get_northstar_release_notes, linux_checks, - get_installed_mods_caller, + get_installed_mods_and_properties, install_mod_caller, clean_up_download_folder_caller, + get_newest_flightcore_version, + delete_northstar_mod, + get_server_player_count, + delete_thunderstore_mod, ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); @@ -274,43 +283,6 @@ async fn launch_northstar_caller( } #[tauri::command] -/// Get list of Northstar logs -async fn get_log_list_caller(game_install: GameInstall) -> Result<Vec<std::path::PathBuf>, String> { - get_log_list(game_install) -} - -#[tauri::command] -async fn verify_game_files_caller(game_install: GameInstall) -> Result<String, String> { - verify_game_files(game_install) -} - -#[tauri::command] -async fn get_enabled_mods_caller( - game_install: GameInstall, -) -> Result<serde_json::value::Value, String> { - get_enabled_mods(game_install) -} - -#[tauri::command] -async fn set_mod_enabled_status_caller( - game_install: GameInstall, - mod_name: String, - is_enabled: bool, -) -> Result<(), String> { - set_mod_enabled_status(game_install, mod_name, is_enabled) -} - -#[tauri::command] -async fn disable_all_but_core_caller(game_install: GameInstall) -> Result<(), String> { - disable_all_but_core(game_install) -} - -#[tauri::command] -async fn get_installed_mods_caller(game_install: GameInstall) -> Result<Vec<NorthstarMod>, String> { - get_installed_mods_and_properties(game_install) -} - -#[tauri::command] /// Installs the specified mod async fn install_mod_caller( game_install: GameInstall, @@ -339,3 +311,32 @@ async fn clean_up_download_folder_caller( Err(err) => Err(err.to_string()), } } + +/// Gets server and playercount from master server API +#[tauri::command] +async fn get_server_player_count() -> Result<(i32, usize), String> { + let url = format!("{MASTER_SERVER_URL}{SERVER_BROWSER_ENDPOINT}"); + let client = reqwest::Client::new(); + let res = client + .get(url) + .header(reqwest::header::USER_AGENT, APP_USER_AGENT) + .send() + .await + .unwrap() + .text() + .await + .unwrap(); + + let ns_servers: Vec<NorthstarServer> = + serde_json::from_str(&res).expect("JSON was not well-formatted"); + + // Get server count + let server_count = ns_servers.len(); + + // Sum up player count + let total_player_count: i32 = ns_servers.iter().map(|server| server.player_count).sum(); + + dbg!((total_player_count, server_count)); + + Ok((total_player_count, server_count)) +} diff --git a/src-tauri/src/mod_management/mod.rs b/src-tauri/src/mod_management/mod.rs index 4fa52127..c37882fe 100644 --- a/src-tauri/src/mod_management/mod.rs +++ b/src-tauri/src/mod_management/mod.rs @@ -3,6 +3,8 @@ use async_recursion::async_recursion; use anyhow::{anyhow, Result}; use app::NorthstarMod; +use serde::{Deserialize, Serialize}; +use std::io::Read; use std::path::PathBuf; use app::get_enabled_mods; @@ -10,12 +12,45 @@ use app::GameInstall; use json5; +use crate::northstar::CORE_MODS; + pub const BLACKLISTED_MODS: [&str; 3] = [ "northstar-Northstar", "northstar-NorthstarReleaseCandidate", "ebkr-r2modman", ]; +#[derive(Debug, Clone)] +struct ParsedThunderstoreModString { + author_name: String, + mod_name: String, + version: Option<String>, +} + +impl std::str::FromStr for ParsedThunderstoreModString { + type Err = (); + + fn from_str(s: &str) -> Result<Self, Self::Err> { + let mut parts = s.split("-"); + + let author_name = parts.next().unwrap().to_string(); + let mod_name = parts.next().unwrap().to_string(); + let version = parts.next().map(|s| s.to_string()); + + Ok(ParsedThunderstoreModString { + author_name, + mod_name, + version, + }) + } +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct ThunderstoreManifest { + name: String, + version_number: String, +} + /// Gets all currently installed and enabled/disabled mods to rebuild `enabledmods.json` pub fn rebuild_enabled_mods_json(game_install: GameInstall) -> Result<(), String> { let enabledmods_json_path = format!("{}/R2Northstar/enabledmods.json", game_install.game_path); @@ -43,6 +78,7 @@ pub fn rebuild_enabled_mods_json(game_install: GameInstall) -> Result<(), String } /// Set the status of a passed mod to enabled/disabled +#[tauri::command] pub fn set_mod_enabled_status( game_install: GameInstall, mod_name: String, @@ -105,6 +141,7 @@ fn parse_mod_json_for_mod_name(mod_json_path: String) -> Result<String, anyhow:: } /// Parses `mod.json` for Thunderstore mod string +/// This is a legacy function as nowadays `manifest.json` should be in Northtar mods folder and read from there // TODO: Maybe pass PathBuf or serde json object fn parse_mod_json_for_thunderstore_mod_string( mod_json_path: String, @@ -125,6 +162,36 @@ fn parse_mod_json_for_thunderstore_mod_string( Ok(thunderstore_mod_string.to_string()) } +/// Parses `manifest.json` for Thunderstore mod string +fn parse_for_thunderstore_mod_string(nsmod_path: String) -> Result<String, anyhow::Error> { + let mod_json_path = format!("{}/mod.json", nsmod_path); + let manifest_json_path = format!("{}/manifest.json", nsmod_path); + let ts_author_txt_path = format!("{}/thunderstore_author.txt", nsmod_path); + + // Attempt legacy method for getting Thunderstore string first + match parse_mod_json_for_thunderstore_mod_string(mod_json_path) { + Ok(thunderstore_mod_string) => return Ok(thunderstore_mod_string), + Err(_err) => (), + } + + // Check if `manifest.json` exists and parse + let data = std::fs::read_to_string(manifest_json_path)?; + let thunderstore_manifest: ThunderstoreManifest = json5::from_str(&data)?; + + // Check if `thunderstore_author.txt` exists and parse + let mut file = std::fs::File::open(ts_author_txt_path)?; + let mut thunderstore_author = String::new(); + file.read_to_string(&mut thunderstore_author)?; + + // Build mod string + let thunderstore_mod_string = format!( + "{}-{}-{}", + thunderstore_author, thunderstore_manifest.name, thunderstore_manifest.version_number + ); + + Ok(thunderstore_mod_string) +} + /// Parse `mods` folder for installed mods. fn parse_installed_mods(game_install: GameInstall) -> Result<Vec<NorthstarMod>, String> { let ns_mods_folder = format!("{}/R2Northstar/mods/", game_install.game_path); @@ -146,8 +213,9 @@ fn parse_installed_mods(game_install: GameInstall) -> Result<Vec<NorthstarMod>, // Iterate over folders and check if they are Northstar mods for directory in directories { + let directory_str = directory.to_str().unwrap().to_string(); // Check if mod.json exists - let mod_json_path = format!("{}/mod.json", directory.to_str().unwrap()); + let mod_json_path = format!("{}/mod.json", directory_str); if !std::path::Path::new(&mod_json_path).exists() { continue; } @@ -160,11 +228,11 @@ fn parse_installed_mods(game_install: GameInstall) -> Result<Vec<NorthstarMod>, continue; } }; - let thunderstore_mod_string = - match parse_mod_json_for_thunderstore_mod_string(mod_json_path.clone()) { - Ok(thunderstore_mod_string) => Some(thunderstore_mod_string), - Err(_err) => None, - }; + // Get Thunderstore mod string if it exists + let thunderstore_mod_string = match parse_for_thunderstore_mod_string(directory_str) { + Ok(thunderstore_mod_string) => Some(thunderstore_mod_string), + Err(_err) => None, + }; // Get directory path let mod_directory = directory.to_str().unwrap().to_string(); @@ -185,6 +253,7 @@ fn parse_installed_mods(game_install: GameInstall) -> Result<Vec<NorthstarMod>, /// Gets list of installed mods and their properties /// - name /// - is enabled? +#[tauri::command] pub fn get_installed_mods_and_properties( game_install: GameInstall, ) -> Result<Vec<NorthstarMod>, String> { @@ -217,8 +286,19 @@ async fn get_ns_mod_download_url(thunderstore_mod_string: String) -> Result<Stri // TODO: This will crash the thread if not internet connection exist. `match` should be used instead let index = thermite::api::get_package_index().await.unwrap().to_vec(); - // String replace works but more care should be taken in the future - let ts_mod_string_url = thunderstore_mod_string.replace("-", "/"); + // Parse mod string + let parsed_ts_mod_string: ParsedThunderstoreModString = match thunderstore_mod_string.parse() { + Ok(res) => res, + Err(_) => return Err("Failed to parse mod string".to_string()), + }; + + // Encode as URL + let ts_mod_string_url = format!( + "{}/{}/{}", + parsed_ts_mod_string.author_name, + parsed_ts_mod_string.mod_name, + parsed_ts_mod_string.version.unwrap() + ); for ns_mod in index { // Iterate over all versions of a given mod @@ -233,32 +313,6 @@ async fn get_ns_mod_download_url(thunderstore_mod_string: String) -> Result<Stri Err("Could not find mod on Thunderstore".to_string()) } -/// Adds given Thunderstore mod string to the given `mod.json` -/// This way we can later check whether a mod is outdated based on the TS mod string -fn add_thunderstore_mod_string( - path_to_mod_json: String, - thunderstore_mod_string: String, -) -> Result<(), anyhow::Error> { - // Read file into string and parse it - let data = std::fs::read_to_string(path_to_mod_json.clone())?; - let parsed_json: serde_json::Value = json5::from_str(&data)?; - - // Insert the Thunderstore mod string - let mut parsed_json = parsed_json.as_object().unwrap().clone(); - parsed_json.insert( - "ThunderstoreModString".to_string(), - serde_json::Value::String(thunderstore_mod_string), - ); - - // And write back to disk - std::fs::write( - path_to_mod_json, - serde_json::to_string_pretty(&parsed_json)?, - )?; - - Ok(()) -} - /// Returns a vector of modstrings containing the dependencies of a given mod async fn get_mod_dependencies( thunderstore_mod_string: String, @@ -348,38 +402,123 @@ pub async fn fc_download_mod_and_install( ); // Download the mod - let f = match thermite::core::actions::download_file(&download_url, path.clone()).await { + let f = match thermite::core::manage::download_file(&download_url, path.clone()).await { Ok(f) => f, Err(e) => return Err(e.to_string()), }; + // Get Thunderstore mod author + let author = thunderstore_mod_string.split("-").next().unwrap(); + // Extract the mod to the mods directory - let pkg = match thermite::core::actions::install_mod(&f, std::path::Path::new(&mods_directory)) - { - Ok(pkg) => pkg, + match thermite::core::manage::install_mod(author, &f, std::path::Path::new(&mods_directory)) { + Ok(()) => (), Err(err) => return Err(err.to_string()), }; - dbg!(pkg.clone()); - - // Add Thunderstore mod string to `mod.json` of installed NorthstarMods - for nsmod in pkg.mods { - let path_to_current_mod_json = format!( - "{}/{}/mod.json", - mods_directory, - nsmod.path.to_string_lossy() - ); - match add_thunderstore_mod_string(path_to_current_mod_json, thunderstore_mod_string.clone()) + + // Delete downloaded zip file + std::fs::remove_file(path).unwrap(); + + Ok(()) +} + +/// Deletes a given Northstar mod folder +fn delete_mod_folder(ns_mod_directory: String) -> Result<(), String> { + let ns_mod_dir_path = std::path::Path::new(&ns_mod_directory); + + // Safety check: Check whether `mod.json` exists and exit early if not + // If it does not exist, we might not be dealing with a Northstar mod + let mod_json_path = ns_mod_dir_path.join("mod.json"); + if !mod_json_path.exists() { + // If it doesn't exist, return an error + return Err(format!("mod.json does not exist in {}", ns_mod_directory)); + } + + match std::fs::remove_dir_all(&ns_mod_directory) { + Ok(()) => Ok(()), + Err(err) => Err(format!("Failed deleting mod: {err}")), + } +} + +/// Deletes a Northstar mod based on its name +#[tauri::command] +pub fn delete_northstar_mod(game_install: GameInstall, nsmod_name: String) -> Result<(), String> { + // Prevent deleting core mod + for core_mod in CORE_MODS { + if nsmod_name == core_mod { + return Err(format!("Cannot remove core mod {nsmod_name}")); + } + } + + // Get installed mods + let installed_ns_mods = get_installed_mods_and_properties(game_install)?; + + // Get folder name based on northstarmods + for installed_ns_mod in installed_ns_mods { + // Installed mod matches specified mod + if installed_ns_mod.name == nsmod_name { + // Delete folder + return delete_mod_folder(installed_ns_mod.directory); + } + } + + Err(format!("Mod {nsmod_name} not found to be installed")) +} + +/// Deletes all NorthstarMods related to a Thunderstore mod +#[tauri::command] +pub fn delete_thunderstore_mod( + game_install: GameInstall, + thunderstore_mod_string: String, +) -> Result<(), String> { + // Prevent deleting core mod + for core_ts_mod in BLACKLISTED_MODS { + if thunderstore_mod_string == core_ts_mod { + return Err(format!("Cannot remove core mod {thunderstore_mod_string}")); + } + } + + let parsed_ts_mod_string: ParsedThunderstoreModString = + thunderstore_mod_string.parse().unwrap(); + + // Get installed mods + let installed_ns_mods = get_installed_mods_and_properties(game_install)?; + + // List of mod folders to remove + let mut mod_folders_to_remove: Vec<String> = Vec::new(); + + // Get folder name based on Thundestore mod string + for installed_ns_mod in installed_ns_mods { + if installed_ns_mod.thunderstore_mod_string.is_none() { + // Not a Thunderstore mod + continue; + } + + let installed_ns_mod_ts_string: ParsedThunderstoreModString = installed_ns_mod + .thunderstore_mod_string + .unwrap() + .parse() + .unwrap(); + + // Installed mod matches specified Thunderstore mod string + if parsed_ts_mod_string.author_name == installed_ns_mod_ts_string.author_name + && parsed_ts_mod_string.mod_name == installed_ns_mod_ts_string.mod_name { - Ok(()) => (), - Err(err) => { - println!("Failed setting modstring for {}", nsmod.name); - println!("{}", err); - } + // Add folder to list of folder to remove + mod_folders_to_remove.push(installed_ns_mod.directory); } } - // Delete downloaded zip file - std::fs::remove_file(path).unwrap(); + if !(mod_folders_to_remove.len() > 0) { + return Err(format!( + "No mods removed as no Northstar mods matching {thunderstore_mod_string} were found to be installed." + )); + } + + // Delete given folders + for mod_folder in mod_folders_to_remove { + delete_mod_folder(mod_folder)?; + } Ok(()) } diff --git a/src-tauri/src/repair_and_verify/mod.rs b/src-tauri/src/repair_and_verify/mod.rs index 64278a25..fb108f37 100644 --- a/src-tauri/src/repair_and_verify/mod.rs +++ b/src-tauri/src/repair_and_verify/mod.rs @@ -1,9 +1,13 @@ -use crate::{mod_management::{set_mod_enabled_status, rebuild_enabled_mods_json}, northstar::CORE_MODS}; +use crate::{ + mod_management::{rebuild_enabled_mods_json, set_mod_enabled_status}, + northstar::CORE_MODS, +}; use anyhow::anyhow; /// Contains various functions to repair common issues and verifying installation use app::{get_enabled_mods, GameInstall}; /// Verifies Titanfall2 game files +#[tauri::command] pub fn verify_game_files(game_install: GameInstall) -> Result<String, String> { dbg!(game_install); Err("TODO, not yet implemented".to_string()) @@ -11,8 +15,8 @@ pub fn verify_game_files(game_install: GameInstall) -> Result<String, String> { /// Disables all mods except core ones /// Enables core mods if disabled +#[tauri::command] pub fn disable_all_but_core(game_install: GameInstall) -> Result<(), String> { - // Rebuild `enabledmods.json` first to ensure all mods are added rebuild_enabled_mods_json(game_install.clone())?; @@ -62,6 +66,8 @@ pub fn clean_up_download_folder( Ok(()) } +/// Get list of Northstar logs +#[tauri::command] pub fn get_log_list(game_install: GameInstall) -> Result<Vec<std::path::PathBuf>, String> { let ns_log_folder = format!("{}/R2Northstar/logs", game_install.game_path); |
