feat: add server state and signaling readiness

This commit is contained in:
2026-08-16 18:26:37 +02:00
parent 71105d9783
commit 44051b0ed8
4 changed files with 62 additions and 5 deletions

View File

@@ -26,6 +26,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
buffer = String::from("A").repeat(1024 * 1024 * 2); buffer = String::from("A").repeat(1024 * 1024 * 2);
} }
if buffer == "/ready\n" {
buffer.clear();
client.signal_readiness().await;
continue;
}
client.send_text_message(buffer.clone()).await; client.send_text_message(buffer.clone()).await;
buffer.clear(); buffer.clear();
} }

View File

@@ -6,7 +6,7 @@ use tokio::sync::mpsc::{self, Receiver, Sender};
use crate::network::{ use crate::network::{
connection::{Connection, ConnectionType}, connection::{Connection, ConnectionType},
message::{ message::{
ClientMessage::{self, TextMessage}, ClientMessage::{self, SignalReadiness, TextMessage},
Message, ServerMessage, Message, ServerMessage,
}, },
}; };
@@ -80,7 +80,10 @@ impl Client {
let _ = sender.send(msg.unwrap()).await; let _ = sender.send(msg.unwrap()).await;
} }
ServerMessage::AcceptHandshake { player_id } => todo!(), ServerMessage::AcceptHandshake { player_id } => todo!(),
ServerMessage::DeclineHandshake { reason } => todo!(), ServerMessage::DeclineHandshake { reason } => {
error!("Server declined connection: {}", reason);
break;
}
ServerMessage::AvailableCaptures { captures } => todo!(), ServerMessage::AvailableCaptures { captures } => todo!(),
ServerMessage::AvailableMoves { moves } => todo!(), ServerMessage::AvailableMoves { moves } => todo!(),
ServerMessage::BroadcastBoardState { board } => todo!(), ServerMessage::BroadcastBoardState { board } => todo!(),
@@ -96,10 +99,17 @@ impl Client {
} }
pub async fn send_text_message(&mut self, content: String) { pub async fn send_text_message(&mut self, content: String) {
debug!("Seding text message: {}", content);
let msg = Message::new(TextMessage(content)); let msg = Message::new(TextMessage(content));
self.send_message(msg).await; self.send_message(msg).await;
} }
pub async fn signal_readiness(&mut self) {
debug!("Signaling readiness!");
let msg = Message::new(SignalReadiness);
self.send_message(msg).await;
}
async fn send_message(&mut self, msg: Result<Message<ClientMessage>, postcard::Error>) { async fn send_message(&mut self, msg: Result<Message<ClientMessage>, postcard::Error>) {
debug!("Sending message to the server!"); debug!("Sending message to the server!");
let _ = match msg { let _ = match msg {

View File

@@ -50,6 +50,7 @@ pub enum ServerMessage {
#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, Clone)] #[derive(Deserialize, Serialize, Debug, PartialEq, Eq, Clone)]
pub enum ClientMessage { pub enum ClientMessage {
AnswerHandshake { player_name: String }, AnswerHandshake { player_name: String },
SignalReadiness,
RequestCapture { capture_path: CapturePath }, RequestCapture { capture_path: CapturePath },
RequestMove { from: Position, to: Position }, RequestMove { from: Position, to: Position },

View File

@@ -26,6 +26,27 @@ pub struct ServerSettings {
pub allow_spectators: bool, pub allow_spectators: bool,
} }
#[derive(PartialEq)]
enum ServerStage {
Lobby,
Game,
End,
}
struct ServerState {
ready_count: usize,
stage: ServerStage,
}
impl Default for ServerState {
fn default() -> Self {
Self {
ready_count: 0,
stage: ServerStage::Lobby,
}
}
}
pub struct Server { pub struct Server {
listener: Option<TcpListener>, listener: Option<TcpListener>,
connections: HashMap<SocketAddr, Sender<Message<ServerMessage>>>, connections: HashMap<SocketAddr, Sender<Message<ServerMessage>>>,
@@ -37,6 +58,8 @@ pub struct Server {
game_master: Option<GameMaster>, game_master: Option<GameMaster>,
settings: ServerSettings, settings: ServerSettings,
state: ServerState,
} }
impl Server { impl Server {
@@ -65,6 +88,7 @@ impl Server {
welcoming_reciever: None, welcoming_reciever: None,
game_master: None, game_master: None,
settings, settings,
state: ServerState::default(),
} }
} }
@@ -109,9 +133,13 @@ impl Server {
tokio::select! { tokio::select! {
new_client_opt = self.welcoming_reciever.as_mut().expect("Welcoming reciever was not set. Was the server started?").recv() => { new_client_opt = self.welcoming_reciever.as_mut().expect("Welcoming reciever was not set. Was the server started?").recv() => {
if let Some((addr, sender)) = new_client_opt { if let Some((addr, sender)) = new_client_opt {
// TODO! Check size options etc if self.state.stage == ServerStage::Lobby && self.connections.keys().len() < self.settings.max_connections && !self.settings.allow_spectators {
self.connections.insert(addr, sender); self.connections.insert(addr, sender);
self.request_handshake(addr).await; self.request_handshake(addr).await;
} else {
let msg = Message::new(ServerMessage::DeclineHandshake { reason: "There is currently game going and it doesn't allow spectators".to_string() });
self.send_message(addr, msg).await;
}
} else { } else {
warn!("Welcoming reciever closed!"); warn!("Welcoming reciever closed!");
break; break;
@@ -126,12 +154,24 @@ impl Server {
ClientMessage::AnswerHandshake { player_name } => { ClientMessage::AnswerHandshake { player_name } => {
self.process_handshake(addr, player_name); self.process_handshake(addr, player_name);
} }
ClientMessage::SignalReadiness => {
self.state.ready_count += 1;
info!("{} signaled readiness. Currently ready: {}/{}", addr, self.state.ready_count, self.settings.max_connections);
if self.state.ready_count == self.settings.max_connections {
info!("All players are ready! Changing state to ServerStage::Game");
self.state.stage = ServerStage::Game;
}
},
ClientMessage::RequestCapture { capture_path: _ } => { ClientMessage::RequestCapture { capture_path: _ } => {
self.process_capture(); self.process_capture();
} }
ClientMessage::RequestMove { from: _, to: _ } => { ClientMessage::RequestMove { from: _, to: _ } => {
self.process_move(); self.process_move();
} }
ClientMessage::TextMessage (content) => { ClientMessage::TextMessage (content) => {
info!("{} sent us a message: {}", addr, content); info!("{} sent us a message: {}", addr, content);
} }