aboutsummaryrefslogtreecommitdiff
path: root/server/src/state.rs
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-09-29 22:52:26 +0200
committermetamuffin <metamuffin@disroot.org>2025-09-29 22:53:12 +0200
commit66d60ed9ab61efc176808b17fc26445dbf5be705 (patch)
tree7774a7625948659c037514e0848ddd3c292fcc54 /server/src/state.rs
parentc1e826625f3ca3116d482b27e2f0b230cbd55346 (diff)
downloadhurrycurry-66d60ed9ab61efc176808b17fc26445dbf5be705.tar
hurrycurry-66d60ed9ab61efc176808b17fc26445dbf5be705.tar.bz2
hurrycurry-66d60ed9ab61efc176808b17fc26445dbf5be705.tar.zst
Implement ready packet + Refactor server pausing
Diffstat (limited to 'server/src/state.rs')
-rw-r--r--server/src/state.rs100
1 files changed, 75 insertions, 25 deletions
diff --git a/server/src/state.rs b/server/src/state.rs
index b4a8ce1f..1d2af247 100644
--- a/server/src/state.rs
+++ b/server/src/state.rs
@@ -15,33 +15,20 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-use crate::{message::TrError, server::Server, tre, trm, ConnectionID};
+use crate::{
+ message::TrError,
+ server::{ConnectionData, GameServerExt, Server},
+ tre, trm, ConnectionID,
+};
use anyhow::Result;
-use hurrycurry_protocol::{Message, PacketC, PacketS, PlayerID};
+use hurrycurry_protocol::{Message, PacketC, PacketS, PlayerID, VERSION};
use log::{debug, info, trace};
impl Server {
pub fn tick_outer(&mut self, dt: f32) -> anyhow::Result<()> {
- if self.start_pause_timer > 0. {
- self.start_pause_timer -= dt
- }
- let should_pause = self.start_pause_timer > 0. || self.connections.values().all(|c| c.idle);
+ let should_pause = self.announce_timer > 0.;
if should_pause != self.paused {
- info!("Game paused: {should_pause}");
self.paused = should_pause;
- for p in self.game.players.keys() {
- self.packet_out
- .push_back(PacketC::Pause { state: self.paused });
- self.packet_out.push_back(PacketC::ServerHint {
- position: None,
- message: if self.paused && self.start_pause_timer <= 0. {
- Some(trm!("s.state.paused"))
- } else {
- None
- },
- player: *p,
- });
- }
}
if !self.paused {
let r = self.tick(dt);
@@ -49,7 +36,13 @@ impl Server {
self.scoreboard.save()?;
self.load(self.index.generate_with_book(&name)?, timer);
}
+ } else if self.announce_timer > 0. {
+ self.announce_timer -= dt;
+ if self.announce_timer <= 0. {
+ self.update_paused();
+ }
}
+
while let Some(p) = self.packet_out.pop_front() {
if matches!(p, PacketC::UpdateMap { .. } | PacketC::Movement { .. }) {
trace!("-> {p:?}");
@@ -60,6 +53,32 @@ impl Server {
}
Ok(())
}
+
+ pub async fn connect(&mut self, id: ConnectionID) -> Vec<PacketC> {
+ let mut init = self.game.prime_client();
+ init.insert(
+ 0,
+ PacketC::Version {
+ major: VERSION.0,
+ minor: VERSION.1,
+ supports_bincode: true,
+ },
+ );
+ self.connections.insert(id, ConnectionData::default());
+ self.update_paused();
+ init
+ }
+
+ pub async fn disconnect(&mut self, conn: ConnectionID) {
+ if let Some(cd) = self.connections.get(&conn) {
+ for player in cd.players.clone() {
+ let _ = self.packet_in_outer(conn, PacketS::Leave { player }).await;
+ }
+ }
+ self.connections.remove(&conn);
+ self.update_paused();
+ }
+
pub async fn packet_in_outer(
&mut self,
conn: ConnectionID,
@@ -96,9 +115,11 @@ impl Server {
}
PacketS::Ready => {
self.connections.entry(conn).or_default().ready = true;
+ self.update_paused();
}
PacketS::Idle { paused } => {
self.connections.entry(conn).or_default().idle = *paused;
+ self.update_paused();
}
PacketS::Leave { player } => {
self.connections
@@ -143,13 +164,42 @@ impl Server {
Ok(replies)
}
- pub async fn disconnect(&mut self, conn: ConnectionID) {
- if let Some(cd) = self.connections.get(&conn) {
- for player in cd.players.clone() {
- let _ = self.packet_in_outer(conn, PacketS::Leave { player }).await;
+ pub fn update_paused(&mut self) {
+ let all_idle = self.connections.values().all(|c| c.idle);
+ let not_ready = self.connections.values().filter(|c| !c.ready).count();
+ let announcing = self.announce_timer > 0.;
+
+ let should_pause = all_idle || not_ready > 0 || announcing;
+
+ let reason = if not_ready > 0 {
+ info!("Game paused: {not_ready} player are not ready");
+ Some(trm!(
+ "s.state.paused.any_not_ready",
+ s = not_ready.to_string()
+ ))
+ } else if all_idle {
+ info!("Game paused: All players idle");
+ Some(trm!("s.state.paused.all_idle"))
+ } else if announcing {
+ info!("Game paused: Waiting for announcement");
+ None
+ } else {
+ if self.paused {
+ info!("Game unpaused");
}
+ None
+ };
+ self.paused = should_pause;
+
+ for p in self.game.players.keys() {
+ self.packet_out
+ .push_back(PacketC::Pause { state: self.paused });
+ self.packet_out.push_back(PacketC::ServerHint {
+ position: None,
+ message: reason.clone(),
+ player: *p,
+ });
}
- self.connections.remove(&conn);
}
}