M Cargo.lock => Cargo.lock +319 -18
@@ 9,6 9,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
+name = "aho-corasick"
+version = "0.7.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.70"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
+
+[[package]]
name = "approx"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 169,6 184,12 @@ dependencies = [
]
[[package]]
+name = "cc"
+version = "1.0.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
+
+[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 336,6 357,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]]
+name = "errno"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
+dependencies = [
+ "errno-dragonfly",
+ "libc",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "errno-dragonfly"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
name = "exr"
version = "1.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 352,6 394,15 @@ dependencies = [
]
[[package]]
+name = "fastrand"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
+dependencies = [
+ "instant",
+]
+
+[[package]]
name = "fdeflate"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 573,6 624,12 @@ dependencies = [
]
[[package]]
+name = "hermit-abi"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
+
+[[package]]
name = "http"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 670,6 727,26 @@ dependencies = [
]
[[package]]
+name = "instant"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "io-lifetimes"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
+dependencies = [
+ "hermit-abi 0.3.1",
+ "libc",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
name = "itoa"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 718,6 795,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb"
[[package]]
+name = "linux-raw-sys"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f"
+
+[[package]]
name = "lock_api"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 1022,6 1105,94 @@ dependencies = [
]
[[package]]
+name = "protobuf"
+version = "2.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94"
+
+[[package]]
+name = "protobuf"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b55bad9126f378a853655831eb7363b7b01b81d19f8cb1218861086ca4a1a61e"
+dependencies = [
+ "once_cell",
+ "protobuf-support",
+ "thiserror",
+]
+
+[[package]]
+name = "protobuf-codegen"
+version = "2.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "033460afb75cf755fcfc16dfaed20b86468082a2ea24e05ac35ab4a099a017d6"
+dependencies = [
+ "protobuf 2.28.0",
+]
+
+[[package]]
+name = "protobuf-codegen"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0dd418ac3c91caa4032d37cb80ff0d44e2ebe637b2fb243b6234bf89cdac4901"
+dependencies = [
+ "anyhow",
+ "once_cell",
+ "protobuf 3.2.0",
+ "protobuf-parse",
+ "regex",
+ "tempfile",
+ "thiserror",
+]
+
+[[package]]
+name = "protobuf-parse"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d39b14605eaa1f6a340aec7f320b34064feb26c93aec35d6a9a2272a8ddfa49"
+dependencies = [
+ "anyhow",
+ "indexmap",
+ "log",
+ "protobuf 3.2.0",
+ "protobuf-support",
+ "tempfile",
+ "thiserror",
+ "which",
+]
+
+[[package]]
+name = "protobuf-support"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5d4d7b8601c814cfb36bcebb79f0e61e45e1e93640cf778837833bbed05c372"
+dependencies = [
+ "thiserror",
+]
+
+[[package]]
+name = "protoc"
+version = "2.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0218039c514f9e14a5060742ecd50427f8ac4f85a6dc58f2ddb806e318c55ee"
+dependencies = [
+ "log",
+ "which",
+]
+
+[[package]]
+name = "protoc-rust"
+version = "2.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22f8a182bb17c485f20bdc4274a8c39000a61024cfe461c799b50fec77267838"
+dependencies = [
+ "protobuf 2.28.0",
+ "protobuf-codegen 2.28.0",
+ "protoc",
+ "tempfile",
+]
+
+[[package]]
name = "qoi"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 1119,6 1290,32 @@ dependencies = [
]
[[package]]
+name = "redox_syscall"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "regex"
+version = "1.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
+
+[[package]]
name = "rmp"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 1173,6 1370,20 @@ dependencies = [
]
[[package]]
+name = "rustix"
+version = "0.37.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77"
+dependencies = [
+ "bitflags",
+ "errno",
+ "io-lifetimes",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
name = "ryu"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 1358,8 1569,9 @@ dependencies = [
name = "starkingdoms-protocol"
version = "0.1.0"
dependencies = [
- "rmp-serde",
- "serde",
+ "protobuf 3.2.0",
+ "protobuf-codegen 3.2.0",
+ "protoc-rust",
]
[[package]]
@@ 1373,7 1585,6 @@ dependencies = [
"log",
"nalgebra",
"rapier2d-f64",
- "rmp-serde",
"serde",
"serde_json",
"simple_logger",
@@ 1406,6 1617,19 @@ dependencies = [
]
[[package]]
+name = "tempfile"
+version = "3.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998"
+dependencies = [
+ "cfg-if",
+ "fastrand",
+ "redox_syscall",
+ "rustix",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
name = "thiserror"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 1746,6 1970,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"
[[package]]
+name = "which"
+version = "4.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
+dependencies = [
+ "either",
+ "libc",
+ "once_cell",
+]
+
+[[package]]
name = "wide"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 1783,13 2018,13 @@ version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
+ "windows_aarch64_gnullvm 0.42.2",
+ "windows_aarch64_msvc 0.42.2",
+ "windows_i686_gnu 0.42.2",
+ "windows_i686_msvc 0.42.2",
+ "windows_x86_64_gnu 0.42.2",
+ "windows_x86_64_gnullvm 0.42.2",
+ "windows_x86_64_msvc 0.42.2",
]
[[package]]
@@ 1798,7 2033,16 @@ version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [
- "windows-targets",
+ "windows-targets 0.42.2",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets 0.48.0",
]
[[package]]
@@ 1807,13 2051,28 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
+ "windows_aarch64_gnullvm 0.42.2",
+ "windows_aarch64_msvc 0.42.2",
+ "windows_i686_gnu 0.42.2",
+ "windows_i686_msvc 0.42.2",
+ "windows_x86_64_gnu 0.42.2",
+ "windows_x86_64_gnullvm 0.42.2",
+ "windows_x86_64_msvc 0.42.2",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+dependencies = [
+ "windows_aarch64_gnullvm 0.48.0",
+ "windows_aarch64_msvc 0.48.0",
+ "windows_i686_gnu 0.48.0",
+ "windows_i686_msvc 0.48.0",
+ "windows_x86_64_gnu 0.48.0",
+ "windows_x86_64_gnullvm 0.48.0",
+ "windows_x86_64_msvc 0.48.0",
]
[[package]]
@@ 1823,42 2082,84 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+
+[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+
+[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]]
+name = "windows_i686_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+
+[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]]
+name = "windows_i686_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+
+[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+
+[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+
+[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
+
+[[package]]
name = "ws_stream_wasm"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
M client/src/chat.rs => client/src/chat.rs +7 -3
@@ 1,7 1,9 @@
+use std::error::Error;
use wasm_bindgen::prelude::*;
use starkingdoms_protocol::MessageC2S;
use crate::CLIENT;
use futures::SinkExt;
+use starkingdoms_protocol::message_c2s::MessageC2SChat;
#[wasm_bindgen]
// TODO: Switch to async-aware mutexes
@@ 10,9 12,11 @@ pub async fn send_chat(message: &str) -> Result<(), JsError> {
let client_data = &mut CLIENT.write()?.client_data;
if let Some(data) = client_data {
- send!(data.tx, &MessageC2S::Chat {
- message: message.to_string()
- }).await?;
+ let msg = MessageC2S::Chat(MessageC2SChat {
+ message: message.to_string(),
+ special_fields: Default::default(),
+ }).try_into().map_err(|e: Box<dyn Error> | JsError::new(&e.to_string()))?;
+ send!(data.tx, msg).await?;
} else {
return Err(JsError::new("Client not yet connected to server"));
}
D client/src/input/mod.rs => client/src/input/mod.rs +0 -37
@@ 1,37 0,0 @@
-use std::error::Error;
-use async_trait::async_trait;
-
-/*
-Functions the input subsystem needs to perform:
-- init
-- register and unregister event handlers for:
- - mouse movement
- - keydown, keyup, keypress
- - clicks
- */
-
-#[async_trait]
-pub trait InputSubsystem {
- async fn init() -> Result<Self, Box<dyn Error>> where Self: Sized;
-
- async fn register_on_mouse_move(&mut self, id: &str, callback: dyn FnMut(OnMouseMoveEvent)) -> Result<(), Box<dyn Error>>;
- async fn unregister_on_mouse_move(&mut self, id: &str) -> Result<(), Box<dyn Error>>;
-
- async fn register_on_key_down(&mut self, id: &str, callback: dyn FnMut(OnKeyDownEvent)) -> Result<(), Box<dyn Error>>;
- async fn unregister_on_key_down(&mut self, id: &str) -> Result<(), Box<dyn Error>>;
-
- async fn register_on_key_up(&mut self, id: &str, callback: dyn FnMut(OnKeyUpEvent)) -> Result<(), Box<dyn Error>>;
- async fn unregister_on_key_up(&mut self, id: &str) -> Result<(), Box<dyn Error>>;
-
- async fn register_on_keypress(&mut self, id: &str, callback: dyn FnMut(OnKeypressEvent)) -> Result<(), Box<dyn Error>>;
- async fn unregister_on_keypress(&mut self, id: &str) -> Result<(), Box<dyn Error>>;
-
- async fn register_on_click(&mut self, id: &str, callback: dyn FnMut(OnClickEvent)) -> Result<(), Box<dyn Error>>;
- async fn unregister_on_click(&mut self, id: &str) -> Result<(), Box<dyn Error>>;
-}
-
-pub struct OnMouseMoveEvent {}
-pub struct OnKeyDownEvent {}
-pub struct OnKeyUpEvent {}
-pub struct OnKeypressEvent {}
-pub struct OnClickEvent {}>
\ No newline at end of file
M client/src/lib.rs => client/src/lib.rs +44 -40
@@ 1,27 1,26 @@
use std::error::Error;
use std::panic;
use std::str::FromStr;
-
use futures::stream::{SplitSink, SplitStream};
-use futures::{StreamExt, TryFutureExt};
-use log::{debug, error, info, Level, trace, warn};
+use futures::{StreamExt};
+use log::{error, info, Level, trace, warn};
use wasm_bindgen::prelude::*;
-use web_sys::console::debug;
use ws_stream_wasm::{WsErr, WsMessage, WsMeta, WsStream};
-use starkingdoms_protocol::{ProtocolPlanet, ProtocolPlayer, State};
-use starkingdoms_protocol::PROTOCOL_VERSION;
-use starkingdoms_protocol::MessageS2C;
-use starkingdoms_protocol::MessageC2S;
use futures::SinkExt;
use lazy_static::lazy_static;
use std::sync::Arc;
use std::sync::RwLock;
-
use async_recursion::async_recursion;
use futures::FutureExt;
use wasm_bindgen_futures::JsFuture;
use web_sys::{Window};
-use starkingdoms_protocol::GoodbyeReason::PingPongTimeout;
+use starkingdoms_protocol::message_c2s::{MessageC2SGoodbye, MessageC2SHello, MessageC2SPing};
+use starkingdoms_protocol::{MessageC2S, MessageS2C, PROTOCOL_VERSION};
+use starkingdoms_protocol::goodbye_reason::GoodbyeReason;
+use starkingdoms_protocol::planet::Planet;
+use starkingdoms_protocol::player::Player;
+use starkingdoms_protocol::state::State;
+
use crate::rendering::Renderer;
use crate::rendering::renderer::WebRenderer;
use crate::textures::loader::TextureLoader;
@@ 33,7 32,6 @@ pub mod macros;
pub mod chat;
pub mod rendering;
pub mod textures;
-pub mod input;
#[wasm_bindgen]
extern {
@@ 43,10 41,10 @@ extern {
#[derive(Debug)]
pub struct Client {
pub client_data: Option<ClientData>,
- pub planets: Vec<ProtocolPlanet>,
+ pub planets: Vec<Planet>,
pub x: f64,
pub y: f64,
- pub players: Vec<ProtocolPlayer>
+ pub players: Vec<Player>
}
#[derive(Debug)]
@@ 70,6 68,7 @@ lazy_static! {
y: 0f64,
players: vec![]
}));
+ //pub static ref BUTTONS: Arc<Buttons> = Arc::new(Buttons { up: false, left: false, right: false, down: false });
}
pub const MAX_CONNECTION_TRIES: i32 = 10;
@@ 152,11 151,13 @@ pub async fn main(gateway: &str, username: &str, backoff: i32, textures: Texture
set_status("Handshaking with server...");
- send!(client_data.tx, &MessageC2S::Hello {
- next_state: State::Play,
+ let msg = MessageC2S::Hello(MessageC2SHello {
version: PROTOCOL_VERSION,
- requested_username: username.to_string()
- }).await?;
+ requested_username: username.to_string(),
+ next_state: State::Play.into(),
+ special_fields: Default::default(),
+ }).try_into()?;
+ send!(client_data.tx, msg).await?;
trace!("Sent handshake start packet");
@@ 164,13 165,13 @@ pub async fn main(gateway: &str, username: &str, backoff: i32, textures: Texture
let typed_msg: MessageS2C = msg;
match typed_msg {
- MessageS2C::Hello { version, given_username, next_state } => {
- info!("FAST CONNECT - connected to server protocol {} given username {}, switching to state {:?}", version, given_username, next_state);
- client_data.state = next_state;
+ MessageS2C::Hello(pkt) => {
+ info!("FAST CONNECT - connected to server protocol {} given username {}, switching to state {:?}", pkt.version, pkt.given_username, pkt.next_state);
+ client_data.state = pkt.next_state.unwrap();
},
- MessageS2C::Goodbye { reason } => {
- error!("server disconnected before finishing handshake: {:?}", reason);
- return Err(format!("disconnected by server: {:?}", reason).into());
+ MessageS2C::Goodbye(pkt) => {
+ error!("server disconnected before finishing handshake: {:?}", pkt.reason);
+ return Err(format!("disconnected by server: {:?}", pkt.reason).into());
},
_ => {
warn!("received unexpected packet from server: {:?}", typed_msg);
@@ 197,7 198,8 @@ pub async fn send_ping_pong() -> Result<(), JsError> {
let client_data = client.client_data.as_mut().unwrap();
- send!(client_data.tx, &MessageC2S::Ping {}).await?;
+
+ send!(client_data.tx, MessageC2S::Ping(MessageC2SPing {special_fields: Default::default()}).try_into().map_err(|_| JsError::new("I/O Error"))?).await?;
Ok(())
}
@@ 215,9 217,11 @@ pub async fn update_socket() -> Result<(), JsError> {
if client_data.pong_timeout < (js_sys::Date::now() as u64 / 1000) {
error!("Connection timed out");
- send!(client_data.tx, &MessageC2S::Goodbye {
- reason: PingPongTimeout
- }).await?;
+ let msg = MessageC2S::Goodbye(MessageC2SGoodbye {
+ reason: GoodbyeReason::PingPongTimeout.into(),
+ special_fields: Default::default(),
+ }).try_into().map_err(|e: Box<dyn Error> | JsError::new(&e.to_string()))?;
+ send!(client_data.tx, msg).await?;
client.client_data = None;
set_status("Connection timed out. Reload to reconnect");
return Err(JsError::new("Connection timed out"));
@@ 232,13 236,13 @@ pub async fn update_socket() -> Result<(), JsError> {
if let Some(msg) = maybe_msg {
match msg {
- MessageS2C::Goodbye { reason } => {
- info!("server sent disconnect: {:?}", reason);
+ MessageS2C::Goodbye(pkt) => {
+ info!("server sent disconnect: {:?}", pkt.reason);
client.client_data = None;
return Err(JsError::new("disconnected by server"));
}
- MessageS2C::Chat { from, message } => {
- info!("[CHAT] {}: {}", from, message);
+ MessageS2C::Chat(pkt) => {
+ info!("[CHAT] {}: {}", pkt.from, pkt.message);
let window: Window = web_sys::window().expect("no global `window` exists");
let document = window.document().expect("should have a document on window");
@@ 246,25 250,25 @@ pub async fn update_socket() -> Result<(), JsError> {
let new_elem = document.create_element("div").expect("could not create element");
- let msg_formatted = markdown::to_html(&format!("**[{}]** {}", from, message));
+ let msg_formatted = markdown::to_html(&format!("**[{}]** {}", pkt.from, pkt.message));
new_elem.set_inner_html(&msg_formatted);
chatbox.append_child(&new_elem).unwrap();
},
- MessageS2C::Pong {} => {
+ MessageS2C::Pong(_) => {
client_data.pong_timeout = (js_sys::Date::now() as u64 / 1000) + PONG_MAX_TIMEOUT
},
- MessageS2C::PlanetData { planets } => {
- client.planets = planets;
+ MessageS2C::PlanetData(pkt) => {
+ client.planets = pkt.planets;
},
- MessageS2C::PlayersUpdate { players } => {
- let me = players.iter().find(|i| i.username == client_data.username);
+ MessageS2C::PlayersUpdate(pkt) => {
+ let me = pkt.players.iter().find(|i| i.username == client_data.username);
if let Some(me) = me {
- client.x = me.x;
- client.y = me.y;
+ client.x = me.x as f64;
+ client.y = me.y as f64;
}
- client.players = players;
+ client.players = pkt.players;
}
_ => {
warn!("server sent unexpected packet {:?}, ignoring", msg);
M client/src/macros.rs => client/src/macros.rs +5 -6
@@ 1,10 1,9 @@
-use serde::{Serialize};
use ws_stream_wasm::WsMessage;
#[macro_export]
macro_rules! send {
($writer:expr,$pkt:expr) => {
- $writer.send($crate::macros::__generic_packet_to_message($pkt).unwrap())
+ $writer.send($crate::macros::__generic_packet_to_message($pkt))
};
}
@@ 15,7 14,7 @@ macro_rules! recv {
if let Some(future_result) = $reader.next().now_or_never() {
if let Some(msg) = future_result {
if let WsMessage::Binary(msg) = msg {
- match rmp_serde::from_slice(&msg) {
+ match MessageS2C::try_from(msg.as_slice()) {
Ok(d) => Ok(Some(d)),
Err(e) => {
log::error!("error deserializing message: {}", e);
@@ 42,7 41,7 @@ macro_rules! recv_now {
{
if let Some(msg) = $reader.next().await {
if let WsMessage::Binary(msg) = msg {
- match rmp_serde::from_slice(&msg) {
+ match MessageS2C::try_from(msg.as_slice()) {
Ok(d) => Ok(Some(d)),
Err(e) => {
log::error!("error deserializing message: {}", e);
@@ 60,6 59,6 @@ macro_rules! recv_now {
};
}
-pub fn __generic_packet_to_message<T: Serialize>(pkt: &T) -> Result<WsMessage, rmp_serde::encode::Error> {
- rmp_serde::to_vec(&pkt).map(WsMessage::from)
+pub fn __generic_packet_to_message(pkt: Vec<u8>) -> WsMessage {
+ WsMessage::from(pkt)
}=
\ No newline at end of file
M client/src/rendering/renderer_playercentric.rs => client/src/rendering/renderer_playercentric.rs +7 -7
@@ 1,11 1,11 @@
use std::error::Error;
use async_trait::async_trait;
-use log::debug;
use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement, HtmlImageElement};
use crate::rendering::Renderer;
use wasm_bindgen::{JsCast, JsValue};
use crate::CLIENT;
-use crate::textures::TextureManager;
+
+// TODO: Remove all the f32s
pub const STARFIELD_RENDER_SCALE: f64 = 1.0;
@@ 35,7 35,7 @@ impl Renderer for WebRenderer {
if client.client_data.is_none() {
return Err("client not yet initialized".into());
}
- let client_data = client.client_data.as_ref().unwrap();
+ let _client_data = client.client_data.as_ref().unwrap();
//let camera_translate_x = -client.x + (typed_canvas_element.width() / 2) as f64;
let viewer_size_x = typed_canvas_element.width() as f64;
@@ 58,10 58,10 @@ impl Renderer for WebRenderer {
//context.set_transform(1f64, 0f64, 0f64, 1f64, 0f64, 0f64).map_err(|e: JsValue| e.as_string().unwrap())?;
//context.translate(-planet.x, -planet.y).map_err(|e: JsValue| e.as_string().unwrap())?;
- let texture_image = document.get_element_by_id(&format!("tex-{}", planet.planet_type.as_texture_id())).unwrap().dyn_into::<HtmlImageElement>().unwrap();
+ let texture_image = document.get_element_by_id(&format!("tex-{}", planet.planet_type.unwrap().as_texture_id())).unwrap().dyn_into::<HtmlImageElement>().unwrap();
// pos:
//debug!("P {} {}", planet.x - planet.radius - client.x, planet.y - planet.radius - client.y);
- context.draw_image_with_html_image_element_and_dw_and_dh(&texture_image, planet.x - planet.radius - client.x, planet.y - planet.radius - client.y, planet.radius * 2f64, planet.radius * 2f64).map_err(|e: JsValue| e.as_string().unwrap())?;
+ context.draw_image_with_html_image_element_and_dw_and_dh(&texture_image, (planet.x - planet.radius - client.x as f32) as f64, (planet.y - planet.radius - client.y as f32) as f64, planet.radius as f64 * 2f64, planet.radius as f64 * 2f64).map_err(|e: JsValue| e.as_string().unwrap())?;
//context.restore();
}
@@ 71,14 71,14 @@ impl Renderer for WebRenderer {
//context.translate(player.x, player.y).map_err(|e: JsValue| e.as_string().unwrap())?;
//gaah fuck why noo i didnt want this. godforsaken canvas rotation
- context.translate(player.x - client.x, player.y - client.y).map_err(|e: JsValue| e.as_string().unwrap())?; // fwip
+ context.translate(player.x as f64 - client.x, player.y as f64 - client.y).map_err(|e: JsValue| e.as_string().unwrap())?; // fwip
context.set_text_align("center");
context.set_font("30px Segoe UI");
context.set_fill_style(&JsValue::from_str("white")); // CssStyleColor
context.fill_text(&player.username, 0f64, -35f64).map_err(|e: JsValue| e.as_string().unwrap())?;
- context.rotate(player.rotation).map_err(|e: JsValue| e.as_string().unwrap())?; // fwip
+ context.rotate(player.rotation as f64).map_err(|e: JsValue| e.as_string().unwrap())?; // fwip
let texture_image = document.get_element_by_id("tex-hearty").unwrap().dyn_into::<HtmlImageElement>().unwrap();
//context.draw_image_with_html_image_element_and_dw_and_dh(&texture_image, player.x - 25f64 - client.x, player.y - 25f64 - client.y, 50f64, 50f64).map_err(|e: JsValue| e.as_string().unwrap())?;
M protocol/Cargo.toml => protocol/Cargo.toml +5 -2
@@ 6,5 6,8 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-serde = { version = "1", features = ["derive"] }
-rmp-serde = "1.1">
\ No newline at end of file
+protobuf = "3"
+
+[build-dependencies]
+protobuf-codegen = "3"
+protoc-rust = "^2.0"<
\ No newline at end of file
A protocol/build.rs => protocol/build.rs +13 -0
@@ 0,0 1,13 @@
+fn main() {
+ protobuf_codegen::Codegen::new()
+ .cargo_out_dir("protos")
+ .include("src/pbuf")
+ .input("src/pbuf/starkingdoms-protocol.proto")
+ .input("src/pbuf/message_c2s.proto")
+ .input("src/pbuf/message_s2c.proto")
+ .input("src/pbuf/planet.proto")
+ .input("src/pbuf/player.proto")
+ .input("src/pbuf/state.proto")
+ .input("src/pbuf/goodbye_reason.proto")
+ .run_from_script();
+}<
\ No newline at end of file
A protocol/src/legacy.rs => protocol/src/legacy.rs +103 -0
@@ 0,0 1,103 @@
+use serde::{Deserialize, Serialize};
+
+pub const PROTOCOL_VERSION: u32 = 1;
+
+#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
+pub enum State {
+ Handshake,
+ Play
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub enum MessageC2S {
+ Hello {
+ version: u32,
+ requested_username: String,
+ next_state: State
+ },
+
+ Goodbye {
+ reason: GoodbyeReason
+ },
+
+ Chat {
+ message: String
+ },
+
+ Ping {},
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub enum MessageS2C {
+ Hello {
+ version: u32,
+ given_username: String,
+ next_state: State
+ },
+
+ Goodbye {
+ reason: GoodbyeReason
+ },
+
+ Chat {
+ from: String,
+ message: String
+ },
+
+ Pong {},
+
+ PlayersUpdate {
+ players: Vec<ProtocolPlayer>
+ },
+
+
+ PlanetData {
+ planets: Vec<ProtocolPlanet>
+ }
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct ProtocolPlayer {
+ pub rotation: f64,
+ pub x: f64,
+ pub y: f64,
+ pub username: String
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub enum GoodbyeReason {
+ UnsupportedProtocol { supported: u32, got: u32 },
+ UnexpectedPacket,
+ UnexpectedNextState,
+ UsernameTaken,
+ PingPongTimeout,
+ Done,
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct ProtocolPlanet {
+ pub planet_type: PlanetType,
+ pub x: f64,
+ pub y: f64,
+ pub radius: f64
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub enum PlanetType {
+ Earth
+}
+
+impl PlanetType {
+ pub fn as_texture_id(&self) -> String {
+ match self {
+ PlanetType::Earth => "earth".to_string()
+ }
+ }
+}
+
+pub fn pc2s(pkt: &MessageC2S) -> Vec<u8> {
+ rmp_serde::to_vec(pkt).unwrap()
+}
+pub fn ps2c(pkt: &MessageS2C) -> Vec<u8> {
+ rmp_serde::to_vec(pkt).unwrap()
+}
M protocol/src/lib.rs => protocol/src/lib.rs +135 -81
@@ 1,103 1,157 @@
-use serde::{Deserialize, Serialize};
+use std::error::Error;
+use protobuf::{Enum, Message};
+use crate::message_c2s::{MessageC2SChat, MessageC2SGoodbye, MessageC2SHello, MessageC2SPing};
+use crate::message_s2c::{MessageS2CChat, MessageS2CGoodbye, MessageS2CHello, MessageS2CPlanetData, MessageS2CPlayersUpdate, MessageS2CPong};
+use crate::planet::PlanetType;
+use crate::starkingdoms_protocol::PacketWrapper;
+include!(concat!(env!("OUT_DIR"), "/protos/mod.rs"));
pub const PROTOCOL_VERSION: u32 = 1;
-#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
-pub enum State {
- Handshake,
- Play
-}
-
-#[derive(Serialize, Deserialize, Debug, Clone)]
+#[derive(Debug)]
pub enum MessageC2S {
- Hello {
- version: u32,
- requested_username: String,
- next_state: State
- },
-
- Goodbye {
- reason: GoodbyeReason
- },
-
- Chat {
- message: String
- },
-
- Ping {},
+ Hello(MessageC2SHello),
+ Goodbye(MessageC2SGoodbye),
+ Chat(MessageC2SChat),
+ Ping(MessageC2SPing)
}
-#[derive(Serialize, Deserialize, Debug, Clone)]
+#[derive(Debug)]
pub enum MessageS2C {
- Hello {
- version: u32,
- given_username: String,
- next_state: State
- },
-
- Goodbye {
- reason: GoodbyeReason
- },
-
- Chat {
- from: String,
- message: String
- },
-
- Pong {},
-
- PlayersUpdate {
- players: Vec<ProtocolPlayer>
- },
-
-
- PlanetData {
- planets: Vec<ProtocolPlanet>
- }
+ Hello(MessageS2CHello),
+ Goodbye(MessageS2CGoodbye),
+ Chat(MessageS2CChat),
+ Pong(MessageS2CPong),
+ PlayersUpdate(MessageS2CPlayersUpdate),
+ PlanetData(MessageS2CPlanetData)
}
-#[derive(Serialize, Deserialize, Debug, Clone)]
-pub struct ProtocolPlayer {
- pub rotation: f64,
- pub x: f64,
- pub y: f64,
- pub username: String
+impl TryFrom<&[u8]> for MessageC2S {
+ type Error = Box<dyn Error>;
+
+ fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
+ let pkt = starkingdoms_protocol::PacketWrapper::parse_from_bytes(value)?;
+
+ let deser_pkt = match pkt.packet_id {
+ _id if _id == message_c2s::message_c2shello::Packet_info::type_.value() as i64 => {
+ MessageC2S::Hello(MessageC2SHello::parse_from_bytes(&pkt.packet_data)?)
+ },
+ _id if _id == message_c2s::message_c2sgoodbye::Packet_info::type_.value() as i64 => {
+ MessageC2S::Goodbye(MessageC2SGoodbye::parse_from_bytes(&pkt.packet_data)?)
+ },
+ _id if _id == message_c2s::message_c2schat::Packet_info::type_.value() as i64 => {
+ MessageC2S::Chat(MessageC2SChat::parse_from_bytes(&pkt.packet_data)?)
+ },
+ _id if _id == message_c2s::message_c2sping::Packet_info::type_.value() as i64 => {
+ MessageC2S::Ping(MessageC2SPing::parse_from_bytes(&pkt.packet_data)?)
+ }
+ _ => { return Err("Not a C2S packet".into()); }
+ };
+
+ Ok(deser_pkt)
+ }
}
-#[derive(Serialize, Deserialize, Debug, Clone)]
-pub enum GoodbyeReason {
- UnsupportedProtocol { supported: u32, got: u32 },
- UnexpectedPacket,
- UnexpectedNextState,
- UsernameTaken,
- PingPongTimeout,
- Done,
+impl TryInto<Vec<u8>> for MessageC2S {
+ type Error = Box<dyn Error>;
+
+ fn try_into(self) -> Result<Vec<u8>, Self::Error> {
+ let (pkt_id, pkt_bytes) = match self {
+ MessageC2S::Hello(p) => {
+ (message_c2s::message_c2shello::Packet_info::type_.value(), p.write_to_bytes()?)
+ }
+ MessageC2S::Goodbye(p) => {
+ (message_c2s::message_c2sgoodbye::Packet_info::type_.value(), p.write_to_bytes()?)
+ }
+ MessageC2S::Chat(p) => {
+ (message_c2s::message_c2schat::Packet_info::type_.value(), p.write_to_bytes()?)
+ }
+ MessageC2S::Ping(p) => {
+ (message_c2s::message_c2sping::Packet_info::type_.value(), p.write_to_bytes()?)
+ }
+ };
+
+ let pkt = PacketWrapper {
+ packet_id: pkt_id as i64,
+ packet_data: pkt_bytes,
+ special_fields: Default::default(),
+ };
+
+ Ok(pkt.write_to_bytes()?)
+ }
}
-#[derive(Serialize, Deserialize, Debug, Clone)]
-pub struct ProtocolPlanet {
- pub planet_type: PlanetType,
- pub x: f64,
- pub y: f64,
- pub radius: f64
+impl TryFrom<&[u8]> for MessageS2C {
+ type Error = Box<dyn Error>;
+
+ fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
+ let pkt = PacketWrapper::parse_from_bytes(value)?;
+
+ let deser_pkt = match pkt.packet_id {
+ _id if _id == message_s2c::message_s2chello::Packet_info::type_.value() as i64 => {
+ MessageS2C::Hello(MessageS2CHello::parse_from_bytes(&pkt.packet_data)?)
+ },
+ _id if _id == message_s2c::message_s2cgoodbye::Packet_info::type_.value() as i64 => {
+ MessageS2C::Goodbye(MessageS2CGoodbye::parse_from_bytes(&pkt.packet_data)?)
+ },
+ _id if _id == message_s2c::message_s2cchat::Packet_info::type_.value() as i64 => {
+ MessageS2C::Chat(MessageS2CChat::parse_from_bytes(&pkt.packet_data)?)
+ },
+ _id if _id == message_s2c::message_s2cpong::Packet_info::type_.value() as i64 => {
+ MessageS2C::Pong(MessageS2CPong::parse_from_bytes(&pkt.packet_data)?)
+ },
+ _id if _id == message_s2c::message_s2cplayers_update::Packet_info::type_.value() as i64 => {
+ MessageS2C::PlayersUpdate(MessageS2CPlayersUpdate::parse_from_bytes(&pkt.packet_data)?)
+ },
+ _id if _id == message_s2c::message_s2cplanet_data::Packet_info::type_.value() as i64 => {
+ MessageS2C::PlanetData(MessageS2CPlanetData::parse_from_bytes(&pkt.packet_data)?)
+ },
+ _ => { return Err("Not a S2C packet".into()); }
+ };
+
+ Ok(deser_pkt)
+ }
}
-#[derive(Serialize, Deserialize, Debug, Clone)]
-pub enum PlanetType {
- Earth
+impl TryInto<Vec<u8>> for MessageS2C {
+ type Error = Box<dyn Error>;
+
+ fn try_into(self) -> Result<Vec<u8>, Self::Error> {
+ let (pkt_id, pkt_bytes) = match self {
+ MessageS2C::Hello(p) => {
+ (message_s2c::message_s2chello::Packet_info::type_.value(), p.write_to_bytes()?)
+ }
+ MessageS2C::Goodbye(p) => {
+ (message_s2c::message_s2cgoodbye::Packet_info::type_.value(), p.write_to_bytes()?)
+ }
+ MessageS2C::Chat(p) => {
+ (message_s2c::message_s2cchat::Packet_info::type_.value(), p.write_to_bytes()?)
+ }
+ MessageS2C::Pong(p) => {
+ (message_s2c::message_s2cpong::Packet_info::type_.value(), p.write_to_bytes()?)
+ }
+ MessageS2C::PlayersUpdate(p) => {
+ (message_s2c::message_s2cplayers_update::Packet_info::type_.value(), p.write_to_bytes()?)
+ }
+ MessageS2C::PlanetData(p) => {
+ (message_s2c::message_s2cplanet_data::Packet_info::type_.value(), p.write_to_bytes()?)
+ }
+ };
+
+ let pkt = PacketWrapper {
+ packet_id: pkt_id as i64,
+ packet_data: pkt_bytes,
+ special_fields: Default::default(),
+ };
+
+ Ok(pkt.write_to_bytes()?)
+ }
}
-impl PlanetType {
+impl planet::PlanetType {
pub fn as_texture_id(&self) -> String {
match self {
PlanetType::Earth => "earth".to_string()
}
}
-}
-
-pub fn pc2s(pkt: &MessageC2S) -> Vec<u8> {
- rmp_serde::to_vec(pkt).unwrap()
-}
-pub fn ps2c(pkt: &MessageS2C) -> Vec<u8> {
- rmp_serde::to_vec(pkt).unwrap()
-}
+}<
\ No newline at end of file
A protocol/src/pbuf/goodbye_reason.proto => protocol/src/pbuf/goodbye_reason.proto +11 -0
@@ 0,0 1,11 @@
+syntax = "proto3";
+package protocol.goodbye_reason;
+
+enum GoodbyeReason {
+ UnsupportedProtocol = 0;
+ UnexpectedPacket = 1;
+ UnexpectedNextState = 2;
+ UsernameTaken = 3;
+ PingPongTimeout = 4;
+ Done = 5;
+}<
\ No newline at end of file
A protocol/src/pbuf/message_c2s.proto => protocol/src/pbuf/message_c2s.proto +29 -0
@@ 0,0 1,29 @@
+syntax = "proto3";
+package protocol.message_c2s;
+
+import "state.proto";
+import "goodbye_reason.proto";
+
+message MessageC2SHello {
+ enum packet_info { unknown = 0; type = 0x01; }
+
+ uint32 version = 1; // Version of the protocol. Currently always 1
+ string requested_username = 2; // The username that the client is requesting.
+ protocol.state.State next_state = 3; // The state the connection will go into after the handshake.
+}
+
+message MessageC2SGoodbye {
+ enum packet_info { unknown = 0; type = 0x02; }
+
+ protocol.goodbye_reason.GoodbyeReason reason = 1; // The reason the client is disconnecting the server
+}
+
+message MessageC2SChat {
+ enum packet_info { unknown = 0; type = 0x03; }
+
+ string message = 1; // The chat message to sent
+}
+
+message MessageC2SPing {
+ enum packet_info { unknown = 0; type = 0x04; }
+}<
\ No newline at end of file
A protocol/src/pbuf/message_s2c.proto => protocol/src/pbuf/message_s2c.proto +44 -0
@@ 0,0 1,44 @@
+syntax = "proto3";
+package protocol.message_s2c;
+
+import "state.proto";
+import "goodbye_reason.proto";
+import "player.proto";
+import "planet.proto";
+
+message MessageS2CHello {
+ enum packet_info { unknown = 0; type = 0x05; }
+
+ uint32 version = 1; // The version of the protocol in use. Currently always 1.
+ string given_username = 2; // The username actually assigned to the player
+ protocol.state.State next_state = 3; // The state to switch the game into
+}
+
+message MessageS2CGoodbye {
+ enum packet_info { unknown = 0; type = 0x06; }
+
+ protocol.goodbye_reason.GoodbyeReason reason = 1; // The reason for the disconnect
+}
+
+message MessageS2CChat {
+ enum packet_info { unknown = 0; type = 0x07; }
+
+ string from = 1; // The username of the player who sent the message
+ string message = 2; // The contents of the chat message
+}
+
+message MessageS2CPong {
+ enum packet_info { unknown = 0; type = 0x08; }
+}
+
+message MessageS2CPlayersUpdate {
+ enum packet_info { unknown = 0; type = 0x09; }
+
+ repeated protocol.player.Player players = 1; // List of all players in the server
+}
+
+message MessageS2CPlanetData {
+ enum packet_info { unknown = 0; type = 0x0a; }
+
+ repeated protocol.planet.Planet planets = 1; // List of all planets on the server
+}<
\ No newline at end of file
A protocol/src/pbuf/planet.proto => protocol/src/pbuf/planet.proto +13 -0
@@ 0,0 1,13 @@
+syntax = "proto3";
+package protocol.planet;
+
+message Planet {
+ PlanetType planet_type = 1; // Type of the planet
+ float x = 2; // Translation on the X axis, in game units
+ float y = 3; // Translation on the Y axis, in game units
+ float radius = 4; // The radius of the planet extending out from (x, y)
+}
+
+enum PlanetType {
+ Earth = 0;
+}<
\ No newline at end of file
A protocol/src/pbuf/player.proto => protocol/src/pbuf/player.proto +9 -0
@@ 0,0 1,9 @@
+syntax = "proto3";
+package protocol.player;
+
+message Player {
+ float rotation = 1; // The rotation, clockwise, in degrees, of the player
+ float x = 2; // The translation on the X axis, in game units, of the player
+ float y = 3; // The translation on the Y axis, in game units, of the player
+ string username = 4; // The username of the player
+}<
\ No newline at end of file
A protocol/src/pbuf/starkingdoms-protocol.proto => protocol/src/pbuf/starkingdoms-protocol.proto +14 -0
@@ 0,0 1,14 @@
+syntax = "proto3";
+package protocol;
+
+import public "message_c2s.proto";
+import public "state.proto";
+import public "goodbye_reason.proto";
+import public "message_s2c.proto";
+import public "player.proto";
+import public "planet.proto";
+
+message PacketWrapper {
+ int64 packet_id = 1; // What is the Packet ID of this packet?
+ bytes packet_data = 2; // Protobuf-encoded bytearray containing the actual packet
+}<
\ No newline at end of file
A protocol/src/pbuf/state.proto => protocol/src/pbuf/state.proto +7 -0
@@ 0,0 1,7 @@
+syntax = "proto3";
+package protocol.state;
+
+enum State {
+ Handshake = 0;
+ Play = 1;
+}<
\ No newline at end of file
M server/Cargo.toml => server/Cargo.toml +0 -1
@@ 12,7 12,6 @@ slp-description = "A StarKingdoms.TK server"
[dependencies]
tokio = { version = "1.27", features = ["macros", "sync", "rt-multi-thread"] }
serde = { version = "1", features = ["derive"] }
-rmp-serde = { version = "1" }
serde_json = "1"
futures = { version = "0.3", default-features = false }
hyper = { version = "0.14", features = ["server", "http1", "http2", "tcp"] }
M server/src/handler.rs => server/src/handler.rs +79 -56
@@ 12,8 12,10 @@ use tokio::sync::RwLock;
use tokio::sync::mpsc::Receiver;
use tokio_tungstenite::WebSocketStream;
use tungstenite::Message;
-use starkingdoms_protocol::{GoodbyeReason, MessageC2S, MessageS2C, PROTOCOL_VERSION, State};
-use starkingdoms_protocol::GoodbyeReason::PingPongTimeout;
+use starkingdoms_protocol::goodbye_reason::GoodbyeReason;
+use starkingdoms_protocol::message_s2c::{MessageS2CChat, MessageS2CGoodbye, MessageS2CHello, MessageS2CPlanetData, MessageS2CPlayersUpdate, MessageS2CPong};
+use starkingdoms_protocol::{MessageS2C, MessageC2S, PROTOCOL_VERSION};
+use starkingdoms_protocol::state::State;
use crate::manager::{ClientHandlerMessage, ClientManager, PhysicsData, Player};
use crate::{send, recv, SCALE};
@@ 29,24 31,30 @@ pub async fn handle_client(mgr: ClientManager, data: Arc<RwLock<PhysicsData>>, r
ClientHandlerMessage::Tick => {} // this intentionally does nothing,
ClientHandlerMessage::ChatMessage { from, message } => {
if matches!(state, State::Play) {
- send!(client_tx, &MessageS2C::Chat {
+ let msg = MessageS2C::Chat(MessageS2CChat {
+ from,
message,
- from
- }).await?;
+ special_fields: Default::default(),
+ }).try_into()?;
+ send!(client_tx, msg).await?;
}
}
ClientHandlerMessage::PlayersUpdate { players } => {
if matches!(state, State::Play) {
- send!(client_tx, &MessageS2C::PlayersUpdate {
- players
- }).await?;
+ let msg = MessageS2C::PlayersUpdate(MessageS2CPlayersUpdate {
+ players,
+ special_fields: Default::default(),
+ }).try_into()?;
+ send!(client_tx, msg).await?;
}
}
ClientHandlerMessage::PlanetData { planets } => {
if matches!(state, State::Play) {
- send!(client_tx, &MessageS2C::PlanetData {
- planets
- }).await?;
+ let msg = MessageS2C::PlanetData(MessageS2CPlanetData {
+ planets,
+ special_fields: Default::default(),
+ }).try_into()?;
+ send!(client_tx, msg).await?;
}
}
}
@@ 57,9 65,11 @@ pub async fn handle_client(mgr: ClientManager, data: Arc<RwLock<PhysicsData>>, r
if ping_timeout < SystemTime::now() {
error!("[{}] ping timeout", remote_addr);
- send!(client_tx, &MessageS2C::Goodbye {
- reason: PingPongTimeout
- }).await?;
+ let msg = MessageS2C::Goodbye(MessageS2CGoodbye {
+ reason: GoodbyeReason::PingPongTimeout.into(),
+ special_fields: Default::default(),
+ }).try_into()?;
+ send!(client_tx, msg).await?;
break;
}
@@ 67,51 77,57 @@ pub async fn handle_client(mgr: ClientManager, data: Arc<RwLock<PhysicsData>>, r
match state {
State::Handshake => {
match pkt {
- MessageC2S::Hello { version, requested_username, next_state } => {
- if !matches!(next_state, State::Play) {
- error!("client sent unexpected state {:?} (expected: Play)", next_state);
- send!(client_tx, &MessageS2C::Goodbye {
- reason: GoodbyeReason::UnexpectedNextState,
- }).await?;
+ MessageC2S::Hello(pkt) => {
+ if !matches!(pkt.next_state.unwrap(), State::Play) {
+ error!("client sent unexpected state {:?} (expected: Play)", pkt.next_state);
+ let msg = MessageS2C::Goodbye(MessageS2CGoodbye {
+ reason: GoodbyeReason::UnexpectedNextState.into(),
+ special_fields: Default::default(),
+ }).try_into()?;
+ send!(client_tx, msg).await?;
break;
}
// check version
- if version != PROTOCOL_VERSION {
- error!("client sent incompatible version {} (expected: {})", version, PROTOCOL_VERSION);
- send!(client_tx, &MessageS2C::Goodbye {
- reason: GoodbyeReason::UnsupportedProtocol {
- supported: PROTOCOL_VERSION,
- got: version,
- },
- }).await?;
+ if pkt.version != PROTOCOL_VERSION {
+ error!("client sent incompatible version {} (expected: {})", pkt.version, PROTOCOL_VERSION);
+ let msg = MessageS2C::Goodbye(MessageS2CGoodbye {
+ reason: GoodbyeReason::UnsupportedProtocol.into(),
+ special_fields: Default::default(),
+ }).try_into()?;
+ send!(client_tx, msg).await?;
break;
}
// determine if we can give them that username
{
- if mgr.usernames.read().await.values().any(|u| *u == requested_username) {
- error!("client requested username {} but it is in use", requested_username);
- send!(client_tx, &MessageS2C::Goodbye {
- reason: GoodbyeReason::UsernameTaken,
- }).await?;
+ if mgr.usernames.read().await.values().any(|u| *u == pkt.requested_username) {
+ error!("client requested username {} but it is in use", pkt.requested_username);
+ let msg: Vec<u8> = MessageS2C::Goodbye(MessageS2CGoodbye {
+ reason: GoodbyeReason::UsernameTaken.into(),
+ special_fields: Default::default(),
+ }).try_into()?;
+ send!(client_tx, msg).await?;
break;
}
}
// username is fine
{
- mgr.usernames.write().await.insert(remote_addr, requested_username.clone());
+ mgr.usernames.write().await.insert(remote_addr, pkt.requested_username.clone());
}
- send!(client_tx, &MessageS2C::Hello {
- version,
- given_username: requested_username.clone(),
- next_state,
- }).await?;
+ let msg = MessageS2C::Hello(MessageS2CHello {
+ version: pkt.version,
+ given_username: pkt.requested_username.clone(),
+ special_fields: Default::default(),
+ next_state: pkt.next_state,
+ }).try_into()?;
- state = next_state;
- username = requested_username;
+ send!(client_tx, msg).await?;
+
+ state = pkt.next_state.unwrap();
+ username = pkt.requested_username;
// make player rigidbody
{
@@ 134,15 150,17 @@ pub async fn handle_client(mgr: ClientManager, data: Arc<RwLock<PhysicsData>>, r
mgr.players.write().await.insert(remote_addr, Player { handle: player_handle });
}
},
- MessageC2S::Goodbye { reason } => {
- info!("client sent goodbye: {:?}", reason);
+ MessageC2S::Goodbye(pkt) => {
+ info!("client sent goodbye: {:?}", pkt.reason);
break;
},
_ => {
error!("client sent unexpected packet {:?} for state {:?}", pkt, state);
- send!(client_tx, &MessageS2C::Goodbye {
- reason: GoodbyeReason::UnexpectedPacket,
- }).await?;
+ let msg = MessageS2C::Goodbye(MessageS2CGoodbye {
+ reason: GoodbyeReason::UnexpectedPacket.into(),
+ special_fields: Default::default(),
+ }).try_into()?;
+ send!(client_tx, msg).await?;
break;
}
}
@@ 151,20 169,22 @@ pub async fn handle_client(mgr: ClientManager, data: Arc<RwLock<PhysicsData>>, r
match pkt {
MessageC2S::Hello { .. } => {
error!("client sent unexpected packet {:?} for state {:?}", pkt, state);
- send!(client_tx, &MessageS2C::Goodbye {
- reason: GoodbyeReason::UnexpectedPacket,
- }).await?;
+ let msg = MessageS2C::Goodbye(MessageS2CGoodbye {
+ reason: GoodbyeReason::UnexpectedPacket.into(),
+ special_fields: Default::default(),
+ }).try_into()?;
+ send!(client_tx, msg).await?;
break;
},
- MessageC2S::Goodbye { reason } => {
- info!("client sent goodbye: {:?}", reason);
+ MessageC2S::Goodbye(pkt) => {
+ info!("client sent goodbye: {:?}", pkt.reason);
break;
},
- MessageC2S::Chat { message } => {
- info!("[{}] CHAT: [{}] {}", remote_addr, username, message);
+ MessageC2S::Chat(pkt) => {
+ info!("[{}] CHAT: [{}] {}", remote_addr, username, pkt.message);
for (_addr, client_thread) in mgr.handlers.read().await.iter() {
- match client_thread.tx.send(ClientHandlerMessage::ChatMessage { from: username.clone(), message: message.clone() }).await {
+ match client_thread.tx.send(ClientHandlerMessage::ChatMessage { from: username.clone(), message: pkt.message.clone() }).await {
Ok(_) => (),
Err(e) => {
error!("unable to update a client thread: {}", e);
@@ 172,8 192,11 @@ pub async fn handle_client(mgr: ClientManager, data: Arc<RwLock<PhysicsData>>, r
}
}
},
- MessageC2S::Ping {} => {
- send!(client_tx, &MessageS2C::Pong {}).await?;
+ MessageC2S::Ping(_) => {
+ let msg = MessageS2C::Pong(MessageS2CPong {
+ special_fields: Default::default(),
+ }).try_into()?;
+ send!(client_tx, msg).await?;
ping_timeout = SystemTime::now() + Duration::from_secs(10);
}
}
M server/src/macros.rs => server/src/macros.rs +7 -8
@@ 1,13 1,16 @@
-use serde::{Serialize};
use tungstenite::Message;
#[macro_export]
macro_rules! send {
($writer:expr,$pkt:expr) => {
- $writer.send($crate::macros::__generic_packet_to_message($pkt).unwrap())
+ $writer.send($crate::macros::_generic_pkt_into($pkt))
};
}
+pub fn _generic_pkt_into(p: Vec<u8>) -> Message {
+ Message::from(p)
+}
+
#[macro_export]
macro_rules! recv {
($reader:expr) => {
@@ 17,7 20,7 @@ macro_rules! recv {
match msg {
Ok(msg) => {
if msg.is_binary() {
- match rmp_serde::from_slice(&msg.into_data()) {
+ match MessageC2S::try_from(msg.into_data().as_slice()) {
Ok(d) => Ok(Some(d)),
Err(e) => {
log::error!("error deserializing message: {}", e);
@@ 52,7 55,7 @@ macro_rules! recv_now {
match msg {
Ok(msg) => {
if msg.is_binary() {
- match rmp_serde::from_slice(&msg.into_data()) {
+ match MessageC2S::try_from(&msg.into_data()) {
Ok(d) => Ok(Some(d)),
Err(e) => {
log::error!("error deserializing message: {}", e);
@@ 74,8 77,4 @@ macro_rules! recv_now {
}
}
};
-}
-
-pub fn __generic_packet_to_message<T: Serialize>(pkt: &T) -> Result<Message, rmp_serde::encode::Error> {
- rmp_serde::to_vec(&pkt).map(Message::from)
}=
\ No newline at end of file
M server/src/main.rs => server/src/main.rs +1 -1
@@ 6,7 6,7 @@ use hyper::service::{make_service_fn, service_fn};
use manager::PhysicsData;
use nalgebra::vector;
use planet::Planets;
-use rapier2d_f64::prelude::{MultibodyJointSet, ImpulseJointSet, ColliderSet, RigidBodySet, NarrowPhase, BroadPhase, IslandManager, CCDSolver, IntegrationParameters, ColliderBuilder, RigidBodyBuilder, RigidBodyHandle};
+use rapier2d_f64::prelude::{MultibodyJointSet, ImpulseJointSet, ColliderSet, RigidBodySet, NarrowPhase, BroadPhase, IslandManager, CCDSolver, IntegrationParameters};
use tokio_tungstenite::WebSocketStream;
use tungstenite::{handshake};
use futures::stream::StreamExt;
M server/src/manager.rs => server/src/manager.rs +2 -5
@@ 1,11 1,8 @@
use std::collections::HashMap;
-
use std::net::SocketAddr;
use std::sync::Arc;
-
use rapier2d_f64::na::{Vector2};
use rapier2d_f64::prelude::{IntegrationParameters, PhysicsPipeline, IslandManager, BroadPhase, NarrowPhase, ImpulseJointSet, MultibodyJointSet, CCDSolver, RigidBodySet, ColliderSet, RigidBodyHandle};
-use starkingdoms_protocol::{ProtocolPlanet, ProtocolPlayer};
use tokio::sync::mpsc::Sender;
use tokio::sync::RwLock;
@@ 61,6 58,6 @@ impl PhysicsData {
pub enum ClientHandlerMessage {
Tick,
ChatMessage { from: String, message: String },
- PlayersUpdate { players: Vec<ProtocolPlayer> },
- PlanetData { planets: Vec<ProtocolPlanet> },
+ PlayersUpdate { players: Vec<starkingdoms_protocol::player::Player> },
+ PlanetData { planets: Vec<starkingdoms_protocol::planet::Planet> },
}
M server/src/planet.rs => server/src/planet.rs +8 -6
@@ 1,7 1,7 @@
use log::debug;
use nalgebra::{Vector2, vector};
use rapier2d_f64::prelude::{RigidBodyHandle, RigidBodySet, ColliderBuilder, RigidBodyBuilder, ColliderSet};
-use starkingdoms_protocol::{PlanetType, ProtocolPlanet};
+use starkingdoms_protocol::planet::PlanetType;
use crate::{SCALE, manager::ClientHandlerMessage};
@@ 72,11 72,13 @@ impl Planets {
let mut planets = vec![];
for planet in self.planets.clone() {
- planets.push(ProtocolPlanet {
- planet_type: planet.planet_type,
- x: planet.position.0 * SCALE,
- y: planet.position.1 * SCALE,
- radius: planet.radius, // DO NOT * SCALE
+ // TODO: Adjust codegen to use f64
+ planets.push(starkingdoms_protocol::planet::Planet {
+ planet_type: planet.planet_type.into(),
+ x: (planet.position.0 * SCALE) as f32,
+ y: (planet.position.1 * SCALE) as f32,
+ radius: planet.radius as f32, // DO NOT * SCALE
+ special_fields: Default::default(),
});
}
M server/src/timer.rs => server/src/timer.rs +9 -9
@@ 1,11 1,9 @@
-
use std::{time::Duration, sync::Arc};
-use log::{error, debug};
-
+use log::{error};
use nalgebra::vector;
-use rapier2d_f64::prelude::{PhysicsPipeline, RigidBodyHandle};
-use starkingdoms_protocol::{ProtocolPlanet, PlanetType, ProtocolPlayer};
+use rapier2d_f64::prelude::{PhysicsPipeline};
use tokio::{time::sleep, sync::RwLock};
+use starkingdoms_protocol::player::Player;
use crate::{manager::{ClientHandlerMessage, ClientManager, PhysicsData}, SCALE, planet::Planets};
pub async fn timer_main(mgr: ClientManager, physics_data: Arc<RwLock<PhysicsData>>, world_data: Arc<RwLock<Planets>>) {
@@ 35,11 33,13 @@ pub async fn timer_main(mgr: ClientManager, physics_data: Arc<RwLock<PhysicsData
username = usernames.get(player_id).unwrap().clone();
}
- protocol_players.push(ProtocolPlayer {
- rotation: rotation.angle(),
- x: translation.x * SCALE,
- y: translation.y * SCALE,
+ // TODO: Figure out how to adjust codegen to use f64
+ protocol_players.push(Player {
+ rotation: rotation.angle() as f32,
+ x: (translation.x * SCALE) as f32,
+ y: (translation.y * SCALE) as f32,
username,
+ special_fields: Default::default(),
});
}
}