From ee7d52f401262c35ce0219dfdaf28d23fdbab1d5 Mon Sep 17 00:00:00 2001 From: Artlef Date: Sat, 23 May 2020 22:36:24 +0200 Subject: [PATCH] Show the username that played received move --- src/bin/client.rs | 22 ++++++++++++----- src/bin/server.rs | 63 +++++++++++++++++++++++++++++++++-------------- src/lib.rs | 7 ++++++ 3 files changed, 67 insertions(+), 25 deletions(-) diff --git a/src/bin/client.rs b/src/bin/client.rs index 3d2aabe..f7f2479 100644 --- a/src/bin/client.rs +++ b/src/bin/client.rs @@ -1,5 +1,5 @@ extern crate ctrlc; -use clichess::{RecvPositionError, UserRole, EXIT_MSG}; +use clichess::{GameInfo, RecvPositionError, UserRole, EXIT_MSG}; use serde_json::json; use shakmaty::fen::Fen; use shakmaty::{Chess, Color, Outcome, Position, Setup}; @@ -15,6 +15,7 @@ struct Client { side: Color, input_buffer: Arc>, server_message_recv: Receiver, + opponent_name: Option, } fn main() { @@ -46,6 +47,7 @@ fn main() { side: Color::White, input_buffer: input_buffer.clone(), server_message_recv, + opponent_name: Option::None, }; match prompt_user_for_role(&client, &mut stream) { @@ -69,6 +71,10 @@ fn main() { } let mut current_position = fetch_initial_chess_position(&client); loop { + client + .opponent_name + .clone() + .map(|name| println!("{} played", &name[1..(name.len() - 1)])); println!( "{}", clichess::board_representation(¤t_position, client.side) @@ -86,7 +92,7 @@ fn main() { } } //update position after playing. - match get_current_position(&client) { + match get_current_position(&mut client) { Ok(position) => current_position = position, Err(_) => { clichess::write_to_stream(&mut stream, String::from(EXIT_MSG)).unwrap(); @@ -150,7 +156,7 @@ fn read_user_input(client: &Client) -> String { let mut user_input = client.input_buffer.lock().unwrap(); user_input.clear(); } - let mut input = String::new(); + let input; loop { thread::sleep(time::Duration::from_millis(10)); { @@ -167,17 +173,21 @@ fn read_user_input(client: &Client) -> String { } //wait for next position from server, then return the current board. -fn get_current_position(client: &Client) -> Result { +fn get_current_position(client: &mut Client) -> Result { let response = fetch_message_from_server(client); + let game_info: GameInfo = serde_json::from_str(&response).unwrap(); + if game_info.opponent_name != "" { + client.opponent_name = Some(game_info.opponent_name); + } if response.is_empty() { Err(RecvPositionError::UserCanceledError) } else { - Ok(parse_position(&response)) + Ok(parse_position(&game_info.game_fen)) } } fn fetch_message_from_server(client: &Client) -> String { - let mut response = String::new(); + let response; loop { thread::sleep(time::Duration::from_millis(10)); { diff --git a/src/bin/server.rs b/src/bin/server.rs index 009139c..48a4f27 100644 --- a/src/bin/server.rs +++ b/src/bin/server.rs @@ -1,5 +1,5 @@ use clichess; -use clichess::{Player, RecvPositionError, UserRole, EXIT_MSG}; +use clichess::{GameInfo, Player, RecvPositionError, UserRole, EXIT_MSG}; use serde_json::Value; use shakmaty::{fen, Chess, Color, Setup}; use std::collections::HashMap; @@ -14,10 +14,11 @@ use std::thread; struct Server { id: usize, chess_position: Arc>, - players: Arc, Arc<(Mutex, Condvar)>)>>>, - others_serv_msg_recv: Receiver, + players: Arc, Arc<(Mutex, Condvar)>)>>>, + others_serv_msg_recv: Receiver, client_message_recv: Receiver, cvar: Arc<(Mutex, Condvar)>, + opponent_name: Option, } fn main() { @@ -36,16 +37,17 @@ fn main() { let client_message_recv = setup_client_message_recv(&stream, condvar_pair.clone()).unwrap(); let (others_serv_msg_sender, others_serv_msg_recv) = channel(); - let server = Server { + let mut server = Server { id: counter, chess_position: chess.clone(), players: players.clone(), others_serv_msg_recv, client_message_recv, cvar: condvar_pair, + opponent_name: Option::None, }; /* connection succeeded */ - thread::spawn(move || handle_player(stream, server, others_serv_msg_sender)); + thread::spawn(move || handle_player(stream, &mut server, others_serv_msg_sender)); counter += 1; } Err(err) => { @@ -56,9 +58,13 @@ fn main() { } } -fn handle_player(mut stream: UnixStream, server: Server, others_serv_msg_sender: Sender) { +fn handle_player( + mut stream: UnixStream, + server: &mut Server, + others_serv_msg_sender: Sender, +) { match initialize_client(&mut stream, &server, others_serv_msg_sender) { - Ok((player, player_turn)) => main_loop(&mut stream, &server, player, player_turn), + Ok((player, player_turn)) => main_loop(&mut stream, server, player, player_turn), Err(e) => println!("User id {} could not be initialized: {}", server.id, e), }; player_disconnected(&server); @@ -67,7 +73,7 @@ fn handle_player(mut stream: UnixStream, server: Server, others_serv_msg_sender: fn initialize_client( stream: &mut UnixStream, server: &Server, - others_serv_msg_sender: Sender, + others_serv_msg_sender: Sender, ) -> Result<(Player, Color), RecvPositionError> { //create player let player = create_player(server, stream, others_serv_msg_sender)?; @@ -86,7 +92,7 @@ fn initialize_client( Ok((player, player_turn)) } -fn main_loop(stream: &mut UnixStream, server: &Server, player: Player, mut player_turn: Color) { +fn main_loop(stream: &mut UnixStream, server: &mut Server, player: Player, mut player_turn: Color) { loop { if clichess::is_player_turn(&player, player_turn) { //let go of the lock while waiting for user input. @@ -110,36 +116,55 @@ fn main_loop(stream: &mut UnixStream, server: &Server, player: Player, mut playe Ok(played_chess) => *chess = played_chess, Err(e) => println!("Error: {}", e), }; - let chessfen = fen::fen(&*chess); + let game_info_to_send = GameInfo { + game_fen: fen::fen(&*chess), + opponent_name: players + .get(&server.id) + .expect("current server is in the server list") + .0 + .username + .clone(), + }; for (id, (_, others_serv_msg_sender, cvar_pair)) in players.iter() { if server.id != *id { - others_serv_msg_sender.send(chessfen.clone()); + others_serv_msg_sender + .send(game_info_to_send.clone()) + .unwrap(); let (lock, cvar) = &**cvar_pair; let mut message_sent = lock.lock().unwrap(); *message_sent = true; cvar.notify_one(); } } - if clichess::write_to_stream(stream, chessfen).is_err() { + if clichess::write_to_stream( + stream, + serde_json::to_string(&GameInfo { + game_fen: fen::fen(&*chess), + opponent_name: server.opponent_name.clone().unwrap_or_default(), + }) + .unwrap(), + ) + .is_err() + { break; } player_turn = chess.turn(); } } else { - let position_as_fen_result = wait_for_opponent_move(server); - if position_as_fen_result.is_err() { + let game_info_result = wait_for_opponent_move(server); + if game_info_result.is_err() { break; } - let position_as_fen = position_as_fen_result.unwrap(); - println!("server id: {}, sending {}", server.id, position_as_fen); - clichess::write_to_stream(stream, position_as_fen.clone()).unwrap(); + let game_info = game_info_result.unwrap(); + clichess::write_to_stream(stream, serde_json::to_string(&game_info).unwrap()).unwrap(); + server.opponent_name = Some(game_info.opponent_name); let chess = server.chess_position.lock().unwrap(); player_turn = chess.turn(); } } } -fn wait_for_opponent_move(server: &Server) -> Result { +fn wait_for_opponent_move(server: &Server) -> Result { println!("server id: {}, waiting for move to send...", server.id); //wait: either we receive next position from other server threads, or we receive //"exit" from the client. @@ -179,7 +204,7 @@ fn wait_for_opponent_move(server: &Server) -> Result fn create_player( server: &Server, stream: &mut UnixStream, - others_serv_msg_sender: Sender, + others_serv_msg_sender: Sender, ) -> Result { println!("Creating player {}...", server.id); //get player name and pubkey diff --git a/src/lib.rs b/src/lib.rs index ce27fc6..555fbff 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ use colored::Colorize; +use serde::{Deserialize, Serialize}; use shakmaty::san::ParseSanError; use shakmaty::san::San; use shakmaty::san::SanError; @@ -20,6 +21,12 @@ pub struct Player { pub public_key: String, } +#[derive(Serialize, Deserialize, Clone)] +pub struct GameInfo { + pub game_fen: String, + pub opponent_name: String, +} + #[derive(PartialEq, Copy, Clone)] pub enum UserRole { White,