mirror of
https://github.com/szymon-jozef/checkers.git
synced 2026-10-27 19:20:44 +01:00
feat: add broadcasting current turn and board view
This commit is contained in:
@@ -3,9 +3,13 @@ use std::{
|
|||||||
io::{self, Write},
|
io::{self, Write},
|
||||||
};
|
};
|
||||||
|
|
||||||
use checkers::network::client::Client;
|
use checkers::network::{
|
||||||
|
client::{Client, ClientData},
|
||||||
|
network_identity::NetworkIdentity,
|
||||||
|
};
|
||||||
use log::{debug, error, info, warn};
|
use log::{debug, error, info, warn};
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
const QUIT_COMMAND: &str = "/quit";
|
const QUIT_COMMAND: &str = "/quit";
|
||||||
const HELP_COMMAND: &str = "/help";
|
const HELP_COMMAND: &str = "/help";
|
||||||
@@ -58,6 +62,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
let (stdin_sender, mut stdin_receiver) = mpsc::channel(1024);
|
let (stdin_sender, mut stdin_receiver) = mpsc::channel(1024);
|
||||||
|
|
||||||
|
let mut indentity: Option<NetworkIdentity> = None;
|
||||||
|
let mut is_my_turn: bool = false;
|
||||||
|
|
||||||
tokio::task::spawn_blocking(move || {
|
tokio::task::spawn_blocking(move || {
|
||||||
let stdin = std::io::stdin();
|
let stdin = std::io::stdin();
|
||||||
|
|
||||||
@@ -87,7 +94,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
tokio::select! {
|
tokio::select! {
|
||||||
msg = client_receiver.recv() => {
|
msg = client_receiver.recv() => {
|
||||||
match msg {
|
match msg {
|
||||||
Some(checkers::network::client::ClientData::GameStart {
|
Some(ClientData::GameStart {
|
||||||
identity,
|
identity,
|
||||||
board_view,
|
board_view,
|
||||||
}) => {
|
}) => {
|
||||||
@@ -95,20 +102,35 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
"Got new identity: {} and board_view. Game is about to start!",
|
"Got new identity: {} and board_view. Game is about to start!",
|
||||||
identity
|
identity
|
||||||
);
|
);
|
||||||
println!("{}", board_view.to_string(identity.id));
|
println!("{}", board_view.to_string(&identity.id));
|
||||||
|
indentity = Some(identity);
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(checkers::network::client::ClientData::AvailableCaptures(capture_paths)) => {
|
Some(ClientData::BoardView(view)) => {
|
||||||
|
info!("New board state:\n{}", view.to_string(&indentity.as_ref().unwrap().id));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(ClientData::CurrentTurn(current_turn)) => {
|
||||||
|
is_my_turn = current_turn == indentity.as_ref().expect("Server sent us new current turn without telling us who we are!").id;
|
||||||
|
if is_my_turn {
|
||||||
|
info!("It's our turn!");
|
||||||
|
} else {
|
||||||
|
info!("It's the turn of our enemy!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(ClientData::AvailableCaptures(capture_paths)) => {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(checkers::network::client::ClientData::AvailableMoves(move_paths)) => todo!(),
|
Some(ClientData::AvailableMoves(move_paths)) => todo!(),
|
||||||
|
|
||||||
Some(checkers::network::client::ClientData::TextMessage(content)) => {
|
Some(ClientData::TextMessage(content)) => {
|
||||||
info!("Got message from the server: {}", content);
|
info!("Got message from the server: {}", content);
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(checkers::network::client::ClientData::GameEnd(game_result)) => {
|
Some(ClientData::GameEnd(game_result)) => {
|
||||||
info!("Game has ended with the result: {:?}", game_result);
|
info!("Game has ended with the result: {:?}", game_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,21 +32,21 @@ impl Index<usize> for BoardView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BoardView {
|
impl BoardView {
|
||||||
pub fn to_string(&self, owner: Uuid) -> String {
|
pub fn to_string(&self, owner: &Uuid) -> String {
|
||||||
(0..self.size)
|
(0..self.size)
|
||||||
.map(move |row| {
|
.map(move |row| {
|
||||||
(0..self.size)
|
(0..self.size)
|
||||||
.map(move |column| match &self[row][column].pawn {
|
.map(move |column| match &self[row][column].pawn {
|
||||||
Some(pawn) => match pawn.state {
|
Some(pawn) => match pawn.state {
|
||||||
super::pawn::PawnState::Man => {
|
super::pawn::PawnState::Man => {
|
||||||
if pawn.owner == owner {
|
if pawn.owner == *owner {
|
||||||
'm'
|
'm'
|
||||||
} else {
|
} else {
|
||||||
'M'
|
'M'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
super::pawn::PawnState::Dame => {
|
super::pawn::PawnState::Dame => {
|
||||||
if pawn.owner == owner {
|
if pawn.owner == *owner {
|
||||||
'd'
|
'd'
|
||||||
} else {
|
} else {
|
||||||
'D'
|
'D'
|
||||||
|
|||||||
@@ -74,6 +74,10 @@ impl GameMaster {
|
|||||||
BoardView::from(self.board.clone())
|
BoardView::from(self.board.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_current_turn(&self) -> Uuid {
|
||||||
|
self.players.get_current_turn().id
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_current_player_captures(&self) -> Vec<CapturePath> {
|
pub fn get_current_player_captures(&self) -> Vec<CapturePath> {
|
||||||
self.board
|
self.board
|
||||||
.get_player_pawns_positions(self.players.get_current_turn())
|
.get_player_pawns_positions(self.players.get_current_turn())
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
|||||||
|
|
||||||
use log::{debug, error, info, warn};
|
use log::{debug, error, info, warn};
|
||||||
use tokio::sync::mpsc::{self, Receiver, Sender};
|
use tokio::sync::mpsc::{self, Receiver, Sender};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
logic::{
|
logic::{
|
||||||
@@ -42,10 +43,15 @@ pub enum ClientData {
|
|||||||
identity: NetworkIdentity,
|
identity: NetworkIdentity,
|
||||||
board_view: BoardView,
|
board_view: BoardView,
|
||||||
},
|
},
|
||||||
|
GameEnd(GameResult),
|
||||||
|
|
||||||
AvailableCaptures(Vec<CapturePath>),
|
AvailableCaptures(Vec<CapturePath>),
|
||||||
AvailableMoves(Vec<MovePath>),
|
AvailableMoves(Vec<MovePath>),
|
||||||
|
|
||||||
|
BoardView(BoardView),
|
||||||
|
CurrentTurn(Uuid),
|
||||||
|
|
||||||
TextMessage(String),
|
TextMessage(String),
|
||||||
GameEnd(GameResult),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
@@ -169,8 +175,12 @@ impl Client {
|
|||||||
|
|
||||||
ServerMessage::AvailableCaptures { captures } => todo!(),
|
ServerMessage::AvailableCaptures { captures } => todo!(),
|
||||||
ServerMessage::AvailableMoves { moves } => todo!(),
|
ServerMessage::AvailableMoves { moves } => todo!(),
|
||||||
ServerMessage::BroadcastBoardState { board } => todo!(),
|
ServerMessage::BroadcastBoardState { board } => {
|
||||||
ServerMessage::BroadcastCurrentTurn { active_player } => todo!(),
|
let _ = update_sender.send(ClientData::BoardView(board)).await;
|
||||||
|
},
|
||||||
|
ServerMessage::BroadcastCurrentTurn { active_player } => {
|
||||||
|
let _ = update_sender.send(ClientData::CurrentTurn(active_player)).await;
|
||||||
|
},
|
||||||
ServerMessage::GameEnd { result } => todo!(),
|
ServerMessage::GameEnd { result } => todo!(),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -51,8 +51,6 @@ pub enum ServerMessage {
|
|||||||
board_view: BoardView,
|
board_view: BoardView,
|
||||||
},
|
},
|
||||||
|
|
||||||
BoardState(BoardView),
|
|
||||||
|
|
||||||
AvailableCaptures {
|
AvailableCaptures {
|
||||||
captures: Vec<CapturePath>,
|
captures: Vec<CapturePath>,
|
||||||
},
|
},
|
||||||
@@ -61,8 +59,9 @@ pub enum ServerMessage {
|
|||||||
},
|
},
|
||||||
|
|
||||||
BroadcastBoardState {
|
BroadcastBoardState {
|
||||||
board: Board,
|
board: BoardView,
|
||||||
},
|
},
|
||||||
|
|
||||||
BroadcastCurrentTurn {
|
BroadcastCurrentTurn {
|
||||||
active_player: Uuid,
|
active_player: Uuid,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
pub mod client;
|
pub mod client;
|
||||||
pub mod connection;
|
pub mod connection;
|
||||||
pub mod message;
|
pub mod message;
|
||||||
mod network_identity;
|
pub mod network_identity;
|
||||||
pub mod server;
|
pub mod server;
|
||||||
|
|||||||
@@ -257,6 +257,7 @@ impl Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.game_master = Some(game_master);
|
self.game_master = Some(game_master);
|
||||||
|
self.on_player_action().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ======= Processing messages :D helper functions ======== */
|
/* ======= Processing messages :D helper functions ======== */
|
||||||
@@ -290,20 +291,22 @@ impl Server {
|
|||||||
identity.identity.name = fixed_name
|
identity.identity.name = fixed_name
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_capture(&mut self, capture_path: CapturePath) {
|
async fn process_capture(&mut self, capture_path: CapturePath) {
|
||||||
if let Some(gm) = self.game_master.as_mut() {
|
if let Some(gm) = self.game_master.as_mut() {
|
||||||
if gm.capture(&capture_path) {
|
if gm.capture(&capture_path) {
|
||||||
debug!("Capture valid!");
|
debug!("Capture valid!");
|
||||||
|
self.on_player_action().await;
|
||||||
} else {
|
} else {
|
||||||
debug!("Invalid capture!");
|
debug!("Invalid capture!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_move(&mut self, from: Position, to: Position) {
|
async fn process_move(&mut self, from: Position, to: Position) {
|
||||||
if let Some(gm) = self.game_master.as_mut() {
|
if let Some(gm) = self.game_master.as_mut() {
|
||||||
if gm.move_pawn(from, to) {
|
if gm.move_pawn(from, to) {
|
||||||
debug!("Move was valid!");
|
debug!("Move was valid!");
|
||||||
|
self.on_player_action().await;
|
||||||
} else {
|
} else {
|
||||||
debug!("Move was invalid!");
|
debug!("Move was invalid!");
|
||||||
}
|
}
|
||||||
@@ -330,6 +333,37 @@ impl Server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* === Sending messages === */
|
||||||
|
|
||||||
|
/// Wrapper around broadcast_current_turn and broadcast_board_view. Should be used after every
|
||||||
|
/// players move
|
||||||
|
async fn on_player_action(&mut self) {
|
||||||
|
self.broadcast_board_view().await;
|
||||||
|
self.broadcast_current_turn().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn broadcast_board_view(&mut self) {
|
||||||
|
if let Some(gm) = &self.game_master {
|
||||||
|
let msg = Message::new(ServerMessage::BroadcastBoardState {
|
||||||
|
board: gm.get_board_view(),
|
||||||
|
});
|
||||||
|
self.broadcast_message(msg).await;
|
||||||
|
} else {
|
||||||
|
error!("Cannot broadcast board view as game manager is not set!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn broadcast_current_turn(&mut self) {
|
||||||
|
if let Some(gm) = &self.game_master {
|
||||||
|
let msg = Message::new(ServerMessage::BroadcastCurrentTurn {
|
||||||
|
active_player: gm.get_current_turn(),
|
||||||
|
});
|
||||||
|
self.broadcast_message(msg).await;
|
||||||
|
} else {
|
||||||
|
error!("Cannot broadcast current turn as game master doesn't exists!!!!!!!!!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* === Helper methods === */
|
/* === Helper methods === */
|
||||||
|
|
||||||
async fn send_message(
|
async fn send_message(
|
||||||
|
|||||||
Reference in New Issue
Block a user