Manage when user leave during connection.
This commit is contained in:
parent
175e8fafe6
commit
0a2aba9619
@ -1,4 +1,6 @@
|
||||
extern crate ctrlc;
|
||||
use clichess::RecvPositionError;
|
||||
use serde_json::json;
|
||||
use shakmaty::fen::Fen;
|
||||
use shakmaty::{Chess, Color, Outcome, Position, Setup};
|
||||
use std::io;
|
||||
@ -7,7 +9,6 @@ use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::thread;
|
||||
use std::time;
|
||||
use serde_json::json;
|
||||
|
||||
struct Client {
|
||||
player: clichess::Player,
|
||||
@ -17,12 +18,6 @@ struct Client {
|
||||
server_message: Arc<Mutex<String>>,
|
||||
}
|
||||
|
||||
enum RecvPositionError {
|
||||
UserCanceledError,
|
||||
CommunicationError,
|
||||
ParsePositionError,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let running = setupctrlc();
|
||||
let username = std::env::args().nth(1).expect("no name given");
|
||||
@ -56,8 +51,10 @@ fn main() {
|
||||
server_message: server_message.clone(),
|
||||
};
|
||||
|
||||
let role = prompt_user_for_role(&client, &mut stream);
|
||||
client.player.role = role.clone();
|
||||
match prompt_user_for_role(&client, &mut stream) {
|
||||
Some(role) => client.player.role = role.clone(),
|
||||
None => return,
|
||||
};
|
||||
println!(
|
||||
"Hello, {} !\n\r You're playing with the {} pieces",
|
||||
client.player.username,
|
||||
@ -218,8 +215,8 @@ fn parse_position(string: &str) -> Chess {
|
||||
position
|
||||
}
|
||||
|
||||
fn prompt_user_for_role(client: &Client, stream: &mut UnixStream) -> clichess::UserRole {
|
||||
let mut role: clichess::UserRole;
|
||||
fn prompt_user_for_role(client: &Client, stream: &mut UnixStream) -> Option<clichess::UserRole> {
|
||||
let mut role = None;
|
||||
loop {
|
||||
println!("fetching roles from server...");
|
||||
let available_roles = fetch_available_roles(client);
|
||||
@ -241,14 +238,18 @@ fn prompt_user_for_role(client: &Client, stream: &mut UnixStream) -> clichess::U
|
||||
println!("{}", prompt);
|
||||
//wait for user to give a correct answer.
|
||||
let input = String::from(read_user_input(client).trim());
|
||||
if input.trim() == "exit" {
|
||||
clichess::write_to_stream(stream, String::from("exit")).unwrap();
|
||||
break;
|
||||
}
|
||||
match clichess::parse_to_role(&input) {
|
||||
Ok(r) => role = r,
|
||||
Ok(r) => role = Some(r),
|
||||
Err(e) => {
|
||||
println!("{}", e);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
if !available_roles.contains(&role) {
|
||||
if role.is_some() && !available_roles.contains(&role.expect("role is some")) {
|
||||
println!("Sorry, this side is not available.");
|
||||
continue;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
use clichess;
|
||||
use clichess::Player;
|
||||
use clichess::RecvPositionError;
|
||||
use clichess::UserRole;
|
||||
use serde_json::Value;
|
||||
use shakmaty::{fen, Chess, Color, Setup};
|
||||
@ -49,9 +50,20 @@ fn main() {
|
||||
}
|
||||
|
||||
fn handle_player(mut stream: UnixStream, server: Server) {
|
||||
match initialize_client(&mut stream, &server) {
|
||||
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();
|
||||
}
|
||||
|
||||
fn initialize_client(
|
||||
stream: &mut UnixStream,
|
||||
server: &Server,
|
||||
) -> Result<(Player, Color), RecvPositionError> {
|
||||
//create player
|
||||
let player = create_player(&server, &mut stream);
|
||||
let mut player_turn: Color;
|
||||
let player = create_player(server, stream)?;
|
||||
let player_turn: Color;
|
||||
//send current position to the player
|
||||
println!(
|
||||
"server {}, send current position to the player...",
|
||||
@ -60,15 +72,19 @@ fn handle_player(mut stream: UnixStream, server: Server) {
|
||||
{
|
||||
let chess = server.chess_position.lock().unwrap();
|
||||
player_turn = chess.turn();
|
||||
clichess::write_to_stream(&mut stream, fen::fen(&*chess)).unwrap();
|
||||
clichess::write_to_stream(stream, fen::fen(&*chess)).unwrap();
|
||||
}
|
||||
println!("server {}, current position to the player sent", server.id);
|
||||
Ok((player, player_turn))
|
||||
}
|
||||
|
||||
fn main_loop(stream: &mut UnixStream, server: &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.
|
||||
println!("server {}, waiting for player move..", server.id);
|
||||
let input;
|
||||
match clichess::read_line_from_stream(&stream) {
|
||||
match clichess::read_line_from_stream(stream) {
|
||||
Ok(i) => input = i,
|
||||
Err(e) => {
|
||||
println!("Error while getting user input: {}", e);
|
||||
@ -93,7 +109,7 @@ fn handle_player(mut stream: UnixStream, server: Server) {
|
||||
cvar_buffer.1.notify_one();
|
||||
}
|
||||
}
|
||||
clichess::write_to_stream(&mut stream, chessfen).unwrap();
|
||||
clichess::write_to_stream(stream, chessfen).unwrap();
|
||||
player_turn = chess.turn();
|
||||
}
|
||||
} else {
|
||||
@ -105,7 +121,7 @@ fn handle_player(mut stream: UnixStream, server: Server) {
|
||||
buffer = cvar.wait(buffer).unwrap();
|
||||
}
|
||||
println!("server id: {}, sending {}", server.id, buffer);
|
||||
match clichess::write_to_stream(&mut stream, buffer.clone()) {
|
||||
match clichess::write_to_stream(stream, buffer.clone()) {
|
||||
Ok(()) => buffer.clear(),
|
||||
Err(e) => {
|
||||
println!("{}", e);
|
||||
@ -117,10 +133,9 @@ fn handle_player(mut stream: UnixStream, server: Server) {
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("Player disconnected.")
|
||||
}
|
||||
|
||||
fn create_player(server: &Server, stream: &mut UnixStream) -> Player {
|
||||
fn create_player(server: &Server, stream: &mut UnixStream) -> Result<Player, RecvPositionError> {
|
||||
println!("Creating player {}...", server.id);
|
||||
//get player name and pubkey
|
||||
let username_pubkey_json =
|
||||
@ -130,7 +145,7 @@ fn create_player(server: &Server, stream: &mut UnixStream) -> Player {
|
||||
let public_key = username_pubkey_value["pubkey"].to_string();
|
||||
println!("got username: {}", username);
|
||||
println!("got pubkey: {}", public_key);
|
||||
let role = receive_user_role(server, stream);
|
||||
let role = receive_user_role(server, stream)?;
|
||||
let mut players = server.players.lock().unwrap();
|
||||
let player = Player {
|
||||
role,
|
||||
@ -139,10 +154,13 @@ fn create_player(server: &Server, stream: &mut UnixStream) -> Player {
|
||||
};
|
||||
players.insert(server.id, (player.clone(), server.receiving_buffer.clone()));
|
||||
println!("Created player {}", server.id);
|
||||
player
|
||||
Ok(player)
|
||||
}
|
||||
|
||||
fn receive_user_role(server: &Server, stream: &mut UnixStream) -> UserRole {
|
||||
fn receive_user_role(
|
||||
server: &Server,
|
||||
stream: &mut UnixStream,
|
||||
) -> Result<UserRole, RecvPositionError> {
|
||||
let mut chosen_role: UserRole;
|
||||
loop {
|
||||
//send available roles
|
||||
@ -152,9 +170,16 @@ fn receive_user_role(server: &Server, stream: &mut UnixStream) -> UserRole {
|
||||
//receive chosen role
|
||||
let chosen_role_str =
|
||||
clichess::read_line_from_stream(stream).expect("Player closed connection.");
|
||||
if chosen_role_str == "exit" {
|
||||
return Err(RecvPositionError::UserCanceledError);
|
||||
}
|
||||
println!("Client id {} has chosen {}", server.id, chosen_role_str);
|
||||
chosen_role =
|
||||
clichess::parse_to_role(&chosen_role_str).expect("Client did not send parsable role.");
|
||||
let chosen_role_parse = clichess::parse_to_role(&chosen_role_str);
|
||||
|
||||
if chosen_role_parse.is_err() {
|
||||
return Err(RecvPositionError::ParsePositionError);
|
||||
}
|
||||
chosen_role = chosen_role_parse.unwrap();
|
||||
//check if role is still available after the choice
|
||||
{
|
||||
let mut available_roles_after_choice =
|
||||
@ -183,7 +208,7 @@ fn receive_user_role(server: &Server, stream: &mut UnixStream) -> UserRole {
|
||||
}
|
||||
}
|
||||
}
|
||||
chosen_role
|
||||
Ok(chosen_role)
|
||||
}
|
||||
|
||||
fn compute_available_roles_to_str(server: &Server) -> String {
|
||||
@ -201,3 +226,7 @@ fn compute_available_roles_to_str(server: &Server) -> String {
|
||||
.collect();
|
||||
available_roles_str.join(",")
|
||||
}
|
||||
|
||||
fn player_disconnected() {
|
||||
println!("Player disconnected.");
|
||||
}
|
||||
|
26
src/lib.rs
26
src/lib.rs
@ -8,7 +8,6 @@ use std::io;
|
||||
use std::io::prelude::*;
|
||||
use std::io::{BufReader, Write};
|
||||
use std::os::unix::net::UnixStream;
|
||||
use std::ops::Add;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Player {
|
||||
@ -38,6 +37,27 @@ impl fmt::Display for UserRole {
|
||||
}
|
||||
}
|
||||
|
||||
pub enum RecvPositionError {
|
||||
UserCanceledError,
|
||||
CommunicationError,
|
||||
ParsePositionError,
|
||||
}
|
||||
|
||||
impl fmt::Display for RecvPositionError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
RecvPositionError::CommunicationError =>
|
||||
"Error during the communication between client and server.",
|
||||
RecvPositionError::ParsePositionError => "Error when parsing current position.",
|
||||
RecvPositionError::UserCanceledError => "Cancelled by user.",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
struct SquareToPrint {
|
||||
color: String,
|
||||
background_color: String,
|
||||
@ -205,7 +225,7 @@ pub fn parse_to_role(s: &str) -> Result<UserRole, String> {
|
||||
"w" => Ok(UserRole::White),
|
||||
"b" => Ok(UserRole::Black),
|
||||
"s" => Ok(UserRole::Spectator),
|
||||
_ => Err(String::from("Please enter a valid answer."))
|
||||
_ => Err(String::from("Please enter a valid answer.")),
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,7 +233,7 @@ pub fn role_to_str(r: &UserRole) -> String {
|
||||
String::from(match *r {
|
||||
UserRole::White => "w",
|
||||
UserRole::Black => "b",
|
||||
UserRole::Spectator => "s"
|
||||
UserRole::Spectator => "s",
|
||||
})
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user