M crates/client/src/ecs.rs => crates/client/src/ecs.rs +7 -0
@@ 4,6 4,7 @@ use bevy_ecs::event::Event;
use bevy_ecs::system::Resource;
use nalgebra::Matrix3;
use starkingdoms_common::packet::Packet;
+use starkingdoms_common::PlanetType;
#[derive(Component, Debug, Clone, Copy)]
pub struct Translation {
@@ 88,6 89,12 @@ pub struct Camera {
pub zoom: f32,
}
+#[derive(Component, Debug, Clone, Copy)]
+pub struct Player;
+
+#[derive(Component, Debug, Clone, Copy)]
+pub struct Planet(PlanetType);
+
#[derive(Event, Clone, PartialEq)]
pub struct SendPacket(pub Packet);
#[derive(Event, Clone, PartialEq)]
M crates/client/src/lib.rs => crates/client/src/lib.rs +14 -7
@@ 6,10 6,11 @@ use bevy_ecs::event::{EventReader, Events};
use bevy_ecs::schedule::Schedule;
use bevy_ecs::system::ResMut;
use bevy_ecs::world::World;
-use ecs::{RecvPacket, SendPacket, Shear};
+use ecs::{Player, RecvPacket, SendPacket, Shear};
use egui::{Context, DragValue};
use networking::ws::Ws;
use rendering::assets::Assets;
+use starkingdoms_common::packet::Packet;
use tracing::info;
use winit::event_loop::{ControlFlow, EventLoop};
@@ 51,7 52,7 @@ pub fn start() {
world.insert_resource(Assets::new());
world.insert_resource(Ws::new());
- let send_packet_events = Events::<SendPacket>::default();
+ let mut send_packet_events = Events::<SendPacket>::default();
let recv_packet_events = Events::<RecvPacket>::default();
let mut start_schedule = Schedule::default();
@@ 64,7 65,13 @@ pub fn start() {
// Caution: This will run once before there are things on screen
update_schedule.add_systems(zoom_camera_on_mouse_events);
- world.spawn(SpriteBundle {
+ send_packet_events.send(SendPacket(Packet::ClientLogin {
+ username: String::new(),
+ save: None,
+ jwt: None,
+ }));
+
+ world.spawn((SpriteBundle {
position: Translation {
x: 100.0,
y: 100.0
@@ 78,12 85,12 @@ pub fn start() {
height: 100.0,
},
rotation: Rotation {
- radians: 45.0_f32.to_radians()
+ radians: 0.0_f32.to_radians()
},
texture: SpriteTexture {
texture: "hearty".to_string(),
},
- });
+ }, Player));
let event_loop = EventLoop::new().unwrap();
event_loop.set_control_flow(ControlFlow::Poll);
@@ 120,7 127,7 @@ impl UiRenderable for Gui {
ui.separator();
let mut sprites = world.query::<(&mut Translation, &mut Shear, &mut Scale, &SpriteTexture, &mut Rotation)>();
- for (mut pos, mut shear, mut scale, tex, mut rot) in sprites.iter_mut(world) {
+ /*for (mut pos, mut shear, mut scale, tex, mut rot) in sprites.iter_mut(world) {
ui.heading(&tex.texture);
egui::Grid::new("sprite_grid")
@@ 180,7 187,7 @@ impl UiRenderable for Gui {
ui.label("Camera Zoom");
ui.add(DragValue::new(&mut camera.zoom).speed(0.1));
ui.end_row();
- });
+ });*/
});
}
}
M crates/client/src/networking/mod.rs => crates/client/src/networking/mod.rs +72 -0
@@ 1,6 1,78 @@
+use std::collections::HashMap;
+
+use bevy_ecs::{entity::Entity, event::Events, query::With, world::World};
+use starkingdoms_common::{packet::Packet, PartType, PlanetType};
+
+use crate::ecs::{Camera, Planet, Player, RecvPacket, Rotation, Scale, SendPacket, Shear, SpriteBundle, SpriteTexture, Translation};
+
#[cfg(target_arch = "wasm32")]
#[path = "ws_wasm.rs"]
pub mod ws;
#[cfg(not(target_arch = "wasm32"))]
#[path = "ws_native.rs"]
pub mod ws;
+
+pub fn process_packets(
+ world: &mut World,
+ send_packet_events: &mut Events<SendPacket>,
+ recv_packet_events: &mut Events<RecvPacket>,
+ planet_types: &mut HashMap<PlanetType, (Entity, u32)>,
+) {
+ use Packet::*;
+ let mut recv_cursor = recv_packet_events.get_cursor();
+ for recv in recv_cursor.read(&recv_packet_events) {
+ match &recv.0 {
+ PartPositions { parts } => {
+ for (id, part) in parts {
+ if part.part_type == PartType::Hearty {
+ let mut player_query = world.query_filtered::<(&mut Translation, &mut Rotation), With<Player>>();
+ let mut camera = world.resource_mut::<Camera>();
+ /*camera.x = part.transform.x;
+ camera.y = part.transform.y;*/
+ camera.x = 0.0;
+ camera.y = 1.0;
+ tracing::info!("camera real {:?}", camera);
+ for (mut translation, mut rotation) in player_query.iter_mut(world) {
+ translation.x = 0.0;
+ translation.y = 1.0;
+ //rotation.radians = part.transform.rot;
+ tracing::info!("part real {:?}", translation);
+ }
+ tracing::info!("part {:?}", part.transform);
+ }
+ }
+ }
+ PlanetPositions { planets } => {
+ for (server_id, planet) in planets {
+ let mut planet_query = world.query_filtered::<(&mut Translation, &mut Rotation), With<Planet>>();
+ if !planet_types.contains_key(&planet.planet_type) {
+ let entity = world.spawn(SpriteBundle {
+ position: Translation { x: planet.transform.x, y: planet.transform.y },
+ shear: Shear { x: 0.0, y: 0.0 },
+ rotation: Rotation { radians: planet.transform.rot },
+ scale: Scale { width: planet.radius, height: planet.radius },
+ texture: SpriteTexture {
+ texture: match planet.planet_type {
+ PlanetType::Sun => "sun",
+ PlanetType::Mercury => "mercury",
+ PlanetType::Venus => "venus",
+ PlanetType::Earth => "earth",
+ PlanetType::Moon => "moon",
+ PlanetType::Mars => "mars",
+ PlanetType::Jupiter => "jupiter",
+ PlanetType::Saturn => "saturn",
+ PlanetType::Uranus => "uranus",
+ PlanetType::Neptune => "neptune",
+ PlanetType::Pluto => "pluto",
+ }.to_string()
+ },
+ });
+ planet_types.insert(planet.planet_type, (entity.id(), *server_id));
+ tracing::info!("{:?}", planet.transform);
+ }
+ }
+ }
+ _ => {}
+ }
+ }
+}
M crates/client/src/networking/ws_wasm.rs => crates/client/src/networking/ws_wasm.rs +6 -4
@@ 1,5 1,3 @@
-use std::{any::Any, cell::{OnceCell, RefCell}, rc::Rc, sync::{Arc, Mutex, RwLock}};
-
use bevy_ecs::system::Resource;
//use crossbeam::channel::{unbounded, Receiver, Sender};
use futures::{channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender}, SinkExt};
@@ 63,7 61,11 @@ impl Ws {
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) {
- 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");
+ });
}
}
M crates/client/src/rendering/assets_wasm.rs => crates/client/src/rendering/assets_wasm.rs +11 -4
@@ 52,7 52,9 @@ impl Assets {
};
if !contains_texture && !contains_texture_receiver {
let textures = self.textures.clone();
- self.texture_receivers.lock().unwrap().insert(local_path.clone(), rx);
+ {
+ self.texture_receivers.lock().unwrap().insert(local_path.clone(), rx);
+ }
spawn_local(async move {
let window = web_sys::window().unwrap();
let resp = match reqwest::get(format!("{}/src/textures/{}", window.location().origin().unwrap(), local_path)).await {
@@ 83,7 85,7 @@ impl Assets {
default_size: usvg::Size::from_wh(20.0, 20.0).unwrap(),
..Default::default()
};
- let tree = usvg::Tree::from_data(&bytes, &opt).expect("Couldn't parse svg");
+ 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(100.0, 100.0).unwrap().to_int_size();
assert!(size.width() > 0 && size.height() > 0);
@@ 95,7 97,9 @@ impl Assets {
height: size.height(),
};
- textures.lock().unwrap().insert(local_path, data.clone());
+ {
+ textures.lock().unwrap().insert(local_path, data.clone());
+ }
tx.send(data).unwrap();
} else if local_path.ends_with(".png") {
let img = image::load_from_memory(&bytes).unwrap();
@@ 105,7 109,9 @@ impl Assets {
width: rgba.width(),
height: rgba.height(),
};
- textures.lock().unwrap().insert(local_path, data.clone());
+ {
+ textures.lock().unwrap().insert(local_path, data.clone());
+ }
tx.send(data).unwrap();
}
});
@@ 115,6 121,7 @@ impl Assets {
let rx = texture_receivers.get_mut(&local_path).unwrap();
if let Ok(Some(texture)) = rx.try_recv() {
self.texture_receivers.lock().unwrap().remove(&local_path);
+ self.textures.lock().unwrap().insert(local_path, texture.clone());
return Some(texture);
}
None
M crates/client/src/rendering/renderer.rs => crates/client/src/rendering/renderer.rs +88 -46
@@ 1,15 1,19 @@
use crate::ecs::{Camera, RecvPacket, Rotation, Scale, SendPacket, Shear, SpriteTexture, Translation};
+use crate::networking::process_packets;
use crate::networking::ws::Ws;
use crate::rendering::assets::Assets;
use crate::rendering::mipmap::MipGenerator;
use crate::rendering::renderer::RenderInitRes::{Initialized, NotReadyYet};
use crate::rendering::texture;
use crate::rendering::ui::UiRenderable;
+use bevy_ecs::entity::Entity;
use bevy_ecs::event::Events;
use bevy_ecs::schedule::Schedule;
use bevy_ecs::world::World;
use egui::ViewportId;
-use std::collections::HashMap;
+use starkingdoms_common::PlanetType;
+use std::collections::hash_map::Entry;
+use std::collections::{HashMap, HashSet};
use std::fmt::{Debug, Formatter};
use std::sync::Arc;
use tracing::info;
@@ 60,6 64,8 @@ pub struct Renderer<T: UiRenderable> {
pub size: PhysicalSize<u32>,
pub logical_size: LogicalSize<u32>,
+
+ pub planet_types: HashMap<PlanetType, (Entity, u32)>, // (world entity, server id)
}
#[allow(clippy::large_enum_variant)]
@@ 210,6 216,7 @@ impl<T: UiRenderable> Renderer<T> {
local_uniform,
size,
surface_configuration: format,
+ planet_types: HashMap::new(),
})
}
@@ 227,6 234,8 @@ impl<T: UiRenderable> Renderer<T> {
self.update_schedule.run(&mut self.world);
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);
// update the UI
let egui_output = self
.gui_ctx
@@ 290,51 299,84 @@ impl<T: UiRenderable> Renderer<T> {
self.queue.write_buffer(&self.frame_uniform, 0, &frame_uniform);
for (pos, shear, scale, tex, rot) in sprites_to_render {
- let tex = self.textures.entry(tex.texture.clone()).or_insert({
- info!("loading texture {}", &tex.texture);
- let assets = self.world.get_resource::<Assets>().unwrap();
- let b = match tex.texture.as_str() {
- "f" => match assets.get("f.png") {
- Some(b) => b,
- None => continue,
- }
- "happy-tree" => match assets.get("happy-tree.png") {
- Some(b) => b,
- None => continue,
- }
- "uv" => match assets.get("uv.png") {
- Some(b) => b,
- None => continue,
- }
- "hearty" => match assets.get("hearty.svg") {
- Some(b) => b,
- None => continue,
- }
- "earth" => match assets.get("earth.svg") {
- Some(b) => b,
- None => continue,
- }
- "mars" => match assets.get("mars.svg") {
- Some(b) => b,
- None => continue,
- }
- u => panic!("unknown texture {u}, has it been added in rendering::renderer::<impl Renderer>::render()?")
- };
- /*let b: &[u8] = match tex.texture.as_str() {
- "f" => include_bytes!("../textures/f.png"),
- "happy-tree" => include_bytes!("../textures/happy-tree.png"),
- "uv" => include_bytes!("../textures/uv.png"),
- u => panic!("unknown texture {u}, has it been added in rendering::renderer::<impl Renderer>::render()?")
- };*/
- texture::Texture::new(
- b,
- &tex.texture,
- &self.device,
- &self.queue,
- &mut self.mip_generator,
- )
- });
+ let tex = match self.textures.entry(tex.texture.clone()) {
+ Entry::Occupied(entry) => entry.into_mut(),
+ Entry::Vacant(entry) => {
+ let assets = self.world.get_resource::<Assets>().unwrap();
+ let b = match tex.texture.as_str() {
+ "f" => match assets.get("f.png") {
+ Some(b) => b,
+ None => continue,
+ }
+ "happy-tree" => match assets.get("happy-tree.png") {
+ Some(b) => b,
+ None => continue,
+ }
+ "uv" => match assets.get("uv.png") {
+ Some(b) => b,
+ None => continue,
+ }
+ "hearty" => match assets.get("hearty.svg") {
+ Some(b) => b,
+ None => continue,
+ }
+ "sun" => match assets.get("sun.svg") {
+ Some(b) => b,
+ None => continue,
+ }
+ "mercury" => match assets.get("moon.svg") {
+ Some(b) => b,
+ None => continue,
+ }
+ "venus" => match assets.get("mars.svg") {
+ Some(b) => b,
+ None => continue,
+ }
+ "earth" => match assets.get("earth.svg") {
+ Some(b) => b,
+ None => continue,
+ }
+ "moon" => match assets.get("moon.svg") {
+ Some(b) => b,
+ None => continue,
+ }
+ "mars" => match assets.get("mars.svg") {
+ Some(b) => b,
+ None => continue,
+ }
+ "jupiter" => match assets.get("sun.svg") {
+ Some(b) => b,
+ None => continue,
+ }
+ "saturn" => match assets.get("moon.svg") {
+ Some(b) => b,
+ None => continue,
+ }
+ "uranus" => match assets.get("earth.svg") {
+ Some(b) => b,
+ None => continue,
+ }
+ "neptune" => match assets.get("moon.svg") {
+ Some(b) => b,
+ None => continue,
+ }
+ "pluto" => match assets.get("mars.svg") {
+ Some(b) => b,
+ None => continue,
+ }
+ u => panic!("unknown texture {u}, has it been added in rendering::renderer::<impl Renderer>::render()?")
+ };
+ entry.insert(texture::Texture::new(
+ b,
+ &tex.texture,
+ &self.device,
+ &self.queue,
+ &mut self.mip_generator,
+ ))
+ }
+ };
+ info!("render: {:?}", pos);
let xy_matrix = pos.as_matrix();
let shear_matrix = shear.as_matrix();
let rot_matrix = rot.as_matrix();
@@ 435,7 477,7 @@ impl<T: UiRenderable> Renderer<T> {
let mut ws = self.world.get_resource_mut::<Ws>().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);
+ ws.send_packet(event.0.clone());
}
let buffer = encoder.finish();