- update: code cleanup

- update: reworked how the launch params are parsed
This commit is contained in:
2024-12-15 01:41:42 -05:00
parent 860b319a03
commit 1b2d6bdac2
2 changed files with 83 additions and 97 deletions

70
launcher/src/launcher.rs Normal file
View File

@@ -0,0 +1,70 @@
use crate::{format_shell_command, wait_for_keypress};
use std::borrow::Cow;
use std::env;
use std::process::{exit, Command, Stdio};
use tracing::{debug, error, info, warn};
use url::Url;
pub(crate) fn launch_game(url: String) {
let exe_dir_path = env::current_exe().unwrap().parent().unwrap().to_path_buf();
// Change the working directory
if let Err(e) = env::set_current_dir(exe_dir_path) {
error!("Failed to set working directory: {}", e);
wait_for_keypress();
exit(1);
}
// Parse the URL
match Url::parse(&url) {
Ok(parsed_url) => {
let params = parsed_url.query_pairs();
let game_executable = "./TRose.exe";
let mut command = Command::new(game_executable);
command.arg("@TRIGGER_SOFT@");
let mut is_direct = false;
for (key, value) in params {
debug!("Query pairs: [{}, {}]", key, value);
match key {
Cow::Borrowed("ip") => {
command.arg("_server").arg(value.to_string());
}
Cow::Borrowed("port") => {
command.arg("_port").arg(value.to_string());
}
Cow::Borrowed("otp") => {
is_direct = true;
command.arg("_direct").arg("_otp").arg(value.to_string());
}
Cow::Borrowed("username") => {
command.arg("_userid").arg(value.to_string());
}
Cow::Borrowed("password") => {
if !is_direct {
command.arg("_pass").arg(value.to_string());
}
}
_ => {
warn!("Unexpected parameter: [{}, {}]", key, value);
}
}
}
command
.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),
}
}

View File

@@ -1,9 +1,9 @@
use std::path::{Path, PathBuf};
use std::process::{exit, Command, Stdio};
mod launcher;
use clap::{Parser, Subcommand};
use std::{env, io};
use std::process::{Command};
use std::{io};
use tracing::{debug, error, info, Level};
use url::Url;
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
@@ -12,17 +12,15 @@ struct Args {
action: Commands,
#[arg(short, long, action = clap::ArgAction::Count)]
verbose: u8
verbose: u8,
}
#[derive(Subcommand, Debug)]
enum Commands {
#[command(name = "launch")]
Launch {
url: String,
},
Launch { url: String },
#[command(name = "update")]
Update
Update,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
@@ -30,18 +28,18 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let verbose = match args.verbose {
0 => Level::INFO,
1 => Level::DEBUG,
_ => Level::TRACE
_ => Level::TRACE,
};
// Set our logging level
tracing_subscriber::fmt().with_max_level(verbose).init();
let action = args.action;
match action {
Commands::Launch { url } => {
debug!("launching with URL {}", url);
launch_game(url);
},
launcher::launch_game(url);
}
Commands::Update => {
error!("Update action not implemented");
return Err("Update action not implemented".into());
@@ -51,88 +49,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}
fn launch_game(url: String) {
let exe_dir_path = env::current_exe().unwrap().parent().unwrap().to_path_buf();
// let working_directory =
// env::var("GAME_CLIENT_PATH").unwrap_or_else(|_| "D:/rose_osirose-new-x64".to_string());
// Change the working directory
if let Err(e) = env::set_current_dir(exe_dir_path) {
error!("Failed to set working directory: {}", e);
wait_for_keypress();
exit(1);
}
// 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);
// 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),
}
}
fn wait_for_keypress() {
// Wait for a keypress
info!("Press Enter to close the launcher...");
@@ -147,4 +63,4 @@ fn format_shell_command(command: &Command) -> String {
.collect();
format!("{} {}", executable, args.join(" "))
}
}