From bb92723517eb6968fc446dc1654ee6c27eceb751 Mon Sep 17 00:00:00 2001 From: c0repwn3r Date: Thu, 13 Apr 2023 23:43:03 -0400 Subject: [PATCH] translate client to protobuf protocol --- client/src/chat.rs | 10 ++- client/src/lib.rs | 90 +++++++++---------- client/src/macros.rs | 11 ++- .../src/rendering/renderer_playercentric.rs | 14 +-- protocol/src/lib.rs | 9 ++ 5 files changed, 72 insertions(+), 62 deletions(-) diff --git a/client/src/chat.rs b/client/src/chat.rs index ae60dfb23baafaf2cc043bbd497d0430a580f3ef..b682366dfa2aa04eb417eca489917c6f2df1327e 100644 --- a/client/src/chat.rs +++ b/client/src/chat.rs @@ -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 | JsError::new(&e.to_string()))?; + send!(data.tx, msg).await?; } else { return Err(JsError::new("Client not yet connected to server")); } diff --git a/client/src/lib.rs b/client/src/lib.rs index ed79d6711921d30fd976d30558be02dc7aee0c19..55f30f827ea860c296cea2896425ef9f860b414c 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -1,17 +1,11 @@ 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; @@ -20,7 +14,13 @@ 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,13 +33,6 @@ pub mod chat; pub mod rendering; pub mod textures; -pub struct Buttons { - up: bool, - right: bool, - down: bool, - left: bool -} - #[wasm_bindgen] extern { pub fn alert(s: &str); @@ -48,10 +41,10 @@ extern { #[derive(Debug)] pub struct Client { pub client_data: Option, - pub planets: Vec, + pub planets: Vec, pub x: f64, pub y: f64, - pub players: Vec + pub players: Vec } #[derive(Debug)] @@ -75,7 +68,7 @@ lazy_static! { y: 0f64, players: vec![] })); - pub static ref BUTTONS: Arc = Arc::new(Buttons { up: false, left: false, right: false, down: false }); + //pub static ref BUTTONS: Arc = Arc::new(Buttons { up: false, left: false, right: false, down: false }); } pub const MAX_CONNECTION_TRIES: i32 = 10; @@ -158,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"); @@ -170,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); @@ -203,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(()) } @@ -221,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 | 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")); @@ -238,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"); @@ -252,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); diff --git a/client/src/macros.rs b/client/src/macros.rs index fe1f822bf1f6cc779604f458a3946beb57690664..5eba8726c9b6c94606bf4b69f107e136412544df 100644 --- a/client/src/macros.rs +++ b/client/src/macros.rs @@ -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(pkt: &T) -> Result { - rmp_serde::to_vec(&pkt).map(WsMessage::from) +pub fn __generic_packet_to_message(pkt: Vec) -> WsMessage { + WsMessage::from(pkt) } \ No newline at end of file diff --git a/client/src/rendering/renderer_playercentric.rs b/client/src/rendering/renderer_playercentric.rs index 28c3305f65ef788a45ff2de8adab201ce751412c..1969b928fb9bc9998cb8ac1bbc655d07ff4ae935 100644 --- a/client/src/rendering/renderer_playercentric.rs +++ b/client/src/rendering/renderer_playercentric.rs @@ -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::().unwrap(); + let texture_image = document.get_element_by_id(&format!("tex-{}", planet.planet_type.unwrap().as_texture_id())).unwrap().dyn_into::().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::().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())?; diff --git a/protocol/src/lib.rs b/protocol/src/lib.rs index a860ceec7d8241d908aebb907b5a59dc2744b5ca..17ce7ab46d4b560371abd3e518f9211629c65b81 100644 --- a/protocol/src/lib.rs +++ b/protocol/src/lib.rs @@ -2,6 +2,7 @@ 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")); @@ -145,4 +146,12 @@ impl TryInto> for MessageS2C { Ok(pkt.write_to_bytes()?) } +} + +impl planet::PlanetType { + pub fn as_texture_id(&self) -> String { + match self { + PlanetType::Earth => "earth".to_string() + } + } } \ No newline at end of file