2 clients can play and see each other moves.
This commit is contained in:
@ -1,4 +1,8 @@
|
||||
use clichess::UserRole;
|
||||
use shakmaty::fen::Fen;
|
||||
use shakmaty::{Chess, Color, Setup};
|
||||
use std::io;
|
||||
use std::io::{BufRead, BufReader};
|
||||
use std::os::unix::net::UnixStream;
|
||||
|
||||
fn main() {
|
||||
@ -10,10 +14,58 @@ fn main() {
|
||||
}
|
||||
};
|
||||
let mut buffer = String::new();
|
||||
let input = clichess::read_from_stream(&stream);
|
||||
println!("{}", input);
|
||||
io::stdin().read_line(&mut buffer).unwrap();
|
||||
clichess::write_to_stream(&mut stream, String::from(buffer.trim()));
|
||||
let response = clichess::read_from_stream(&stream);
|
||||
println!("{}", response);
|
||||
let (client, chess) = get_connection_info_from_stream(&stream);
|
||||
//First prompt when connecting to the server
|
||||
println!(
|
||||
"Hello, anonymous !\n\r You're playing with the {} pieces",
|
||||
client.role.to_string()
|
||||
);
|
||||
//then we get the initial role of the connected client.
|
||||
let mut current_position = chess;
|
||||
loop {
|
||||
println!(
|
||||
"{}",
|
||||
clichess::board_representation(¤t_position, clichess::to_color(client.side))
|
||||
);
|
||||
if clichess::is_player_turn(client, current_position.turn()) {
|
||||
//it's the user turn, taking user input
|
||||
io::stdin().read_line(&mut buffer).unwrap();
|
||||
println!("trying to play {}", buffer);
|
||||
clichess::write_to_stream(&mut stream, String::from(buffer.trim()));
|
||||
buffer.clear();
|
||||
}
|
||||
//update position after playing.
|
||||
current_position = get_current_position(&stream);
|
||||
|
||||
//come back at the beginning of the loop to wait for incoming moves.
|
||||
}
|
||||
}
|
||||
|
||||
//wait for next position from server, then return the current board.
|
||||
fn get_current_position(stream: &UnixStream) -> Chess {
|
||||
let response = clichess::read_line_from_stream(&stream);
|
||||
parse_position(&response)
|
||||
}
|
||||
|
||||
fn parse_position(string: &str) -> Chess {
|
||||
let setup: Fen = string.trim().parse().expect("Invalid message from server.");
|
||||
let position: Chess = setup.position().expect("Invalid message from server.");
|
||||
position
|
||||
}
|
||||
|
||||
fn get_connection_info_from_stream(stream: &UnixStream) -> (clichess::Client, Chess) {
|
||||
println!("Read lines from stream...");
|
||||
let mut buf = String::new();
|
||||
let mut reader = BufReader::new(stream);
|
||||
//first, client as json.
|
||||
reader
|
||||
.read_line(&mut buf)
|
||||
.expect("Server closed connection.");
|
||||
let client = serde_json::from_str(&(buf.trim())).unwrap();
|
||||
buf.clear();
|
||||
reader
|
||||
.read_line(&mut buf)
|
||||
.expect("Server closed connection.");
|
||||
let chess = parse_position(buf.trim());
|
||||
(client, chess)
|
||||
}
|
||||
|
@ -1,19 +1,25 @@
|
||||
use clichess;
|
||||
use shakmaty::{Chess, Color};
|
||||
use clichess::Client;
|
||||
use clichess::UserRole;
|
||||
use shakmaty::{fen, Chess, Color, Setup};
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::io::prelude::*;
|
||||
use std::os::unix::net::{UnixListener, UnixStream};
|
||||
use std::str;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::{Arc, Condvar, Mutex};
|
||||
|
||||
use std::thread;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Server {
|
||||
id: usize,
|
||||
chess_position: Arc<Mutex<Chess>>,
|
||||
clients: Arc<Mutex<HashMap<usize, (Client, Arc<(Mutex<String>, Condvar)>)>>>,
|
||||
receiving_buffer: Arc<(Mutex<String>, Condvar)>,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let chess = Arc::new(Mutex::new(Chess::default()));
|
||||
let clients = Arc::new(Mutex::new(HashMap::new()));
|
||||
let mut counter = 0;
|
||||
fs::remove_file("/tmp/clichess.socket");
|
||||
|
||||
@ -23,12 +29,13 @@ fn main() {
|
||||
for stream in listener.incoming() {
|
||||
match stream {
|
||||
Ok(stream) => {
|
||||
let chess = Arc::clone(&chess);
|
||||
/* connection succeeded */
|
||||
let server = Server {
|
||||
id: counter,
|
||||
chess_position: chess,
|
||||
chess_position: chess.clone(),
|
||||
clients: clients.clone(),
|
||||
receiving_buffer: Arc::new((Mutex::new(String::new()), Condvar::new())),
|
||||
};
|
||||
/* connection succeeded */
|
||||
thread::spawn(|| handle_client(stream, server));
|
||||
counter += 1;
|
||||
}
|
||||
@ -41,24 +48,81 @@ fn main() {
|
||||
}
|
||||
|
||||
fn handle_client(mut stream: UnixStream, server: Server) {
|
||||
//create client
|
||||
let client = create_client(&server);
|
||||
//send its information to the client
|
||||
println!(
|
||||
"server {}, send first information to the client...",
|
||||
server.id
|
||||
);
|
||||
clichess::write_to_stream(&mut stream, serde_json::to_string(&client).unwrap());
|
||||
println!("server {}, information to the client sent", server.id);
|
||||
let mut player_turn: Color;
|
||||
//send current position to the client
|
||||
println!(
|
||||
"server {}, send current position to the client...",
|
||||
server.id
|
||||
);
|
||||
{
|
||||
let chess = server.chess_position.lock().unwrap();
|
||||
clichess::write_to_stream(
|
||||
&mut stream,
|
||||
clichess::board_representation(&chess, Color::White),
|
||||
);
|
||||
player_turn = chess.turn();
|
||||
clichess::write_to_stream(&mut stream, fen::fen(&*chess));
|
||||
}
|
||||
//let go of the lock while waiting for user input.
|
||||
let input = clichess::read_from_stream(&stream);
|
||||
{
|
||||
let mut chess = server.chess_position.lock().unwrap();
|
||||
match clichess::try_to_play_move(&chess, input) {
|
||||
Ok(played_chess) => *chess = played_chess,
|
||||
Err(e) => println!("Error: {}", e),
|
||||
};
|
||||
clichess::write_to_stream(
|
||||
&mut stream,
|
||||
clichess::board_representation(&chess, Color::White),
|
||||
);
|
||||
println!("server {}, current position to the client sent", server.id);
|
||||
loop {
|
||||
if clichess::is_player_turn(client, player_turn) {
|
||||
//let go of the lock while waiting for user input.
|
||||
println!("server {}, waiting for client move..", server.id);
|
||||
let input = clichess::read_line_from_stream(&stream);
|
||||
{
|
||||
let mut chess = server.chess_position.lock().unwrap();
|
||||
let clients = server.clients.lock().unwrap();
|
||||
println!("User tried to play {}", input);
|
||||
match clichess::try_to_play_move(&chess, input) {
|
||||
Ok(played_chess) => *chess = played_chess,
|
||||
Err(e) => println!("Error: {}", e),
|
||||
};
|
||||
let chessfen = fen::fen(&*chess);
|
||||
for (id, (_, cvar_buffer)) in clients.iter() {
|
||||
if server.id != *id {
|
||||
cvar_buffer.0.lock().unwrap().push_str(&chessfen);
|
||||
cvar_buffer.1.notify_one();
|
||||
}
|
||||
}
|
||||
clichess::write_to_stream(&mut stream, chessfen);
|
||||
player_turn = chess.turn();
|
||||
}
|
||||
} else {
|
||||
{
|
||||
let (buffer_mutex, cvar) = &*server.receiving_buffer;
|
||||
let mut buffer = buffer_mutex.lock().unwrap();
|
||||
println!("server id: {}, waiting for move to send...", server.id);
|
||||
while buffer.is_empty() {
|
||||
buffer = cvar.wait(buffer).unwrap();
|
||||
}
|
||||
println!("server id: {}, sending {}", server.id, buffer);
|
||||
clichess::write_to_stream(&mut stream, buffer.clone());
|
||||
buffer.clear();
|
||||
let chess = server.chess_position.lock().unwrap();
|
||||
player_turn = chess.turn();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_client(server: &Server) -> Client {
|
||||
println!("Creating client {}...", server.id);
|
||||
let role = match server.id {
|
||||
0 => UserRole::White,
|
||||
1 => UserRole::Black,
|
||||
_ => UserRole::Spectator,
|
||||
};
|
||||
let mut clients = server.clients.lock().unwrap();
|
||||
let client = Client {
|
||||
role,
|
||||
side: clichess::from_color(clichess::get_default_side(role)),
|
||||
};
|
||||
clients.insert(server.id, (client, server.receiving_buffer.clone()));
|
||||
println!("Created client {}", server.id);
|
||||
client
|
||||
}
|
||||
|
Reference in New Issue
Block a user