diff options
| author | salmonik <salmonik@tuta.io> | 2026-08-24 14:48:12 +0200 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-08-24 14:48:12 +0200 |
| commit | 5d6b5049c2a34a3f8abe725d4a871ba84a0dd714 (patch) | |
| tree | 57cb03bf59b3358a96742f455d38c21f4f645396 /src/bin/client/games/manager.rs | |
| parent | stable and working, both platforms (diff) | |
| download | zagan-bet-5d6b5049c2a34a3f8abe725d4a871ba84a0dd714.tar.gz zagan-bet-5d6b5049c2a34a3f8abe725d4a871ba84a0dd714.zip | |
TLS transport and games framework on client and server
Diffstat (limited to 'src/bin/client/games/manager.rs')
| -rw-r--r-- | src/bin/client/games/manager.rs | 127 |
1 files changed, 127 insertions, 0 deletions
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 @@ | |||
| 1 | use crate::games::slots::SlotsGame; | ||
| 2 | use crate::games::traits::{Game, GameError, GamePhase, GameState}; | ||
| 3 | use std::collections::HashMap; | ||
| 4 | use std::io::Write; | ||
| 5 | |||
| 6 | pub struct GameManager { | ||
| 7 | current_session: Option<GameState>, | ||
| 8 | pending_game_type: Option<String>, | ||
| 9 | games: HashMap<String, Box<dyn Game>>, | ||
| 10 | } | ||
| 11 | |||
| 12 | impl GameManager { | ||
| 13 | pub fn new() -> Self { | ||
| 14 | let mut games: HashMap<String, Box<dyn Game>> = HashMap::new(); | ||
| 15 | games.insert("slots".to_string(), Box::new(SlotsGame::new())); | ||
| 16 | |||
| 17 | Self { | ||
| 18 | current_session: None, | ||
| 19 | pending_game_type: None, | ||
| 20 | games, | ||
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 24 | pub fn get_available_games(&self) -> Vec<(&str, &str)> { | ||
| 25 | self.games | ||
| 26 | .iter() | ||
| 27 | .map(|(k, v)| (k.as_str(), v.get_name())) | ||
| 28 | .collect() | ||
| 29 | } | ||
| 30 | |||
| 31 | pub fn enter_game(&mut self, game_type: &str) -> Result<(), GameError> { | ||
| 32 | if self.current_session.is_some() { | ||
| 33 | return Err(GameError::InvalidAction); | ||
| 34 | } | ||
| 35 | |||
| 36 | if !self.games.contains_key(game_type) { | ||
| 37 | return Err(GameError::InvalidAction); | ||
| 38 | } | ||
| 39 | |||
| 40 | self.pending_game_type = Some(game_type.to_string()); | ||
| 41 | |||
| 42 | self.current_session = Some(GameState { | ||
| 43 | game_type: game_type.to_string(), | ||
| 44 | bet_amount: 10, | ||
| 45 | phase: GamePhase::WaitingToStart, | ||
| 46 | data: HashMap::new(), | ||
| 47 | }); | ||
| 48 | |||
| 49 | Ok(()) | ||
| 50 | } | ||
| 51 | |||
| 52 | pub fn start_game( | ||
| 53 | &mut self, | ||
| 54 | stream: &mut crate::connection::TlsStream, | ||
| 55 | ) -> Result<(), GameError> { | ||
| 56 | let game_type = self | ||
| 57 | .pending_game_type | ||
| 58 | .take() | ||
| 59 | .ok_or(GameError::InvalidAction)?; | ||
| 60 | |||
| 61 | let state = self | ||
| 62 | .current_session | ||
| 63 | .as_mut() | ||
| 64 | .ok_or(GameError::InvalidAction)?; | ||
| 65 | |||
| 66 | if state.phase != GamePhase::WaitingToStart { | ||
| 67 | return Err(GameError::InvalidAction); | ||
| 68 | } | ||
| 69 | |||
| 70 | let bet_amount = state.bet_amount; | ||
| 71 | |||
| 72 | let writer = stream; | ||
| 73 | writeln!(writer, "PLAY_START {} {}", game_type, bet_amount) | ||
| 74 | .map_err(|_| GameError::NetworkError)?; | ||
| 75 | |||
| 76 | Ok(()) | ||
| 77 | } | ||
| 78 | |||
| 79 | pub fn get_current_game(&self) -> Option<&dyn Game> { | ||
| 80 | self.current_session | ||
| 81 | .as_ref() | ||
| 82 | .and_then(|session| self.games.get(&session.game_type).map(|game| game.as_ref())) | ||
| 83 | } | ||
| 84 | |||
| 85 | pub fn get_current_state(&self) -> Option<&GameState> { | ||
| 86 | self.current_session.as_ref() | ||
| 87 | } | ||
| 88 | |||
| 89 | pub fn get_current_render_lines(&self) -> Option<usize> { | ||
| 90 | let session = self.current_session.as_ref()?; | ||
| 91 | let game = self.games.get(&session.game_type)?; | ||
| 92 | Some(game.render_lines(session)) | ||
| 93 | } | ||
| 94 | |||
| 95 | pub fn is_in_game(&self) -> bool { | ||
| 96 | self.current_session.is_some() | ||
| 97 | } | ||
| 98 | |||
| 99 | pub fn is_game_started(&self) -> bool { | ||
| 100 | self.current_session | ||
| 101 | .as_ref() | ||
| 102 | .map(|s| s.phase != GamePhase::WaitingToStart) | ||
| 103 | .unwrap_or(false) | ||
| 104 | } | ||
| 105 | |||
| 106 | pub fn end_game(&mut self) { | ||
| 107 | self.current_session = None; | ||
| 108 | self.pending_game_type = None; | ||
| 109 | } | ||
| 110 | |||
| 111 | pub fn adjust_bet(&mut self, delta: i64) -> Result<u64, GameError> { | ||
| 112 | if let Some(ref session) = self.current_session { | ||
| 113 | if session.phase != GamePhase::WaitingToStart { | ||
| 114 | return Err(GameError::InvalidAction); | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | if let Some(ref mut session) = self.current_session { | ||
| 119 | let current_bet = session.bet_amount as i64; | ||
| 120 | let new_bet = (current_bet + delta).max(10) as u64; | ||
| 121 | session.bet_amount = new_bet; | ||
| 122 | Ok(new_bet) | ||
| 123 | } else { | ||
| 124 | Err(GameError::InvalidAction) | ||
| 125 | } | ||
| 126 | } | ||
| 127 | } | ||
