mirror of
https://github.com/Drop-OSS/drop.git
synced 2026-07-27 18:24:43 +10:00
feat: switch to shell-based command launching
note: needs error handling
This commit is contained in:
@@ -4,6 +4,7 @@ use std::{
|
|||||||
io::{self, Error},
|
io::{self, Error},
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
process::{Child, Command, ExitStatus},
|
process::{Child, Command, ExitStatus},
|
||||||
|
str::FromStr,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
thread::spawn,
|
thread::spawn,
|
||||||
};
|
};
|
||||||
@@ -74,24 +75,6 @@ impl ProcessManager<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_command(
|
|
||||||
&self,
|
|
||||||
install_dir: &String,
|
|
||||||
command: Vec<String>,
|
|
||||||
) -> (PathBuf, Vec<String>) {
|
|
||||||
let root = &command[0];
|
|
||||||
|
|
||||||
let install_dir = Path::new(install_dir);
|
|
||||||
let absolute_exe = install_dir.join(root);
|
|
||||||
|
|
||||||
/*
|
|
||||||
let args = command_components[1..]
|
|
||||||
.iter()
|
|
||||||
.map(|v| v.to_string())
|
|
||||||
.collect();
|
|
||||||
*/
|
|
||||||
(absolute_exe, Vec::new())
|
|
||||||
}
|
|
||||||
pub fn kill_game(&mut self, game_id: String) -> Result<(), io::Error> {
|
pub fn kill_game(&mut self, game_id: String) -> Result<(), io::Error> {
|
||||||
match self.processes.get(&game_id) {
|
match self.processes.get(&game_id) {
|
||||||
Some(child) => {
|
Some(child) => {
|
||||||
@@ -218,37 +201,6 @@ impl ProcessManager<'_> {
|
|||||||
.get(version_name)
|
.get(version_name)
|
||||||
.ok_or(ProcessError::InvalidVersion)?;
|
.ok_or(ProcessError::InvalidVersion)?;
|
||||||
|
|
||||||
let mut command: Vec<String> = Vec::new();
|
|
||||||
|
|
||||||
match game_status {
|
|
||||||
GameDownloadStatus::Installed {
|
|
||||||
version_name: _,
|
|
||||||
install_dir: _,
|
|
||||||
} => {
|
|
||||||
command.extend([game_version.launch_command.clone()]);
|
|
||||||
command.extend(game_version.launch_args.clone());
|
|
||||||
}
|
|
||||||
GameDownloadStatus::SetupRequired {
|
|
||||||
version_name: _,
|
|
||||||
install_dir: _,
|
|
||||||
} => {
|
|
||||||
command.extend([game_version.setup_command.clone()]);
|
|
||||||
command.extend(game_version.setup_args.clone());
|
|
||||||
}
|
|
||||||
_ => panic!("unreachable code"),
|
|
||||||
};
|
|
||||||
info!("Command: {:?}", &command);
|
|
||||||
|
|
||||||
let (command, args) = self.process_command(install_dir, command);
|
|
||||||
|
|
||||||
let target_current_dir = command.parent().unwrap().to_str().unwrap();
|
|
||||||
|
|
||||||
info!(
|
|
||||||
"launching process {} in {}",
|
|
||||||
command.to_str().unwrap(),
|
|
||||||
target_current_dir
|
|
||||||
);
|
|
||||||
|
|
||||||
let current_time = chrono::offset::Local::now();
|
let current_time = chrono::offset::Local::now();
|
||||||
let log_file = OpenOptions::new()
|
let log_file = OpenOptions::new()
|
||||||
.write(true)
|
.write(true)
|
||||||
@@ -284,19 +236,50 @@ impl ProcessManager<'_> {
|
|||||||
.get(&(current_platform, target_platform))
|
.get(&(current_platform, target_platform))
|
||||||
.ok_or(ProcessError::InvalidPlatform)?;
|
.ok_or(ProcessError::InvalidPlatform)?;
|
||||||
|
|
||||||
let launch_process = game_launcher
|
let (launch, args) = match game_status {
|
||||||
.launch_process(
|
GameDownloadStatus::Installed {
|
||||||
&meta,
|
version_name: _,
|
||||||
command.to_string_lossy().to_string(),
|
install_dir: _,
|
||||||
game_version,
|
} => (&game_version.launch_command, &game_version.launch_args),
|
||||||
target_current_dir,
|
GameDownloadStatus::SetupRequired {
|
||||||
log_file,
|
version_name: _,
|
||||||
error_file,
|
install_dir: _,
|
||||||
)
|
} => (&game_version.setup_command, &game_version.setup_args),
|
||||||
.map_err(ProcessError::IOError)?;
|
GameDownloadStatus::Remote {} => unreachable!("nuh uh"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let launch = PathBuf::from_str(&install_dir).unwrap().join(launch);
|
||||||
|
let launch = launch.to_str().unwrap();
|
||||||
|
|
||||||
|
let launch_string = game_launcher.create_launch_process(
|
||||||
|
&meta,
|
||||||
|
launch.to_string(),
|
||||||
|
args.to_vec(),
|
||||||
|
game_version,
|
||||||
|
install_dir,
|
||||||
|
);
|
||||||
|
|
||||||
|
info!("launching process {} in {}", launch_string, install_dir);
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
let mut command = Command::new("cmd");
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
command.args(["/C", &launch_string]);
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
let mut command: Command = Command::new("sh");
|
||||||
|
#[cfg(unix)]
|
||||||
|
command.arg("-c").arg(launch_string);
|
||||||
|
|
||||||
|
command
|
||||||
|
.stderr(error_file)
|
||||||
|
.stdout(log_file)
|
||||||
|
.current_dir(install_dir);
|
||||||
|
|
||||||
|
let child = command.spawn().map_err(ProcessError::IOError)?;
|
||||||
|
|
||||||
let launch_process_handle =
|
let launch_process_handle =
|
||||||
Arc::new(SharedChild::new(launch_process).map_err(ProcessError::IOError)?);
|
Arc::new(SharedChild::new(child).map_err(ProcessError::IOError)?);
|
||||||
|
|
||||||
db_lock
|
db_lock
|
||||||
.applications
|
.applications
|
||||||
@@ -341,49 +324,41 @@ pub enum Platform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait ProcessHandler: Send + 'static {
|
pub trait ProcessHandler: Send + 'static {
|
||||||
fn launch_process(
|
fn create_launch_process(
|
||||||
&self,
|
&self,
|
||||||
meta: &DownloadableMetadata,
|
meta: &DownloadableMetadata,
|
||||||
launch_command: String,
|
launch_command: String,
|
||||||
|
args: Vec<String>,
|
||||||
game_version: &GameVersion,
|
game_version: &GameVersion,
|
||||||
current_dir: &str,
|
current_dir: &str,
|
||||||
log_file: File,
|
) -> String;
|
||||||
error_file: File,
|
|
||||||
) -> Result<Child, Error>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NativeGameLauncher;
|
struct NativeGameLauncher;
|
||||||
impl ProcessHandler for NativeGameLauncher {
|
impl ProcessHandler for NativeGameLauncher {
|
||||||
fn launch_process(
|
fn create_launch_process(
|
||||||
&self,
|
&self,
|
||||||
_meta: &DownloadableMetadata,
|
_meta: &DownloadableMetadata,
|
||||||
launch_command: String,
|
launch_command: String,
|
||||||
|
args: Vec<String>,
|
||||||
game_version: &GameVersion,
|
game_version: &GameVersion,
|
||||||
current_dir: &str,
|
current_dir: &str,
|
||||||
log_file: File,
|
) -> String {
|
||||||
error_file: File,
|
format!("\"{}\" {}", launch_command, args.join(" "))
|
||||||
) -> Result<Child, Error> {
|
|
||||||
Command::new(PathBuf::from(launch_command))
|
|
||||||
.current_dir(current_dir)
|
|
||||||
.stdout(log_file)
|
|
||||||
.stderr(error_file)
|
|
||||||
.args(game_version.launch_args.clone())
|
|
||||||
.spawn()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const UMU_LAUNCHER_EXECUTABLE: &str = "umu-run";
|
const UMU_LAUNCHER_EXECUTABLE: &str = "umu-run";
|
||||||
struct UMULauncher;
|
struct UMULauncher;
|
||||||
impl ProcessHandler for UMULauncher {
|
impl ProcessHandler for UMULauncher {
|
||||||
fn launch_process(
|
fn create_launch_process(
|
||||||
&self,
|
&self,
|
||||||
_meta: &DownloadableMetadata,
|
_meta: &DownloadableMetadata,
|
||||||
launch_command: String,
|
launch_command: String,
|
||||||
|
args: Vec<String>,
|
||||||
game_version: &GameVersion,
|
game_version: &GameVersion,
|
||||||
_current_dir: &str,
|
_current_dir: &str,
|
||||||
_log_file: File,
|
) -> String {
|
||||||
_error_file: File,
|
|
||||||
) -> Result<Child, Error> {
|
|
||||||
debug!("Game override: \"{:?}\"", &game_version.umu_id_override);
|
debug!("Game override: \"{:?}\"", &game_version.umu_id_override);
|
||||||
let game_id = match &game_version.umu_id_override {
|
let game_id = match &game_version.umu_id_override {
|
||||||
Some(game_override) => game_override
|
Some(game_override) => game_override
|
||||||
@@ -392,11 +367,11 @@ impl ProcessHandler for UMULauncher {
|
|||||||
.unwrap_or(game_override.clone()),
|
.unwrap_or(game_override.clone()),
|
||||||
None => game_version.game_id.clone(),
|
None => game_version.game_id.clone(),
|
||||||
};
|
};
|
||||||
info!("Game ID: {}", game_id);
|
format!(
|
||||||
UmuCommandBuilder::new(UMU_LAUNCHER_EXECUTABLE, launch_command)
|
"GAMEID={game_id} {umu} \"{launch}\" {args}",
|
||||||
.game_id(game_id)
|
umu = UMU_LAUNCHER_EXECUTABLE,
|
||||||
.launch_args(game_version.launch_args.clone())
|
launch = launch_command,
|
||||||
.build()
|
args = args.join(" ")
|
||||||
.spawn()
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user