|
|
|
@ -1,10 +1,12 @@
|
|
|
|
|
use crate::player::Player;
|
|
|
|
|
use board_network::protocol::{ClientMessage, ServerMessage};
|
|
|
|
|
use board_network::types::TileRef;
|
|
|
|
|
use board_shared::board::Board;
|
|
|
|
|
use board_shared::deck::RngDeck;
|
|
|
|
|
use board_shared::expr::is_valid_guess;
|
|
|
|
|
use board_shared::game::Hand;
|
|
|
|
|
use board_shared::position::Position2d;
|
|
|
|
|
use board_shared::tile::Tile;
|
|
|
|
|
use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender};
|
|
|
|
|
use futures::StreamExt;
|
|
|
|
|
use rand::distributions::{Alphanumeric, DistString};
|
|
|
|
@ -108,6 +110,13 @@ impl Room {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ClientMessage::TilePlaceEqual(pos) => {
|
|
|
|
|
if let Some(p) = self.connections.get(&addr) {
|
|
|
|
|
if *p == self.active_player {
|
|
|
|
|
self.on_tile_place(pos.into(), Tile::Equals);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ClientMessage::Validate => {
|
|
|
|
|
if let Some(p) = self.connections.get(&addr) {
|
|
|
|
|
if *p == self.active_player {
|
|
|
|
@ -134,16 +143,31 @@ impl Room {
|
|
|
|
|
.expect("Not enough tiles in deck");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for i in 0..self.players.len() {
|
|
|
|
|
self.sync_hand(i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self.broadcast(ServerMessage::PlayerTurn(self.active_player));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn on_tile_use(&mut self, pos: Position2d, tile_idx: usize) {
|
|
|
|
|
let hand = &mut self.players[self.active_player].hand;
|
|
|
|
|
if let Some(tile) = hand.remove(tile_idx) {
|
|
|
|
|
self.board.set(pos.x, pos.y, tile);
|
|
|
|
|
self.on_tile_place(pos, tile);
|
|
|
|
|
self.sync_hand(self.active_player);
|
|
|
|
|
} else {
|
|
|
|
|
self.send(
|
|
|
|
|
self.active_player,
|
|
|
|
|
ServerMessage::TurnRejected("Invalid tile index".to_string()),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn on_tile_place(&mut self, pos: Position2d, tile: Tile) {
|
|
|
|
|
self.board.set(pos.x, pos.y, tile);
|
|
|
|
|
self.broadcast(ServerMessage::TilePlaced(pos.into(), tile.into()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn on_validate(&mut self) {
|
|
|
|
|
let diff = self.board.difference(&self.validated_board);
|
|
|
|
|
if !Board::has_alignment(&diff) {
|
|
|
|
@ -180,6 +204,7 @@ impl Room {
|
|
|
|
|
self.broadcast(ServerMessage::TileRemoved(pos.into()));
|
|
|
|
|
}
|
|
|
|
|
self.board = self.validated_board.clone();
|
|
|
|
|
self.sync_hand(self.active_player);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn on_client_disconnected(&mut self, addr: SocketAddr) {
|
|
|
|
@ -194,26 +219,39 @@ impl Room {
|
|
|
|
|
if let Some(ws) = &self.players[*c].ws {
|
|
|
|
|
if let Err(e) = ws.unbounded_send(s.clone()) {
|
|
|
|
|
eprintln!(
|
|
|
|
|
"[{}] Failed to send broadcast to {}: {}",
|
|
|
|
|
self.name, self.players[*c].name, e
|
|
|
|
|
"[{}] Failed to send broadcast to {}: {e}",
|
|
|
|
|
self.name, self.players[*c].name
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn send(&self, i: usize, s: ServerMessage) {
|
|
|
|
|
if let Some(p) = self.players[i].ws.as_ref() {
|
|
|
|
|
fn send(&self, player_id: usize, s: ServerMessage) {
|
|
|
|
|
if let Some(p) = self.players[player_id].ws.as_ref() {
|
|
|
|
|
if let Err(e) = p.unbounded_send(s) {
|
|
|
|
|
eprintln!(
|
|
|
|
|
"[{}] Failed to send message to {}: {}",
|
|
|
|
|
self.name, self.players[i].name, e
|
|
|
|
|
"[{}] Failed to send message to {}: {e}",
|
|
|
|
|
self.name, self.players[player_id].name
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
eprintln!("[{}] Tried sending message to inactive player", self.name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn sync_hand(&mut self, player_id: usize) {
|
|
|
|
|
self.send(
|
|
|
|
|
player_id,
|
|
|
|
|
ServerMessage::SyncHand(
|
|
|
|
|
self.players[player_id]
|
|
|
|
|
.hand
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|t| <Tile as Into<TileRef>>::into(*t))
|
|
|
|
|
.collect::<Vec<_>>(),
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type RoomPtr = Arc<Mutex<Room>>;
|
|
|
|
|