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"));
}
M client/src/lib.rs => client/src/lib.rs +44 -46
@@ 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<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)]
@@ 75,7 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 static ref BUTTONS: Arc<Buttons> = 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<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"));
@@ 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);
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/src/lib.rs => protocol/src/lib.rs +9 -0
@@ 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<Vec<u8>> 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