diff --git a/src/net/server.rs b/src/net/server.rs index b3bf2d4..3e12687 100644 --- a/src/net/server.rs +++ b/src/net/server.rs @@ -4,7 +4,7 @@ use futures::{channel::mpsc::*, future::try_join, lock::Mutex, prelude::*}; use serde_json::json; use std::sync::Arc; use stream::iter; -use future::abortable; +use future::{AbortHandle, abortable}; /// There is a point at which a client falls far enough behind /// that it's probably not worth trying to catch them up; for now, @@ -38,6 +38,7 @@ pub struct PlayerState { pub struct Server { players: Vec>, + heartbeat_task: Option, } #[derive(Clone)] @@ -50,6 +51,7 @@ impl Server { Handle { server: Arc::new(Mutex::new(Server { players: Vec::new(), + heartbeat_task: None, })), } } @@ -75,6 +77,10 @@ impl Server { greet(&mut sender).await?; self.players[player_id] = Some(PlayerState { sender }); info!("Client#{} connected", player_id); + + // ensure server task is running + self.spinup(); + Ok(player_id) } @@ -85,6 +91,31 @@ impl Server { } else { error!("Tried to disconnect Client#{} but there was no record for them", player_id); } + + // check if no players left + if self.players.iter().all(Option::is_none) { + self.shutdown(); + } + } + + /// Start the heartbeat task, if it's not running + fn spinup(&mut self) { + if let None = self.heartbeat_task { + info!("Starting heartbeat task"); + let (task, handle) = abortable(async { + info!("Heartbeat task started"); + }); + self.heartbeat_task = Some(handle); + tokio::spawn(task); + } + } + + /// Stop any active heartbeat task + fn shutdown(&mut self) { + if let Some(handle) = self.heartbeat_task.take() { + info!("Stopping heartbeat task"); + handle.abort(); + } } }