aboutsummaryrefslogtreecommitdiff
path: root/server/src/state.rs
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/state.rs')
-rw-r--r--server/src/state.rs83
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,