diff --git a/src/main.rs b/src/main.rs index 553b034..64a6e59 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,7 +17,9 @@ use std::{ os::unix::fs::MetadataExt, path::{Path, PathBuf}, }; -use steam_linux_runtime_injector::restore_runtime_entrypoint; +use steam_linux_runtime_injector::{ + restore_sniper_runtime_entrypoint, restore_soldier_runtime_entrypoint, +}; use tracing::{error, warn}; use tracing_subscriber::{ filter::LevelFilter, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer, @@ -68,7 +70,8 @@ fn restore_steam_xr_files() { } } } - restore_runtime_entrypoint(); + restore_sniper_runtime_entrypoint(); + restore_soldier_runtime_entrypoint(); } const LOGS_MAX_SIZE_BYTES: u64 = 1000000000; // 1GB diff --git a/src/steam_linux_runtime_injector.rs b/src/steam_linux_runtime_injector.rs index eb76029..6e08b5f 100644 --- a/src/steam_linux_runtime_injector.rs +++ b/src/steam_linux_runtime_injector.rs @@ -15,39 +15,67 @@ use std::{ }; use tracing::error; -pub const PRESSURE_VESSEL_STEAM_APPID: u32 = 1628350; +pub const SNIPER_RUNTIME_STEAM_APPID: u32 = 1628350; +pub const SOLDIER_RUNTIME_STEAM_APPID: u32 = 1391110; -fn get_runtime_entrypoint_path() -> Option { +fn get_sniper_runtime_entrypoint_path() -> Option { match SteamLibraryFolder::get_folders() { Ok(libraryfolders) => libraryfolders .iter() - .find(|(_, folder)| folder.apps.contains_key(&PRESSURE_VESSEL_STEAM_APPID)) + .find(|(_, folder)| folder.apps.contains_key(&SNIPER_RUNTIME_STEAM_APPID)) .map(|(_, folder)| { PathBuf::from(&folder.path) .join("steamapps/common/SteamLinuxRuntime_sniper/_v2-entry-point") }), Err(e) => { - error!("unable to get runtime entrypoint path: {e}"); + error!("unable to get sniper runtime entrypoint path: {e}"); + None + } + } +} + +fn get_soldier_runtime_entrypoint_path() -> Option { + match SteamLibraryFolder::get_folders() { + Ok(libraryfolders) => libraryfolders + .iter() + .find(|(_, folder)| folder.apps.contains_key(&SOLDIER_RUNTIME_STEAM_APPID)) + .map(|(_, folder)| { + PathBuf::from(&folder.path) + .join("steamapps/common/SteamLinuxRuntime_soldier/_v2-entry-point") + }), + Err(e) => { + error!("unable to get soldier runtime entrypoint path: {e}"); None } } } lazy_static! { - static ref STEAM_RUNTIME_ENTRYPOINT_PATH: Option = get_runtime_entrypoint_path(); + static ref STEAM_SNIPER_RUNTIME_ENTRYPOINT_PATH: Option = + get_sniper_runtime_entrypoint_path(); + static ref STEAM_SOLDIER_RUNTIME_ENTRYPOINT_PATH: Option = + get_soldier_runtime_entrypoint_path(); } -fn get_backup_runtime_entrypoint_location() -> PathBuf { +fn get_backup_sniper_runtime_entrypoint_location() -> PathBuf { get_backup_dir().join("_v2-entry-point.bak") } -fn backup_runtime_entrypoint(path: &Path) { - copy_file(path, &get_backup_runtime_entrypoint_location()); +fn get_backup_soldier_runtime_entrypoint_location() -> PathBuf { + get_backup_dir().join("_v2-entry-point.soldier.bak") } -pub fn restore_runtime_entrypoint() { - if let Some(path) = STEAM_RUNTIME_ENTRYPOINT_PATH.as_ref() { - let backup = get_backup_runtime_entrypoint_location(); +fn backup_sniper_runtime_entrypoint(path: &Path) { + copy_file(path, &get_backup_sniper_runtime_entrypoint_location()); +} + +fn backup_soldier_runtime_entrypoint(path: &Path) { + copy_file(path, &get_backup_soldier_runtime_entrypoint_location()); +} + +pub fn restore_sniper_runtime_entrypoint() { + if let Some(path) = STEAM_SNIPER_RUNTIME_ENTRYPOINT_PATH.as_ref() { + let backup = get_backup_sniper_runtime_entrypoint_location(); if Path::new(&backup).is_file() { copy_file(&backup, path); let _ = mark_as_executable(path); @@ -55,6 +83,17 @@ pub fn restore_runtime_entrypoint() { } } +pub fn restore_soldier_runtime_entrypoint() { + if let Some(path) = STEAM_SOLDIER_RUNTIME_ENTRYPOINT_PATH.as_ref() { + let backup = get_backup_soldier_runtime_entrypoint_location(); + if Path::new(&backup).is_file() { + copy_file(&backup, path); + let _ = mark_as_executable(path); + } + } +} + +/// this implementation is identical for both sniper and soldier runtimes fn append_to_runtime_entrypoint(data: &str, path: &Path) -> anyhow::Result<()> { let existing = read_to_string(path)?; let new = existing.replace( @@ -66,10 +105,12 @@ fn append_to_runtime_entrypoint(data: &str, path: &Path) -> anyhow::Result<()> { Ok(()) } -pub fn set_runtime_entrypoint_launch_opts_from_profile(profile: &Profile) -> anyhow::Result<()> { - restore_runtime_entrypoint(); - if let Some(dest) = STEAM_RUNTIME_ENTRYPOINT_PATH.as_ref() { - backup_runtime_entrypoint(dest); +pub fn set_sniper_runtime_entrypoint_launch_opts_from_profile( + profile: &Profile, +) -> anyhow::Result<()> { + restore_sniper_runtime_entrypoint(); + if let Some(dest) = STEAM_SNIPER_RUNTIME_ENTRYPOINT_PATH.as_ref() { + backup_sniper_runtime_entrypoint(dest); append_to_runtime_entrypoint( &profile .get_env_vars() @@ -83,5 +124,27 @@ pub fn set_runtime_entrypoint_launch_opts_from_profile(profile: &Profile) -> any return Ok(()); } - bail!("Could not find valid runtime entrypoint"); + bail!("Could not find valid sniper runtime entrypoint"); +} + +pub fn set_soldier_runtime_entrypoint_launch_opts_from_profile( + profile: &Profile, +) -> anyhow::Result<()> { + restore_soldier_runtime_entrypoint(); + if let Some(dest) = STEAM_SOLDIER_RUNTIME_ENTRYPOINT_PATH.as_ref() { + backup_soldier_runtime_entrypoint(dest); + append_to_runtime_entrypoint( + &profile + .get_env_vars() + .iter() + .map(|ev| "export ".to_string() + ev) + .collect::>() + .join("\n"), + dest, + )?; + mark_as_executable(dest)?; + + return Ok(()); + } + bail!("Could not find valid soldier runtime entrypoint"); } diff --git a/src/ui/app.rs b/src/ui/app.rs index db02e88..a9b9265 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -41,7 +41,9 @@ use crate::{ profile::{OvrCompatibilityModuleType, Profile, XRServiceType}, stateless_action, steam_linux_runtime_injector::{ - restore_runtime_entrypoint, set_runtime_entrypoint_launch_opts_from_profile, + restore_sniper_runtime_entrypoint, restore_soldier_runtime_entrypoint, + set_sniper_runtime_entrypoint_launch_opts_from_profile, + set_soldier_runtime_entrypoint_launch_opts_from_profile, }, termcolor::TermColor, util::file_utils::{ @@ -234,13 +236,17 @@ impl App { ); worker.start(); self.xrservice_worker = Some(worker); + let set_sniper_launch_opts_res = + set_sniper_runtime_entrypoint_launch_opts_from_profile(&prof); + let set_soldier_launch_opts_res = + set_soldier_runtime_entrypoint_launch_opts_from_profile(&prof); self.main_view .sender() .emit(MainViewMsg::XRServiceActiveChanged( true, Some(self.get_selected_profile()), // show launch opts only if setting the runtime entrypoint fails - set_runtime_entrypoint_launch_opts_from_profile(&prof).is_err(), + set_sniper_launch_opts_res.is_err() || set_soldier_launch_opts_res.is_err(), )); self.debug_view .sender() @@ -304,7 +310,8 @@ impl App { } pub fn restore_openxr_openvr_files(&self) { - restore_runtime_entrypoint(); + restore_sniper_runtime_entrypoint(); + restore_soldier_runtime_entrypoint(); if let Err(e) = remove_current_active_runtime() { alert( "Could not remove profile active runtime",