From dd1e870b279f990981dcbaff79c9db58fde18ba9 Mon Sep 17 00:00:00 2001 From: Jan Date: Thu, 6 Apr 2023 15:06:38 +0200 Subject: feat: Add ability to launch via Steam to DevView (#178) * feat: Add ability to launch via Steam * document what get_titanfall_proton() does * revert explicit use of newly imported Path * Format source code to pass CI * Use new steamlocate compat_tool helper * cargo fmt * fix: Address various clippy issues Addresses clippy warnings caused by newly introduced code * fix: Cargo toml dependency formatting --- src-tauri/src/constants.rs | 3 ++ src-tauri/src/lib.rs | 99 ++++++++++++++++++++++++++++++++++++++++++++-- src-tauri/src/main.rs | 10 +++++ 3 files changed, 108 insertions(+), 4 deletions(-) (limited to 'src-tauri/src') diff --git a/src-tauri/src/constants.rs b/src-tauri/src/constants.rs index 0f4e9ab4..8c88df1e 100644 --- a/src-tauri/src/constants.rs +++ b/src-tauri/src/constants.rs @@ -29,6 +29,9 @@ pub const BLACKLISTED_MODS: [&str; 3] = [ // Titanfall2 game IDs on Origin/EA-App pub const TITANFALL2_ORIGIN_IDS: [&str; 2] = ["Origin.OFR.50.0001452", "Origin.OFR.50.0001456"]; +// Titanfall2 Steam App ID +pub const TITANFALL2_STEAM_ID: &str = "1237970"; + // Order in which the sections for release notes should be displayed pub const SECTION_ORDER: [&str; 9] = [ "feat", "fix", "docs", "style", "refactor", "build", "test", "chore", "other", diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index ff1445e5..a3553448 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,4 +1,4 @@ -use std::env; +use std::{env, fs, path::Path, time::Duration}; use anyhow::{anyhow, Context, Result}; @@ -14,11 +14,14 @@ use platform_specific::linux; use serde::{Deserialize, Serialize}; use sysinfo::SystemExt; +use tokio::time::sleep; use ts_rs::TS; use zip::ZipArchive; use northstar::get_northstar_version_number; +use crate::constants::TITANFALL2_STEAM_ID; + #[derive(Serialize, Deserialize, Debug, Clone)] pub enum InstallType { STEAM, @@ -92,7 +95,7 @@ pub fn find_game_install_location() -> Result { // Attempt parsing Steam library directly match steamlocate::SteamDir::locate() { Some(mut steamdir) => { - let titanfall2_steamid = 1237970; + let titanfall2_steamid = TITANFALL2_STEAM_ID.parse().unwrap(); match steamdir.app(&titanfall2_steamid) { Some(app) => { // println!("{:#?}", app); @@ -328,6 +331,93 @@ pub fn launch_northstar( )) } +/// Prepare Northstar and Launch through Steam using the Browser Protocol +pub fn launch_northstar_steam( + game_install: GameInstall, + _bypass_checks: Option, +) -> Result { + if !matches!(game_install.install_type, InstallType::STEAM) { + return Err("Titanfall2 was not installed via Steam".to_string()); + } + + match steamlocate::SteamDir::locate() { + Some(mut steamdir) => { + if get_host_os() != "windows" { + let titanfall2_steamid: u32 = TITANFALL2_STEAM_ID.parse().unwrap(); + match steamdir.compat_tool(&titanfall2_steamid) { + Some(compat) => { + if !compat + .name + .clone() + .unwrap() + .to_ascii_lowercase() + .contains("northstarproton") + { + return Err( + "Titanfall2 was not configured to use NorthstarProton".to_string() + ); + } + } + None => { + return Err( + "Titanfall2 was not configured to use a compatibility tool".to_string() + ); + } + } + } + } + None => { + return Err("Couldn't access Titanfall2 directory".to_string()); + } + } + + // Switch to Titanfall2 directory to set everything up + if std::env::set_current_dir(game_install.game_path).is_err() { + // We failed to get to Titanfall2 directory + return Err("Couldn't access Titanfall2 directory".to_string()); + } + + let run_northstar = "run_northstar.txt"; + let run_northstar_bak = "run_northstar.txt.bak"; + + if Path::new(run_northstar).exists() { + // rename should ovewrite existing files + fs::rename(run_northstar, run_northstar_bak).unwrap(); + } + + // Passing arguments gives users a prompt, so we use run_northstar.txt + fs::write(run_northstar, b"1").unwrap(); + + let retval = match open::that(format!("steam://run/{}/", TITANFALL2_STEAM_ID)) { + Ok(()) => Ok("Started game".to_string()), + Err(_err) => Err("Failed to launch Titanfall 2 via Steam".to_string()), + }; + + let is_err = retval.is_err(); + + // Handle the rest in the backround + tauri::async_runtime::spawn(async move { + // Starting the EA app and Titanfall might take a good minute or three + let mut wait_countdown = 60 * 3; + while wait_countdown > 0 && !check_northstar_running() && !is_err { + sleep(Duration::from_millis(1000)).await; + wait_countdown -= 1; + } + + // Northstar may be running, but it may not have loaded the file yet + sleep(Duration::from_millis(2000)).await; + + // intentionally ignore Result + let _ = fs::remove_file(run_northstar); + + if Path::new(run_northstar_bak).exists() { + fs::rename(run_northstar_bak, run_northstar).unwrap(); + } + }); + + retval +} + pub fn check_origin_running() -> bool { let s = sysinfo::System::new_all(); s.processes_by_name("Origin.exe").next().is_some() @@ -336,10 +426,11 @@ pub fn check_origin_running() -> bool { /// Checks if Northstar process is running pub fn check_northstar_running() -> bool { - sysinfo::System::new_all() - .processes_by_name("NorthstarLauncher.exe") + let s = sysinfo::System::new_all(); + s.processes_by_name("NorthstarLauncher.exe") .next() .is_some() + || s.processes_by_name("Titanfall2.exe").next().is_some() } /// Helps with converting release candidate numbers which are different on Thunderstore diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 21045db1..16b951ec 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -121,6 +121,7 @@ fn main() { install_northstar_caller, update_northstar_caller, launch_northstar_caller, + launch_northstar_steam_caller, check_is_flightcore_outdated_caller, get_log_list, verify_game_files, @@ -323,6 +324,15 @@ async fn launch_northstar_caller( launch_northstar(game_install, bypass_checks) } +#[tauri::command] +/// Launches Northstar +async fn launch_northstar_steam_caller( + game_install: GameInstall, + bypass_checks: Option, +) -> Result { + launch_northstar_steam(game_install, bypass_checks) +} + #[tauri::command] /// Installs the specified mod async fn install_mod_caller( -- cgit v1.2.3