feat: write game output to the game.log file in the launcher's folder

This commit is contained in:
Nikita Podvirnyi 2024-07-19 12:59:15 +02:00
parent 07531ab509
commit cfdf942e09
No known key found for this signature in database
GPG key ID: 859D416E5142AFF3
6 changed files with 319 additions and 62 deletions

View file

@ -1,3 +1,4 @@
use std::io::{Read, Write};
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
use std::path::PathBuf; use std::path::PathBuf;
@ -302,9 +303,51 @@ pub fn run() -> anyhow::Result<()> {
// We use real current dir here because sandboxed one // We use real current dir here because sandboxed one
// obviously doesn't exist // obviously doesn't exist
command.current_dir(config.game.path.for_edition(config.launcher.edition)) let mut child = command.current_dir(config.game.path.for_edition(config.launcher.edition))
.spawn()?.wait_with_output()?; .stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()?;
// Create new game.log file to log all the game output
let mut game_output = std::fs::File::create(consts::launcher_dir()?.join("game.log"))?;
// Log process output while it's running
while child.try_wait()?.is_none() {
std::thread::sleep(std::time::Duration::from_secs(3));
// Redirect stdout to the game.log file
if let Some(stdout) = &mut child.stdout {
let mut buf = Vec::new();
stdout.read_to_end(&mut buf)?;
for line in buf.split(|c| c == &b'\n') {
game_output.write_all(b" [stdout] ")?;
game_output.write_all(line)?;
game_output.write_all(b"\n")?;
}
}
// Redirect stdout to the game.log file
if let Some(stderr) = &mut child.stderr {
let mut buf = Vec::new();
stderr.read_to_end(&mut buf)?;
for line in buf.split(|c| c == &b'\n') {
game_output.write_all(b"[!] [stderr] ")?;
game_output.write_all(line)?;
game_output.write_all(b"\n")?;
}
}
#[cfg(feature = "discord-rpc")]
if let Some(rpc) = &rpc {
rpc.update(RpcUpdates::Update)?;
}
}
// Workaround for fast process closing (is it still a thing?)
loop { loop {
std::thread::sleep(std::time::Duration::from_secs(3)); std::thread::sleep(std::time::Duration::from_secs(3));

View file

@ -1,3 +1,4 @@
use std::io::{Read, Write};
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
use std::path::PathBuf; use std::path::PathBuf;
@ -231,20 +232,7 @@ pub fn run() -> anyhow::Result<()> {
Sessions::apply(current, config.get_wine_prefix_path())?; Sessions::apply(current, config.get_wine_prefix_path())?;
} }
// Run command // Start Discord RPC just before the game
let variables = command
.get_envs()
.map(|(key, value)| format!("{}=\"{}\"", key.to_string_lossy(), value.unwrap_or_default().to_string_lossy()))
.fold(String::new(), |acc, env| acc + " " + &env);
tracing::info!("Running the game with command: {variables} bash -c \"{bash_command}\"");
// We use real current dir here because sandboxed one
// obviously doesn't exist
command.current_dir(game_path)
.spawn()?.wait_with_output()?;
#[cfg(feature = "discord-rpc")] #[cfg(feature = "discord-rpc")]
let rpc = if config.launcher.discord_rpc.enabled { let rpc = if config.launcher.discord_rpc.enabled {
Some(DiscordRpc::new(config.launcher.discord_rpc.clone().into())) Some(DiscordRpc::new(config.launcher.discord_rpc.clone().into()))
@ -257,6 +245,62 @@ pub fn run() -> anyhow::Result<()> {
rpc.update(RpcUpdates::Connect)?; rpc.update(RpcUpdates::Connect)?;
} }
// Run command
let variables = command
.get_envs()
.map(|(key, value)| format!("{}=\"{}\"", key.to_string_lossy(), value.unwrap_or_default().to_string_lossy()))
.fold(String::new(), |acc, env| acc + " " + &env);
tracing::info!("Running the game with command: {variables} bash -c \"{bash_command}\"");
// We use real current dir here because sandboxed one
// obviously doesn't exist
let mut child = command.current_dir(game_path)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()?;
// Create new game.log file to log all the game output
let mut game_output = std::fs::File::create(consts::launcher_dir()?.join("game.log"))?;
// Log process output while it's running
while child.try_wait()?.is_none() {
std::thread::sleep(std::time::Duration::from_secs(3));
// Redirect stdout to the game.log file
if let Some(stdout) = &mut child.stdout {
let mut buf = Vec::new();
stdout.read_to_end(&mut buf)?;
for line in buf.split(|c| c == &b'\n') {
game_output.write_all(b" [stdout] ")?;
game_output.write_all(line)?;
game_output.write_all(b"\n")?;
}
}
// Redirect stdout to the game.log file
if let Some(stderr) = &mut child.stderr {
let mut buf = Vec::new();
stderr.read_to_end(&mut buf)?;
for line in buf.split(|c| c == &b'\n') {
game_output.write_all(b"[!] [stderr] ")?;
game_output.write_all(line)?;
game_output.write_all(b"\n")?;
}
}
#[cfg(feature = "discord-rpc")]
if let Some(rpc) = &rpc {
rpc.update(RpcUpdates::Update)?;
}
}
// Workaround for fast process closing (is it still a thing?)
loop { loop {
std::thread::sleep(std::time::Duration::from_secs(3)); std::thread::sleep(std::time::Duration::from_secs(3));

View file

@ -222,20 +222,7 @@ pub fn run() -> anyhow::Result<()> {
Sessions::apply(current, config.get_wine_prefix_path())?; Sessions::apply(current, config.get_wine_prefix_path())?;
} }
// Run command // Start Discord RPC just before the game
let variables = command
.get_envs()
.map(|(key, value)| format!("{}=\"{}\"", key.to_string_lossy(), value.unwrap_or_default().to_string_lossy()))
.fold(String::new(), |acc, env| acc + " " + &env);
tracing::info!("Running the game with command: {variables} bash -c \"{bash_command}\"");
// We use real current dir here because sandboxed one
// obviously doesn't exist
command.current_dir(&config.game.path)
.spawn()?.wait_with_output()?;
#[cfg(feature = "discord-rpc")] #[cfg(feature = "discord-rpc")]
let rpc = if config.launcher.discord_rpc.enabled { let rpc = if config.launcher.discord_rpc.enabled {
Some(DiscordRpc::new(config.launcher.discord_rpc.clone().into())) Some(DiscordRpc::new(config.launcher.discord_rpc.clone().into()))
@ -248,6 +235,62 @@ pub fn run() -> anyhow::Result<()> {
rpc.update(RpcUpdates::Connect)?; rpc.update(RpcUpdates::Connect)?;
} }
// Run command
let variables = command
.get_envs()
.map(|(key, value)| format!("{}=\"{}\"", key.to_string_lossy(), value.unwrap_or_default().to_string_lossy()))
.fold(String::new(), |acc, env| acc + " " + &env);
tracing::info!("Running the game with command: {variables} bash -c \"{bash_command}\"");
// We use real current dir here because sandboxed one
// obviously doesn't exist
let mut child = command.current_dir(config.game.path)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()?;
// Create new game.log file to log all the game output
let mut game_output = std::fs::File::create(consts::launcher_dir()?.join("game.log"))?;
// Log process output while it's running
while child.try_wait()?.is_none() {
std::thread::sleep(std::time::Duration::from_secs(3));
// Redirect stdout to the game.log file
if let Some(stdout) = &mut child.stdout {
let mut buf = Vec::new();
stdout.read_to_end(&mut buf)?;
for line in buf.split(|c| c == &b'\n') {
game_output.write_all(b" [stdout] ")?;
game_output.write_all(line)?;
game_output.write_all(b"\n")?;
}
}
// Redirect stdout to the game.log file
if let Some(stderr) = &mut child.stderr {
let mut buf = Vec::new();
stderr.read_to_end(&mut buf)?;
for line in buf.split(|c| c == &b'\n') {
game_output.write_all(b"[!] [stderr] ")?;
game_output.write_all(line)?;
game_output.write_all(b"\n")?;
}
}
#[cfg(feature = "discord-rpc")]
if let Some(rpc) = &rpc {
rpc.update(RpcUpdates::Update)?;
}
}
// Workaround for fast process closing (is it still a thing?)
loop { loop {
std::thread::sleep(std::time::Duration::from_secs(3)); std::thread::sleep(std::time::Duration::from_secs(3));

View file

@ -233,20 +233,7 @@ pub fn run() -> anyhow::Result<()> {
Sessions::apply(current, config.get_wine_prefix_path())?; Sessions::apply(current, config.get_wine_prefix_path())?;
} }
// Run command // Start Discord RPC just before the game
let variables = command
.get_envs()
.map(|(key, value)| format!("{}=\"{}\"", key.to_string_lossy(), value.unwrap_or_default().to_string_lossy()))
.fold(String::new(), |acc, env| acc + " " + &env);
tracing::info!("Running the game with command: {variables} bash -c \"{bash_command}\"");
// We use real current dir here because sandboxed one
// obviously doesn't exist
command.current_dir(game_path)
.spawn()?.wait_with_output()?;
#[cfg(feature = "discord-rpc")] #[cfg(feature = "discord-rpc")]
let rpc = if config.launcher.discord_rpc.enabled { let rpc = if config.launcher.discord_rpc.enabled {
Some(DiscordRpc::new(config.launcher.discord_rpc.clone().into())) Some(DiscordRpc::new(config.launcher.discord_rpc.clone().into()))
@ -259,6 +246,62 @@ pub fn run() -> anyhow::Result<()> {
rpc.update(RpcUpdates::Connect)?; rpc.update(RpcUpdates::Connect)?;
} }
// Run command
let variables = command
.get_envs()
.map(|(key, value)| format!("{}=\"{}\"", key.to_string_lossy(), value.unwrap_or_default().to_string_lossy()))
.fold(String::new(), |acc, env| acc + " " + &env);
tracing::info!("Running the game with command: {variables} bash -c \"{bash_command}\"");
// We use real current dir here because sandboxed one
// obviously doesn't exist
let mut child = command.current_dir(config.game.path.for_edition(config.launcher.edition))
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()?;
// Create new game.log file to log all the game output
let mut game_output = std::fs::File::create(consts::launcher_dir()?.join("game.log"))?;
// Log process output while it's running
while child.try_wait()?.is_none() {
std::thread::sleep(std::time::Duration::from_secs(3));
// Redirect stdout to the game.log file
if let Some(stdout) = &mut child.stdout {
let mut buf = Vec::new();
stdout.read_to_end(&mut buf)?;
for line in buf.split(|c| c == &b'\n') {
game_output.write_all(b" [stdout] ")?;
game_output.write_all(line)?;
game_output.write_all(b"\n")?;
}
}
// Redirect stdout to the game.log file
if let Some(stderr) = &mut child.stderr {
let mut buf = Vec::new();
stderr.read_to_end(&mut buf)?;
for line in buf.split(|c| c == &b'\n') {
game_output.write_all(b"[!] [stderr] ")?;
game_output.write_all(line)?;
game_output.write_all(b"\n")?;
}
}
#[cfg(feature = "discord-rpc")]
if let Some(rpc) = &rpc {
rpc.update(RpcUpdates::Update)?;
}
}
// Workaround for fast process closing (is it still a thing?)
loop { loop {
std::thread::sleep(std::time::Duration::from_secs(3)); std::thread::sleep(std::time::Duration::from_secs(3));

View file

@ -214,20 +214,6 @@ pub fn run() -> anyhow::Result<()> {
command.envs(&config.game.environment); command.envs(&config.game.environment);
// Run command
let variables = command
.get_envs()
.map(|(key, value)| format!("{}=\"{}\"", key.to_string_lossy(), value.unwrap_or_default().to_string_lossy()))
.fold(String::new(), |acc, env| acc + " " + &env);
tracing::info!("Running the game with command: {variables} bash -c \"{bash_command}\"");
// We use real current dir here because sandboxed one
// obviously doesn't exist
command.current_dir(&config.game.path.for_edition(config.launcher.edition))
.spawn()?.wait_with_output()?;
#[cfg(feature = "discord-rpc")] #[cfg(feature = "discord-rpc")]
let rpc = if config.launcher.discord_rpc.enabled { let rpc = if config.launcher.discord_rpc.enabled {
Some(DiscordRpc::new(config.launcher.discord_rpc.clone().into())) Some(DiscordRpc::new(config.launcher.discord_rpc.clone().into()))
@ -240,6 +226,62 @@ pub fn run() -> anyhow::Result<()> {
rpc.update(RpcUpdates::Connect)?; rpc.update(RpcUpdates::Connect)?;
} }
// Run command
let variables = command
.get_envs()
.map(|(key, value)| format!("{}=\"{}\"", key.to_string_lossy(), value.unwrap_or_default().to_string_lossy()))
.fold(String::new(), |acc, env| acc + " " + &env);
tracing::info!("Running the game with command: {variables} bash -c \"{bash_command}\"");
// We use real current dir here because sandboxed one
// obviously doesn't exist
let mut child = command.current_dir(config.game.path.for_edition(config.launcher.edition))
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()?;
// Create new game.log file to log all the game output
let mut game_output = std::fs::File::create(consts::launcher_dir()?.join("game.log"))?;
// Log process output while it's running
while child.try_wait()?.is_none() {
std::thread::sleep(std::time::Duration::from_secs(3));
// Redirect stdout to the game.log file
if let Some(stdout) = &mut child.stdout {
let mut buf = Vec::new();
stdout.read_to_end(&mut buf)?;
for line in buf.split(|c| c == &b'\n') {
game_output.write_all(b" [stdout] ")?;
game_output.write_all(line)?;
game_output.write_all(b"\n")?;
}
}
// Redirect stdout to the game.log file
if let Some(stderr) = &mut child.stderr {
let mut buf = Vec::new();
stderr.read_to_end(&mut buf)?;
for line in buf.split(|c| c == &b'\n') {
game_output.write_all(b"[!] [stderr] ")?;
game_output.write_all(line)?;
game_output.write_all(b"\n")?;
}
}
#[cfg(feature = "discord-rpc")]
if let Some(rpc) = &rpc {
rpc.update(RpcUpdates::Update)?;
}
}
// Workaround for fast process closing (is it still a thing?)
loop { loop {
std::thread::sleep(std::time::Duration::from_secs(3)); std::thread::sleep(std::time::Duration::from_secs(3));

View file

@ -255,9 +255,51 @@ pub fn run() -> anyhow::Result<()> {
// We use real current dir here because sandboxed one // We use real current dir here because sandboxed one
// obviously doesn't exist // obviously doesn't exist
command.current_dir(config.game.path.for_edition(config.launcher.edition)) let mut child = command.current_dir(config.game.path.for_edition(config.launcher.edition))
.spawn()?.wait_with_output()?; .stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()?;
// Create new game.log file to log all the game output
let mut game_output = std::fs::File::create(consts::launcher_dir()?.join("game.log"))?;
// Log process output while it's running
while child.try_wait()?.is_none() {
std::thread::sleep(std::time::Duration::from_secs(3));
// Redirect stdout to the game.log file
if let Some(stdout) = &mut child.stdout {
let mut buf = Vec::new();
stdout.read_to_end(&mut buf)?;
for line in buf.split(|c| c == &b'\n') {
game_output.write_all(b" [stdout] ")?;
game_output.write_all(line)?;
game_output.write_all(b"\n")?;
}
}
// Redirect stdout to the game.log file
if let Some(stderr) = &mut child.stderr {
let mut buf = Vec::new();
stderr.read_to_end(&mut buf)?;
for line in buf.split(|c| c == &b'\n') {
game_output.write_all(b"[!] [stderr] ")?;
game_output.write_all(line)?;
game_output.write_all(b"\n")?;
}
}
#[cfg(feature = "discord-rpc")]
if let Some(rpc) = &rpc {
rpc.update(RpcUpdates::Update)?;
}
}
// Workaround for fast process closing (is it still a thing?)
loop { loop {
std::thread::sleep(std::time::Duration::from_secs(3)); std::thread::sleep(std::time::Duration::from_secs(3));