diff options
Diffstat (limited to 'src-tauri/src/northstar/install.rs')
-rw-r--r-- | src-tauri/src/northstar/install.rs | 358 |
1 files changed, 0 insertions, 358 deletions
diff --git a/src-tauri/src/northstar/install.rs b/src-tauri/src/northstar/install.rs deleted file mode 100644 index 0953fa38..00000000 --- a/src-tauri/src/northstar/install.rs +++ /dev/null @@ -1,358 +0,0 @@ -use anyhow::Result; -use serde::{Deserialize, Serialize}; -use std::time::Duration; -use std::{cell::RefCell, time::Instant}; -use ts_rs::TS; - -use crate::constants::{CORE_MODS, NORTHSTAR_DEFAULT_PROFILE, NORTHSTAR_DLL}; -use crate::{ - util::{extract, move_dir_all}, - GameInstall, InstallType, -}; - -#[cfg(target_os = "windows")] -use crate::platform_specific::windows; - -#[derive(Serialize, Deserialize, Debug, Clone, TS)] -#[ts(export)] -enum InstallState { - Downloading, - Extracting, - Done, -} - -#[derive(Serialize, Deserialize, Debug, Clone, TS)] -#[ts(export)] -struct InstallProgress { - current_downloaded: u64, - total_size: u64, - state: InstallState, -} - -/// Installs Northstar to the given path -#[tauri::command] -pub async fn install_northstar_wrapper( - window: tauri::Window, - game_install: GameInstall, - northstar_package_name: Option<String>, - version_number: Option<String>, -) -> Result<bool, String> { - log::info!("Running Northstar install"); - - // Get Northstar package name (`Northstar` vs `NorthstarReleaseCandidate`) - let northstar_package_name = northstar_package_name - .map(|name| { - if name.len() <= 1 { - "Northstar".to_string() - } else { - name - } - }) - .unwrap_or("Northstar".to_string()); - - match install_northstar(window, game_install, northstar_package_name, version_number).await { - Ok(_) => Ok(true), - Err(err) => { - log::error!("{}", err); - Err(err) - } - } -} - -/// Update Northstar install in the given path -#[tauri::command] -pub async fn update_northstar( - window: tauri::Window, - game_install: GameInstall, - northstar_package_name: Option<String>, -) -> Result<bool, String> { - log::info!("Updating Northstar"); - - // Simply re-run install with up-to-date version for upate - install_northstar_wrapper(window, game_install, northstar_package_name, None).await -} - -/// Copied from `papa` source code and modified -///Install N* from the provided mod -/// -///Checks cache, else downloads the latest version -async fn do_install( - window: tauri::Window, - nmod: &thermite::model::ModVersion, - game_install: GameInstall, -) -> Result<()> { - let filename = format!("northstar-{}.zip", nmod.version); - let temp_dir = format!("{}/___flightcore-temp", game_install.game_path); - let download_directory = format!("{}/download-dir", temp_dir); - let extract_directory = format!("{}/extract-dir", temp_dir); - - log::info!("Attempting to create temporary directory {}", temp_dir); - std::fs::create_dir_all(download_directory.clone())?; - std::fs::create_dir_all(extract_directory.clone())?; - - let download_path = format!("{}/{}", download_directory, filename); - log::info!("Download path: {download_path}"); - - let last_emit = RefCell::new(Instant::now()); // Keep track of the last time a signal was emitted - let mut nfile = std::fs::File::options() - .read(true) - .write(true) - .truncate(true) - .create(true) - .open(download_path)?; - thermite::core::manage::download_with_progress( - &mut nfile, - &nmod.url, - |delta, current, total| { - if delta != 0 { - // Only emit a signal once every 100ms - // This way we don't bombard the frontend with events on fast download speeds - let time_since_last_emit = Instant::now().duration_since(*last_emit.borrow()); - if time_since_last_emit >= Duration::from_millis(100) { - window - .emit( - "northstar-install-download-progress", - InstallProgress { - current_downloaded: current, - total_size: total, - state: InstallState::Downloading, - }, - ) - .unwrap(); - *last_emit.borrow_mut() = Instant::now(); - } - } - }, - )?; - - window - .emit( - "northstar-install-download-progress", - InstallProgress { - current_downloaded: 0, - total_size: 0, - state: InstallState::Extracting, - }, - ) - .unwrap(); - - log::info!("Extracting Northstar..."); - extract(nfile, std::path::Path::new(&extract_directory))?; - - // Prepare Northstar for Installation - log::info!("Preparing Northstar..."); - if game_install.profile != NORTHSTAR_DEFAULT_PROFILE { - // We are using a non standard Profile, we must: - // - move the DLL - // - rename the Profile - - // Move DLL into the default R2Northstar Profile - let old_dll_path = format!("{}/{}", extract_directory, NORTHSTAR_DLL); - let new_dll_path = format!( - "{}/{}/{}", - extract_directory, NORTHSTAR_DEFAULT_PROFILE, NORTHSTAR_DLL - ); - std::fs::rename(old_dll_path, new_dll_path)?; - - // rename default R2Northstar Profile to the profile we want to use - let old_profile_path = format!("{}/{}/", extract_directory, NORTHSTAR_DEFAULT_PROFILE); - let new_profile_path = format!("{}/{}/", extract_directory, game_install.profile); - std::fs::rename(old_profile_path, new_profile_path)?; - } - - log::info!("Installing Northstar..."); - - // Delete previous version here - for core_mod in CORE_MODS { - let path_to_delete_string = format!( - "{}/{}/mods/{}/", - game_install.game_path, game_install.profile, core_mod - ); - log::info!("Preparing to remove {}", path_to_delete_string); - - // Check if folder exists - let path_to_delete = std::path::Path::new(&path_to_delete_string); - - // Check if path even exists before we attempt to remove - if !path_to_delete.exists() { - log::info!("{} does not exist. Skipping", path_to_delete_string); - continue; - } - - if !path_to_delete.is_dir() { - log::error!( - "{} exists but is a file? This should never happen", - path_to_delete_string - ); - continue; - } - - // Safety check for mod.json - // Just so that we won't ever have a https://github.com/ValveSoftware/steam-for-linux/issues/3671 moment - let mod_json_path = format!("{}/mod.json", path_to_delete_string); - let mod_json_path = std::path::Path::new(&mod_json_path); - - if !mod_json_path.exists() { - log::error!("Missing mod.json for {path_to_delete_string} this shouldn't happen"); - continue; - } - - // Finally delete file - match std::fs::remove_dir_all(path_to_delete) { - Ok(()) => { - log::info!("Succesfully removed") - } - Err(err) => { - log::error!("Failed removing {} due to {}", path_to_delete_string, err) - } - }; - } - - for entry in std::fs::read_dir(extract_directory).unwrap() { - let entry = entry.unwrap(); - let destination = format!( - "{}/{}", - game_install.game_path, - entry.path().file_name().unwrap().to_str().unwrap() - ); - - log::info!("Installing {}", entry.path().display()); - if !entry.file_type().unwrap().is_dir() { - std::fs::rename(entry.path(), destination)?; - } else { - move_dir_all(entry.path(), destination)?; - } - } - - // Delete old copy - log::info!("Delete temporary directory"); - std::fs::remove_dir_all(temp_dir).unwrap(); - - log::info!("Done installing Northstar!"); - window - .emit( - "northstar-install-download-progress", - InstallProgress { - current_downloaded: 0, - total_size: 0, - state: InstallState::Done, - }, - ) - .unwrap(); - - Ok(()) -} - -pub async fn install_northstar( - window: tauri::Window, - game_install: GameInstall, - northstar_package_name: String, - version_number: Option<String>, -) -> Result<String, String> { - let index = match thermite::api::get_package_index() { - Ok(res) => res.to_vec(), - Err(err) => { - log::warn!("Failed fetching package index due to: {err}"); - return Err("Failed to connect to Thunderstore.".to_string()); - } - }; - let nmod = index - .iter() - .find(|f| f.name.to_lowercase() == northstar_package_name.to_lowercase()) - .ok_or_else(|| panic!("Couldn't find Northstar on thunderstore???")) - .unwrap(); - - // Use passed version or latest if no version was passed - let version = version_number.as_ref().unwrap_or(&nmod.latest); - - let game_path = game_install.game_path.clone(); - log::info!("Install path \"{}\"", game_path); - - match do_install(window, nmod.versions.get(version).unwrap(), game_install).await { - Ok(_) => (), - Err(err) => { - if game_path - .to_lowercase() - .contains(&r"C:\Program Files\".to_lowercase()) - // default is `C:\Program Files\EA Games\Titanfall2` - { - return Err( - "Cannot install to default EA App install path, please move Titanfall2 to a different install location.".to_string(), - ); - } else { - return Err(err.to_string()); - } - } - } - - Ok(nmod.latest.clone()) -} - -/// Attempts to find the game install location -#[tauri::command] -pub fn find_game_install_location() -> Result<GameInstall, String> { - // Attempt parsing Steam library directly - match steamlocate::SteamDir::locate() { - Ok(steamdir) => { - #[cfg(target_os = "linux")] - { - let snap_dir = match std::env::var("SNAP_USER_DATA") { - Ok(snap_dir) => std::path::PathBuf::from(snap_dir), - Err(_) => match dirs::home_dir() { - Some(path) => path, - None => std::path::PathBuf::new(), - } - .join("snap"), - }; - - if steamdir.path().starts_with(snap_dir) { - log::warn!("Found Steam installed via Snap, you may encounter issues"); - } - } - - match steamdir.find_app(thermite::TITANFALL2_STEAM_ID) { - Ok(Some((app, library))) => { - let app_path = library - .path() - .join("steamapps") - .join("common") - .join(app.install_dir) - .into_os_string() - .into_string() - .unwrap(); - - let game_install = GameInstall { - game_path: app_path, - profile: "R2Northstar".to_string(), - install_type: InstallType::STEAM, - }; - return Ok(game_install); - } - Ok(None) => log::info!("Couldn't locate your Titanfall 2 Steam install."), - Err(err) => log::info!( - "Something went wrong while trying to find Titanfall 2 {}", - err - ), - } - } - Err(err) => log::info!("Couldn't locate Steam on this computer! {}", err), - } - - // (On Windows only) try parsing Windows registry for Origin install path - #[cfg(target_os = "windows")] - match windows::origin_install_location_detection() { - Ok(game_path) => { - let game_install = GameInstall { - game_path, - profile: "R2Northstar".to_string(), - install_type: InstallType::ORIGIN, - }; - return Ok(game_install); - } - Err(err) => { - log::info!("{}", err); - } - }; - - Err("Could not auto-detect game install location! Please enter it manually.".to_string()) -} |