From 5d6b5049c2a34a3f8abe725d4a871ba84a0dd714 Mon Sep 17 00:00:00 2001 From: salmonik Date: Mon, 24 Aug 2026 14:48:12 +0200 Subject: TLS transport and games framework on client and server --- src/bin/client/games/manager.rs | 127 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 src/bin/client/games/manager.rs (limited to 'src/bin/client/games/manager.rs') diff --git a/src/bin/client/games/manager.rs b/src/bin/client/games/manager.rs new file mode 100644 index 0000000..6959214 --- /dev/null +++ b/src/bin/client/games/manager.rs @@ -0,0 +1,127 @@ +use crate::games::slots::SlotsGame; +use crate::games::traits::{Game, GameError, GamePhase, GameState}; +use std::collections::HashMap; +use std::io::Write; + +pub struct GameManager { + current_session: Option, + pending_game_type: Option, + games: HashMap>, +} + +impl GameManager { + pub fn new() -> Self { + let mut games: HashMap> = HashMap::new(); + games.insert("slots".to_string(), Box::new(SlotsGame::new())); + + Self { + current_session: None, + pending_game_type: None, + games, + } + } + + pub fn get_available_games(&self) -> Vec<(&str, &str)> { + self.games + .iter() + .map(|(k, v)| (k.as_str(), v.get_name())) + .collect() + } + + pub fn enter_game(&mut self, game_type: &str) -> Result<(), GameError> { + if self.current_session.is_some() { + return Err(GameError::InvalidAction); + } + + if !self.games.contains_key(game_type) { + return Err(GameError::InvalidAction); + } + + self.pending_game_type = Some(game_type.to_string()); + + self.current_session = Some(GameState { + game_type: game_type.to_string(), + bet_amount: 10, + phase: GamePhase::WaitingToStart, + data: HashMap::new(), + }); + + Ok(()) + } + + pub fn start_game( + &mut self, + stream: &mut crate::connection::TlsStream, + ) -> Result<(), GameError> { + let game_type = self + .pending_game_type + .take() + .ok_or(GameError::InvalidAction)?; + + let state = self + .current_session + .as_mut() + .ok_or(GameError::InvalidAction)?; + + if state.phase != GamePhase::WaitingToStart { + return Err(GameError::InvalidAction); + } + + let bet_amount = state.bet_amount; + + let writer = stream; + writeln!(writer, "PLAY_START {} {}", game_type, bet_amount) + .map_err(|_| GameError::NetworkError)?; + + Ok(()) + } + + pub fn get_current_game(&self) -> Option<&dyn Game> { + self.current_session + .as_ref() + .and_then(|session| self.games.get(&session.game_type).map(|game| game.as_ref())) + } + + pub fn get_current_state(&self) -> Option<&GameState> { + self.current_session.as_ref() + } + + pub fn get_current_render_lines(&self) -> Option { + let session = self.current_session.as_ref()?; + let game = self.games.get(&session.game_type)?; + Some(game.render_lines(session)) + } + + pub fn is_in_game(&self) -> bool { + self.current_session.is_some() + } + + pub fn is_game_started(&self) -> bool { + self.current_session + .as_ref() + .map(|s| s.phase != GamePhase::WaitingToStart) + .unwrap_or(false) + } + + pub fn end_game(&mut self) { + self.current_session = None; + self.pending_game_type = None; + } + + pub fn adjust_bet(&mut self, delta: i64) -> Result { + if let Some(ref session) = self.current_session { + if session.phase != GamePhase::WaitingToStart { + return Err(GameError::InvalidAction); + } + } + + if let Some(ref mut session) = self.current_session { + let current_bet = session.bet_amount as i64; + let new_bet = (current_bet + delta).max(10) as u64; + session.bet_amount = new_bet; + Ok(new_bet) + } else { + Err(GameError::InvalidAction) + } + } +} -- cgit v1.2.3