diff options
Diffstat (limited to 'server/src/state.rs')
-rw-r--r-- | server/src/state.rs | 100 |
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); } } |