From 949a931914b701df9d3bb9210804ce53deff3f282163a82bb671620dbfe33779 Mon Sep 17 00:00:00 2001 From: RavenX8 <7156279+RavenX8@users.noreply.github.com> Date: Sat, 14 Dec 2024 01:52:27 -0500 Subject: [PATCH] - add: launcher for custom uri protocol to allow pass token and server info to the client --- Cargo.toml | 2 +- launcher/Cargo.toml | 10 ++++ launcher/src/main.rs | 120 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 launcher/Cargo.toml create mode 100644 launcher/src/main.rs diff --git a/Cargo.toml b/Cargo.toml index fa38619..a2417f0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,6 @@ members = [ "database-service", "packet-service", "world-service", - "utils", + "utils", "launcher", "api-service", ] resolver = "2" diff --git a/launcher/Cargo.toml b/launcher/Cargo.toml new file mode 100644 index 0000000..ec255dc --- /dev/null +++ b/launcher/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "launcher" +version = "0.1.0" +edition = "2021" + +[dependencies] +shell-escape = "0.1.5" +tracing = "0.1.41" +tracing-subscriber = "0.3.19" +url = "2.5.4" diff --git a/launcher/src/main.rs b/launcher/src/main.rs new file mode 100644 index 0000000..eaffe37 --- /dev/null +++ b/launcher/src/main.rs @@ -0,0 +1,120 @@ +use std::path::Path; +use std::process::{exit, Command, Stdio}; +use std::str::FromStr; +use std::{env, io}; +use tracing::{error, info, Level}; +use url::Url; + +fn wait_for_keypress() { + // Wait for a keypress + info!("Press Enter to close the launcher..."); + let _ = io::stdin().read_line(&mut String::new()); +} + +fn format_shell_command(command: &Command) -> String { + let executable = command.get_program().to_string_lossy(); + let args: Vec = command + .get_args() + .map(|arg| shell_escape::escape(arg.to_string_lossy()).into_owned()) + .collect(); + + format!("{} {}", executable, args.join(" ")) +} + +fn main() { + tracing_subscriber::fmt() + .with_max_level( + Level::from_str(&env::var("LOG_LEVEL").unwrap_or_else(|_| "info".to_string())) + .unwrap_or_else(|_| Level::INFO), + ) + .init(); + + // Get the full command-line arguments (the URL is passed as the first argument after the executable) + let args: Vec = env::args().collect(); + if args.len() < 2 { + error!("Usage: osirose-launcher "); + wait_for_keypress(); + return; + } + + let url = &args[1]; + let working_directory = + env::var("GAME_CLIENT_PATH").unwrap_or_else(|_| "D:/rose_osirose-new-x64".to_string()); + + // Parse the URL + match Url::parse(url) { + Ok(parsed_url) => { + // Extract the "otp" parameter + let otp = parsed_url + .query_pairs() + .find(|(key, _)| key == "otp") + .map(|(_, value)| value.to_string()); + let ip = parsed_url + .query_pairs() + .find(|(key, _)| key == "ip") + .map(|(_, value)| value.to_string()); + let username = parsed_url + .query_pairs() + .find(|(key, _)| key == "username") + .map(|(_, value)| value.to_string()); + let port = parsed_url + .query_pairs() + .find(|(key, _)| key == "port") + .map(|(_, value)| value.to_string()) + .unwrap_or("4000".to_string()); + + // Ensure required parameters are present + if otp.is_none() || ip.is_none() || username.is_none() { + error!("Missing required parameters: otp, ip, or username"); + wait_for_keypress(); + return; + } + + // Unwrap the parameters + let otp = otp.unwrap(); + let ip = ip.unwrap(); + let username = username.unwrap(); + + info!("Launching game with:"); + info!(" OTP: {}", otp); + info!(" IP: {}", ip); + info!(" Username: {}", username); + + // Change the working directory + if let Err(e) = env::set_current_dir(Path::new(&working_directory)) { + eprintln!("Failed to set working directory: {}", e); + wait_for_keypress(); + exit(1); + } + + // Construct the game client command + let game_executable = "./TRose.exe"; + let mut command = Command::new(game_executable); + command + .arg("@TRIGGER_SOFT@") + .arg("_direct") + .arg("_server") + .arg(ip) + .arg("_port") + .arg(port) + .arg("_userid") + .arg(username) + .arg("_otp") + .arg(otp) + .stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()); + + info!("Executing: {:?}", format_shell_command(&command)); + + // Check if the game launched successfully + match command.spawn() { + Ok(_) => info!("Game launched successfully!"), + Err(e) => error!("Failed to launch the game: {}", e), + } + } + Err(e) => error!("Failed to parse URL: {}", e), + } + + info!("Launcher is closing..."); +}