Send the complete board when joining a room
continuous-integration/drone/push Build is passing Details

main
Clément FRÉVILLE 2 years ago
parent 091aa81e70
commit 60e4713f7f

@ -1,5 +1,4 @@
use crate::types::{Position2dRef, TileRef}; use crate::types::{BoardRef, Position2dRef, TileRef};
use board_shared::{position::Position2d, tile::Tile};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
/// A message sent by the client to the server. /// 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. /// 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. /// 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. /// 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. /// Get the server to validate the current player moves.
Validate, Validate,
} }
@ -34,6 +33,7 @@ pub enum ServerMessage {
JoinedRoom { JoinedRoom {
room_name: String, room_name: String,
players: Vec<(String, u32, bool)>, players: Vec<(String, u32, bool)>,
board: BoardRef,
active_player: usize, active_player: usize,
has_started: bool, has_started: bool,
}, },
@ -48,13 +48,10 @@ pub enum ServerMessage {
/// Change the current player /// Change the current player
PlayerTurn(usize), PlayerTurn(usize),
/// Update the current hand of the player /// Update the current hand of the player
SyncHand(#[serde(with = "TileRef")] Tile), // TODO: Vec<Tile> SyncHand(Vec<TileRef>),
/// Informs that a tile has been placed /// Informs that a tile has been placed
TilePlaced( TilePlaced(Position2dRef, TileRef),
#[serde(with = "Position2dRef")] Position2d,
#[serde(with = "TileRef")] Tile,
),
/// Informs that a tile has been removed /// Informs that a tile has been removed
TileRemoved(#[serde(with = "Position2dRef")] Position2d), TileRemoved(Position2dRef),
TurnRejected(String), TurnRejected(String),
} }

@ -1,17 +1,25 @@
use board_shared::position::Position2d; use board_shared::{
use board_shared::tile::{Digit, Operator, Tile}; board::Board,
position::{Grid2d, Position2d},
tile::{Digit, Operator, Tile},
};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(remote = "Tile")] pub struct BoardRef {
pub tiles: Vec<Option<TileRef>>,
pub width: usize,
pub height: usize,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum TileRef { pub enum TileRef {
Digit(#[serde(with = "DigitRef")] Digit), Digit(DigitRef),
Operator(#[serde(with = "OperatorRef")] Operator), Operator(OperatorRef),
Equals, Equals,
} }
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(remote = "Digit")]
pub struct DigitRef { pub struct DigitRef {
pub value: i8, pub value: i8,
pub has_left_parenthesis: bool, pub has_left_parenthesis: bool,
@ -19,7 +27,6 @@ pub struct DigitRef {
} }
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(remote = "Operator")]
pub enum OperatorRef { pub enum OperatorRef {
Add, Add,
Subtract, Subtract,
@ -28,8 +35,69 @@ pub enum OperatorRef {
} }
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(remote = "Position2d")]
pub struct Position2dRef { pub struct Position2dRef {
pub x: usize, pub x: usize,
pub y: 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::<Vec<_>>(),
width: value.width(),
height: value.height(),
}
}
}
impl From<Tile> 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<Digit> 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<Operator> 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<Position2d> for Position2dRef {
fn from(value: Position2d) -> Self {
Self {
x: value.x,
y: value.y,
}
}
}
impl From<Position2dRef> for Position2d {
fn from(value: Position2dRef) -> Self {
Self {
x: value.x,
y: value.y,
}
}
}

@ -71,6 +71,7 @@ impl Room {
.iter() .iter()
.map(|p| (p.name.clone(), p.score, p.ws.is_some())) .map(|p| (p.name.clone(), p.score, p.ws.is_some()))
.collect(), .collect(),
board: (&self.board).into(),
active_player: self.active_player, active_player: self.active_player,
has_started: self.has_started, has_started: self.has_started,
})?; })?;
@ -103,7 +104,7 @@ impl Room {
ClientMessage::TileUse(pos, tile_idx) => { ClientMessage::TileUse(pos, tile_idx) => {
if let Some(p) = self.connections.get(&addr) { if let Some(p) = self.connections.get(&addr) {
if *p == self.active_player { 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) { fn reset_player_moves(&mut self) {
let diff = self.board.difference(&self.validated_board); let diff = self.board.difference(&self.validated_board);
for pos in diff { for pos in diff {
self.broadcast(ServerMessage::TileRemoved(pos)); self.broadcast(ServerMessage::TileRemoved(pos.into()));
} }
self.board = self.validated_board.clone(); self.board = self.validated_board.clone();
} }

@ -134,6 +134,20 @@ impl Board {
Self::is_aligned(positions, Alignment::Horizontal) Self::is_aligned(positions, Alignment::Horizontal)
|| Self::is_aligned(positions, Alignment::Vertical) || 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<Item = Option<Tile>> + '_ {
self.tiles.iter().copied()
}
} }
impl Grid2d for Board { impl Grid2d for Board {

Loading…
Cancel
Save