diff options
Diffstat (limited to 'server/src/state.rs')
| -rw-r--r-- | server/src/state.rs | 83 |
1 files changed, 56 insertions, 27 deletions
diff --git a/server/src/state.rs b/server/src/state.rs index 001e2bf0..a42c1663 100644 --- a/server/src/state.rs +++ b/server/src/state.rs @@ -23,10 +23,25 @@ use anyhow::Result; use hurrycurry_locale::{TrError, tre, trm}; use hurrycurry_protocol::{Menu, Message, PacketC, PacketS, PlayerID, VERSION}; use log::{debug, info, trace}; -use std::time::{Duration, Instant}; +use std::{ + collections::HashSet, + time::{Duration, Instant}, +}; +use tokio::sync::{broadcast, mpsc}; impl Server { pub fn tick_outer(&mut self, dt: f32) -> anyhow::Result<()> { + let mut idle_kick = Vec::new(); + for (cid, conn) in &mut self.connections { + conn.last_player_input += dt; + if conn.last_player_input > 60. { + idle_kick.push(*cid); + } + } + for cid in idle_kick { + self.disconnect(cid); + } + if !self.paused { let start = Instant::now(); let r = self.tick(dt); @@ -66,13 +81,22 @@ impl Server { } else { debug!("-> {p:?}"); } - self.tx.send(p).unwrap(); + let _ = self.broadcast.send(p); } Ok(()) } - pub async fn connect(&mut self, id: ConnectionID) -> Vec<PacketC> { + pub async fn connect( + &mut self, + id: ConnectionID, + ) -> ( + Vec<PacketC>, + broadcast::Receiver<PacketC>, + mpsc::Receiver<PacketC>, + ) { let mut init = self.game.prime_client(); + let (replies_tx, replies_rx) = mpsc::channel(1024); + let broadcast_rx = self.broadcast.subscribe(); init.insert( 0, PacketC::Version { @@ -81,33 +105,37 @@ impl Server { supports_bincode: true, }, ); - self.connections.insert(id, ConnectionData::default()); + self.connections.insert( + id, + ConnectionData { + idle: false, + ready: false, + players: HashSet::new(), + last_player_input: 0., + replies: replies_tx, + }, + ); self.update_paused(); - init + (init, broadcast_rx, replies_rx) } - pub async fn disconnect(&mut self, conn: ConnectionID) { + pub 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; + let _ = self.packet_in_outer(conn, PacketS::Leave { player }); } + self.connections.remove(&conn); + self.update_paused(); } - self.connections.remove(&conn); - self.update_paused(); } - pub async fn packet_in_outer( + pub fn packet_in_outer( &mut self, conn: ConnectionID, packet: PacketS, ) -> Result<Vec<PacketC>, TrError> { if let Some(p) = get_packet_player(&packet) - && !self - .connections - .entry(conn) - .or_default() - .players - .contains(&p) + && !self.connections.get(&conn).unwrap().players.contains(&p) { return Err(tre!("s.error.packet_sender_invalid")); } @@ -130,41 +158,42 @@ impl Server { } } PacketS::Ready => { - self.connections.entry(conn).or_default().ready = true; + self.connections.get_mut(&conn).unwrap().ready = true; self.update_paused(); } PacketS::Idle { paused } => { - self.connections.entry(conn).or_default().idle = *paused; + self.connections.get_mut(&conn).unwrap().idle = *paused; self.update_paused(); } PacketS::Leave { player } => { self.connections - .entry(conn) - .or_default() + .get_mut(&conn) + .unwrap() .players .remove(player); } PacketS::Join { .. } => { - if self.connections.entry(conn).or_default().players.len() > 8 { + if self.connections.get_mut(&conn).unwrap().players.len() > 8 { return Err(tre!("s.error.conn_too_many_players")); } } + PacketS::Interact { .. } + | PacketS::Communicate { .. } + | PacketS::Movement { boost: true, .. } => { + self.connections.get_mut(&conn).unwrap().last_player_input = 0.; + } _ => (), } self.packet_in(Some(conn), packet, &mut replies)?; for p in &replies { if let PacketC::Joined { id } = p { - self.connections - .entry(conn) - .or_default() - .players - .insert(*id); + self.connections.get_mut(&conn).unwrap().players.insert(*id); } } if self.count_chefs() == 0 && !self.game.lobby { - self.tx + self.broadcast .send(PacketC::ServerMessage { message: trm!("s.state.abort_no_players"), error: false, |