aboutsummaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-09-11 23:59:43 +0200
committermetamuffin <metamuffin@disroot.org>2025-09-11 23:59:43 +0200
commit732850dbde6788c7585ad0152e2ef6c17da79bfc (patch)
tree1df1d0ff5577e066752e2fbd0b1cc29f1781137f /server
parent2b1d79588241fc9afa3ef9ddc3b20b26b8ce2433 (diff)
downloadhurrycurry-732850dbde6788c7585ad0152e2ef6c17da79bfc.tar
hurrycurry-732850dbde6788c7585ad0152e2ef6c17da79bfc.tar.bz2
hurrycurry-732850dbde6788c7585ad0152e2ef6c17da79bfc.tar.zst
add render subcommand to replaytool
Diffstat (limited to 'server')
-rw-r--r--server/replaytool/src/main.rs25
-rw-r--r--server/replaytool/src/render.rs56
2 files changed, 79 insertions, 2 deletions
diff --git a/server/replaytool/src/main.rs b/server/replaytool/src/main.rs
index 5ff821cc..40496786 100644
--- a/server/replaytool/src/main.rs
+++ b/server/replaytool/src/main.rs
@@ -15,10 +15,13 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+#![feature(exit_status_error)]
pub mod record;
+pub mod render;
pub mod replay;
+use crate::{record::record, render::render, replay::replay};
use clap::Parser;
use hurrycurry_protocol::PacketC;
use log::{info, warn, LevelFilter};
@@ -29,8 +32,6 @@ use std::{
};
use tokio::{net::TcpListener, time::sleep};
-use crate::{record::record, replay::replay};
-
#[derive(Parser)]
enum Args {
/// Connects as a spectator and saves the protocol packets for replay
@@ -43,6 +44,18 @@ 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,
+ },
}
#[derive(Serialize, Deserialize)]
@@ -99,6 +112,14 @@ async fn main() -> anyhow::Result<()> {
replay(&ws_listener, &input).await?;
}
}
+ Args::Render {
+ input,
+ output,
+ framerate,
+ headless,
+ } => {
+ render(&input, &output, framerate, headless).await?;
+ }
}
Ok(())
}
diff --git a/server/replaytool/src/render.rs b/server/replaytool/src/render.rs
new file mode 100644
index 00000000..79eb483b
--- /dev/null
+++ b/server/replaytool/src/render.rs
@@ -0,0 +1,56 @@
+/*
+ Hurry Curry! - a game about cooking
+ Copyright (C) 2025 Hurry Curry! Contributors
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, version 3 of the License only.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+*/
+
+use crate::replay::replay;
+use anyhow::Result;
+use log::info;
+use std::path::Path;
+use tokio::{net::TcpListener, process::Command};
+
+pub async fn render(input: &Path, output: &Path, framerate: usize, headless: bool) -> Result<()> {
+ let port = 27090;
+ let ws_listener = TcpListener::bind(("127.0.0.1", port)).await?;
+
+ let mut args = Vec::new();
+ if headless {
+ args.push("wlheadless-run");
+ args.extend(["-c", "mutter"]);
+ args.push("--");
+ }
+ args.push("hurrycurry-client");
+ if headless {
+ args.extend(["--video-driver", "wayland"]);
+ args.extend(["--rendering-driver", "vulkan"]);
+ }
+ args.extend(["--write-movie", output.to_str().unwrap()]);
+ let fps = framerate.to_string();
+ args.extend(["--fixed-fps", &fps]);
+ args.push("--print-fps");
+ args.push("--");
+ let uri = format!("ws://127.0.0.1:{port}");
+ args.push(&uri);
+
+ 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?;
+
+ client.wait().await?.exit_ok()?;
+
+ Ok(())
+}