team04_server/messages/
game_state.rs1use player_character::PlayerCharacter;
2
3use crate::{
4 lobby::{
5 game::next_phases,
6 state::{LobbyPhase, LobbyState, clients::PlayerId},
7 },
8 server::state::LobbyId,
9 unit::UnitType,
10};
11
12use super::*;
13
14pub struct GameState<'a> {
15 current_round: u64,
16 current_phase: LobbyPhase,
17 next_phases: Vec<LobbyPhase>,
18 lobby_id: LobbyId,
19 is_paused: bool,
20 players: Vec<Player<'a>>,
21 matches: Vec<[PlayerId; 2]>,
22}
23#[derive(Serialize)]
24#[serde(rename_all = "camelCase")]
25pub struct Player<'a> {
26 #[serde(rename = "playerID")]
27 player_id: PlayerId,
28 name: &'a str,
29 character: PlayerCharacter,
30 is_active: bool,
31 lives: i64,
32 unit_placement: Vec<PlacedUnit>,
33 unit_bank: &'a [UnitType],
34 lightsabers: Lightsabers<'a>,
35}
36
37#[derive(Serialize)]
38struct PlacedUnit {
39 r#type: UnitType,
40 position: [usize; 2],
41}
42
43#[derive(Serialize)]
44#[serde(rename = "SCREAMING_SNAKE_CASE")]
45struct Lightsabers<'a> {
46 red: &'a [f64],
47 green: &'a [f64],
48 blue: &'a [f64],
49}
50
51impl<'a> GameState<'a> {
52 pub fn new_from_lobby_state(lobby_state: &'a LobbyState) -> Self {
54 assert!(lobby_state.game_started());
55 Self {
56 current_round: lobby_state.round,
57 current_phase: lobby_state.phase,
58 next_phases: next_phases(
59 lobby_state.round,
60 lobby_state.configs.game_config.max_rounds,
61 lobby_state.phase,
62 )
63 .take(5)
64 .collect(),
65 lobby_id: lobby_state.id(),
66 is_paused: lobby_state.paused(),
67 players: lobby_state
68 .clients
69 .players
70 .iter_all()
71 .map(|(id, player)| Player {
72 player_id: *id,
73 name: player.name(),
74 character: player.character.unwrap(),
75 is_active: player.con.as_ref().is_some_and(|con| con.is_active()),
76 lives: player.lives,
77 lightsabers: Lightsabers {
78 red: &player.red_lightsabers,
79 green: &player.green_lightsabers,
80 blue: &player.blue_lightsabers,
81 },
82 unit_bank: &player.unit_bank,
83 unit_placement: player
84 .unit_placement
85 .iter()
86 .map(|v| PlacedUnit {
87 r#type: v.unit_type,
88 position: [v.position.x, v.position.y],
89 })
90 .collect(),
91 })
92 .collect(),
93 matches: lobby_state
94 .matchups
95 .iter()
96 .map(|(p1, p2, _)| [*p1, *p2])
97 .collect(),
98 }
99 }
100}
101
102impl MessageTx for GameState<'_> {
103 fn serialize(&self) -> String {
104 #[derive(Serialize)]
105 #[serde(rename_all = "camelCase")]
106 pub struct GameState<'a, 'b> {
107 message_type: &'static str,
108 current_round: u64,
109 current_phase: LobbyPhase,
110 next_phases: &'b [LobbyPhase],
111 #[serde(rename = "lobbyID")]
112 lobby_id: LobbyId,
113 is_paused: bool,
114 players: &'b [Player<'a>],
115 matches: &'b [[PlayerId; 2]],
116 }
117
118 let message = GameState {
119 message_type: "GAMESTATE",
120 current_round: self.current_round,
121 current_phase: self.current_phase,
122 next_phases: &self.next_phases,
123 lobby_id: self.lobby_id,
124 is_paused: self.is_paused,
125 players: &self.players,
126 matches: &self.matches,
127 };
128
129 serialize(&message)
130 }
131}