diff options
author | metamuffin <metamuffin@disroot.org> | 2024-07-14 21:00:54 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2024-07-14 21:00:54 +0200 |
commit | f6cc57f29fc65a33219b1266b3508dc40536f3c2 (patch) | |
tree | 3a5ee5897f778fd1e0547a3026060e579a4c7c56 /server | |
parent | 721b9ecb282f84839eb096de4d269176f8ab389f (diff) | |
download | hurrycurry-f6cc57f29fc65a33219b1266b3508dc40536f3c2.tar hurrycurry-f6cc57f29fc65a33219b1266b3508dc40536f3c2.tar.bz2 hurrycurry-f6cc57f29fc65a33219b1266b3508dc40536f3c2.tar.zst |
add binary protocol support
Diffstat (limited to 'server')
-rw-r--r-- | server/Cargo.toml | 1 | ||||
-rw-r--r-- | server/protocol/Cargo.toml | 2 | ||||
-rw-r--r-- | server/protocol/src/lib.rs | 50 | ||||
-rw-r--r-- | server/src/main.rs | 92 |
4 files changed, 98 insertions, 47 deletions
diff --git a/server/Cargo.toml b/server/Cargo.toml index da084855..39b9ea1c 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -19,5 +19,6 @@ shlex = "1.3.0" clap = { version = "4.5.8", features = ["derive"] } fake = "2.9.2" pollster = "0.3.0" +bincode = "2.0.0-rc.3" hurrycurry-protocol = { path = "protocol" } diff --git a/server/protocol/Cargo.toml b/server/protocol/Cargo.toml index 8fc63121..6c51c86d 100644 --- a/server/protocol/Cargo.toml +++ b/server/protocol/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" [dependencies] serde = { version = "1.0.204", features = ["derive"] } glam = { version = "0.28.0", features = ["serde"] } - +bincode = { version = "2.0.0-rc.3", features = ["serde", "derive"] } diff --git a/server/protocol/src/lib.rs b/server/protocol/src/lib.rs index 94bebf05..895af376 100644 --- a/server/protocol/src/lib.rs +++ b/server/protocol/src/lib.rs @@ -15,6 +15,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ +use bincode::{ + config::{standard, Configuration, Limit, LittleEndian, Varint}, + Decode, Encode, +}; use glam::{IVec2, Vec2}; use serde::{Deserialize, Serialize}; use std::{ @@ -26,31 +30,44 @@ pub use glam; pub const VERSION: (u32, u32) = (1, 0); -#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub const BINCODE_CONFIG: Configuration<LittleEndian, Varint, Limit<4096>> = + standard().with_limit(); + +#[derive( + Debug, Clone, Copy, Serialize, Deserialize, Encode, Decode, PartialEq, Eq, PartialOrd, Ord, Hash, +)] #[serde(transparent)] pub struct PlayerID(pub i64); -#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive( + Debug, Clone, Copy, Serialize, Deserialize, Encode, Decode, PartialEq, Eq, PartialOrd, Ord, Hash, +)] #[serde(transparent)] pub struct ItemIndex(pub usize); -#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive( + Debug, Clone, Copy, Serialize, Deserialize, Encode, Decode, PartialEq, Eq, PartialOrd, Ord, Hash, +)] #[serde(transparent)] pub struct TileIndex(pub usize); -#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive( + Debug, Clone, Copy, Serialize, Deserialize, Encode, Decode, PartialEq, Eq, PartialOrd, Ord, Hash, +)] #[serde(transparent)] pub struct RecipeIndex(pub usize); -#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive( + Debug, Clone, Copy, Serialize, Deserialize, Encode, Decode, PartialEq, Eq, PartialOrd, Ord, Hash, +)] #[serde(transparent)] pub struct DemandIndex(pub usize); -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] pub struct MapMetadata { name: String, players: usize, difficulty: i32, } -#[derive(Debug, Clone, Serialize, Deserialize, Default)] +#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode, Default)] #[rustfmt::skip] pub struct ClientGamedata { pub item_names: Vec<String>, @@ -61,7 +78,7 @@ pub struct ClientGamedata { pub maps: HashMap<String, MapMetadata>, } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] #[serde(rename_all = "snake_case", tag = "type")] pub enum PacketS { Join { @@ -70,15 +87,18 @@ pub enum PacketS { }, Leave, Position { + #[bincode(with_serde)] pos: Vec2, rot: f32, boosting: bool, }, Interact { + #[bincode(with_serde)] pos: Option<IVec2>, }, Collide { player: PlayerID, + #[bincode(with_serde)] force: Vec2, }, Communicate { @@ -87,6 +107,7 @@ pub enum PacketS { }, #[serde(skip)] + #[bincode(skip)] /// For internal use only ReplaceHand { item: Option<ItemIndex>, @@ -97,7 +118,7 @@ pub enum PacketS { }, } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] #[serde(rename_all = "snake_case")] pub enum Message { Text(String), @@ -105,12 +126,13 @@ pub enum Message { Effect(String), } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] #[serde(rename_all = "snake_case", tag = "type")] pub enum PacketC { Version { minor: u32, major: u32, + supports_bincode: bool, }, Init { id: PlayerID, @@ -120,6 +142,7 @@ pub enum PacketC { }, AddPlayer { id: PlayerID, + #[bincode(with_serde)] position: Vec2, character: i32, name: String, @@ -129,6 +152,7 @@ pub enum PacketC { }, Position { player: PlayerID, + #[bincode(with_serde)] pos: Vec2, rot: f32, boosting: bool, @@ -147,12 +171,14 @@ pub enum PacketC { warn: bool, }, UpdateMap { + #[bincode(with_serde)] tile: IVec2, kind: Option<TileIndex>, neighbors: [Option<TileIndex>; 4], }, Collide { player: PlayerID, + #[bincode(with_serde)] force: Vec2, }, Communicate { @@ -181,10 +207,10 @@ pub enum PacketC { ReplayStart, } -#[derive(Debug, Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode, Copy, PartialEq, Eq, Hash)] #[serde(rename_all = "snake_case")] pub enum ItemLocation { - Tile(IVec2), + Tile(#[bincode(with_serde)] IVec2), Player(PlayerID), } diff --git a/server/src/main.rs b/server/src/main.rs index 90d090d8..6f73851a 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -18,10 +18,19 @@ use anyhow::{anyhow, Result}; use clap::Parser; use futures_util::{SinkExt, StreamExt}; -use hurrycurry_protocol::{PacketC, PacketS, PlayerID, VERSION}; +use hurrycurry_protocol::{PacketC, PacketS, PlayerID, BINCODE_CONFIG, VERSION}; use hurrycurry_server::{data::DATA_DIR, state::State}; use log::{debug, info, trace, warn, LevelFilter}; -use std::{path::PathBuf, process::exit, str::FromStr, sync::Arc, time::Duration}; +use std::{ + path::PathBuf, + process::exit, + str::FromStr, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, + time::Duration, +}; use tokio::{ net::TcpListener, spawn, @@ -121,9 +130,14 @@ async fn run() -> anyhow::Result<()> { PacketC::Version { major: VERSION.0, minor: VERSION.1, + supports_bincode: true, }, ); init.insert(1, PacketC::Init { id }); + + let supports_binary = Arc::new(AtomicBool::new(false)); + let supports_binary2 = supports_binary.clone(); + spawn(async move { for p in init { if let Err(e) = write @@ -154,52 +168,62 @@ async fn run() -> anyhow::Result<()> { info!("client outbound sender dropped. closing connection"); break; }; - if let Err(e) = write - .send(tokio_tungstenite::tungstenite::Message::Text( - serde_json::to_string(&packet).unwrap(), - )) - .await - { + let message = if supports_binary.load(Ordering::Relaxed) { + Message::Binary(bincode::encode_to_vec(&packet, BINCODE_CONFIG).unwrap()) + } else { + Message::Text(serde_json::to_string(&packet).unwrap()) + }; + if let Err(e) = write.send(message).await { warn!("ws error: {e}"); break; } } }); + spawn(async move { info!("{id:?} joined"); while let Some(Ok(message)) = read.next().await { - match message { - Message::Text(line) => { - let packet = match serde_json::from_str(&line) { - Ok(p) => p, - Err(e) => { - warn!("invalid packet: {e}"); - break; - } - }; - if matches!( - packet, - PacketS::Position { .. } | PacketS::ReplayTick { .. } - ) { - trace!("<- {id:?} {packet:?}"); - } else { - debug!("<- {id:?} {packet:?}"); + let packet = match message { + Message::Text(line) => match serde_json::from_str(&line) { + Ok(p) => p, + Err(e) => { + warn!("invalid json packet: {e}"); + break; } - let packet_out = match state.write().await.packet_in(id, packet).await { - Ok(packets) => packets, + }, + Message::Binary(packet) => { + supports_binary2.store(true, Ordering::Relaxed); + match bincode::decode_from_slice::<PacketS, _>(&packet, BINCODE_CONFIG) { + Ok((p, _size)) => p, Err(e) => { - warn!("client error: {e}"); - vec![PacketC::Error { - message: format!("{e}"), - }] + warn!("invalid binary packet: {e}"); + break; } - }; - for packet in packet_out { - let _ = error_tx.send(packet).await; } } Message::Close(_) => break, - _ => (), + _ => continue, + }; + + if matches!( + packet, + PacketS::Position { .. } | PacketS::ReplayTick { .. } + ) { + trace!("<- {id:?} {packet:?}"); + } else { + debug!("<- {id:?} {packet:?}"); + } + let packet_out = match state.write().await.packet_in(id, packet).await { + Ok(packets) => packets, + Err(e) => { + warn!("client error: {e}"); + vec![PacketC::Error { + message: format!("{e}"), + }] + } + }; + for packet in packet_out { + let _ = error_tx.send(packet).await; } } info!("{id:?} left"); |