aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-10-30 11:22:38 +0100
committermetamuffin <metamuffin@disroot.org>2025-10-30 11:22:38 +0100
commita85f6200517405918941cc64ba4b734e246bc411 (patch)
tree267f027215e38f5db55181cf3b9706962763cdfa
parent269da6178e51f727a2b80a784e59981a13704df4 (diff)
downloadhurrycurry-a85f6200517405918941cc64ba4b734e246bc411.tar
hurrycurry-a85f6200517405918941cc64ba4b734e246bc411.tar.bz2
hurrycurry-a85f6200517405918941cc64ba4b734e246bc411.tar.zst
Configurable lobby map and inactivity kick timout (close #492)
-rw-r--r--server/src/commands.rs2
-rw-r--r--server/src/main.rs45
-rw-r--r--server/src/server.rs65
-rw-r--r--server/src/state.rs4
4 files changed, 81 insertions, 35 deletions
diff --git a/server/src/commands.rs b/server/src/commands.rs
index a59d93a0..bc4696ae 100644
--- a/server/src/commands.rs
+++ b/server/src/commands.rs
@@ -194,7 +194,7 @@ impl Server {
.ok();
self.load(
self.index
- .generate_with_book("lobby")
+ .generate_with_book(&self.config.lobby)
.map_err(|e| TrError::Plain(e.to_string()))?,
None,
);
diff --git a/server/src/main.rs b/server/src/main.rs
index 727ad4b1..b1086b39 100644
--- a/server/src/main.rs
+++ b/server/src/main.rs
@@ -20,7 +20,10 @@ use clap::Parser;
use futures_util::{SinkExt, StreamExt};
use hurrycurry_locale::trm;
use hurrycurry_protocol::{PacketC, PacketS};
-use hurrycurry_server::{ConnectionID, server::Server};
+use hurrycurry_server::{
+ ConnectionID,
+ server::{Server, ServerConfig},
+};
use log::{LevelFilter, debug, info, trace, warn};
use std::{
env::var, net::SocketAddr, path::PathBuf, process::exit, str::FromStr, sync::Arc,
@@ -45,6 +48,12 @@ pub(crate) struct Args {
/// Set the address on which the server should listen
#[arg(short, long, default_value = "[::]:27032")]
listen: SocketAddr,
+ /// Map name to use as lobby
+ #[arg(long, default_value = "lobby")]
+ lobby: String,
+ /// Inactivity kick timeout in seconds
+ #[arg(long, default_value_t = 60.)]
+ inactivity_kick_timeout: f32,
/// Enables submissions to the public server registry
#[arg(long)]
#[cfg(feature = "register")]
@@ -115,8 +124,13 @@ async fn run(data_path: PathBuf, args: Args) -> anyhow::Result<()> {
let (tx, _) = broadcast::channel::<PacketC>(128 * 1024);
- let mut state = Server::new(data_path, tx)?;
- state.load(state.index.generate_with_book("lobby")?, None);
+ let config = ServerConfig {
+ inactivity_kick_timeout: args.inactivity_kick_timeout,
+ lobby: args.lobby,
+ };
+
+ let mut state = Server::new(data_path, config, tx)?;
+ state.load(state.index.generate_with_book(&state.config.lobby)?, None);
let state = Arc::new(RwLock::new(state));
#[cfg(feature = "register")]
@@ -313,7 +327,10 @@ fn find_data_path() -> Result<PathBuf> {
#[cfg(test)]
mod test {
use hurrycurry_protocol::{Character, PacketS, PlayerClass, PlayerID};
- use hurrycurry_server::{ConnectionID, server::Server};
+ use hurrycurry_server::{
+ ConnectionID,
+ server::{Server, ServerConfig},
+ };
use std::future::Future;
use tokio::sync::broadcast;
@@ -324,29 +341,39 @@ mod test {
.unwrap()
.block_on(body);
}
+ fn server() -> Server {
+ Server::new(
+ "../data".into(),
+ ServerConfig::default(),
+ broadcast::channel(1024).0,
+ )
+ .unwrap()
+ }
#[test]
fn run() {
- harness(async { Server::new("../data".into(), broadcast::channel(1024).0).unwrap() });
+ harness(async {
+ server();
+ });
}
#[test]
fn map_load() {
harness(async {
- let mut s = Server::new("../data".into(), broadcast::channel(1024).0).unwrap();
+ let mut s = server();
s.load(s.index.generate("5star").unwrap(), None);
});
}
#[test]
fn map_load_book() {
harness(async {
- let mut s = Server::new("../data".into(), broadcast::channel(1024).0).unwrap();
+ let mut s = server();
s.load(s.index.generate_with_book("lobby").unwrap(), None);
});
}
#[test]
fn tick() {
harness(async {
- let mut s = Server::new("../data".into(), broadcast::channel(1024).0).unwrap();
+ let mut s = server();
for _ in 0..100 {
s.tick(0.1);
}
@@ -355,7 +382,7 @@ mod test {
#[test]
fn packet_sender_verif() {
harness(async {
- let mut s = Server::new("../data".into(), broadcast::channel(1024).0).unwrap();
+ let mut s = server();
for (conn, p) in [
PacketS::Effect {
diff --git a/server/src/server.rs b/server/src/server.rs
index e3bcd63d..66553640 100644
--- a/server/src/server.rs
+++ b/server/src/server.rs
@@ -59,7 +59,13 @@ pub enum AnnounceState {
Done,
}
+pub struct ServerConfig {
+ pub inactivity_kick_timeout: f32,
+ pub lobby: String,
+}
+
pub struct Server {
+ pub config: ServerConfig,
pub tick_perf: (Duration, usize),
pub broadcast: broadcast::Sender<PacketC>,
pub connections: HashMap<ConnectionID, ConnectionData>,
@@ -79,6 +85,41 @@ pub struct Server {
pub editor_address: Option<String>,
}
+impl Server {
+ pub fn new(
+ data_path: PathBuf,
+ config: ServerConfig,
+ tx: broadcast::Sender<PacketC>,
+ ) -> Result<Self> {
+ Ok(Self {
+ config,
+ game: Game::default(),
+ tick_perf: (Duration::ZERO, 0),
+ index: DataIndex::new(data_path).context("Failed to load data index")?,
+ broadcast: tx,
+ announce_state: AnnounceState::Done,
+ packet_out: VecDeque::new(),
+ connections: HashMap::new(),
+ data: Serverdata::default().into(),
+ entities: Vec::new(),
+ score_changed: false,
+ packet_loopback: VecDeque::new(),
+ last_movement_update: HashMap::default(),
+ scoreboard: ScoreboardStore::load().context("Failed to load scoreboards")?,
+ editor_address: None,
+ paused: false,
+ })
+ }
+}
+impl Default for ServerConfig {
+ fn default() -> Self {
+ Self {
+ inactivity_kick_timeout: 60.,
+ lobby: "lobby".to_string(),
+ }
+ }
+}
+
pub trait GameServerExt {
fn unload(&mut self, packet_out: &mut VecDeque<PacketC>);
fn load(
@@ -313,28 +354,6 @@ impl GameServerExt for Game {
}
impl Server {
- pub fn new(data_path: PathBuf, tx: broadcast::Sender<PacketC>) -> Result<Self> {
- Ok(Self {
- game: Game::default(),
- tick_perf: (Duration::ZERO, 0),
- index: DataIndex::new(data_path).context("Failed to load data index")?,
- broadcast: tx,
- announce_state: AnnounceState::Done,
- packet_out: VecDeque::new(),
- connections: HashMap::new(),
- data: Serverdata::default().into(),
- entities: Vec::new(),
- score_changed: false,
- packet_loopback: VecDeque::new(),
- last_movement_update: HashMap::default(),
- scoreboard: ScoreboardStore::load().context("Failed to load scoreboards")?,
- editor_address: None,
- paused: false,
- })
- }
-}
-
-impl Server {
pub fn load(
&mut self,
(gamedata, serverdata): (Gamedata, Serverdata),
@@ -778,7 +797,7 @@ impl Server {
.collect(),
self.game.score.clone(),
);
- Some(("lobby".to_string(), None))
+ Some((self.config.lobby.to_string(), None))
} else {
None
}
diff --git a/server/src/state.rs b/server/src/state.rs
index a42c1663..fc97a7d1 100644
--- a/server/src/state.rs
+++ b/server/src/state.rs
@@ -34,7 +34,7 @@ impl Server {
let mut idle_kick = Vec::new();
for (cid, conn) in &mut self.connections {
conn.last_player_input += dt;
- if conn.last_player_input > 60. {
+ if conn.last_player_input > self.config.inactivity_kick_timeout {
idle_kick.push(*cid);
}
}
@@ -201,7 +201,7 @@ impl Server {
.ok();
self.load(
self.index
- .generate_with_book("lobby")
+ .generate_with_book(&self.config.lobby)
.map_err(|m| tre!("s.error.map_load", s = format!("{m}")))?,
None,
);