diff --git a/board-network/src/protocol.rs b/board-network/src/protocol.rs index 7ebc34f..ceac38c 100644 --- a/board-network/src/protocol.rs +++ b/board-network/src/protocol.rs @@ -1,5 +1,4 @@ -use crate::types::{Position2dRef, TileRef}; -use board_shared::{position::Position2d, tile::Tile}; +use crate::types::{BoardRef, Position2dRef, TileRef}; use serde::{Deserialize, Serialize}; /// A message sent by the client to the server. @@ -20,9 +19,9 @@ pub enum ClientMessage { /// Try to place a tile from the hand on the board. /// /// The server will validate the move and answer with a TilePlaced if the message is valid. - TileUse(#[serde(with = "Position2dRef")] Position2d, usize), + TileUse(Position2dRef, usize), /// Try to remove a tile from the board to add it to the hand. - TileTake(#[serde(with = "Position2dRef")] Position2d), + TileTake(Position2dRef), /// Get the server to validate the current player moves. Validate, } @@ -34,6 +33,7 @@ pub enum ServerMessage { JoinedRoom { room_name: String, players: Vec<(String, u32, bool)>, + board: BoardRef, active_player: usize, has_started: bool, }, @@ -48,13 +48,10 @@ pub enum ServerMessage { /// Change the current player PlayerTurn(usize), /// Update the current hand of the player - SyncHand(#[serde(with = "TileRef")] Tile), // TODO: Vec + SyncHand(Vec), /// Informs that a tile has been placed - TilePlaced( - #[serde(with = "Position2dRef")] Position2d, - #[serde(with = "TileRef")] Tile, - ), + TilePlaced(Position2dRef, TileRef), /// Informs that a tile has been removed - TileRemoved(#[serde(with = "Position2dRef")] Position2d), + TileRemoved(Position2dRef), TurnRejected(String), } diff --git a/board-network/src/types.rs b/board-network/src/types.rs index f6ecc51..f326d02 100644 --- a/board-network/src/types.rs +++ b/board-network/src/types.rs @@ -1,17 +1,25 @@ -use board_shared::position::Position2d; -use board_shared::tile::{Digit, Operator, Tile}; +use board_shared::{ + board::Board, + position::{Grid2d, Position2d}, + tile::{Digit, Operator, Tile}, +}; use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(remote = "Tile")] +pub struct BoardRef { + pub tiles: Vec>, + pub width: usize, + pub height: usize, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] pub enum TileRef { - Digit(#[serde(with = "DigitRef")] Digit), - Operator(#[serde(with = "OperatorRef")] Operator), + Digit(DigitRef), + Operator(OperatorRef), Equals, } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(remote = "Digit")] pub struct DigitRef { pub value: i8, pub has_left_parenthesis: bool, @@ -19,7 +27,6 @@ pub struct DigitRef { } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(remote = "Operator")] pub enum OperatorRef { Add, Subtract, @@ -28,8 +35,69 @@ pub enum OperatorRef { } #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(remote = "Position2d")] pub struct Position2dRef { pub x: usize, pub y: usize, } + +impl From<&Board> for BoardRef { + fn from(value: &Board) -> Self { + Self { + tiles: value + .iter() + .map(|tile| tile.map(Into::into)) + .collect::>(), + width: value.width(), + height: value.height(), + } + } +} + +impl From for TileRef { + fn from(value: Tile) -> Self { + match value { + Tile::Digit(digit) => TileRef::Digit(digit.into()), + Tile::Operator(operator) => TileRef::Operator(operator.into()), + Tile::Equals => TileRef::Equals, + } + } +} + +impl From for DigitRef { + fn from(value: Digit) -> Self { + Self { + value: value.value, + has_left_parenthesis: value.has_left_parenthesis, + has_right_parenthesis: value.has_right_parenthesis, + } + } +} + +impl From for OperatorRef { + fn from(value: Operator) -> Self { + match value { + Operator::Add => OperatorRef::Add, + Operator::Subtract => OperatorRef::Subtract, + Operator::Multiply => OperatorRef::Multiply, + Operator::Divide => OperatorRef::Divide, + } + } +} + +impl From for Position2dRef { + fn from(value: Position2d) -> Self { + Self { + x: value.x, + y: value.y, + } + } +} + +impl From for Position2d { + fn from(value: Position2dRef) -> Self { + Self { + x: value.x, + y: value.y, + } + } +} diff --git a/board-server/src/room.rs b/board-server/src/room.rs index a97f952..81de110 100644 --- a/board-server/src/room.rs +++ b/board-server/src/room.rs @@ -71,6 +71,7 @@ impl Room { .iter() .map(|p| (p.name.clone(), p.score, p.ws.is_some())) .collect(), + board: (&self.board).into(), active_player: self.active_player, has_started: self.has_started, })?; @@ -103,7 +104,7 @@ impl Room { ClientMessage::TileUse(pos, tile_idx) => { if let Some(p) = self.connections.get(&addr) { if *p == self.active_player { - self.on_tile_use(pos, tile_idx); + self.on_tile_use(pos.into(), tile_idx); } } } @@ -176,7 +177,7 @@ impl Room { fn reset_player_moves(&mut self) { let diff = self.board.difference(&self.validated_board); for pos in diff { - self.broadcast(ServerMessage::TileRemoved(pos)); + self.broadcast(ServerMessage::TileRemoved(pos.into())); } self.board = self.validated_board.clone(); } diff --git a/board-shared/src/board.rs b/board-shared/src/board.rs index ea46527..a71d0d5 100644 --- a/board-shared/src/board.rs +++ b/board-shared/src/board.rs @@ -134,6 +134,20 @@ impl Board { Self::is_aligned(positions, Alignment::Horizontal) || Self::is_aligned(positions, Alignment::Vertical) } + + /// Gets a linear iterator over the tiles, row by row. + /// + /// # Example: + /// ``` + /// use board_shared::board::Board; + /// + /// let board = Board::default(); + /// let placed_tiles = board.iter().filter(Option::is_some).count(); + /// assert_eq!(placed_tiles, 0); + /// ``` + pub fn iter(&self) -> impl Iterator> + '_ { + self.tiles.iter().copied() + } } impl Grid2d for Board {