use std::collections::HashMap;
use tracing::info;
use crate::{broker::ConnectionListener, BitBrokerMessage, Connection, Error, Result};
pub struct BrokerSetup {
pub players: HashMap<u8, Connection>,
num_players: usize,
pub game: Option<Connection>,
}
impl BrokerSetup {
pub fn new(num_players: usize) -> Self {
Self {
players: HashMap::new(),
num_players,
game: None,
}
}
pub async fn run(mut self, host: &str, port: usize) -> Result<Self> {
let listener = ConnectionListener::new(host, port).await?;
info!("Tcp listener setup");
while self.expecting_connection() {
info!("{}", self.expecting_msg());
info!("Waiting for connection...");
let mut connection = listener.accept().await?;
let message: BitBrokerMessage = connection.read_message().await?;
match message.codes() {
(0x00, 0x01) => self.handle_game_connection(connection)?,
(0x00, 0x02) => self.handle_player_connection(connection)?,
_ => return Err(Error::from(message)),
}
}
info!("All players and game connected");
Ok(self)
}
fn handle_player_connection(&mut self, connection: Connection) -> Result<()> {
info!("Handling new player connection");
if self.expecting_player() {
let player_id = self.players.len() as u8;
self.players.insert(player_id, connection);
Ok(())
} else {
Err(Error::BrokerError("Too many players tried to connect"))
}
}
fn handle_game_connection(&mut self, connection: Connection) -> Result<()> {
info!("Handling new game connection");
if self.expecting_game() {
self.game = Some(connection);
Ok(())
} else {
Err(Error::BrokerError("Multiple games tried to connect"))
}
}
fn expecting_msg(&self) -> String {
let player_part = format!("{} player(s)", self.num_players - self.players.len());
if self.expecting_game() {
format!("Expecting {player_part} and a game")
} else {
format!("Expecting {player_part}")
}
}
fn expecting_game(&self) -> bool {
self.game.is_none()
}
fn expecting_player(&self) -> bool {
self.players.len() < self.num_players
}
fn expecting_connection(&self) -> bool {
self.expecting_game() || self.expecting_player()
}
}