WS client can send boats layout

This commit is contained in:
Pierre HUBERT 2022-09-14 18:02:11 +02:00
parent 70cb99a0a0
commit 54f7566016
7 changed files with 147 additions and 11 deletions

58
Cargo.lock generated
View File

@ -566,12 +566,65 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "futures"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab30e97ab6aacfe635fad58f22c2bb06c8b685f7421eb1e064a729e2a5f481fa"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bfc52cbddcfd745bf1740338492bb0bd83d76c67b445f91c5fb29fae29ecaa1"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2acedae88d38235936c3922476b10fced7b2b68136f5e3c03c2d5be348a1115"
[[package]]
name = "futures-executor"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d11aa21b5b587a64682c0094c2bdd4df0076c5324961a40cc3abd7f37930528"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93a66fc6d035a26a3ae255a6d2bca35eda63ae4c5512bef54449113f7a1228e5"
[[package]]
name = "futures-macro"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0db9cce532b0eae2ccf2766ab246f114b56b9cf6d445e00c2549fbc100ca045d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-sink"
version = "0.3.23"
@ -590,9 +643,13 @@ version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0828a5471e340229c11c77ca80017937ce3c58cb788a17e5f1c2d5c485a9577"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
"pin-utils",
"slab",
@ -1026,6 +1083,7 @@ dependencies = [
"actix-web-actors",
"clap",
"env_logger",
"futures",
"log",
"rand",
"serde",

View File

@ -23,4 +23,5 @@ rand = "0.8.5"
tokio = { version = "1", features = ["full"] }
#reqwest = { version = "0.11.11", default-features = false, features = ["json", "rustls-tls"] }
tokio-tungstenite = "0.17.2"
serde_urlencoded = "0.7.1"
serde_urlencoded = "0.7.1"
futures = "0.3.23"

View File

@ -1,10 +1,10 @@
use std::error::Error;
use tokio::net::TcpStream;
use tokio_tungstenite::tungstenite::handshake::client::Response;
use tokio_tungstenite::{MaybeTlsStream, WebSocketStream};
use futures::{SinkExt, StreamExt};
use tokio_tungstenite::tungstenite::Message;
use crate::data::GameRules;
use crate::data::{BoatsLayout, GameRules};
use crate::human_player_ws::{ClientMessage, ServerMessage};
pub async fn run_client(server: &str, rules: &GameRules) -> Result<(), Box<dyn Error>> {
let url = format!(
@ -13,7 +13,7 @@ pub async fn run_client(server: &str, rules: &GameRules) -> Result<(), Box<dyn E
serde_urlencoded::to_string(rules).unwrap()
);
log::debug!("Connecting to {}...", url);
let (socket, _) = match tokio_tungstenite::connect_async(url).await {
let (mut socket, _) = match tokio_tungstenite::connect_async(url).await {
Ok(s) => s,
Err(e) => {
log::error!("Failed to establish WebSocket connection! {:?}", e);
@ -21,5 +21,54 @@ pub async fn run_client(server: &str, rules: &GameRules) -> Result<(), Box<dyn E
}
};
while let Some(chunk) = socket.next().await {
let message = match chunk? {
Message::Text(message) => {
log::debug!("TEXT message from server: {}", message);
let msg: ServerMessage = serde_json::from_str(&message)?;
msg
}
Message::Binary(_) => {
log::debug!("BINARY message from server");
continue;
}
Message::Ping(_) => {
log::debug!("PING from server");
continue;
}
Message::Pong(_) => {
log::debug!("PONG from server");
continue;
}
Message::Close(_) => {
log::debug!("CLOSE message request from server");
break;
}
Message::Frame(_) => {
log::debug!("Frame from server");
continue;
}
};
match message {
ServerMessage::WaitingForAnotherPlayer => log::debug!("Waiting for other player..."),
ServerMessage::QueryBoatsLayout { rules } => {
log::debug!("Server requested boats layout");
let layout = BoatsLayout::gen_random_for_rules(&rules)?;
socket
.send(Message::Text(serde_json::to_string(
&ClientMessage::BoatsLayout { layout },
)?))
.await?;
}
ServerMessage::WaitingForOtherPlayerConfiguration => {
log::debug!("Waiting for other player configuration...")
}
ServerMessage::OtherPlayerReady => log::debug!("Other player is ready!"),
ServerMessage::GameStarting => log::debug!("The game is starting..."),
}
}
Ok(())
}

View File

@ -2,7 +2,7 @@ use actix::Addr;
use uuid::Uuid;
use crate::data::GameRules;
use crate::game::{Game, Player};
use crate::game::{Game, Player, SetBoatsLayout};
use crate::human_player_ws::{ClientMessage, HumanPlayerWS, ServerMessage};
pub struct HumanPlayer {
@ -38,6 +38,13 @@ impl Player for HumanPlayer {
impl HumanPlayer {
pub fn handle_client_message(&self, msg: ClientMessage) {
log::info!("Got message from client: {:?}", msg);
match msg {
ClientMessage::StopGame => {
// TODO : do something}
}
ClientMessage::BoatsLayout { layout } => {
self.game.do_send(SetBoatsLayout(self.uuid, layout))
}
}
}
}

View File

@ -6,7 +6,7 @@ use actix_web_actors::ws;
use actix_web_actors::ws::{CloseCode, CloseReason, Message, ProtocolError, WebsocketContext};
use uuid::Uuid;
use crate::data::{BotType, GameRules};
use crate::data::{BoatsLayout, BotType, GameRules};
use crate::game::{AddPlayer, Game};
use crate::human_player::HumanPlayer;
use crate::random_bot::RandomBot;
@ -19,15 +19,16 @@ pub enum StartMode {
AgainstHuman,
}
#[derive(serde::Deserialize, Debug)]
#[derive(serde::Deserialize, serde::Serialize, Debug)]
#[serde(tag = "type")]
pub enum ClientMessage {
StopGame,
BoatsLayout { layout: BoatsLayout },
}
#[derive(Message)]
#[rtype(result = "()")]
#[derive(serde::Serialize, Debug)]
#[derive(serde::Serialize, serde::Deserialize, Debug)]
#[serde(tag = "type")]
pub enum ServerMessage {
WaitingForAnotherPlayer,

View File

@ -1,3 +1,5 @@
extern crate core;
pub mod args;
#[cfg(test)]
pub mod bot_client;

View File

@ -37,3 +37,21 @@ async fn invalid_rules() {
})
.await;
}
#[tokio::test]
async fn full_game() {
let _ = env_logger::builder().is_test(true).try_init();
let local_set = task::LocalSet::new();
local_set
.run_until(async move {
let rules = GameRules::random_players_rules();
task::spawn_local(start_server(Args::for_test(TestPort::ClientInvalidRules)));
wait_for_port(TestPort::ClientInvalidRules.port()).await;
bot_client::run_client(&TestPort::ClientInvalidRules.as_url(), &rules)
.await
.unwrap();
})
.await;
}