team04_server/lobby/game/
start.rs1use std::time::Duration;
2
3use rand::seq::IndexedRandom;
4
5use crate::{
6 lobby::state::{LobbyState, SharedLobbyState, matchups::Matchups},
7 log,
8 messages::{MessageTx, game_start::GameStart, player_character::PlayerCharacter},
9};
10
11impl SharedLobbyState {
12 pub async fn wait_for_game_start(&self) {
16 let lock = self.lock().await;
17 let mut wait = lock.on_game_start.recv();
18 drop(lock);
19 wait.wait_for(|v| *v).await.ok();
20 }
21
22 pub async fn start_game_after_timeout(&self, extend_timer: bool) {
33 let mut lock = self.lock().await;
34 let mut pfx = log::pfx();
35 pfx.lobby(lock.id());
36
37 if lock.game_start_timer_id != 0 && !extend_timer {
39 log::debug!("timer id {} > 0 and extend_timer = false, not starting a new timer", lock.game_start_timer_id; &pfx);
40 drop(lock);
41 return self.wait_for_game_start().await;
42 }
43
44 let timer_id = (lock.game_start_timer_id + 1).max(1);
45 log::debug!("starting new timer with id {timer_id}"; &pfx);
46 lock.game_start_timer_id = timer_id;
47 let mut wait = lock.on_game_start.recv();
48 let timeout = Duration::from_millis(lock.configs.game_config.timeout_lobby);
49 drop(lock);
50
51 let waiter = wait.wait_for(|v| *v);
52 if tokio::time::timeout(timeout, waiter).await.is_err() {
53 log::debug!("timer ended before the game started, ..."; &pfx);
54 let mut lock = self.lock().await;
56 if timer_id == lock.game_start_timer_id {
57 log::debug!("... starting game now"; &pfx);
58 lock.consider_starting_game().await;
59 } else {
60 drop(lock);
61 log::debug!("... but another timer has taken over"; &pfx);
62 wait.wait_for(|v| *v).await.ok();
65 }
66 }
67 }
68}
69
70impl LobbyState {
71 pub async fn consider_starting_game(&mut self) {
72 if !self.game_started()
73 && self.clients.players.len() >= self.min_players()
74 && self
75 .clients
76 .players
77 .players_all()
78 .all(|player| player.ready)
79 {
80 self.start_game_now().await;
81 }
82 }
83 pub fn could_start_timer_for_game_start(&self) -> bool {
84 !self.game_started() && self.clients.players.len() >= self.min_players()
85 }
86 pub async fn start_game_now(&mut self) {
87 if !self.game_started() {
88 log::info!("starting game now"; log::pfx().lobby(self.id()));
89 self.set_game_started();
90 let available_characters = self.available_characters();
91 for player in self.clients.players.players_all_mut() {
92 player.ready = true;
93 if player.character.is_none() {
94 player.character = Some(
95 available_characters
96 .choose(&mut rand::rng())
97 .copied()
98 .unwrap_or_else(PlayerCharacter::random),
99 );
100 }
101 player.lives = self.configs.game_config.player_lives as i64;
102 player.red_lightsabers.clear();
103 player.green_lightsabers.clear();
104 player.blue_lightsabers.clear();
105 }
106 self.prev_matchups = Matchups::new(self.clients.players.len());
107 self.clients
108 .broadcast_message(&GameStart::new().serialize())
109 .await;
110 }
111 }
112}