From a2b60ac08cb2e9eaf8f40896258f558498ed8225 Mon Sep 17 00:00:00 2001 From: Pierre Hubert Date: Sun, 25 Sep 2022 17:20:56 +0200 Subject: [PATCH] Players must specify their name when starting a new game --- sea_battle_backend/Cargo.lock | 207 ++++++++++++++++++++++ sea_battle_backend/Cargo.toml | 1 + sea_battle_backend/src/data/game_rules.rs | 7 + sea_battle_backend/src/server.rs | 59 ++++-- sea_battle_backend/src/test/bot_client.rs | 19 +- 5 files changed, 277 insertions(+), 16 deletions(-) diff --git a/sea_battle_backend/Cargo.lock b/sea_battle_backend/Cargo.lock index b3bb35c..82b1e62 100644 --- a/sea_battle_backend/Cargo.lock +++ b/sea_battle_backend/Cargo.lock @@ -290,6 +290,15 @@ dependencies = [ "alloc-no-stdlib", ] +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "atty" version = "0.2.14" @@ -349,6 +358,12 @@ dependencies = [ "alloc-stdlib", ] +[[package]] +name = "bumpalo" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" + [[package]] name = "byteorder" version = "1.4.3" @@ -385,6 +400,19 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" +dependencies = [ + "iana-time-zone", + "num-integer", + "num-traits", + "serde", + "winapi", +] + [[package]] name = "clap" version = "3.2.17" @@ -441,6 +469,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + [[package]] name = "cpufeatures" version = "0.2.4" @@ -489,6 +523,41 @@ dependencies = [ "typenum", ] +[[package]] +name = "darling" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4529658bdda7fd6769b8614be250cdcfc3aeb0ee72fe66f9e41e5e5eb73eac02" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "649c91bc01e8b1eac09fb91e8dbc7d517684ca6be8ebc75bb9cafc894f9fdb6f" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc69c5bfcbd2fc09a0f38451d2daf0e372e367986a83906d1b0dbc88134fb5" +dependencies = [ + "darling_core", + "quote", + "syn", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -716,6 +785,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "http" version = "0.2.8" @@ -745,6 +820,25 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "iana-time-zone" +version = "0.1.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd911b35d940d2bd0bea0f9100068e5b97b51a1cbe13d13382f132e0365257a0" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "js-sys", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.2.3" @@ -764,6 +858,7 @@ checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ "autocfg", "hashbrown", + "serde", ] [[package]] @@ -781,6 +876,15 @@ dependencies = [ "libc", ] +[[package]] +name = "js-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "language-tags" version = "0.3.2" @@ -869,6 +973,25 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + [[package]] name = "num_cpus" version = "1.13.1" @@ -1089,6 +1212,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", + "serde_with", "tokio", "tokio-tungstenite", "uuid", @@ -1143,6 +1267,34 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368f2d60d049ea019a84dcd6687b0d1e0030fe663ae105039bdf967ed5e6a9a7" +dependencies = [ + "base64", + "chrono", + "hex", + "indexmap", + "serde", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ccadfacf6cf10faad22bbadf55986bdd0856edfb5d9210aa1dcf1f516e84e93" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "sha-1" version = "0.10.0" @@ -1260,6 +1412,7 @@ dependencies = [ "itoa", "libc", "num_threads", + "serde", "time-macros", ] @@ -1448,6 +1601,60 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" + [[package]] name = "winapi" version = "0.3.9" diff --git a/sea_battle_backend/Cargo.toml b/sea_battle_backend/Cargo.toml index f5e5651..e141d11 100644 --- a/sea_battle_backend/Cargo.toml +++ b/sea_battle_backend/Cargo.toml @@ -18,6 +18,7 @@ actix-web-actors = "4.1.0" actix-rt = "2.7.0" uuid = { version = "1.1.2", features = ["v4"] } rand = "0.8.5" +serde_with = "2.0.1" [dev-dependencies] tokio = { version = "1", features = ["full"] } diff --git a/sea_battle_backend/src/data/game_rules.rs b/sea_battle_backend/src/data/game_rules.rs index 9198f9a..a05a6e0 100644 --- a/sea_battle_backend/src/data/game_rules.rs +++ b/sea_battle_backend/src/data/game_rules.rs @@ -1,12 +1,19 @@ use crate::consts::*; use crate::data::{BotType, PlayConfiguration}; +use serde_with::{serde_as, DisplayFromStr}; +#[serde_as] #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Eq, PartialEq)] pub struct GameRules { + #[serde_as(as = "DisplayFromStr")] pub map_width: usize, + #[serde_as(as = "DisplayFromStr")] pub map_height: usize, + #[serde_as(as = "DisplayFromStr")] pub boats_str: String, + #[serde_as(as = "DisplayFromStr")] pub boats_can_touch: bool, + #[serde_as(as = "DisplayFromStr")] pub player_continue_on_hit: bool, pub bot_type: BotType, } diff --git a/sea_battle_backend/src/server.rs b/sea_battle_backend/src/server.rs index 769e007..66447da 100644 --- a/sea_battle_backend/src/server.rs +++ b/sea_battle_backend/src/server.rs @@ -23,56 +23,73 @@ async fn game_configuration() -> impl Responder { HttpResponse::Ok().json(PlayConfiguration::default()) } +#[derive(serde::Serialize, serde::Deserialize, Eq, PartialEq, Debug)] +pub struct BotPlayQuery { + #[serde(flatten)] + pub rules: GameRules, + pub player_name: String, +} + /// Start bot game async fn start_bot_play( req: HttpRequest, stream: web::Payload, - query: web::Query, + query: web::Query, dispatcher: web::Data>, ) -> Result { - let errors = query.0.get_errors(); + let errors = query.rules.get_errors(); if !errors.is_empty() { return Ok(HttpResponse::BadRequest().json(errors)); } let player_ws = HumanPlayerWS::new( - StartMode::Bot(query.0.clone()), + StartMode::Bot(query.rules.clone()), &dispatcher, - "Human".to_string(), + query.player_name.clone(), ); let resp = ws::start(player_ws, &req, stream); - log::info!("New bot play with configuration: {:?}", &query.0); + log::info!("New bot play with configuration: {:?}", &query.rules); resp } +#[derive(serde::Serialize, serde::Deserialize)] +pub struct CreateInviteQuery { + #[serde(flatten)] + pub rules: GameRules, + pub player_name: String, +} + /// Start game by creating invite async fn start_create_invite( req: HttpRequest, stream: web::Payload, - query: web::Query, // TODO : add player name to query + query: web::Query, dispatcher: web::Data>, ) -> Result { - let errors = query.0.get_errors(); + let errors = query.rules.get_errors(); if !errors.is_empty() { return Ok(HttpResponse::BadRequest().json(errors)); } let player_ws = HumanPlayerWS::new( - StartMode::CreateInvite(query.0.clone()), + StartMode::CreateInvite(query.rules.clone()), &dispatcher, - "Human".to_string(), + query.0.player_name, ); let resp = ws::start(player_ws, &req, stream); - log::info!("New create invite play with configuration: {:?}", &query.0); + log::info!( + "New create invite play with configuration: {:?}", + &query.0.rules + ); resp } #[derive(serde::Serialize, serde::Deserialize)] pub struct AcceptInviteQuery { pub code: String, - // TODO : add player name to query + pub player_name: String, } /// Start game by creating invite @@ -87,7 +104,7 @@ async fn start_accept_invite( code: query.code.clone(), }, &dispatcher, - "Human".to_string(), + query.0.player_name, ); let resp = ws::start(player_ws, &req, stream); @@ -123,3 +140,21 @@ pub async fn start_server(args: Args) -> std::io::Result<()> { .run() .await } + +#[cfg(test)] +mod test { + use crate::server::BotPlayQuery; + + #[test] + fn simple_bot_request_serialize_deserialize() { + let query = BotPlayQuery { + rules: Default::default(), + player_name: "Player".to_string(), + }; + + let string = serde_urlencoded::to_string(&query).unwrap(); + let des = serde_urlencoded::from_str(&string).unwrap(); + + assert_eq!(query, des) + } +} diff --git a/sea_battle_backend/src/test/bot_client.rs b/sea_battle_backend/src/test/bot_client.rs index a22d75a..99fb05a 100644 --- a/sea_battle_backend/src/test/bot_client.rs +++ b/sea_battle_backend/src/test/bot_client.rs @@ -6,7 +6,9 @@ use tokio_tungstenite::tungstenite::Message; use crate::data::{BoatsLayout, BotType, GameRules}; use crate::human_player_ws::{ClientMessage, ServerMessage}; -use crate::server::AcceptInviteQuery; +use crate::server::{AcceptInviteQuery, BotPlayQuery, CreateInviteQuery}; + +const PLAYER_NAME: &str = "Bot client"; #[derive(Default)] pub enum RunMode { @@ -99,14 +101,22 @@ impl BotClient { format!( "{}/play/bot?{}", self.server.replace("http", "ws"), - serde_urlencoded::to_string(&self.requested_rules).unwrap() + serde_urlencoded::to_string(&BotPlayQuery { + rules: self.requested_rules.clone(), + player_name: PLAYER_NAME.to_string() + }) + .unwrap() ) } RunMode::CreateInvite => { format!( "{}/play/create_invite?{}", self.server.replace("http", "ws"), - serde_urlencoded::to_string(&self.requested_rules).unwrap() + serde_urlencoded::to_string(&CreateInviteQuery { + rules: self.requested_rules.clone(), + player_name: PLAYER_NAME.to_string(), + }) + .unwrap() ) } RunMode::AcceptInvite { code } => { @@ -114,7 +124,8 @@ impl BotClient { "{}/play/accept_invite?{}", self.server.replace("http", "ws"), serde_urlencoded::to_string(&AcceptInviteQuery { - code: code.to_string() + code: code.to_string(), + player_name: PLAYER_NAME.to_string() }) .unwrap() )