M Cargo.lock => Cargo.lock +7 -0
@@ 5570,6 5570,12 @@ dependencies = [
]
[[package]]
+name = "smolvec"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b43855ed42c16647e6f7d19fdef4b020529c822f77a5ab417eb2278e11756da7"
+
+[[package]]
name = "socket2"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 5653,6 5659,7 @@ dependencies = [
"postcard",
"rand 0.10.1",
"serde",
+ "smolvec",
"tracing-subscriber",
"tracing-web",
"wasm-bindgen",
M Cargo.toml => Cargo.toml +1 -0
@@ 68,6 68,7 @@ aeronet_transport = { version = "0.20" }
aeronet_replicon = { version = "0.20" }
bevy_replicon = { version = "0.39"}
postcard = { version = "1.1.3", features = ["alloc"] }
+smolvec = { version = "1" }
[profile.dev]
opt-level = 1
M crates/unified/Cargo.toml => crates/unified/Cargo.toml +1 -0
@@ 20,6 20,7 @@ web-time = { workspace = true }
aeronet = { workspace = true }
aeronet_transport = { workspace = true }
postcard = { workspace = true }
+smolvec = { workspace = true }
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
ctrlc = { workspace = true, optional = true }
M crates/unified/src/client/mod.rs => crates/unified/src/client/mod.rs +5 -11
@@ 22,7 22,7 @@ use crate::client::components::Me;
use crate::client::ship::attachment::client_attachment_plugin;
use crate::shared::ecs::{GameplayState, TimeOffset};
use crate::shared::gravity::update_gravity;
-use crate::shared::net::{Hi, ClientMessageRegistry, ServerMessageRegistry, ServerEntityMap};
+use crate::shared::net::{Hi, ClientMessageRegistry, ServerMessageRegistry, ServerEntityMap, TransportLanes};
use crate::shared::orbit::OrbitPlugin;
pub mod colors;
@@ 104,8 104,7 @@ pub fn on_connected(
trigger: On<Add, Session>,
names: Query<&Name>,
sessions: Query<&Session>,
- server_message_registry: Res<ServerMessageRegistry>,
- client_message_registry: Res<ClientMessageRegistry>,
+ lanes: Res<TransportLanes>,
mut commands: Commands,
) {
let entity = trigger.event_target();
@@ 114,15 113,10 @@ pub fn on_connected(
return;
};
- let server_message_count = server_message_registry.message_count();
- let client_message_count = client_message_registry.message_count();
- let message_count = server_message_count + client_message_count;
- debug!("message count: {}", message_count);
- let lanes = [LaneKind::ReliableOrdered].repeat(message_count);
let transport = Transport::new(
session,
- lanes.clone(),
- lanes,
+ lanes.lanes.iter().map(|u| u.clone()),
+ lanes.lanes.iter().map(|u| u.clone()),
bevy::platform::time::Instant::now(),
).expect("packet MTU too small to support transport");
commands.entity(entity).insert(transport);
@@ 147,7 141,7 @@ pub fn on_disconnected(trigger: On<Disconnected>, names: Query<&Name>) {
}
#[derive(Resource)]
-struct HeartyEntityId(Option<Entity>);
+pub struct HeartyEntityId(Option<Entity>);
pub fn handle_hi(
mut msgs: MessageReader<Hi>,
M crates/unified/src/client/net/incoming_parts.rs => crates/unified/src/client/net/incoming_parts.rs +22 -25
@@ 2,39 2,36 @@ use bevy::log::{debug, warn};
use bevy::prelude::{Commands, MessageReader, ResMut, Transform};
use crate::prelude::Query;
use crate::shared::ecs::{Part, Temperature};
-use crate::shared::net::part::PartUpdatePacket;
+use crate::shared::net::part::{PartDto};
use crate::shared::net::ServerEntityMap;
pub fn handle_incoming_parts(
- mut msgs: MessageReader<PartUpdatePacket>,
+ mut msgs: MessageReader<PartDto>,
mut q_parts: Query<(&mut Part, &mut Transform, &mut Temperature)>,
mut entity_map: ResMut<ServerEntityMap>,
mut commands: Commands
) {
- for msg in msgs.read() {
- 'to_next_part: for part in &msg.updated_parts {
- if let Some(local_entity) = entity_map.server_to_client.get(&part.server_entity) {
- let Ok((mut part_data, mut transform, mut temperature)) = q_parts.get_mut(*local_entity) else {
- warn!("local part entity {:?} for part srv:{:?} doesn't exist? skipping update, this is a bug", local_entity, part.server_entity);
- continue 'to_next_part
- };
- if part.part_data_changed {
- *part_data = part.part.clone();
- }
- *transform = part.transform;
- *temperature = part.temperature;
- } else {
- // Spawn new part
- let e = commands.spawn((
- part.part.clone(),
- part.transform,
- part.temperature,
- )).id();
- entity_map.server_to_client.insert(part.server_entity, e.clone());
- entity_map.client_to_server.insert(e.clone(), part.server_entity);
- debug!(?part.part, "spawned new part");
- }
+ for part in msgs.read() {
+ if let Some(local_entity) = entity_map.server_to_client.get(&part.server_entity) {
+ let Ok((mut part_data, mut transform, mut temperature)) = q_parts.get_mut(*local_entity) else {
+ warn!("local part entity {:?} for part srv:{:?} doesn't exist? skipping update, this is a bug", local_entity, part.server_entity);
+ continue;
+ };
+ part.part.update(part_data);
+ part.transform.update(transform);
+ part.temperature.update(temperature);
+ } else {
+ // Spawn new part
+ let e = commands.spawn((
+ part.part.data().clone(),
+ *part.transform.data(),
+ *part.temperature.data(),
+ )).id();
+ entity_map.server_to_client.insert(part.server_entity, e.clone());
+ entity_map.client_to_server.insert(e.clone(), part.server_entity);
+ debug!(?part.part, "spawned new part");
}
+
}
}=
\ No newline at end of file
M crates/unified/src/client/net/incoming_planets.rs => crates/unified/src/client/net/incoming_planets.rs +20 -23
@@ 2,37 2,34 @@ use bevy::log::{debug, warn};
use bevy::prelude::{Commands, MessageReader, ResMut, Transform};
use crate::prelude::Query;
use crate::shared::config::planet::Planet;
-use crate::shared::net::planet::PlanetUpdatePacket;
+use crate::shared::net::planet::{PlanetDto};
use crate::shared::net::ServerEntityMap;
pub fn handle_incoming_planets(
- mut msgs: MessageReader<PlanetUpdatePacket>,
+ mut msgs: MessageReader<PlanetDto>,
mut q_planets: Query<(&mut Planet, &mut Transform)>,
mut entity_map: ResMut<ServerEntityMap>,
mut commands: Commands
) {
- for msg in msgs.read() {
- 'to_next_planet: for planet in &msg.updated_planets {
- if let Some(local_entity) = entity_map.server_to_client.get(&planet.server_entity) {
- let Ok((mut planet_data, mut transform)) = q_planets.get_mut(*local_entity) else {
- warn!("local planet entity {:?} for planet srv:{:?} doesn't exist? skipping update, this is a bug", local_entity, planet.server_entity);
- continue 'to_next_planet
- };
- if planet.planet_data_changed {
- *planet_data = planet.planet.clone();
- }
- *transform = planet.transform;
- } else {
- // Spawn new planet
- let e = commands.spawn((
- planet.planet.clone(),
- planet.transform
- )).id();
- entity_map.server_to_client.insert(planet.server_entity, e.clone());
- entity_map.client_to_server.insert(e.clone(), planet.server_entity);
- debug!(?planet.planet, "spawned new planet");
- }
+ for planet in msgs.read() {
+ if let Some(local_entity) = entity_map.server_to_client.get(&planet.server_entity) {
+ let Ok((mut planet_data, mut transform)) = q_planets.get_mut(*local_entity) else {
+ warn!("local planet entity {:?} for planet srv:{:?} doesn't exist? skipping update, this is a bug", local_entity, planet.server_entity);
+ continue;
+ };
+ planet.planet.update(planet_data);
+ planet.transform.update(transform);
+ } else {
+ // Spawn new planet
+ let e = commands.spawn((
+ planet.planet.data().clone(),
+ *planet.transform.data(),
+ )).id();
+ entity_map.server_to_client.insert(planet.server_entity, e.clone());
+ entity_map.client_to_server.insert(e.clone(), planet.server_entity);
+ debug!(?planet.planet, "spawned new planet");
}
+
}
}=
\ No newline at end of file
M crates/unified/src/server/mod.rs => crates/unified/src/server/mod.rs +4 -11
@@ 37,7 37,7 @@ use crate::server::system_sets::{PlayerInputSet, WorldUpdateSet};
use crate::prelude::*;
use crate::server::orbit::OrbitPlugin;
use crate::server::player::thrust::server_thrust_plugin;
-use crate::shared::net::{ClientMessageRegistry, ServerMessageRegistry};
+use crate::shared::net::{ClientMessageRegistry, ServerMessageRegistry, TransportLanes};
pub struct ServerPlugin {
pub bind: SocketAddr
@@ 95,8 95,7 @@ fn on_connected(
trigger: On<Add, Session>,
clients: Query<&ChildOf>,
sessions: Query<&Session>,
- server_message_registry: Res<ServerMessageRegistry>,
- client_message_registry: Res<ClientMessageRegistry>,
+ lanes: Res<TransportLanes>,
mut commands: Commands,
) {
let client = trigger.event_target();
@@ 112,16 111,10 @@ fn on_connected(
network_entity: client,
}))
.id();
-
- let server_message_count = server_message_registry.message_count();
- let client_message_count = client_message_registry.message_count();
- let message_count = server_message_count + client_message_count;
- debug!("message count: {}", message_count);
- let lanes = [LaneKind::ReliableOrdered].repeat(message_count);
let transport = Transport::new(
session,
- lanes.clone(),
- lanes,
+ lanes.lanes.iter().map(|u| u.clone()),
+ lanes.lanes.iter().map(|u| u.clone()),
bevy::platform::time::Instant::now(),
).expect("packet MTU too small to support transport");
commands.entity(client).insert((
M crates/unified/src/server/net/update_parts.rs => crates/unified/src/server/net/update_parts.rs +13 -65
@@ 1,75 1,23 @@
use std::collections::BTreeSet;
-use bevy::prelude::{Added, Changed, Commands, MessageWriter, Query};
+use bevy::prelude::{Added, Changed, Commands, MessageWriter, Query, Ref};
use crate::prelude::{debug, Entity, ParamSet, Transform};
use crate::shared::ecs::{Part, Temperature};
-use crate::shared::net::part::{PartUpdatePacket, PartDto};
+use crate::shared::net::part::{PartDto};
use crate::shared::net::staged_transform::LastStagedTransform;
use crate::shared::net::{SendTargets, ToClients};
-
pub fn send_updated_parts(
- mut set: ParamSet<(
- // If you need to send more data, don't add it here...
- Query<(Entity, &Transform), Added<Part>>,
- Query<(Entity, &Transform, &LastStagedTransform), Changed<Transform>>,
- Query<Entity, Changed<Part>>,
-
- // add it here.
- Query<(&Part, &Transform, &Temperature, &mut LastStagedTransform)>,
- )>,
-
- mut update_packets_out: MessageWriter<ToClients<PartUpdatePacket>>,
- mut commands: Commands
+ parts: Query<(Entity, Ref<Part>, Ref<Transform>, Ref<Temperature>)>,
+ mut messages: MessageWriter<ToClients<PartDto>>
) {
- let start = bevy::platform::time::Instant::now();
- let mut parts_to_send: BTreeSet<Entity> = BTreeSet::new();
-
- // Updating the part behavior triggers sprite loading on the client. We don't want to send it every time the Transform changes
- let mut parts_with_part_change: BTreeSet<Entity> = BTreeSet::new();
-
- for (new_part, transform) in set.p0().iter() {
- parts_to_send.insert(new_part); // Always send newly created parts...
- // ...and add LastStagedTransform...
- commands.entity(new_part).insert(LastStagedTransform(*transform));
- // and put a marker, we need to copy part data across
- parts_with_part_change.insert(new_part);
- }
- for (moved_part, current_transform, maybe_staged_transform) in set.p1().iter() {
- // have we had a significant transform change?
- if !maybe_staged_transform.should_update(current_transform) { continue; }
- // we have, resend
- parts_to_send.insert(moved_part);
- }
- for changed_part in set.p2().iter() {
- // if part changed, always resend
- parts_to_send.insert(changed_part);
- // and put a marker, we need to copy part data across
- parts_with_part_change.insert(changed_part);
- }
-
- // process all parts to send
- let mut packet = PartUpdatePacket {
- updated_parts: vec![]
- };
-
- for part_to_send in parts_to_send.iter() {
- let mut q = set.p3();
- let Ok(mut part_info) = q.get_mut(*part_to_send) else { continue };
-
- *part_info.3 = LastStagedTransform(*part_info.1);
-
- packet.updated_parts.push(PartDto {
- server_entity: *part_to_send,
- part: part_info.0.clone(),
- part_data_changed: parts_with_part_change.contains(part_to_send),
- transform: *part_info.1,
- temperature: *part_info.2
+ for part in parts {
+ messages.write(ToClients {
+ message: PartDto {
+ server_entity: part.0,
+ part: part.1.into(),
+ transform: part.2.into(),
+ temperature: part.3.into()
+ },
+ targets: SendTargets::All
});
-
}
-
- update_packets_out.write(ToClients {
- message: packet,
- targets: SendTargets::All,
- });
-
}=
\ No newline at end of file
M crates/unified/src/server/net/update_planets.rs => crates/unified/src/server/net/update_planets.rs +14 -60
@@ 1,71 1,25 @@
use std::collections::BTreeSet;
use bevy::prelude::{Added, Changed, Commands, MessageWriter, Query};
-use crate::prelude::{Entity, ParamSet, Transform};
+use crate::prelude::{Entity, ParamSet, Ref, Transform};
use crate::shared::config::planet::Planet;
-use crate::shared::net::planet::{PlanetUpdatePacket, PlanetDto};
+use crate::shared::ecs::{Part, Temperature};
+use crate::shared::net::planet::PlanetDto;
use crate::shared::net::staged_transform::LastStagedTransform;
use crate::shared::net::{SendTargets, ToClients};
+use crate::shared::net::part::PartDto;
pub fn send_updated_planets(
- mut set: ParamSet<(
- // If you need to send more data, don't add it here...
- Query<(Entity, &Transform), Added<Planet>>,
- Query<(Entity, &Transform, &LastStagedTransform), Changed<Transform>>,
- Query<Entity, Changed<Planet>>,
-
- // add it here.
- Query<(&Planet, &Transform, &mut LastStagedTransform)>,
- )>,
-
- mut update_packets_out: MessageWriter<ToClients<PlanetUpdatePacket>>,
- mut commands: Commands
+ planets: Query<(Entity, Ref<Planet>, Ref<Transform>, Ref<Temperature>)>,
+ mut messages: MessageWriter<ToClients<PlanetDto>>
) {
- let mut planets_to_send: BTreeSet<Entity> = BTreeSet::new();
-
- // Updating the Planet behavior triggers sprite loading on the client. We don't want to send it every time the Transform changes
- let mut planets_with_planet_change: BTreeSet<Entity> = BTreeSet::new();
-
- for (new_planet, transform) in set.p0().iter() {
- planets_to_send.insert(new_planet); // Always send newly created planets...
- // ...and add LastStagedTransform...
- commands.entity(new_planet).insert(LastStagedTransform(*transform));
- // and put a marker, we need to copy planet data across
- planets_with_planet_change.insert(new_planet);
- }
- for (moved_planet, current_transform, maybe_staged_transform) in set.p1().iter() {
- // have we had a significant transform change?
- if !maybe_staged_transform.should_update(current_transform) { continue; }
- // we have, resend
- planets_to_send.insert(moved_planet);
- }
- for changed_planet in set.p2().iter() {
- // if Planet changed, always resend
- planets_to_send.insert(changed_planet);
- // and put a marker, we need to copy planet data across
- planets_with_planet_change.insert(changed_planet);
- }
-
- // process all planets to send
- let mut packet = PlanetUpdatePacket {
- updated_planets: vec![]
- };
-
- for planet_to_send in planets_to_send.iter() {
- let mut p3 = set.p3();
- let Ok(mut planet_info) = p3.get_mut(*planet_to_send) else { continue };
-
- *planet_info.2 = LastStagedTransform(*planet_info.1);
-
- packet.updated_planets.push(PlanetDto {
- server_entity: *planet_to_send,
- planet: planet_info.0.clone(),
- planet_data_changed: planets_with_planet_change.contains(planet_to_send),
- transform: *planet_info.1,
+ for planet in planets {
+ messages.write(ToClients {
+ message: PlanetDto {
+ server_entity: planet.0,
+ planet: planet.1.into(),
+ transform: planet.2.into(),
+ },
+ targets: SendTargets::All
});
}
-
- update_packets_out.write(ToClients {
- message: packet,
- targets: SendTargets::All,
- });
}=
\ No newline at end of file
M crates/unified/src/shared/net.rs => crates/unified/src/shared/net.rs +32 -30
@@ 1,6 1,7 @@
pub mod planet;
pub mod staged_transform;
pub mod part;
+pub mod was_updated;
use std::any::TypeId;
use std::collections::HashMap;
@@ 9,7 10,7 @@ use std::sync::atomic::{AtomicU32, AtomicUsize, Ordering};
use std::time::Instant;
use aeronet_transport::Transport;
-use aeronet_transport::lane::LaneIndex;
+use aeronet_transport::lane::{LaneIndex, LaneKind};
use aeronet_websocket::tungstenite::Bytes;
use avian2d::prelude::{AngularInertia, AngularVelocity, Collider, LinearVelocity, Mass, Position, Rotation};
use bevy::ecs::entity::{EntityHashMap, MapEntities};
@@ 20,24 21,25 @@ use postcard::{from_bytes, to_allocvec, to_slice, to_vec};
use crate::prelude::{App, Message};
use crate::shared::thrust::ThrustSolution;
use serde::{Deserialize, Serialize};
+use smolvec::SmolVec;
use crate::shared::attachment::{Joint, JointOf, PartInShip, Peer, Ship, SnapOf, SnapOfJoint};
use crate::shared::config::planet::{Planet, PlanetSpring, PlanetSpringJoint};
use crate::shared::ecs::{CanCraft, CraftPartRequest, DragRequestEvent, Drill, Part, Player, PlayerStorage, SingleStorage, Temperature, ToggleDrillEvent};
use crate::shared::ecs::thruster::{Thruster, ThrusterOfPart};
-use crate::shared::net::part::PartUpdatePacket;
-use crate::shared::net::planet::PlanetUpdatePacket;
+use crate::shared::net::part::PartDto;
+use crate::shared::net::planet::PlanetDto;
pub fn register_net(app: &mut App) {
app
- .add_server_message::<Hi>()
+ .add_server_message::<Hi>(LaneKind::ReliableOrdered)
- .add_server_message::<PlanetUpdatePacket>()
- .add_server_message::<PartUpdatePacket>()
+ .add_server_message::<PlanetDto>(LaneKind::UnreliableSequenced)
+ .add_server_message::<PartDto>(LaneKind::UnreliableSequenced)
- .add_client_message::<DragRequestEvent>()
- .add_client_message::<ToggleDrillEvent>()
- .add_client_message::<CraftPartRequest>()
- .add_client_message::<ThrustSolution>()
+ .add_client_message::<DragRequestEvent>(LaneKind::ReliableOrdered)
+ .add_client_message::<ToggleDrillEvent>(LaneKind::ReliableOrdered)
+ .add_client_message::<CraftPartRequest>(LaneKind::ReliableOrdered)
+ .add_client_message::<ThrustSolution>(LaneKind::ReliableOrdered)
.add_systems(PostStartup, |srv_msg_reg: Res<ServerMessageRegistry>, client_msg_reg: Res<ClientMessageRegistry>| {
debug!("network registration complete");
@@ 56,6 58,7 @@ pub struct Hi {
pub fn setup_net(app: &mut App) {
app.insert_resource(ServerMessageRegistry::default());
app.insert_resource(ClientMessageRegistry::default());
+ app.insert_resource(TransportLanes::default());
app.add_systems(Update, recv_from_server);
app.add_systems(Update, recv_from_client);
}
@@ 85,6 88,11 @@ pub enum ClientId {
}
#[derive(Resource, Default)]
+pub struct TransportLanes {
+ pub lanes: Vec<LaneKind>
+}
+
+#[derive(Resource, Default)]
pub struct ServerEntityMap {
pub server_to_client: EntityHashMap<Entity>,
pub client_to_server: EntityHashMap<Entity>,
@@ 94,21 102,11 @@ pub struct ServerMessageRegistry {
forward: HashMap<TypeId, LaneIndex>,
reverse: HashMap<LaneIndex, fn(Vec<u8>, &mut World)>,
}
-impl ServerMessageRegistry {
- pub fn message_count(&self) -> usize {
- self.forward.len()
- }
-}
#[derive(Resource, Default, Debug)]
pub struct ClientMessageRegistry {
forward: HashMap<TypeId, LaneIndex>,
reverse: HashMap<LaneIndex, fn(Vec<u8>, ClientId, &mut World)>,
}
-impl ClientMessageRegistry {
- pub fn message_count(&self) -> usize {
- self.forward.len()
- }
-}
static COUNTER: AtomicU32 = AtomicU32::new(0);
fn get_lane_index() -> LaneIndex {
@@ 116,39 114,43 @@ fn get_lane_index() -> LaneIndex {
}
pub trait NetAppExt {
- fn add_mapped_server_message<T: Message + MapEntities + TypePath + Serialize + for<'a> Deserialize<'a>>(&mut self) -> &mut Self;
- fn add_server_message<T: Message + TypePath + Serialize + for<'a> Deserialize<'a>>(&mut self) -> &mut Self;
- fn add_mapped_client_message<T: Message + Clone + MapEntities + TypePath + Serialize + for<'a> Deserialize<'a>>(&mut self) -> &mut Self;
- fn add_client_message<T: Message + TypePath + Serialize + for<'a> Deserialize<'a>>(&mut self) -> &mut Self;
+ fn add_mapped_server_message<T: Message + MapEntities + TypePath + Serialize + for<'a> Deserialize<'a>>(&mut self, kind: LaneKind) -> &mut Self;
+ fn add_server_message<T: Message + TypePath + Serialize + for<'a> Deserialize<'a>>(&mut self, kind: LaneKind) -> &mut Self;
+ fn add_mapped_client_message<T: Message + Clone + MapEntities + TypePath + Serialize + for<'a> Deserialize<'a>>(&mut self, kind: LaneKind) -> &mut Self;
+ fn add_client_message<T: Message + TypePath + Serialize + for<'a> Deserialize<'a>>(&mut self, kind: LaneKind) -> &mut Self;
}
impl NetAppExt for App {
- fn add_mapped_server_message<T: Message + MapEntities + TypePath + Serialize + for<'a> Deserialize<'a>>(&mut self) -> &mut Self {
+ fn add_mapped_server_message<T: Message + MapEntities + TypePath + Serialize + for<'a> Deserialize<'a>>(&mut self, kind: LaneKind) -> &mut Self {
let mut registry = self.world_mut().resource_mut::<ServerMessageRegistry>();
register_mapped_server_message::<T>(&mut registry);
+ self.world_mut().resource_mut::<TransportLanes>().lanes.push(kind);
self
.add_message::<ToClients<T>>()
.add_message::<T>()
.add_systems(Update, send_to_client::<T>)
}
- fn add_server_message<T: Message + TypePath + Serialize + for<'a> Deserialize<'a>>(&mut self) -> &mut Self {
+ fn add_server_message<T: Message + TypePath + Serialize + for<'a> Deserialize<'a>>(&mut self, kind: LaneKind) -> &mut Self {
let mut registry = self.world_mut().resource_mut::<ServerMessageRegistry>();
register_server_message::<T>(&mut registry);
+ self.world_mut().resource_mut::<TransportLanes>().lanes.push(kind);
self
.add_message::<ToClients<T>>()
.add_message::<T>()
.add_systems(Update, send_to_client::<T>)
}
- fn add_mapped_client_message<T: Message + Clone + MapEntities + TypePath + Serialize + for<'a> Deserialize<'a>>(&mut self) -> &mut Self {
+ fn add_mapped_client_message<T: Message + Clone + MapEntities + TypePath + Serialize + for<'a> Deserialize<'a>>(&mut self, kind: LaneKind) -> &mut Self {
let mut registry = self.world_mut().resource_mut::<ClientMessageRegistry>();
register_client_message::<T>(&mut registry);
+ self.world_mut().resource_mut::<TransportLanes>().lanes.push(kind);
self
.add_message::<FromClients<T>>()
.add_message::<T>()
.add_systems(Update, send_mapped_to_server::<T>)
}
- fn add_client_message<T: Message + TypePath + Serialize + for<'a> Deserialize<'a>>(&mut self) -> &mut Self {
+ fn add_client_message<T: Message + TypePath + Serialize + for<'a> Deserialize<'a>>(&mut self, kind: LaneKind) -> &mut Self {
let mut registry = self.world_mut().resource_mut::<ClientMessageRegistry>();
register_client_message::<T>(&mut registry);
+ self.world_mut().resource_mut::<TransportLanes>().lanes.push(kind);
self
.add_message::<FromClients<T>>()
.add_message::<T>()
@@ 260,7 262,7 @@ fn recv_from_server(
Res<ServerMessageRegistry>,
)> = SystemState::new(world);
let (mut sessions, message_registry) = system_state.get_mut(world);
- let mut messages = Vec::new();
+ let mut messages = SmolVec::new();
for mut transport in sessions.iter_mut() {
for message in transport.recv.msgs.drain() {
let payload = message.payload;
@@ 283,7 285,7 @@ fn recv_from_client(
Res<ClientMessageRegistry>,
)> = SystemState::new(world);
let (mut clients, message_registry) = system_state.get_mut(world);
- let mut messages = Vec::new();
+ let mut messages = SmolVec::new();
for (client_entity, mut transport) in clients.iter_mut() {
for message in transport.recv.msgs.drain() {
let payload = message.payload;
M crates/unified/src/shared/net/part.rs => crates/unified/src/shared/net/part.rs +5 -11
@@ 2,19 2,13 @@ use bevy::prelude::{Entity, Message, Transform, TypePath};
use serde::{Deserialize, Serialize};
use crate::shared::config::planet::Planet;
use crate::shared::ecs::{Part, Temperature};
+use crate::shared::net::was_updated::WasUpdated;
-#[derive(Serialize, Deserialize, Message, TypePath, Debug, Clone)]
-pub struct PartUpdatePacket {
- pub updated_parts: Vec<PartDto>
-}
-
-#[derive(Serialize, Deserialize, TypePath, Debug, Clone)]
+#[derive(Serialize, Deserialize, TypePath, Debug, Clone, Message)]
pub struct PartDto {
pub server_entity: Entity,
- pub part: Part,
- pub part_data_changed: bool,
-
- pub transform: Transform,
- pub temperature: Temperature,
+ pub part: WasUpdated<Part>,
+ pub transform: WasUpdated<Transform>,
+ pub temperature: WasUpdated<Temperature>,
}=
\ No newline at end of file
M crates/unified/src/shared/net/planet.rs => crates/unified/src/shared/net/planet.rs +4 -10
@@ 1,18 1,12 @@
use bevy::prelude::{Entity, Message, Transform, TypePath};
use serde::{Deserialize, Serialize};
use crate::shared::config::planet::Planet;
+use crate::shared::net::was_updated::WasUpdated;
-#[derive(Serialize, Deserialize, Message, TypePath, Debug, Clone)]
-pub struct PlanetUpdatePacket {
- pub updated_planets: Vec<PlanetDto>
-}
-
-#[derive(Serialize, Deserialize, TypePath, Debug, Clone)]
+#[derive(Serialize, Deserialize, TypePath, Debug, Clone, Message)]
pub struct PlanetDto {
pub server_entity: Entity,
- pub planet: Planet,
- pub planet_data_changed: bool,
-
- pub transform: Transform
+ pub planet: WasUpdated<Planet>,
+ pub transform: WasUpdated<Transform>
}=
\ No newline at end of file
A crates/unified/src/shared/net/was_updated.rs => crates/unified/src/shared/net/was_updated.rs +24 -0
@@ 0,0 1,24 @@
+use std::fmt::Debug;
+use bevy::prelude::{Mut, Ref};
+use serde::{Deserialize, Serialize};
+use serde::de::DeserializeOwned;
+use crate::prelude::DetectChanges;
+
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub struct WasUpdated<T: Clone + Serialize + Debug>(T, bool);
+impl<T: Clone + Serialize + DeserializeOwned + Debug> From<Ref<'_, T>> for WasUpdated<T> {
+ fn from(value: Ref<T>) -> Self {
+ let changed = value.is_changed();
+ Self(value.into_inner().clone(), changed)
+ }
+}
+impl<T: Clone + Serialize + DeserializeOwned + Debug> WasUpdated<T> {
+ pub fn update(&self, mut data: Mut<T>) {
+ if self.1 {
+ *data = self.0.clone();
+ }
+ }
+ pub fn data(&self) -> &T {
+ &self.0
+ }
+}<
\ No newline at end of file