diff options
Diffstat (limited to 'server/replaytool/src')
| -rw-r--r-- | server/replaytool/src/main.rs | 45 | ||||
| -rw-r--r-- | server/replaytool/src/render.rs | 97 | 
2 files changed, 85 insertions, 57 deletions
diff --git a/server/replaytool/src/main.rs b/server/replaytool/src/main.rs index a9032a61..1e5be601 100644 --- a/server/replaytool/src/main.rs +++ b/server/replaytool/src/main.rs @@ -21,7 +21,11 @@ pub mod record;  pub mod render;  pub mod replay; -use crate::{record::record, render::render, replay::replay}; +use crate::{ +    record::record, +    render::{render, RenderArgs}, +    replay::replay, +};  use clap::Parser;  use hurrycurry_protocol::PacketC;  use log::{info, warn, LevelFilter}; @@ -45,23 +49,7 @@ enum Args {      /// Starts a local server that replays previously recorded sessions      Replay { input: PathBuf },      /// Runs a replay server and the client in movie mode to record that replay -    Render { -        /// Replay file path -        input: PathBuf, -        /// Output video file path passed to godot (must end in either .avi for MJPEG or .png for PNG sequence) -        output: PathBuf, -        #[arg(short = 'r', long, default_value = "30")] -        framerate: usize, -        /// Render without display server; Requires wlheadless-run and mutter -        #[arg(short = 'H', long)] -        headless: bool, -        #[arg(long, default_value = "wayland")] -        video_driver: String, -        #[arg(long, default_value = "vulkan")] -        rendering_driver: String, -        #[arg(long, default_value = "mutter")] -        headless_compositor: String, -    }, +    Render(#[command(flatten)] RenderArgs),  }  #[derive(Serialize, Deserialize)] @@ -118,25 +106,8 @@ async fn main() -> anyhow::Result<()> {                  replay(&ws_listener, &input).await?;              }          } -        Args::Render { -            input, -            output, -            framerate, -            headless, -            rendering_driver, -            headless_compositor, -            video_driver, -        } => { -            render( -                &input, -                &output, -                framerate, -                headless, -                &rendering_driver, -                &video_driver, -                &headless_compositor, -            ) -            .await?; +        Args::Render(a) => { +            render(a).await?;          }      }      Ok(()) diff --git a/server/replaytool/src/render.rs b/server/replaytool/src/render.rs index bb5e8a57..2314de79 100644 --- a/server/replaytool/src/render.rs +++ b/server/replaytool/src/render.rs @@ -17,40 +17,93 @@  */  use crate::replay::replay; -use anyhow::Result; +use anyhow::{anyhow, Result};  use log::info; -use std::path::Path; -use tokio::{net::TcpListener, process::Command}; +use rand::random; +use std::{path::PathBuf, str::FromStr}; +use tokio::{ +    fs::{create_dir_all, remove_dir, remove_file, File}, +    io::AsyncWriteExt, +    net::TcpListener, +    process::Command, +}; -pub async fn render( -    input: &Path, -    output: &Path, +#[derive(clap::Parser)] +pub struct RenderArgs { +    /// Replay file path +    input: PathBuf, +    /// Output video file path passed to godot (must end in either .avi for MJPEG or .png for PNG sequence) +    output: PathBuf, +    #[arg(short = 'r', long, default_value = "30")]      framerate: usize, +    #[arg(short = 'R', long, default_value = "1280x720")] +    resolution: String, +    /// Render without display server; Requires wlheadless-run and mutter +    #[arg(short = 'H', long)]      headless: bool, -    rendering_driver: &str, -    video_driver: &str, -    headless_compositor: &str, -) -> Result<()> { +    #[arg(long, default_value = "wayland")] +    video_driver: String, +    #[arg(long, default_value = "vulkan")] +    rendering_driver: String, +    #[arg(long, default_value = "mutter")] +    headless_compositor: String, +    #[arg(long, default_value = "/usr/share/hurrycurry/client.pck")] +    client_pck: PathBuf, +} + +pub async fn render(a: RenderArgs) -> Result<()> {      let port = 27090;      let ws_listener = TcpListener::bind(("127.0.0.1", port)).await?; +    let cwd = PathBuf::from_str("/tmp") +        .unwrap() +        .join(format!("hurrycurry-render-cfg-{:016x}", random::<u64>())); + +    let config = { +        let (width, height) = a +            .resolution +            .split_once("x") +            .ok_or(anyhow!("resolution malformed"))?; +        format!( +            r#"config_version=5 +[display] +window/size/viewport_width={width} +window/size/viewport_height={height} +"#, +        ) +    }; + +    create_dir_all(&cwd).await?; +    File::create(cwd.join("override.cfg")) +        .await? +        .write_all(config.as_bytes()) +        .await?; + +    #[cfg(unix)] +    tokio::fs::symlink(&a.client_pck, cwd.join("client.pck")).await?; +    #[cfg(not(unix))] +    tokio::fs::copy(&a.client_pck, cwd.join("client.pck")).await?; +      let mut args = Vec::new(); -    if headless { +    if a.headless {          args.push("wlheadless-run"); -        args.extend(["-c", headless_compositor]); +        args.extend(["-c", &a.headless_compositor]);          args.push("--");      } -    if headless && video_driver == "x11" { +    if a.headless && a.video_driver == "x11" {          args.push("xwayland-run");          args.push("--");      } -    args.push("hurrycurry-client"); -    if headless { -        args.extend(["--video-driver", video_driver]); -        args.extend(["--rendering-driver", rendering_driver]); +    args.push("godot"); +    let main_pack = cwd.join("client.pck"); +    let main_pack = main_pack.to_str().unwrap(); +    args.extend(["--main-pack", main_pack]); +    if a.headless { +        args.extend(["--video-driver", &a.video_driver]); +        args.extend(["--rendering-driver", &a.rendering_driver]);      } -    args.extend(["--write-movie", output.to_str().unwrap()]); -    let fps = framerate.to_string(); +    args.extend(["--write-movie", a.output.to_str().unwrap()]); +    let fps = a.framerate.to_string();      args.extend(["--fixed-fps", &fps]);      args.push("--print-fps");      args.push("--"); @@ -61,9 +114,13 @@ pub async fn render(      let mut client = Command::new(args[0]).args(&args[1..]).spawn()?;      info!("listening for websockets on {}", ws_listener.local_addr()?); -    replay(&ws_listener, &input).await?; +    replay(&ws_listener, &a.input).await?;      client.wait().await?.exit_ok()?; +    remove_file(cwd.join("override.cfg")).await?; +    remove_file(cwd.join("client.pck")).await?; +    remove_dir(cwd).await?; +      Ok(())  }  |