From 28b96352b6cdc2a7bf0bd91ec8de51d6ccab11c4 Mon Sep 17 00:00:00 2001 From: core Date: Fri, 28 Mar 2025 21:54:55 -0400 Subject: [PATCH] network refactor --- Cargo.lock | 1 + crates/client/Cargo.toml | 2 +- crates/client/src/components.rs | 34 ++++ crates/client/src/lib.rs | 48 +++-- crates/client/src/networking/handlers.rs | 153 +++++++++++++++ crates/client/src/networking/mod.rs | 230 +++-------------------- crates/client/src/rendering/mod.rs | 23 ++- crates/client/src/systems.rs | 21 +++ crates/common/Cargo.toml | 5 + crates/common/src/packet.rs | 44 ++++- 10 files changed, 334 insertions(+), 227 deletions(-) create mode 100644 crates/client/src/networking/handlers.rs create mode 100644 crates/client/src/systems.rs diff --git a/Cargo.lock b/Cargo.lock index 834adefb1ff5102bc1c3de4a011c04e1b5e573e1..f2afdcfa3b5f55eca0d11ed80a87bd29e481ab75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6297,6 +6297,7 @@ name = "starkingdoms-common" version = "0.1.0" dependencies = [ "base64 0.21.7", + "bevy_ecs 0.15.3", "hmac", "rmp-serde", "serde", diff --git a/crates/client/Cargo.toml b/crates/client/Cargo.toml index 74272bea2242163b5a9c696e513e95b22e3465ee..4c0952a10861149c6d5b3798eb0402c4ae768fa9 100644 --- a/crates/client/Cargo.toml +++ b/crates/client/Cargo.toml @@ -21,7 +21,7 @@ egui-winit = { version = "0.31.1", default-features = false, features = ["links" web-time = "1" futures = "0.3" nalgebra = "0.33" -starkingdoms-common = { version = "0.1", path = "../common" } +starkingdoms-common = { version = "0.1", path = "../common", features = ["bevy"] } serde = "1" serde_json = "1" crossbeam = "0.8.4" diff --git a/crates/client/src/components.rs b/crates/client/src/components.rs index 19addb39d56f72f92d41bb300de7701f6c9b50f7..433acb7bcdd184400cafc1f11f5661dd78ebb34b 100644 --- a/crates/client/src/components.rs +++ b/crates/client/src/components.rs @@ -1,7 +1,41 @@ use bevy_ecs::{bundle::Bundle, component::Component, event::Event, system::Resource}; +use bevy_ecs::schedule::ScheduleLabel; use nalgebra::{Matrix3, Matrix4, Rotation2, Scale2, Scale3, Translation2, Translation3}; use starkingdoms_common::packet::Packet; +#[derive(Bundle)] +pub struct PlayerBundle { + pub transform: Transform, + pub texture: Texture, + pub player: Player, + pub part: Part +} + +#[derive(Bundle)] +pub struct PartBundle { + pub transform: Transform, + pub texture: Texture, + pub server_id: ServerId, + pub part: Part +} + +#[derive(Bundle)] +pub struct OtherPlayerBundle { + pub part: PartBundle, + pub username: PlayerUsername +} + +#[derive(ScheduleLabel, Hash, Clone, Debug, Eq, PartialEq)] +pub enum Schedule { + Startup, + Update +} + +#[derive(Component, Debug)] +pub struct PlayerUsername { + pub username: String +} + #[derive(Component, Debug)] pub struct Texture { pub name: String, diff --git a/crates/client/src/lib.rs b/crates/client/src/lib.rs index aa574006c4fa734e40e898bcc253791c1dd89e97..47cf14def9b17e10995f451c27541cfeb52f87b9 100644 --- a/crates/client/src/lib.rs +++ b/crates/client/src/lib.rs @@ -1,6 +1,9 @@ use crate::components::PlayerResources; use crate::networking::websocket::Websocket; use bevy_ecs::{event::Events, world::World}; +use bevy_ecs::event::EventRegistry; +use bevy_ecs::prelude::Event; +use bevy_ecs::schedule::Schedule; use components::{Camera, Chat, Part, Player, RecvPacket, SendPacket, Texture, Transform}; use nalgebra::{Rotation2, Scale3, Translation3}; use platform::assets::Assets; @@ -9,6 +12,10 @@ use rendering::assets::AssetLoader; use rendering::App; use tracing::info; use winit::event_loop::{ControlFlow, EventLoop}; +use starkingdoms_common::packet::{ClientLoginPacket, DespawnPartPacket, EnergyUpdatePacket, LoginResponsePacket, MessagePacket, OpenCraftingUiPacket, PartPositionsPacket, PlanetPositionsPacket, PlayerInputPacket, PlayerLeavePacket, PlayerListPacket, PlayerMouseInputPacket, RequestSavePacket, SaveDataPacket, SaveEligibilityPacket, SendMessagePacket, SpawnPartPacket, SpawnPlayerPacket, SpecialDisconnectPacket}; +use crate::components::Schedule::{Startup, Update}; +use crate::networking::handlers::{handle_crafting_ui, handle_despawn_part, handle_energy_update, handle_existing_players_list, handle_login_response, handle_message, handle_part_positions, handle_player_leave, handle_spawn_part, handle_spawn_player}; +use crate::systems::create_hearty; #[cfg(target_arch = "wasm32")] #[path = "wasm/mod.rs"] @@ -21,6 +28,7 @@ pub mod components; pub mod networking; pub mod rendering; pub mod ui; +pub mod systems; // Hi, you've found the real main function! This is called AFTER platform-specific initialization code. pub fn start() { @@ -59,18 +67,32 @@ pub fn start() { let 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), - )); + starkingdoms_common::packet::register_packet_events(&mut world); + + let mut startup_schedule = Schedule::new(Startup); + + startup_schedule.add_systems(create_hearty); + + let mut update_schedule = Schedule::new(Update); + + update_schedule.add_systems(handle_existing_players_list); + update_schedule.add_systems(handle_spawn_player); + update_schedule.add_systems(handle_spawn_part); + update_schedule.add_systems(handle_part_positions); + update_schedule.add_systems(handle_energy_update); + update_schedule.add_systems(handle_crafting_ui); + update_schedule.add_systems(handle_message); + update_schedule.add_systems(handle_player_leave); + update_schedule.add_systems(handle_despawn_part); + update_schedule.add_systems(handle_login_response); + + + // add systems here + + world.add_schedule(startup_schedule); + world.add_schedule(update_schedule); + + world.run_schedule(Startup); let event_loop = EventLoop::new().unwrap(); event_loop.set_control_flow(ControlFlow::Wait); @@ -78,4 +100,4 @@ pub fn start() { event_loop .run_app(&mut App::new(world, send_packet_events, recv_packet_events)) .unwrap(); -} +} \ No newline at end of file diff --git a/crates/client/src/networking/handlers.rs b/crates/client/src/networking/handlers.rs new file mode 100644 index 0000000000000000000000000000000000000000..816bb47c3686906159196ec0a6dfe907c2125601 --- /dev/null +++ b/crates/client/src/networking/handlers.rs @@ -0,0 +1,153 @@ +use bevy_ecs::prelude::*; +use nalgebra::{Rotation2, Scale3, Translation3}; +use starkingdoms_common::packet::{DespawnPartPacket, EnergyUpdatePacket, LoginResponsePacket, MessagePacket, OpenCraftingUiPacket, PartPositionsPacket, PlanetPositionsPacket, PlayerLeavePacket, PlayerListPacket, SpawnPartPacket, SpawnPlayerPacket}; +use starkingdoms_common::PartType; +use crate::components::{Camera, Chat, Menu, OtherPlayerBundle, Part, PartBundle, Player, PlayerBundle, PlayerResources, PlayerUsername, ServerId, Texture, Transform}; +use crate::networking::texture_name; + +pub fn handle_login_response(mut reader: EventReader, mut player: Query>, mut commands: Commands) { + for packet in reader.read() { + let player = player.single(); + commands.entity(player).insert(ServerId(packet.id)); + } +} + +pub fn handle_message(mut reader: EventReader, mut chat: ResMut) { + for message in reader.read() { + chat.messages.push( + format!("{}: {}", message.actor, message.content) + ); + } +} + +pub fn handle_existing_players_list(mut reader: EventReader, mut commands: Commands) { + for packet in reader.read() { + for (server_id, username) in &packet.players { + commands.spawn(OtherPlayerBundle { + part: PartBundle { + transform: 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: Texture { + name: "hearty.svg".to_string() + }, + server_id: ServerId(*server_id), + part: Part(false), + }, + username: PlayerUsername { + username: username.clone() + } + }); + } + } +} + +pub fn handle_spawn_player(mut reader: EventReader, mut commands: Commands) { + for SpawnPlayerPacket { id: server_id, username } in reader.read() { + commands.spawn(OtherPlayerBundle { + part: PartBundle { + transform: 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: Texture { + name: "hearty.svg".to_string() + }, + server_id: ServerId(*server_id), + part: Part(false), + }, + username: PlayerUsername { + username: username.clone() + } + }); + } +} + +pub fn handle_spawn_part(mut reader: EventReader, mut commands: Commands) { + for SpawnPartPacket { id: server_id, part } in reader.read() { + commands.spawn(PartBundle { + transform: 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: Texture { + name: texture_name(part.part_type, part.flags.attached), + }, + server_id: ServerId(*server_id), + part: Part(part.flags.attached), + }); + } +} + +pub fn handle_part_positions(mut reader: EventReader, mut parts_query: Query<(Entity, &ServerId, &mut Transform, &mut Texture, &mut Part)>, mut player: Query<&ServerId, With>, mut camera: ResMut) { + for PartPositionsPacket { parts } in reader.read() { + for (this_id, part) in parts { + for (_, server_id, mut transform, mut texture, mut bevy_part) in &mut parts_query { + if *this_id == server_id.0 { + transform.translation.x = part.transform.x; + transform.translation.y = part.transform.y; + transform.rotation = Rotation2::new(part.transform.rot); + + if part.flags.attached && !bevy_part.0 { + texture.name = texture_name(part.part_type, part.flags.attached); + bevy_part.0 = true; + } else if !part.flags.attached && bevy_part.0 { + texture.name = texture_name(part.part_type, part.flags.attached); + bevy_part.0 = false; + } + } + + if part.part_type == PartType::Hearty { + let player_id = player.single(); + if player_id.0 == server_id.0 { + camera.x = -part.transform.x; + camera.y = -part.transform.y; + } + } + } + } + } +} + + +pub fn handle_energy_update(mut reader: EventReader, mut player_res: ResMut) { + for EnergyUpdatePacket { amount, max } in reader.read() { + player_res.fuel_amount = *amount; + player_res.fuel_max = *max; + } +} + +pub fn handle_crafting_ui(mut reader: EventReader, entities: Query<(Entity, &ServerId)>, mut commands: Commands) { + for OpenCraftingUiPacket { id } in reader.read() { + for (entity, server_id) in &entities { + if server_id.0 == *id { + commands.entity(entity) + .insert(Menu); + } + } + } +} + +pub fn handle_player_leave(mut reader: EventReader, mut part_query: Query<(Entity, &ServerId), With>, mut commands: Commands) { + for PlayerLeavePacket { id } in reader.read() { + for (entity, server_id) in &mut part_query { + if server_id.0 == *id { + commands.entity(entity).despawn(); + } + } + } +} + +pub fn handle_despawn_part(mut reader: EventReader, mut part_query: Query<(Entity, &ServerId), With>, mut commands: Commands) { + for DespawnPartPacket { id } in reader.read() { + for (entity, server_id) in &mut part_query { + if server_id.0 == *id { + commands.entity(entity).despawn(); + } + } + } +} \ No newline at end of file diff --git a/crates/client/src/networking/mod.rs b/crates/client/src/networking/mod.rs index 4f25649059d53dd768468bfb13e1777e04219627..2627177fee986f5be1c6aa97fa7689fed504fc52 100644 --- a/crates/client/src/networking/mod.rs +++ b/crates/client/src/networking/mod.rs @@ -10,19 +10,17 @@ use bevy_ecs::{ query::{QuerySingleError, With}, world::World, }; +use bevy_ecs::prelude::Event; use nalgebra::{Rotation2, Scale3, Translation3}; use starkingdoms_common::packet::Packet::{ DespawnPart, EnergyUpdate, LoginResponse, Message, OpenCraftingUi, PartPositions, PlanetPositions, PlayerLeave, PlayerList, SpawnPart, SpawnPlayer, }; -use starkingdoms_common::packet::{ - DespawnPartPacket, EnergyUpdatePacket, LoginResponsePacket, MessagePacket, - OpenCraftingUiPacket, PartPositionsPacket, PlanetPositionsPacket, PlayerLeavePacket, - PlayerListPacket, SpawnPartPacket, SpawnPlayerPacket, -}; +use starkingdoms_common::packet::{DespawnPartPacket, EnergyUpdatePacket, LoginResponsePacket, MessagePacket, OpenCraftingUiPacket, Packet, PartPositionsPacket, PlanetPositionsPacket, PlayerLeavePacket, PlayerListPacket, SpawnPartPacket, SpawnPlayerPacket}; use starkingdoms_common::{PartType, PlanetType}; pub mod websocket; +pub mod handlers; fn texture_name(part_type: PartType, attached: bool) -> String { use PartType::*; @@ -49,203 +47,31 @@ fn texture_name(part_type: PartType, attached: bool) -> String { } } -pub fn process_packets( - world: &mut World, - _send_packet_events: &mut Events, - recv_packet_events: &mut Events, - planet_types: &mut HashMap, -) { - let mut recv_cursor = recv_packet_events.get_cursor(); - for recv in recv_cursor.read(recv_packet_events) { - match &recv.0 { - LoginResponse(LoginResponsePacket { id }) => { - let mut player_query = world.query_filtered::>(); - let entity = player_query.single(world); - world.entity_mut(entity).insert(ServerId(*id)); - } - PlayerList(PlayerListPacket { 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), - )); - } - } - SpawnPlayer(SpawnPlayerPacket { id, .. }) => { - // 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), - )); - } - SpawnPart(SpawnPartPacket { 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), - )); - } - PartPositions(PartPositionsPacket { parts }) => { - for (id, part) in parts { - if part.part_type == PartType::Hearty { - let mut player_query = world.query_filtered::<&ServerId, With>(); - let server_id = match player_query.get_single(world) { - Ok(player) => player, - Err(e) => match e { - QuerySingleError::NoEntities(_) => { - continue; - } - QuerySingleError::MultipleEntities(_) => { - panic!("There should never multiple players marked as players"); - } - }, - }; - if server_id.0 == *id { - let mut camera = world.resource_mut::(); - camera.x = -part.transform.x; - camera.y = -part.transform.y; - } - } - let mut part_query = - world - .query::<(Entity, &ServerId, &mut Transform, &mut Texture, &mut Part)>( - ); - for (_, 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; - transform.rotation = Rotation2::new(part.transform.rot); +pub fn send_event(e: T, world: &mut World) { + let mut events = world.resource_mut::>(); + events.send(e); +} - if part.flags.attached && !bevy_part.0 { - texture.name = texture_name(part.part_type, part.flags.attached); - bevy_part.0 = true; - } else if !part.flags.attached && bevy_part.0 { - texture.name = texture_name(part.part_type, part.flags.attached); - bevy_part.0 = false; - } - } - } - } - } - PlanetPositions(PlanetPositionsPacket { planets }) => { - for (server_id, planet) in planets { - planet_types.entry(planet.planet_type).or_insert_with(|| { - let entity = world.spawn(SpriteBundle { - transform: Transform { - 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), - }, - texture: Texture { - name: match planet.planet_type { - /*PlanetType::Sun => "sun.svg", - PlanetType::Mercury => "mercury.svg", - PlanetType::Venus => "venus.svg", - PlanetType::Earth => "earth.svg", - PlanetType::Moon => "moon.svg", - PlanetType::Mars => "mars.svg", - PlanetType::Jupiter => "jupiter.svg", - PlanetType::Saturn => "saturn.svg", - PlanetType::Uranus => "uranus.svg", - PlanetType::Neptune => "neptune.svg", - PlanetType::Pluto => "pluto.svg",*/ - PlanetType::Sun => "sun.svg", - PlanetType::Mercury => "moon.svg", - PlanetType::Venus => "venus.svg", - PlanetType::Earth => "earth.svg", - PlanetType::Moon => "moon.svg", - PlanetType::Mars => "mars.svg", - PlanetType::Jupiter => "jupiter.svg", - PlanetType::Saturn => "sun.svg", - PlanetType::Uranus => "venus.svg", - PlanetType::Neptune => "mars.svg", - PlanetType::Pluto => "earth.svg", - } - .to_string(), - }, - }); - (entity.id(), *server_id) - }); - } - } - EnergyUpdate(EnergyUpdatePacket { amount, max }) => { - let mut r = world.resource_mut::(); - r.fuel_amount = *amount; - r.fuel_max = *max; - } - OpenCraftingUi(OpenCraftingUiPacket { id }) => { - let mut query = world.query::<(Entity, &ServerId)>(); - let mut matching_id = None; - for (entity, server_id) in query.iter(world) { - if server_id.0 == *id { - matching_id = Some(entity); - } - } - if let Some(id) = matching_id { - world.entity_mut(id).insert(Menu); - } - } - Message(MessagePacket { actor, content, .. }) => { - let mut chat = world.get_resource_mut::().unwrap(); - chat.messages - .push(format!("{}: {}", actor.clone(), content.clone())); - } - PlayerLeave(PlayerLeavePacket { id }) => { - let mut part_query = world.query_filtered::<(Entity, &ServerId), With>(); - let mut entity_to_remove = None; - for (entity, server_id) in part_query.iter_mut(world) { - if server_id.0 == *id { - entity_to_remove = Some(entity); - } - } - if let Some(entity) = entity_to_remove { - world.despawn(entity); - } - } - DespawnPart(DespawnPartPacket { id }) => { - let mut part_query = world.query_filtered::<(Entity, &ServerId), With>(); - let mut entity_to_remove = None; - for (entity, server_id) in part_query.iter_mut(world) { - if server_id.0 == *id { - entity_to_remove = Some(entity); - } - } - if let Some(entity) = entity_to_remove { - world.despawn(entity); - } - } - _ => {} - } +pub fn send_packet_event(packet: Packet, world: &mut World) { + match packet { + Packet::ClientLogin(e) => send_event(e, world), + Packet::SendMessage(e) => send_event(e, world), + Packet::PlayerInput(e) => send_event(e, world), + Packet::PlayerMouseInput(e) => send_event(e, world), + Packet::RequestSave(e) => send_event(e, world), + Packet::_SpecialDisconnect(e) => send_event(e, world), + LoginResponse(e) => send_event(e, world), + SpawnPlayer(e) => send_event(e, world), + PlayerList(e) => send_event(e, world), + PlanetPositions(e) => send_event(e, world), + PartPositions(e) => send_event(e, world), + SpawnPart(e) => send_event(e, world), + DespawnPart(e) => send_event(e, world), + PlayerLeave(e) => send_event(e, world), + Message(e) => send_event(e, world), + Packet::SaveEligibility(e) => send_event(e, world), + Packet::SaveData(e) => send_event(e, world), + EnergyUpdate(e) => send_event(e, world), + OpenCraftingUi(e) => send_event(e, world), } } diff --git a/crates/client/src/rendering/mod.rs b/crates/client/src/rendering/mod.rs index cd94dc5eb470e4856a48fc8ff3378d1a75fefad9..43933c8faa34d0662fadc928c09fa86b85515d7d 100644 --- a/crates/client/src/rendering/mod.rs +++ b/crates/client/src/rendering/mod.rs @@ -34,12 +34,13 @@ use winit::{ }; use crate::components::{Camera, Menu, RecvPacket, SendPacket}; -use crate::networking::process_packets; +use crate::networking::send_packet_event; use crate::networking::websocket::Websocket; use crate::platform::websocket::Ws; use crate::rendering::renderer::{RenderCreateContext, Renderer}; use crate::rendering::MaybeRenderer::{Initialized, Initializing}; use assets::AssetLoader; +use crate::components::Schedule::Update; pub mod assets; mod renderer; @@ -402,28 +403,30 @@ impl ApplicationHandler for App { }; let Some(window) = &self.window else { return }; - let ws = self + let mut ws = self .world .get_resource_mut::() .expect("Failed to get Ws resource"); + + let mut packets = vec![]; + #[cfg(target_arch = "wasm32")] while let Ok(Some(packet)) = ws.receiver.try_next() { - renderer.recv_packet_events.send(RecvPacket(packet)); + packets.push(packet); } #[cfg(not(target_arch = "wasm32"))] while let Ok(packet) = ws.receiver.try_recv() { - renderer.recv_packet_events.send(RecvPacket(packet)); + packets.push(packet); + } + + for packet in packets { + send_packet_event(packet, &mut self.world); } renderer.send_packet_events.update(); renderer.recv_packet_events.update(); - process_packets( - &mut self.world, - &mut renderer.send_packet_events, - &mut renderer.recv_packet_events, - &mut renderer.planet_types, - ); + self.world.run_schedule(Update); let gl = self.gl.as_ref().unwrap(); unsafe { diff --git a/crates/client/src/systems.rs b/crates/client/src/systems.rs new file mode 100644 index 0000000000000000000000000000000000000000..053aad47f2725611af59b4e5c06a9612412f8bc5 --- /dev/null +++ b/crates/client/src/systems.rs @@ -0,0 +1,21 @@ +use bevy_ecs::bundle::Bundle; +use bevy_ecs::prelude::Commands; +use nalgebra::{Rotation2, Scale3, Translation3}; +use crate::components::{Part, Player, PlayerBundle, Texture, Transform}; + + + +pub fn create_hearty(mut commands: Commands) { + commands.spawn(PlayerBundle { + transform: 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: Texture { + name: "hearty.svg".to_string(), + }, + player: Player, + part: Part(false) + }); +} \ No newline at end of file diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml index 6318577b6d88cb38bcb520d0d7e7e426ed0f8e55..c797ef5cf5d392a532d4d5cda4872be75d256080 100644 --- a/crates/common/Cargo.toml +++ b/crates/common/Cargo.toml @@ -12,3 +12,8 @@ rmp-serde = "1" hmac = "0.12" sha2 = "0.10" base64 = "0.21" +bevy_ecs = { version = "0.15", optional = true } + +[features] +default = [] +bevy = ["dep:bevy_ecs"] \ No newline at end of file diff --git a/crates/common/src/packet.rs b/crates/common/src/packet.rs index e1eb256857e9affc365c0767a15b311aa1c858b9..905bab9aabafed5b7fbb55340f803c4d41e2541b 100644 --- a/crates/common/src/packet.rs +++ b/crates/common/src/packet.rs @@ -77,17 +77,20 @@ pub enum ButtonType { } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[cfg_attr(feature = "bevy", derive(::bevy_ecs::event::Event))] pub struct ClientLoginPacket { pub username: String, pub save: Option, pub jwt: Option, } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[cfg_attr(feature = "bevy", derive(::bevy_ecs::event::Event))] pub struct SendMessagePacket { pub target: Option, pub content: String, } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[cfg_attr(feature = "bevy", derive(::bevy_ecs::event::Event))] pub struct PlayerInputPacket { pub up: bool, pub down: bool, @@ -96,6 +99,7 @@ pub struct PlayerInputPacket { } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[cfg_attr(feature = "bevy", derive(::bevy_ecs::event::Event))] pub struct PlayerMouseInputPacket { pub x: f32, pub y: f32, @@ -104,56 +108,67 @@ pub struct PlayerMouseInputPacket { } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[cfg_attr(feature = "bevy", derive(::bevy_ecs::event::Event))] pub struct RequestSavePacket { pub old_save: Option, } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[cfg_attr(feature = "bevy", derive(::bevy_ecs::event::Event))] pub struct SpecialDisconnectPacket {} #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[cfg_attr(feature = "bevy", derive(::bevy_ecs::event::Event))] pub struct LoginResponsePacket { pub id: u32, } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[cfg_attr(feature = "bevy", derive(::bevy_ecs::event::Event))] pub struct SpawnPlayerPacket { pub id: u32, pub username: String, } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[cfg_attr(feature = "bevy", derive(::bevy_ecs::event::Event))] pub struct PlayerListPacket { pub players: Vec<(u32, String)>, } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[cfg_attr(feature = "bevy", derive(::bevy_ecs::event::Event))] pub struct PlanetPositionsPacket { pub planets: Vec<(u32, Planet)>, } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[cfg_attr(feature = "bevy", derive(::bevy_ecs::event::Event))] pub struct PartPositionsPacket { pub parts: Vec<(u32, Part)>, } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[cfg_attr(feature = "bevy", derive(::bevy_ecs::event::Event))] pub struct SpawnPartPacket { pub id: u32, pub part: Part, } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[cfg_attr(feature = "bevy", derive(::bevy_ecs::event::Event))] pub struct DespawnPartPacket { pub id: u32, } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[cfg_attr(feature = "bevy", derive(::bevy_ecs::event::Event))] pub struct PlayerLeavePacket { pub id: u32, } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[cfg_attr(feature = "bevy", derive(::bevy_ecs::event::Event))] pub struct MessagePacket { pub message_type: MessageType, pub actor: String, @@ -161,22 +176,26 @@ pub struct MessagePacket { } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[cfg_attr(feature = "bevy", derive(::bevy_ecs::event::Event))] pub struct SaveEligibilityPacket { pub eligible: bool, } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[cfg_attr(feature = "bevy", derive(::bevy_ecs::event::Event))] pub struct SaveDataPacket { pub payload: String, } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[cfg_attr(feature = "bevy", derive(::bevy_ecs::event::Event))] pub struct EnergyUpdatePacket { pub amount: u32, pub max: u32, } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[cfg_attr(feature = "bevy", derive(::bevy_ecs::event::Event))] pub struct OpenCraftingUiPacket { pub id: u32, } @@ -208,6 +227,29 @@ pub enum Packet { OpenCraftingUi(OpenCraftingUiPacket), } +#[cfg(feature = "bevy")] +pub fn register_packet_events(world: &mut bevy_ecs::prelude::World) { + bevy_ecs::event::EventRegistry::register_event::(world); + bevy_ecs::event::EventRegistry::register_event::(world); + bevy_ecs::event::EventRegistry::register_event::(world); + bevy_ecs::event::EventRegistry::register_event::(world); + bevy_ecs::event::EventRegistry::register_event::(world); + bevy_ecs::event::EventRegistry::register_event::(world); + bevy_ecs::event::EventRegistry::register_event::(world); + bevy_ecs::event::EventRegistry::register_event::(world); + bevy_ecs::event::EventRegistry::register_event::(world); + bevy_ecs::event::EventRegistry::register_event::(world); + bevy_ecs::event::EventRegistry::register_event::(world); + bevy_ecs::event::EventRegistry::register_event::(world); + bevy_ecs::event::EventRegistry::register_event::(world); + bevy_ecs::event::EventRegistry::register_event::(world); + bevy_ecs::event::EventRegistry::register_event::(world); + bevy_ecs::event::EventRegistry::register_event::(world); + bevy_ecs::event::EventRegistry::register_event::(world); + bevy_ecs::event::EventRegistry::register_event::(world); + bevy_ecs::event::EventRegistry::register_event::(world); +} + impl From for String { fn from(val: Packet) -> Self { serde_json::to_string(&val).expect("failed to serialize packet to json") @@ -238,4 +280,4 @@ impl TryFrom<&Vec> for Packet { fn try_from(value: &Vec) -> Result { serde_json::from_slice(value).map_err(MsgFromError::JSONError) } -} +} \ No newline at end of file