From 1286ad4253f09c965ae14ff9a2694acd6d9e2396 Mon Sep 17 00:00:00 2001 From: core Date: Mon, 24 Mar 2025 19:16:09 -0400 Subject: [PATCH] format --- crates/client/src/components.rs | 28 +- crates/client/src/lib.rs | 23 +- crates/client/src/networking/mod.rs | 103 +++-- crates/client/src/networking/ws_native.rs | 27 +- crates/client/src/networking/ws_wasm.rs | 47 ++- crates/client/src/rendering/assets_native.rs | 24 +- crates/client/src/rendering/assets_wasm.rs | 52 ++- crates/client/src/rendering/mod.rs | 401 +++++++++++++------ 8 files changed, 503 insertions(+), 202 deletions(-) diff --git a/crates/client/src/components.rs b/crates/client/src/components.rs index c49bd96c7f32d074577ef6e96f392ef0b1f4949e..c26c75321dceaa42b8ebdc9ed50d0f6677561f7d 100644 --- a/crates/client/src/components.rs +++ b/crates/client/src/components.rs @@ -15,7 +15,9 @@ pub struct Transform { } impl Transform { pub fn to_matrix(&self) -> Matrix4 { - self.translation.to_homogeneous() * self.rotation.to_homogeneous().to_homogeneous() * self.scale.to_homogeneous() + self.translation.to_homogeneous() + * self.rotation.to_homogeneous().to_homogeneous() + * self.scale.to_homogeneous() } } @@ -30,7 +32,7 @@ pub struct Camera { pub x: f32, pub y: f32, pub zoom: f32, - pub width: u32, // screen width (these are for aspect ratio) + pub width: u32, // screen width (these are for aspect ratio) pub height: u32, // screen height } impl Camera { @@ -38,17 +40,29 @@ impl Camera { let x_scale = self.zoom / self.width as f32 * 2.0; let y_scale = self.zoom / self.height as f32 * 2.0; Matrix4::from_vec(vec![ - x_scale, 0.0, 0.0, 0.0, - 0.0, y_scale, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - self.x*x_scale, self.y*y_scale, 0.0, 1.0, + x_scale, + 0.0, + 0.0, + 0.0, + 0.0, + y_scale, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + self.x * x_scale, + self.y * y_scale, + 0.0, + 1.0, ]) } pub fn to_cursor_matrix(&self) -> Matrix3 { let x = -(self.width as f32 / 2.0); let y = -(self.height as f32 / 2.0); Translation2::new(-self.x, -self.y).to_homogeneous() - * Scale2::new(1.0/self.zoom, 1.0/self.zoom).to_homogeneous() + * Scale2::new(1.0 / self.zoom, 1.0 / self.zoom).to_homogeneous() * Translation2::new(x, y).to_homogeneous() } } diff --git a/crates/client/src/lib.rs b/crates/client/src/lib.rs index 5da87b168bd8ff1f0dcfc9ca4fde012b3d99a022..b0ddd0259caba5776ff1cfc495d38455bafef93a 100644 --- a/crates/client/src/lib.rs +++ b/crates/client/src/lib.rs @@ -14,9 +14,9 @@ pub mod platform; #[path = "native/mod.rs"] pub mod platform; -pub mod rendering; pub mod components; pub mod networking; +pub mod rendering; // Hi, you've found the real main function! This is called AFTER platform-specific initialization code. pub fn start() { @@ -47,14 +47,23 @@ pub fn start() { let mut send_packet_events = Events::::default(); let recv_packet_events = Events::::default(); - world.spawn((Transform { - translation: Translation3::new(0.0, 0.0, 0.0), - rotation: Rotation2::new(0.0), - scale: Scale3::new(25.0, 25.0, 1.0), - }, Texture { name: "hearty.svg".to_string() }, Player, Part(false))); + world.spawn(( + Transform { + translation: Translation3::new(0.0, 0.0, 0.0), + rotation: Rotation2::new(0.0), + scale: Scale3::new(25.0, 25.0, 1.0), + }, + Texture { + name: "hearty.svg".to_string(), + }, + Player, + Part(false), + )); let event_loop = EventLoop::new().unwrap(); event_loop.set_control_flow(ControlFlow::Wait); - event_loop.run_app(&mut App::new(world, send_packet_events, recv_packet_events)).unwrap(); + event_loop + .run_app(&mut App::new(world, send_packet_events, recv_packet_events)) + .unwrap(); } diff --git a/crates/client/src/networking/mod.rs b/crates/client/src/networking/mod.rs index 7c657269418121ca897d5c302824555ba873416a..65a1ed5e6ba3443c403e733034b23193f2ef6e58 100644 --- a/crates/client/src/networking/mod.rs +++ b/crates/client/src/networking/mod.rs @@ -1,10 +1,18 @@ use std::collections::HashMap; -use bevy_ecs::{entity::Entity, event::Events, query::{QuerySingleError, With}, world::World}; +use bevy_ecs::{ + entity::Entity, + event::Events, + query::{QuerySingleError, With}, + world::World, +}; use nalgebra::{Rotation2, Scale2, Scale3, Translation3}; use starkingdoms_common::{packet::Packet, PartType, PlanetType}; -use crate::components::{Camera, Part, Planet, Player, RecvPacket, SendPacket, ServerId, SpriteBundle, Texture, Transform}; +use crate::components::{ + Camera, Part, Planet, Player, RecvPacket, SendPacket, ServerId, SpriteBundle, Texture, + Transform, +}; #[cfg(target_arch = "wasm32")] #[path = "ws_wasm.rs"] @@ -23,7 +31,8 @@ fn texture_name(part_type: PartType, attached: bool) -> String { Hub => "hub_on.svg", LandingThruster => "landingthruster_on.svg", LandingThrusterSuspension => "landingleg.svg", - }.to_string() + } + .to_string() } else { match part_type { Placeholder => panic!("AHHHH PLACEHOLDER PANIC"), @@ -32,7 +41,8 @@ fn texture_name(part_type: PartType, attached: bool) -> String { Hub => "hub_off.svg", LandingThruster => "landingthruster_off.svg", LandingThrusterSuspension => "landingleg.svg", - }.to_string() + } + .to_string() } } @@ -53,36 +63,52 @@ pub fn process_packets( let entity = player_query.single(world); world.entity_mut(entity).insert(ServerId(*id)); } - PlayerList { players } => { // existing players + PlayerList { players } => { + // existing players // username sync, eventually for player in players { - world.spawn((Transform { - translation: Translation3::new(0.0, 0.0, 0.0), - rotation: Rotation2::new(0.0), - scale: Scale3::new(25.0, 25.0, 1.0), - }, Texture { - name: "hearty.svg".to_string(), - }, ServerId(player.0), Part(false))); + world.spawn(( + Transform { + translation: Translation3::new(0.0, 0.0, 0.0), + rotation: Rotation2::new(0.0), + scale: Scale3::new(25.0, 25.0, 1.0), + }, + Texture { + name: "hearty.svg".to_string(), + }, + ServerId(player.0), + Part(false), + )); } } SpawnPlayer { id, username } => { // username sync, eventually - world.spawn((Transform { - translation: Translation3::new(0.0, 0.0, 0.0), - rotation: Rotation2::new(0.0), - scale: Scale3::new(25.0, 25.0, 1.0), - }, Texture { - name: "hearty.svg".to_string(), - }, ServerId(*id), Part(false))); + world.spawn(( + Transform { + translation: Translation3::new(0.0, 0.0, 0.0), + rotation: Rotation2::new(0.0), + scale: Scale3::new(25.0, 25.0, 1.0), + }, + Texture { + name: "hearty.svg".to_string(), + }, + ServerId(*id), + Part(false), + )); } SpawnPart { id, part } => { - world.spawn((Transform { - translation: Translation3::new(part.transform.x, part.transform.y, 0.0), - rotation: Rotation2::new(part.transform.rot), - scale: Scale3::new(25.0, 25.0, 1.0), - }, Texture { - name: texture_name(part.part_type, part.flags.attached), - }, ServerId(*id), Part(part.flags.attached))); + world.spawn(( + Transform { + translation: Translation3::new(part.transform.x, part.transform.y, 0.0), + rotation: Rotation2::new(part.transform.rot), + scale: Scale3::new(25.0, 25.0, 1.0), + }, + Texture { + name: texture_name(part.part_type, part.flags.attached), + }, + ServerId(*id), + Part(part.flags.attached), + )); } PartPositions { parts } => { for (id, part) in parts { @@ -97,7 +123,7 @@ pub fn process_packets( QuerySingleError::MultipleEntities(s) => { panic!("There should never multiple players marked as players"); } - } + }, }; if server_id.0 == *id { let mut camera = world.resource_mut::(); @@ -105,8 +131,13 @@ pub fn process_packets( camera.y = -part.transform.y; } } - let mut part_query = world.query::<(Entity, &ServerId, &mut Transform, &mut Texture, &mut Part)>(); - for (entity, server_id, mut transform, mut texture, mut bevy_part) in part_query.iter_mut(world) { + let mut part_query = + world + .query::<(Entity, &ServerId, &mut Transform, &mut Texture, &mut Part)>( + ); + for (entity, server_id, mut transform, mut texture, mut bevy_part) in + part_query.iter_mut(world) + { if server_id.0 == *id { transform.translation.x = part.transform.x; transform.translation.y = part.transform.y; @@ -129,7 +160,11 @@ pub fn process_packets( if !planet_types.contains_key(&planet.planet_type) { let entity = world.spawn(SpriteBundle { transform: Transform { - translation: Translation3::new(planet.transform.x, planet.transform.y, 0.0), + translation: Translation3::new( + planet.transform.x, + planet.transform.y, + 0.0, + ), rotation: Rotation2::new(planet.transform.rot), scale: Scale3::new(planet.radius, planet.radius, 1.0), }, @@ -157,14 +192,18 @@ pub fn process_packets( PlanetType::Uranus => "venus.svg", PlanetType::Neptune => "mars.svg", PlanetType::Pluto => "earth.svg", - }.to_string() + } + .to_string(), }, }); planet_types.insert(planet.planet_type, (entity.id(), *server_id)); } } } - EnergyUpdate { amount: m_amount, max: m_max } => { + EnergyUpdate { + amount: m_amount, + max: m_max, + } => { *amount = *m_amount; *max = *m_max; } diff --git a/crates/client/src/networking/ws_native.rs b/crates/client/src/networking/ws_native.rs index 61a07169c88058d531241e96b0f4e53e0e888a50..cee8db9718d430034c4701f90241c7bc42690171 100644 --- a/crates/client/src/networking/ws_native.rs +++ b/crates/client/src/networking/ws_native.rs @@ -1,4 +1,7 @@ -use std::{net::TcpStream, sync::{Arc, Mutex}}; +use std::{ + net::TcpStream, + sync::{Arc, Mutex}, +}; use bevy_ecs::system::Resource; use crossbeam::channel::{unbounded, Receiver, Sender}; @@ -22,7 +25,11 @@ impl PacketMessageConvert for Packet { } } fn into_message(&self) -> Message { - Message::Text(serde_json::to_string(self).expect("failed to serialize packet to json").into()) + Message::Text( + serde_json::to_string(self) + .expect("failed to serialize packet to json") + .into(), + ) } } @@ -43,9 +50,15 @@ impl Ws { std::thread::spawn(move || { let socket = socket_clone; loop { - let message = socket.lock().unwrap().read().expect("Failed to reading message"); + let message = socket + .lock() + .unwrap() + .read() + .expect("Failed to reading message"); let packet = Packet::from_message(&message).expect("Server sent invalid packet"); - packet_sender.send(packet).expect("Couldn't send packet to server"); + packet_sender + .send(packet) + .expect("Couldn't send packet to server"); } }); Ws { @@ -56,6 +69,10 @@ impl Ws { } } pub fn send_packet(&mut self, packet: &Packet) { - self.socket.lock().unwrap().send(packet.into_message()).expect("Couldn't send packet to server"); + self.socket + .lock() + .unwrap() + .send(packet.into_message()) + .expect("Couldn't send packet to server"); } } diff --git a/crates/client/src/networking/ws_wasm.rs b/crates/client/src/networking/ws_wasm.rs index c438a92aa05f4ea335f5e0f741e5b49666dcb370..340e868bcfece1d50bedf3ca4b8a93db57853517 100644 --- a/crates/client/src/networking/ws_wasm.rs +++ b/crates/client/src/networking/ws_wasm.rs @@ -2,11 +2,14 @@ use std::thread::yield_now; use bevy_ecs::system::Resource; //use crossbeam::channel::{unbounded, Receiver, Sender}; -use futures::{channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender}, SinkExt}; +use futures::{ + channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender}, + SinkExt, +}; +use starkingdoms_common::packet::Packet; use wasm_bindgen::{prelude::Closure, JsCast, JsValue}; use wasm_bindgen_futures::spawn_local; use web_sys::{MessageEvent, WebSocket}; -use starkingdoms_common::packet::Packet; const PORT: u16 = 3000; @@ -26,8 +29,12 @@ pub struct Ws { impl Ws { pub fn new() -> Self { let window = web_sys::window().unwrap(); - let ws = WebSocket::new(&format!("ws://{}:{}", - window.location().hostname().unwrap(), PORT)).expect("Couldn't connect to server"); + let ws = WebSocket::new(&format!( + "ws://{}:{}", + window.location().hostname().unwrap(), + PORT + )) + .expect("Couldn't connect to server"); let (packet_sender, receiver) = unbounded(); //let packet_sender = Rc::new(RwLock::new(packet_sender)); let (sender, packet_receiver) = unbounded(); @@ -40,17 +47,28 @@ impl Ws { jwt: None, }; - ws_clone.send_with_str(&serde_json::to_string(&packet).expect("Couldn't convert packet to string")).expect("Failed to send packet"); + ws_clone + .send_with_str( + &serde_json::to_string(&packet).expect("Couldn't convert packet to string"), + ) + .expect("Failed to send packet"); }); ws.set_onopen(Some(onopen_callback.as_ref().unchecked_ref())); onopen_callback.forget(); let onmessage_callback = Closure::::new(move |e: MessageEvent| { //tracing::error!("{}", ws.ready_state()); - let data = e.data().as_string().expect("Expected string, found some other type"); - let data: Packet = serde_json::from_str(&data).expect("Received invalid json from server"); + let data = e + .data() + .as_string() + .expect("Expected string, found some other type"); + let data: Packet = + serde_json::from_str(&data).expect("Received invalid json from server"); let mut sender_clone = packet_sender.clone(); spawn_local(async move { - sender_clone.send(data).await.expect("Couldn't transmit packet to client"); + sender_clone + .send(data) + .await + .expect("Couldn't transmit packet to client"); }); }); ws.set_onmessage(Some(onmessage_callback.as_ref().unchecked_ref())); @@ -65,14 +83,23 @@ impl Ws { pub fn send_all_packets_from_channel(&mut self) { //for packet in self.packet_receiver.iter() { while let Ok(Some(packet)) = self.packet_receiver.try_next() { - self.socket.0.send_with_str(&serde_json::to_string(&packet).expect("Couldn't convert packet to json")).expect("Couldn't send packet to server"); + self.socket + .0 + .send_with_str( + &serde_json::to_string(&packet).expect("Couldn't convert packet to json"), + ) + .expect("Couldn't send packet to server"); } } pub fn send_packet(&mut self, packet: Packet) { let socket = self.socket.0.clone(); spawn_local(async move { //while socket.ready_state() != 1 { } - socket.send_with_str(&serde_json::to_string(&packet).expect("Couldn't convert packet to json")).expect("Couldn't send packet to server"); + socket + .send_with_str( + &serde_json::to_string(&packet).expect("Couldn't convert packet to json"), + ) + .expect("Couldn't send packet to server"); }); } } diff --git a/crates/client/src/rendering/assets_native.rs b/crates/client/src/rendering/assets_native.rs index e55b80aea13bffce44cc375929c9db58d8f97678..f04e9b4968a3ca92c9d193916b69ede0cc7725d8 100644 --- a/crates/client/src/rendering/assets_native.rs +++ b/crates/client/src/rendering/assets_native.rs @@ -11,12 +11,10 @@ pub struct ImgData { } #[derive(Resource)] -pub struct Assets { - -} +pub struct Assets {} impl Assets { pub fn new() -> Self { - Assets { } + Assets {} } pub fn get(&self, local_path: impl Into) -> Option { let local_path = local_path.into(); @@ -26,18 +24,27 @@ impl Assets { default_size: usvg::Size::from_wh(20.0, 20.0).unwrap(), ..Default::default() }; - let tree = usvg::Tree::from_data(&bytes, &opt).expect(&format!("Couldn't parse svg {}", local_path)); + let tree = usvg::Tree::from_data(&bytes, &opt) + .expect(&format!("Couldn't parse svg {}", local_path)); let tree_size = tree.size().to_int_size(); let size = usvg::Size::from_wh(200.0, 200.0).unwrap().to_int_size(); assert!(size.width() > 0 && size.height() > 0); - let mut pixmap = tiny_skia::Pixmap::new(size.width(), size.height()).expect("Failed to construct pixmap"); - resvg::render(&tree, tiny_skia::Transform::from_scale((size.width() as f32)/(tree_size.height() as f32), (size.height() as f32)/(tree_size.height() as f32)), &mut pixmap.as_mut()); + let mut pixmap = tiny_skia::Pixmap::new(size.width(), size.height()) + .expect("Failed to construct pixmap"); + resvg::render( + &tree, + tiny_skia::Transform::from_scale( + (size.width() as f32) / (tree_size.height() as f32), + (size.height() as f32) / (tree_size.height() as f32), + ), + &mut pixmap.as_mut(), + ); let data = ImgData { bytes: pixmap.data().to_vec(), width: size.width(), height: size.height(), }; - + Some(data) } else if local_path.ends_with(".png") { let img = image::load_from_memory(&bytes).unwrap(); @@ -53,4 +60,3 @@ impl Assets { } } } - diff --git a/crates/client/src/rendering/assets_wasm.rs b/crates/client/src/rendering/assets_wasm.rs index 4919ed8c12afa34ce6454e5463eb4e8cb1a44470..df726c80f5d282c5fcfd6c0a6d7b2023fd5ae7fb 100644 --- a/crates/client/src/rendering/assets_wasm.rs +++ b/crates/client/src/rendering/assets_wasm.rs @@ -1,4 +1,8 @@ -use std::{collections::HashMap, fmt::Display, sync::{Arc, Mutex}}; +use std::{ + collections::HashMap, + fmt::Display, + sync::{Arc, Mutex}, +}; use bevy_ecs::system::Resource; use image::EncodableLayout; @@ -42,40 +46,54 @@ impl Assets { } pub fn get(&self, local_path: impl Into) -> Option { let local_path = local_path.into(); - let contains_texture = { - self.textures.lock().unwrap().contains_key(&local_path) - }; + let contains_texture = { self.textures.lock().unwrap().contains_key(&local_path) }; let contains_texture_promise = { - self.texture_promises.lock().unwrap().contains_key(&local_path) + self.texture_promises + .lock() + .unwrap() + .contains_key(&local_path) }; if !contains_texture && !contains_texture_promise { let local_path_clone = local_path.clone(); let request_promise = poll_promise::Promise::spawn_local(async move { let window = web_sys::window().unwrap(); - let request = ehttp::Request::get(format!("{}/src/assets/{}", window.location().origin().unwrap(), local_path_clone)); + let request = ehttp::Request::get(format!( + "{}/src/assets/{}", + window.location().origin().unwrap(), + local_path_clone + )); let response = match ehttp::fetch_async(request).await { Ok(resp) => resp, Err(e) => { panic!("{}", e); - }, + } }; if local_path_clone.ends_with(".svg") { let opt = usvg::Options { default_size: usvg::Size::from_wh(20.0, 20.0).unwrap(), ..Default::default() }; - let tree = usvg::Tree::from_data(&response.bytes, &opt).expect(&format!("Couldn't parse svg {}", local_path_clone)); + let tree = usvg::Tree::from_data(&response.bytes, &opt) + .expect(&format!("Couldn't parse svg {}", local_path_clone)); let tree_size = tree.size().to_int_size(); let size = usvg::Size::from_wh(512.0, 512.0).unwrap().to_int_size(); assert!(size.width() > 0 && size.height() > 0); - let mut pixmap = tiny_skia::Pixmap::new(size.width(), size.height()).expect("Failed to construct pixmap"); - resvg::render(&tree, tiny_skia::Transform::from_scale((size.width() as f32)/(tree_size.height() as f32), (size.height() as f32)/(tree_size.height() as f32)), &mut pixmap.as_mut()); + let mut pixmap = tiny_skia::Pixmap::new(size.width(), size.height()) + .expect("Failed to construct pixmap"); + resvg::render( + &tree, + tiny_skia::Transform::from_scale( + (size.width() as f32) / (tree_size.height() as f32), + (size.height() as f32) / (tree_size.height() as f32), + ), + &mut pixmap.as_mut(), + ); let data = ImgData { bytes: pixmap.data().to_vec(), width: size.width(), height: size.height(), }; - + data } else if local_path_clone.ends_with(".png") { let img = image::load_from_memory(&response.bytes).unwrap(); @@ -91,7 +109,10 @@ impl Assets { } }); { - self.texture_promises.lock().unwrap().insert(local_path.clone(), request_promise); + self.texture_promises + .lock() + .unwrap() + .insert(local_path.clone(), request_promise); } None } else if !contains_texture { @@ -99,11 +120,14 @@ impl Assets { let promise = texture_promises.get_mut(&local_path).unwrap(); let mut returned_value = None; if let Some(texture) = promise.ready() { - self.textures.lock().unwrap().insert(local_path.clone(), texture.clone()); + self.textures + .lock() + .unwrap() + .insert(local_path.clone(), texture.clone()); returned_value = Some(texture.clone()); texture_promises.remove(&local_path); } - return returned_value + return returned_value; } else { self.textures.lock().unwrap().get(&local_path).cloned() } diff --git a/crates/client/src/rendering/mod.rs b/crates/client/src/rendering/mod.rs index d43f57ddce10140504f00418aa911af5715e8061..d2904704cafab3028edc70efce26d6575d848949 100644 --- a/crates/client/src/rendering/mod.rs +++ b/crates/client/src/rendering/mod.rs @@ -11,9 +11,14 @@ use egui::{Label, ProgressBar}; use egui_glow::EguiGlow; use glow::{HasContext, PixelUnpackData}; #[cfg(not(target_arch = "wasm32"))] -use glutin::surface::{Surface, WindowSurface, GlSurface, SwapInterval}; +use glutin::surface::{GlSurface, Surface, SwapInterval, WindowSurface}; #[cfg(not(target_arch = "wasm32"))] -use glutin::{config::{ConfigTemplateBuilder, GlConfig}, context::{ContextApi, ContextAttributesBuilder, PossiblyCurrentContext}, display::GetGlDisplay, prelude::{GlDisplay, NotCurrentGlContext}}; +use glutin::{ + config::{ConfigTemplateBuilder, GlConfig}, + context::{ContextApi, ContextAttributesBuilder, PossiblyCurrentContext}, + display::GetGlDisplay, + prelude::{GlDisplay, NotCurrentGlContext}, +}; #[cfg(not(target_arch = "wasm32"))] use glutin_winit::{DisplayBuilder, GlWindow}; use nalgebra::{Vector3, Vector4}; @@ -29,15 +34,22 @@ use winit::event_loop::ControlFlow; use winit::keyboard::{KeyCode, PhysicalKey}; #[cfg(target_arch = "wasm32")] use winit::platform::web::{WindowAttributesExtWebSys, WindowExtWebSys}; -use winit::{application::ApplicationHandler, dpi::LogicalSize, event::WindowEvent, event_loop::ActiveEventLoop, raw_window_handle::HasWindowHandle, window::{Window, WindowAttributes}}; +use winit::{ + application::ApplicationHandler, + dpi::LogicalSize, + event::WindowEvent, + event_loop::ActiveEventLoop, + raw_window_handle::HasWindowHandle, + window::{Window, WindowAttributes}, +}; use crate::components::{Camera, Player, RecvPacket, SendPacket, Texture, Transform}; use crate::networking::process_packets; use crate::networking::ws::Ws; -#[cfg(not(target_arch="wasm32"))] +#[cfg(not(target_arch = "wasm32"))] #[path = "assets_native.rs"] pub mod assets; -#[cfg(target_arch="wasm32")] +#[cfg(target_arch = "wasm32")] #[path = "assets_wasm.rs"] pub mod assets; @@ -73,21 +85,15 @@ pub struct App { } const VERTICES: [f32; 16] = [ - -1.0, -1.0, 0.0, 1.0, - 1.0, -1.0, 1.0, 1.0, - 1.0, 1.0, 1.0, 0.0, - -1.0, 1.0, 0.0, 0.0, -]; -const INDICES: [u32; 6] = [ - 0, 1, 2, - 2, 3, 0, + -1.0, -1.0, 0.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, -1.0, 1.0, 0.0, 0.0, ]; +const INDICES: [u32; 6] = [0, 1, 2, 2, 3, 0]; impl App { pub fn new( world: World, send_packet_events: Events, - recv_packet_events: Events + recv_packet_events: Events, ) -> Self { Self { world, @@ -104,28 +110,53 @@ impl ApplicationHandler for App { let attributes = { let document = web_sys::window().unwrap().document().unwrap(); let canvas = document.get_element_by_id("canvas").unwrap(); - let canvas = canvas.dyn_into::() - .map_err(|_| ()).unwrap(); - canvas.set_width(web_sys::window().unwrap().inner_width().unwrap().as_f64().unwrap() as u32); - canvas.set_height(web_sys::window().unwrap().inner_height().unwrap().as_f64().unwrap() as u32); + let canvas = canvas + .dyn_into::() + .map_err(|_| ()) + .unwrap(); + canvas.set_width( + web_sys::window() + .unwrap() + .inner_width() + .unwrap() + .as_f64() + .unwrap() as u32, + ); + canvas.set_height( + web_sys::window() + .unwrap() + .inner_height() + .unwrap() + .as_f64() + .unwrap() as u32, + ); Window::default_attributes() .with_title("StarKingdoms.TK") .with_canvas(Some(canvas)) }; #[cfg(not(target_arch = "wasm32"))] let attributes = { - Window::default_attributes().with_transparent(true).with_title("StarKingdoms.TK") + Window::default_attributes() + .with_transparent(true) + .with_title("StarKingdoms.TK") .with_inner_size(LogicalSize::new(400, 300)) }; self.window = Some(event_loop.create_window(attributes.clone()).unwrap()); let window = self.window.as_ref().unwrap(); #[cfg(target_arch = "wasm32")] - let context = window.canvas().unwrap().get_context("webgl2") - .unwrap().unwrap() + let context = window + .canvas() + .unwrap() + .get_context("webgl2") + .unwrap() + .unwrap() .dyn_into::() .unwrap(); #[cfg(target_arch = "wasm32")] - let (gl, shader_version) = (Arc::new(glow::Context::from_webgl2_context(context)), "#version 300 es"); + let (gl, shader_version) = ( + Arc::new(glow::Context::from_webgl2_context(context)), + "#version 300 es", + ); #[cfg(not(target_arch = "wasm32"))] let (gl, shader_version) = unsafe { @@ -133,36 +164,55 @@ impl ApplicationHandler for App { let display_builder = DisplayBuilder::new().with_window_attributes(Some(attributes)); - let (window, gl_config) = display_builder.build(event_loop, template, |configs| { - configs.reduce(|accum, config| { - let supports_transparency = config.supports_transparency().unwrap_or(false) - && !accum.supports_transparency().unwrap_or(false); - if supports_transparency || config.num_samples() > accum.num_samples() { - config - } else { - accum - } - }).unwrap() - }).unwrap(); - let raw_handle = window.as_ref().map(|window| window.window_handle().unwrap().window_handle().unwrap().as_raw()); + let (window, gl_config) = display_builder + .build(event_loop, template, |configs| { + configs + .reduce(|accum, config| { + let supports_transparency = + config.supports_transparency().unwrap_or(false) + && !accum.supports_transparency().unwrap_or(false); + if supports_transparency || config.num_samples() > accum.num_samples() { + config + } else { + accum + } + }) + .unwrap() + }) + .unwrap(); + let raw_handle = window.as_ref().map(|window| { + window + .window_handle() + .unwrap() + .window_handle() + .unwrap() + .as_raw() + }); let gl_display = gl_config.display(); let context_attributes = ContextAttributesBuilder::new() .with_context_api(ContextApi::OpenGl(Some(glutin::context::Version { major: 3, minor: 0, - }))).build(raw_handle); + }))) + .build(raw_handle); - let not_current_gl_context = gl_display.create_context(&gl_config, &context_attributes).unwrap(); + let not_current_gl_context = gl_display + .create_context(&gl_config, &context_attributes) + .unwrap(); let window = window.unwrap(); let surface_attributes = window.build_surface_attributes(Default::default()).unwrap(); - let gl_surface = gl_display.create_window_surface(&gl_config, &surface_attributes).unwrap(); + let gl_surface = gl_display + .create_window_surface(&gl_config, &surface_attributes) + .unwrap(); let gl_context = not_current_gl_context.make_current(&gl_surface).unwrap(); let gl = glow::Context::from_loader_function_cstr(|s| gl_display.get_proc_address(s)); - gl_surface.set_swap_interval(&gl_context, SwapInterval::Wait(NonZeroU32::new(1).unwrap())).unwrap(); + gl_surface + .set_swap_interval(&gl_context, SwapInterval::Wait(NonZeroU32::new(1).unwrap())) + .unwrap(); self.gl_surface = Some(gl_surface); self.gl_context = Some(gl_context); @@ -171,17 +221,31 @@ impl ApplicationHandler for App { }; unsafe { let shaders = [ - ("vertex", include_str!("../shaders/vertex.glsl"), glow::VERTEX_SHADER), - ("fragment", include_str!("../shaders/fragment.glsl"), glow::FRAGMENT_SHADER), + ( + "vertex", + include_str!("../shaders/vertex.glsl"), + glow::VERTEX_SHADER, + ), + ( + "fragment", + include_str!("../shaders/fragment.glsl"), + glow::FRAGMENT_SHADER, + ), ]; let program = gl.create_program().expect("Failed to create program"); for (name, source, shader_type) in shaders { - let shader = gl.create_shader(shader_type).expect("Failed to create vertex shader"); + let shader = gl + .create_shader(shader_type) + .expect("Failed to create vertex shader"); gl.shader_source(shader, &format!("{}\n{}", shader_version, source)); gl.compile_shader(shader); if !gl.get_shader_compile_status(shader) { - tracing::error!("error in {} shader: {}", name, gl.get_shader_info_log(shader)); + tracing::error!( + "error in {} shader: {}", + name, + gl.get_shader_info_log(shader) + ); } gl.attach_shader(program, shader); gl.delete_shader(shader); @@ -190,27 +254,44 @@ impl ApplicationHandler for App { gl.use_program(Some(program)); - let vertex_array = gl.create_vertex_array().expect("Failed to create vertex array"); + let vertex_array = gl + .create_vertex_array() + .expect("Failed to create vertex array"); gl.bind_vertex_array(Some(vertex_array)); let vertex_buffer = gl.create_buffer().expect("Failed to create vertex buffer"); gl.bind_buffer(glow::ARRAY_BUFFER, Some(vertex_buffer)); let element_buffer = gl.create_buffer().expect("Failed to create element buffer"); gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(element_buffer)); - gl.buffer_data_u8_slice(glow::ARRAY_BUFFER, + gl.buffer_data_u8_slice( + glow::ARRAY_BUFFER, std::slice::from_raw_parts(VERTICES.as_ptr() as *const u8, size_of_val(&VERTICES)), - glow::STATIC_DRAW); - gl.buffer_data_u8_slice(glow::ELEMENT_ARRAY_BUFFER, + glow::STATIC_DRAW, + ); + gl.buffer_data_u8_slice( + glow::ELEMENT_ARRAY_BUFFER, std::slice::from_raw_parts(INDICES.as_ptr() as *const u8, size_of_val(&INDICES)), - glow::STATIC_DRAW); + glow::STATIC_DRAW, + ); - gl.vertex_attrib_pointer_f32(0, 2, glow::FLOAT, false, 4*size_of::() as i32, 0); + gl.vertex_attrib_pointer_f32(0, 2, glow::FLOAT, false, 4 * size_of::() as i32, 0); gl.enable_vertex_attrib_array(0); - gl.vertex_attrib_pointer_f32(1, 2, glow::FLOAT, false, 4*size_of::() as i32, 2*size_of::() as i32); + gl.vertex_attrib_pointer_f32( + 1, + 2, + glow::FLOAT, + false, + 4 * size_of::() as i32, + 2 * size_of::() as i32, + ); gl.enable_vertex_attrib_array(1); - gl.clear_color(0.1, 0.1, 0.1, 1.0); - gl.viewport(0, 0, window.inner_size().width as i32, window.inner_size().height as i32); + gl.viewport( + 0, + 0, + window.inner_size().width as i32, + window.inner_size().height as i32, + ); gl.enable(glow::BLEND); gl.blend_func(glow::SRC_ALPHA, glow::ONE_MINUS_SRC_ALPHA); @@ -220,14 +301,35 @@ impl ApplicationHandler for App { self.element_buffer = Some(element_buffer); } #[cfg(target_arch = "wasm32")] - web_sys::window().unwrap().set_onresize(Some(Closure::::new(move |_| { - let document = web_sys::window().unwrap().document().unwrap(); - let canvas = document.get_element_by_id("canvas").unwrap(); - let canvas = canvas.dyn_into::() - .map_err(|_| ()).unwrap(); - canvas.set_width(web_sys::window().unwrap().inner_width().unwrap().as_f64().unwrap() as u32); - canvas.set_height(web_sys::window().unwrap().inner_height().unwrap().as_f64().unwrap() as u32); - }).into_js_value().as_ref().unchecked_ref())); + web_sys::window().unwrap().set_onresize(Some( + Closure::::new(move |_| { + let document = web_sys::window().unwrap().document().unwrap(); + let canvas = document.get_element_by_id("canvas").unwrap(); + let canvas = canvas + .dyn_into::() + .map_err(|_| ()) + .unwrap(); + canvas.set_width( + web_sys::window() + .unwrap() + .inner_width() + .unwrap() + .as_f64() + .unwrap() as u32, + ); + canvas.set_height( + web_sys::window() + .unwrap() + .inner_height() + .unwrap() + .as_f64() + .unwrap() as u32, + ); + }) + .into_js_value() + .as_ref() + .unchecked_ref(), + )); let egui_glow = egui_glow::EguiGlow::new(event_loop, gl.clone(), None, None, true); self.egui_glow = Some(egui_glow); @@ -245,32 +347,33 @@ impl ApplicationHandler for App { } WindowEvent::Resized(size) => { #[cfg(not(target_arch = "wasm32"))] - self.gl_surface.as_ref().unwrap().resize(self.gl_context.as_ref().unwrap(), - NonZeroU32::new(size.width).unwrap(), NonZeroU32::new(size.height).unwrap()); + self.gl_surface.as_ref().unwrap().resize( + self.gl_context.as_ref().unwrap(), + NonZeroU32::new(size.width).unwrap(), + NonZeroU32::new(size.height).unwrap(), + ); let mut camera = self.world.get_resource_mut::().unwrap(); camera.width = size.width; camera.height = size.height; unsafe { - self.gl.as_ref().unwrap().viewport(0, 0, size.width as i32, size.height as i32); + self.gl + .as_ref() + .unwrap() + .viewport(0, 0, size.width as i32, size.height as i32); } } WindowEvent::MouseWheel { delta, .. } => { let mut camera = self.world.get_resource_mut::().unwrap(); let raw_delta = match delta { - MouseScrollDelta::PixelDelta(pos) => { - pos.y as f32 - } - MouseScrollDelta::LineDelta(y, .. ) => { - y - } + MouseScrollDelta::PixelDelta(pos) => pos.y as f32, + MouseScrollDelta::LineDelta(y, ..) => y, }; let delta = 1.1; if raw_delta < 0.0 { camera.zoom *= 1.0 / delta; } else { - camera.zoom *= delta; } } @@ -296,8 +399,8 @@ impl ApplicationHandler for App { self.right = true; matched = true; } - _ => matched = false - } + _ => matched = false, + }, ElementState::Released => match key { KeyCode::KeyW => { self.up = false; @@ -315,16 +418,17 @@ impl ApplicationHandler for App { self.right = false; matched = true; } - _ => matched = false - } + _ => matched = false, + }, } if matched { - self.send_packet_events.send(SendPacket(Packet::PlayerInput { - up: self.up, - down: self.down, - left: self.left, - right: self.right, - })); + self.send_packet_events + .send(SendPacket(Packet::PlayerInput { + up: self.up, + down: self.down, + left: self.left, + right: self.right, + })); } } PhysicalKey::Unidentified(_) => {} // unsupported @@ -340,22 +444,30 @@ impl ApplicationHandler for App { }; let camera = self.world.get_resource::().unwrap(); let view = camera.to_cursor_matrix(); - let pos = view * Vector3::new(self.mouse_pos.x as f32, self.mouse_pos.y as f32, 1.0); + let pos = + view * Vector3::new(self.mouse_pos.x as f32, self.mouse_pos.y as f32, 1.0); let pos = pos / pos.z; - self.send_packet_events.send(SendPacket(Packet::PlayerMouseInput { - x: pos.x, - y: pos.y, - released: !state.is_pressed(), - button, - })); + self.send_packet_events + .send(SendPacket(Packet::PlayerMouseInput { + x: pos.x, + y: pos.y, + released: !state.is_pressed(), + button, + })); } _ => {} } - let event_response = self.egui_glow.as_mut().unwrap() + let event_response = self + .egui_glow + .as_mut() + .unwrap() .on_window_event(self.window.as_ref().unwrap(), &event); } fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) { - let mut ws = self.world.get_resource_mut::().expect("Failed to get Ws resource"); + let mut ws = self + .world + .get_resource_mut::() + .expect("Failed to get Ws resource"); #[cfg(target_arch = "wasm32")] while let Ok(Some(packet)) = ws.receiver.try_next() { self.recv_packet_events.send(RecvPacket(packet)); @@ -367,36 +479,61 @@ impl ApplicationHandler for App { self.send_packet_events.update(); self.recv_packet_events.update(); - process_packets(&mut self.world, &mut self.send_packet_events, - &mut self.recv_packet_events, &mut self.planet_types, - &mut self.amount, &mut self.max); + process_packets( + &mut self.world, + &mut self.send_packet_events, + &mut self.recv_packet_events, + &mut self.planet_types, + &mut self.amount, + &mut self.max, + ); let window = self.window.as_ref().unwrap(); let gl = self.gl.as_ref().unwrap(); let mut player = self.world.query_filtered::<&Transform, With>(); let player = player.single(&self.world); - self.egui_glow.as_mut().unwrap().run( - self.window.as_ref().unwrap(), - |ctx| { - egui::Window::new("Main Menu").resizable(false).show(ctx, |ui| { - ui.heading("Starkingdoms.tk"); - - ui.add(Label::new("Fuel:")); - ui.add(ProgressBar::new((self.amount as f32)/(self.max as f32)).corner_radius(0)); - ui.add(Label::new(format!("Pos: {}, {}", player.translation.x as u32, player.translation.y as u32))); - }); - }, - ); + self.egui_glow + .as_mut() + .unwrap() + .run(self.window.as_ref().unwrap(), |ctx| { + egui::Window::new("Main Menu") + .resizable(false) + .show(ctx, |ui| { + ui.heading("Starkingdoms.tk"); + + ui.add(Label::new("Fuel:")); + ui.add( + ProgressBar::new((self.amount as f32) / (self.max as f32)) + .corner_radius(0), + ); + ui.add(Label::new(format!( + "Pos: {}, {}", + player.translation.x as u32, player.translation.y as u32 + ))); + }); + }); let camera = self.world.get_resource::().unwrap(); let x_scale = camera.zoom / camera.width as f32 * 2.0; let y_scale = camera.zoom / camera.height as f32 * 2.0; let view = &[ - x_scale, 0.0, 0.0, camera.x*x_scale, - 0.0, y_scale,0.0, camera.y*y_scale, - 0.0, 0.0, 1.0, 0.0, - 0.0, 0.0, 0.0, 1.0, + x_scale, + 0.0, + 0.0, + camera.x * x_scale, + 0.0, + y_scale, + 0.0, + camera.y * y_scale, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, ]; let mut sprite_query = self.world.query::<(&Transform, &mut Texture)>(); @@ -413,7 +550,7 @@ impl ApplicationHandler for App { gl.bind_buffer(glow::ARRAY_BUFFER, self.vertex_buffer); gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, self.element_buffer); gl.active_texture(glow::TEXTURE0); - + let view_loc = gl.get_uniform_location(self.program.unwrap(), "view"); gl.uniform_matrix_4_f32_slice(view_loc.as_ref(), true, view); let model_loc = gl.get_uniform_location(self.program.unwrap(), "model"); @@ -423,15 +560,29 @@ impl ApplicationHandler for App { let assets = self.world.resource::(); let image = match assets.get(texture.name.clone()) { Some(t) => t, - None => continue + None => continue, }; - let texture_object = gl.create_texture().expect("Failed to create texture object"); + let texture_object = gl + .create_texture() + .expect("Failed to create texture object"); gl.bind_texture(glow::TEXTURE_2D, Some(texture_object)); - gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MIN_FILTER, glow::LINEAR_MIPMAP_LINEAR as i32); - gl.tex_image_2d(glow::TEXTURE_2D, 0, glow::RGBA as i32, - image.width as i32, image.height as i32, 0, glow::RGBA, - glow::UNSIGNED_BYTE, PixelUnpackData::Slice(Some(&image.bytes))); + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_MIN_FILTER, + glow::LINEAR_MIPMAP_LINEAR as i32, + ); + gl.tex_image_2d( + glow::TEXTURE_2D, + 0, + glow::RGBA as i32, + image.width as i32, + image.height as i32, + 0, + glow::RGBA, + glow::UNSIGNED_BYTE, + PixelUnpackData::Slice(Some(&image.bytes)), + ); gl.generate_mipmap(glow::TEXTURE_2D); self.textures.insert(texture.name.clone(), texture_object); @@ -447,17 +598,31 @@ impl ApplicationHandler for App { } } - self.egui_glow.as_mut().unwrap().paint(self.window.as_ref().unwrap()); + self.egui_glow + .as_mut() + .unwrap() + .paint(self.window.as_ref().unwrap()); #[cfg(not(target_arch = "wasm32"))] - self.gl_surface.as_ref().unwrap().swap_buffers(self.gl_context.as_ref().unwrap()).unwrap(); + self.gl_surface + .as_ref() + .unwrap() + .swap_buffers(self.gl_context.as_ref().unwrap()) + .unwrap(); - let mut ws = self.world.get_resource_mut::().expect("Failed to get Ws resource"); + let mut ws = self + .world + .get_resource_mut::() + .expect("Failed to get Ws resource"); let mut send_event_cursor = self.send_packet_events.get_cursor(); for event in send_event_cursor.read(&self.send_packet_events) { ws.send_packet(event.0.clone()); } - event_loop.set_control_flow(ControlFlow::WaitUntil(web_time::Instant::now().checked_add(web_time::Duration::from_millis(16)).unwrap())); + event_loop.set_control_flow(ControlFlow::WaitUntil( + web_time::Instant::now() + .checked_add(web_time::Duration::from_millis(16)) + .unwrap(), + )); } }