diff --git a/src-tauri/src/northstar/mod.rs b/src-tauri/src/northstar/mod.rs index 9953d742e..7ae44e28c 100644 --- a/src-tauri/src/northstar/mod.rs +++ b/src-tauri/src/northstar/mod.rs @@ -160,11 +160,12 @@ pub fn get_northstar_version_number(game_install: GameInstall) -> Result, ) -> Result { dbg!(game_install.clone()); if launch_options.launch_via_steam { - return launch_northstar_steam(game_install); + return launch_northstar_steam(game_install, launch_arguments); } let host_os = get_host_os(); @@ -179,7 +180,7 @@ pub fn launch_northstar( )); } - return launch_northstar_steam(game_install); + return launch_northstar_steam(game_install, launch_arguments); } // Only check guards if bypassing checks is not enabled @@ -213,9 +214,11 @@ pub fn launch_northstar( { let ns_exe_path = format!("{}/NorthstarLauncher.exe", game_install.game_path); let ns_profile_arg = format!("-profile={}", game_install.profile); + let mut arguments = vec!["/C", "start", "", &ns_exe_path, &ns_profile_arg]; + arguments.extend(launch_arguments); let mut output = std::process::Command::new("C:\\Windows\\System32\\cmd.exe") - .args(["/C", "start", "", &ns_exe_path, &ns_profile_arg]) + .args(arguments) .spawn() .expect("failed to execute process"); output.wait().expect("failed waiting on child process"); @@ -230,7 +233,10 @@ pub fn launch_northstar( } /// Prepare Northstar and Launch through Steam using the Browser Protocol -pub fn launch_northstar_steam(game_install: GameInstall) -> Result { +pub fn launch_northstar_steam( + game_install: GameInstall, + launch_arguments: Vec<&str>, +) -> Result { if !matches!(game_install.install_type, InstallType::STEAM) { return Err("Titanfall2 was not installed via Steam".to_string()); } @@ -266,9 +272,10 @@ pub fn launch_northstar_steam(game_install: GameInstall) -> Result Ok("Started game".to_string()), Err(_err) => Err("Failed to launch Titanfall 2 via Steam".to_string()), diff --git a/src-tauri/src/platform_specific/linux.rs b/src-tauri/src/platform_specific/linux.rs index fcac5b671..348f22821 100644 --- a/src-tauri/src/platform_specific/linux.rs +++ b/src-tauri/src/platform_specific/linux.rs @@ -65,14 +65,14 @@ pub fn install_ns_proton() -> Result<(), String> { /// Remove NS Proton pub fn uninstall_ns_proton() -> Result<(), String> { let compat_dir = get_proton_dir()?; - let pattern = format!("{}/NorthstarProton*", compat_dir); + let pattern = format!("{compat_dir}/NorthstarProton*"); for e in glob::glob(&pattern).expect("Failed to read glob pattern") { match e { Ok(path) => match std::fs::remove_dir_all(path.clone()) { Ok(_) => {} Err(_) => return Err(format!("Failed to remove {}", path.display())), }, - Err(e) => return Err(format!("Found unprocessable entry {}", e)), + Err(e) => return Err(format!("Found unprocessable entry {e}")), } } @@ -82,7 +82,7 @@ pub fn uninstall_ns_proton() -> Result<(), String> { /// Get the latest installed NS Proton version pub fn get_local_ns_proton_version() -> Result { let compat_dir = get_proton_dir().unwrap(); - let pattern = format!("{}/NorthstarProton*/version", compat_dir); + let pattern = format!("{compat_dir}/NorthstarProton*/version"); if let Some(e) = glob::glob(&pattern) .expect("Failed to read glob pattern") diff --git a/src-vue/src/components/LaunchArgumentsSelector.vue b/src-vue/src/components/LaunchArgumentsSelector.vue new file mode 100644 index 000000000..8f9c061b6 --- /dev/null +++ b/src-vue/src/components/LaunchArgumentsSelector.vue @@ -0,0 +1,235 @@ + + + + + \ No newline at end of file diff --git a/src-vue/src/i18n/lang/en.json b/src-vue/src/i18n/lang/en.json index 4f32e082f..cc2f757fc 100644 --- a/src-vue/src/i18n/lang/en.json +++ b/src-vue/src/i18n/lang/en.json @@ -154,6 +154,23 @@ "reinstall_text": "Please wait", "reinstall_success": "Successfully reinstalled Northstar" } + }, + + "launch_args": { + "title": "Launch arguments", + "new_arg_btn": "+ New launch argument", + "select_game_language": "Select game language", + "descriptions": { + "disablelogs": "Disable logging and creation of log files", + "vanilla": "Disables Northstar loading", + "northstar": "Enables Northstar loading", + "dedicated": "Starts a dedicated server without video output", + "waitfordebugger": "Waits for debugger to connect before launching game", + "enablechathooks": "Enables the use of chathooks for use by mods", + "noplugins": "Disables the plugin system", + "novid": "Disables startup videos", + "nosound": "Disables all game sounds" + } } }, diff --git a/src-vue/src/i18n/lang/fr.json b/src-vue/src/i18n/lang/fr.json index da9c2b1a0..3b444a2f4 100644 --- a/src-vue/src/i18n/lang/fr.json +++ b/src-vue/src/i18n/lang/fr.json @@ -131,7 +131,24 @@ "new_profile_name": "Entrez le nouveau nom du profil" } }, - "show_nsfw_mods": "Montrer les mods NSFW de Thunderstore" + "show_nsfw_mods": "Montrer les mods NSFW de Thunderstore", + + "launch_args": { + "title": "Paramètres de démarrage", + "new_arg_btn": "+ Nouveau paramètre", + "select_game_language": "Langage du jeu", + "descriptions": { + "disablelogs": "Désactive la journalisation et la création de journaux", + "vanilla": "Désactive le chargement de Northstar", + "northstar": "Active le chargement de Northstar", + "dedicated": "Démarre un serveur dédié sans sortie graphique", + "waitfordebugger": "Attend la connexion au débuggueur avant de lancer le jeu", + "enablechathooks": "Active les chathooks pour les mods", + "noplugins": "Désactive le système de plugins", + "novid": "Désactive les vidéos au démarrage", + "nosound": "Désactive tous les sons du jeu" + } + } }, "notification": { "date_prefix": "à", diff --git a/src-vue/src/main.ts b/src-vue/src/main.ts index 73219c9d7..60eb337d3 100644 --- a/src-vue/src/main.ts +++ b/src-vue/src/main.ts @@ -64,5 +64,7 @@ export const router = createRouter({ }); app.use(router); +// Store keys +export const argumentsStoreKey = 'launch_arguments'; app.mount('#app') diff --git a/src-vue/src/plugins/store.ts b/src-vue/src/plugins/store.ts index dcd6a211b..8f49bff59 100644 --- a/src-vue/src/plugins/store.ts +++ b/src-vue/src/plugins/store.ts @@ -10,7 +10,7 @@ import { NorthstarState } from '../utils/NorthstarState'; import { appDataDir } from '@tauri-apps/api/path'; import { open } from '@tauri-apps/plugin-dialog'; import { load } from '@tauri-apps/plugin-store'; -import { router } from "../main"; +import { argumentsStoreKey, router } from "../main"; import { ReleaseInfo } from "../../../src-tauri/bindings/ReleaseInfo"; import { ThunderstoreMod } from "../../../src-tauri/bindings/ThunderstoreMod"; import { NorthstarMod } from "../../../src-tauri/bindings/NorthstarMod"; @@ -180,9 +180,10 @@ export const store = createStore({ } }, async launchGame(state: any, launch_options: NorthstarLaunchOptions = { launch_via_steam: false, bypass_checks: false}) { + const launchArguments: string[] = await persistentStore.get(argumentsStoreKey) ?? []; if (launch_options.bypass_checks) { - await invoke("launch_northstar", { gameInstall: state.game_install, launchOptions: launch_options }) + await invoke("launch_northstar", { gameInstall: state.game_install, launchOptions: launch_options, launchArguments }) .then((message) => { console.log("Launched with bypassed checks"); console.log(message); @@ -232,7 +233,7 @@ export const store = createStore({ // Game is ready to play. case NorthstarState.READY_TO_PLAY: - await invoke("launch_northstar", { gameInstall: state.game_install, launchOptions: launch_options }) + await invoke("launch_northstar", { gameInstall: state.game_install, launchOptions: launch_options, launchArguments }) .then((message) => { console.log(message); // NorthstarState.RUNNING @@ -249,7 +250,9 @@ export const store = createStore({ } }, async launchGameSteam(state: any, launch_options: NorthstarLaunchOptions = { launch_via_steam: true, bypass_checks: false}) { - await invoke("launch_northstar", { gameInstall: state.game_install, launchOptions: launch_options }) + const launchArguments: string[] = await persistentStore.get(argumentsStoreKey) ?? []; + + await invoke("launch_northstar", { gameInstall: state.game_install, launchOptions: launch_options, launchArguments }) .then((_message) => { showNotification('Success'); }) diff --git a/src-vue/src/utils/LaunchArgument.ts b/src-vue/src/utils/LaunchArgument.ts new file mode 100644 index 000000000..55b907bd4 --- /dev/null +++ b/src-vue/src/utils/LaunchArgument.ts @@ -0,0 +1,9 @@ +export class LaunchArgument { + public argumentName: string; + public i18nEntry: string; + + constructor(argumentName: string, i18nEntry: string = '') { + this.argumentName = argumentName; + this.i18nEntry = i18nEntry; + } +} \ No newline at end of file diff --git a/src-vue/src/views/SettingsView.vue b/src-vue/src/views/SettingsView.vue index efc16e187..a29ef9230 100644 --- a/src-vue/src/views/SettingsView.vue +++ b/src-vue/src/views/SettingsView.vue @@ -67,6 +67,12 @@ + +
+

{{ $t('settings.launch_args.title') }}

+ +
+

{{ $t('settings.nb_ts_mods_per_page') }}

@@ -148,6 +154,7 @@ import { ReleaseCanal } from "../utils/ReleaseCanal"; import { load } from '@tauri-apps/plugin-store'; import { showErrorNotification, showNotification } from "../utils/ui"; import LanguageSelector from "../components/LanguageSelector.vue"; +import LaunchArgumentsSelector from "../components/LaunchArgumentsSelector.vue"; const persistentStore = await load('flight-core-settings.json', { autoSave: false }); import { open } from '@tauri-apps/plugin-shell'; import { i18n } from '../main'; @@ -156,7 +163,8 @@ import { ElMessageBox } from 'element-plus' export default defineComponent({ name: "SettingsView", components: { - LanguageSelector + LanguageSelector, + LaunchArgumentsSelector }, data() { return {