M Cargo.lock => Cargo.lock +12 -0
@@ 29,6 29,17 @@ dependencies = [
]
[[package]]
+name = "async-trait"
+version = "0.1.68"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.13",
+]
+
+[[package]]
name = "async_io_stream"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 1052,6 1063,7 @@ name = "starkingdoms-client"
version = "0.1.0"
dependencies = [
"async-recursion",
+ "async-trait",
"console_error_panic_hook",
"console_log",
"futures",
M client/Cargo.toml => client/Cargo.toml +3 -2
@@ 24,13 24,14 @@ lazy_static = "1.4"
markdown = "1.0.0-alpha.7" # DO NOT DOWNGRADE
async-recursion = "1"
console_error_panic_hook = "0.1"
+async-trait = "0.1.68"
[dependencies.web-sys]
version = "0.3.4"
features = [
'Document',
'Element',
- 'HtmlElement',
- 'Node',
+ 'HtmlCanvasElement',
'Window',
+ 'CanvasRenderingContext2d'
]=
\ No newline at end of file
M client/src/lib.rs => client/src/lib.rs +47 -22
@@ 17,62 17,87 @@ use std::sync::RwLock;
use async_recursion::async_recursion;
use futures::FutureExt;
use wasm_bindgen_futures::JsFuture;
-use web_sys::Window;
+use web_sys::{Window};
use starkingdoms_protocol::GoodbyeReason::PingPongTimeout;
+use crate::rendering::renderer::WebRenderer;
+
#[macro_use]
pub mod macros;
pub mod chat;
+pub mod rendering;
#[wasm_bindgen]
extern {
pub fn alert(s: &str);
}
+pub struct Client {
+ pub client_data: Option<ClientData>
+}
+
+pub struct ClientData {
+ pub state: State,
+ pub tx: SplitSink<WsStream, WsMessage>,
+ pub rx: SplitStream<WsStream>,
+ pub pong_timeout: u64
+}
+
+pub const PONG_MAX_TIMEOUT: u64 = 5;
+
+lazy_static! {
+ pub static ref CLIENT: Arc<RwLock<Client>> = Arc::new(RwLock::new(Client {
+ client_data: None,
+ renderer: None
+ }));
+}
+
+pub const MAX_CONNECTION_TRIES: i32 = 10;
+
#[wasm_bindgen]
-pub async fn rust_init(gateway: &str, username: &str) -> Result<(), JsError> {
+pub async fn rust_init(gateway: &str, username: &str) -> Result<(), JsValue> {
console_error_panic_hook::set_once();
set_status("Starting logger...");
console_log::init_with_level(Level::Debug).unwrap();
-
info!("Logger setup successfully");
match main(gateway, username, 1).await {
Ok(c) => c,
Err(e) => {
error!("Error initializing gateway client: {}", e);
- return Err(JsError::new(&e.to_string()));
+ return Err(JsValue::from_str(&e.to_string()));
}
};
- info!("Gateway client set up successfully");
+ let mut client = CLIENT.write().unwrap();
- Ok(())
-}
+ set_status("Initializing render subsystem...");
+ info!("Starting renderer");
-pub struct Client {
- pub client_data: Option<ClientData>,
-}
+ let renderer = match WebRenderer::init().await {
+ Ok(renderer) => renderer,
+ Err(e) => {
+ error!("Error initializing WebRenderer: {}", e);
+ return Err(JsValue::from_str(&e.to_string()));
+ }
+ };
-pub struct ClientData {
- pub state: State,
- pub tx: SplitSink<WsStream, WsMessage>,
- pub rx: SplitStream<WsStream>,
- pub pong_timeout: u64
-}
+ client.renderer = Some(renderer);
-pub const PONG_MAX_TIMEOUT: u64 = 5;
+ info!("StarKingdoms client set up successfully");
-lazy_static! {
- pub static ref CLIENT: Arc<RwLock<Client>> = Arc::new(RwLock::new(Client {
- client_data: None
- }));
+ Ok(())
}
-pub const MAX_CONNECTION_TRIES: i32 = 10;
+fn draw(context: &WebGl2RenderingContext, vert_count: i32) {
+ context.clear_color(0.0, 0.0, 0.0, 1.0);
+ context.clear(WebGl2RenderingContext::COLOR_BUFFER_BIT);
+
+ context.draw_arrays(WebGl2RenderingContext::TRIANGLES, 0, vert_count);
+}
#[async_recursion(?Send)]
pub async fn main(gateway: &str, username: &str, backoff: i32) -> Result<(), Box<dyn Error>> {
A client/src/rendering/mod.rs => client/src/rendering/mod.rs +10 -0
@@ 0,0 1,10 @@
+use std::error::Error;
+use async_trait::async_trait;
+
+pub mod renderer;
+pub mod texture;
+
+#[async_trait]
+pub trait Renderer {
+ async fn get(canvas_element_id: &str) -> Result<Self, Box<dyn Error>> where Self: Sized;
+}<
\ No newline at end of file
A client/src/rendering/renderer.rs => client/src/rendering/renderer.rs +25 -0
@@ 0,0 1,25 @@
+use std::error::Error;
+use async_trait::async_trait;
+use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement};
+use crate::rendering::Renderer;
+use wasm_bindgen::JsCast;
+
+pub struct WebRenderer {
+ canvas: HtmlCanvasElement,
+ context: CanvasRenderingContext2d
+}
+
+#[async_trait]
+impl Renderer for WebRenderer {
+ async fn get(canvas_element_id: &str) -> Result<Self, Box<dyn Error>> {
+ let window = web_sys::window().ok_or("window needs to exist")?;
+ let document = window.document().ok_or("window.document needs to exist")?;
+ let canvas_element = document.get_element_by_id(canvas_element_id).ok_or("canvas element does not exist")?;
+ let typed_canvas_element: HtmlCanvasElement = canvas_element.dyn_into::<web_sys::HtmlCanvasElement>().map_err(|_| ()).unwrap();
+ let context = typed_canvas_element.get_context("2d").unwrap().unwrap().dyn_into::<CanvasRenderingContext2d>().unwrap();
+ Ok(Self {
+ canvas: typed_canvas_element,
+ context
+ })
+ }
+}<
\ No newline at end of file
A client/src/rendering/texture.rs => client/src/rendering/texture.rs +0 -0
M web/play.html => web/play.html +2 -0
@@ 18,6 18,8 @@
<p id="status">Loading WASM module...</p>
</div>
+ <canvas style="width: 100%; height: 100%" id="canvas"></canvas>
+
<script type="module">
// If you're getting build errors here | you need to run `just build_client_bundle` first, to compile client code
// v