From c7da20800d035a6491e612693b2039aa99988c15 Mon Sep 17 00:00:00 2001 From: core Date: Tue, 9 Jun 2026 00:09:32 -0400 Subject: [PATCH] netcode: easing --- Cargo.lock | 8 +--- Cargo.toml | 2 +- crates/unified/Cargo.toml | 2 +- crates/unified/src/client/net.rs | 48 ++++++++++++++++++- .../unified/src/client/net/incoming_parts.rs | 14 +++++- .../src/client/net/incoming_planets.rs | 14 +++++- crates/unified/src/client/plugins.rs | 5 ++ crates/unified/src/server/net/update_parts.rs | 7 ++- .../unified/src/server/net/update_planets.rs | 5 +- crates/unified/src/shared/net/part.rs | 3 ++ crates/unified/src/shared/net/planet.rs | 5 +- 11 files changed, 95 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c8bf7d9ca06a01bff67487443abe01af8a92b32d..764a7a06f01324c77a866d7a36dde30d6e44d249 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5569,12 +5569,6 @@ dependencies = [ "serde", ] -[[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" @@ -5650,6 +5644,7 @@ dependencies = [ "avian2d", "bevy", "bevy_common_assets", + "bevy_transform_interpolation", "console_error_panic_hook", "ctrlc", "getrandom 0.4.2", @@ -5659,7 +5654,6 @@ dependencies = [ "postcard", "rand 0.10.1", "serde", - "smolvec", "tracing-subscriber", "tracing-web", "wasm-bindgen", diff --git a/Cargo.toml b/Cargo.toml index db014f773729d80c4687c5f636add12a8f10c63a..228e152fa3db1ba29d7af38610b6c1e88ae56bea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -68,7 +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" } +bevy_transform_interpolation = { version = "0.4" } [profile.dev] opt-level = 1 diff --git a/crates/unified/Cargo.toml b/crates/unified/Cargo.toml index 19e5edaf232efd2c57c4b7ced77990c047e12a41..423ce7e867f090bd9327182ea19f0fe240f8705a 100644 --- a/crates/unified/Cargo.toml +++ b/crates/unified/Cargo.toml @@ -20,7 +20,7 @@ web-time = { workspace = true } aeronet = { workspace = true } aeronet_transport = { workspace = true } postcard = { workspace = true } -smolvec = { workspace = true } +bevy_transform_interpolation = { workspace = true } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] ctrlc = { workspace = true, optional = true } diff --git a/crates/unified/src/client/net.rs b/crates/unified/src/client/net.rs index 9b330025249f5ff465884537466fa1de29c6fd15..992e4a463daf328082b22d4b9d3eb521a52e1995 100644 --- a/crates/unified/src/client/net.rs +++ b/crates/unified/src/client/net.rs @@ -1,6 +1,9 @@ pub mod incoming_planets; pub mod incoming_parts; +use avian2d::math::{Scalar, Vector}; +use bevy::ecs::query::QueryData; +use bevy_transform_interpolation::VelocitySource; use crate::{prelude::*, shared::net::{ServerEntityMap}}; use crate::client::net::incoming_parts::handle_incoming_parts; use crate::client::net::incoming_planets::handle_incoming_planets; @@ -8,5 +11,48 @@ use crate::client::net::incoming_planets::handle_incoming_planets; pub fn net_plugin(app: &mut App) { app .insert_resource(ServerEntityMap::default()) - .add_systems(PostUpdate, (handle_incoming_planets, handle_incoming_parts)); + .add_systems(FixedUpdate, (update_previous_velocities, (handle_incoming_planets, handle_incoming_parts)).chain()); +} + +#[derive(Component)] +pub struct PreviousAngularVelocity(Scalar); +#[derive(Component)] +pub struct PreviousLinearVelocity(Vector); +#[derive(QueryData)] +pub struct LinearVelocitySource; +#[derive(QueryData)] +pub struct AngularVelocitySource; +impl VelocitySource for LinearVelocitySource { + type Previous = PreviousLinearVelocity; + type Current = LinearVelocity; + + fn previous(start: &Self::Previous) -> Vec3 { + let v = start.0.extend(0.0); + Vec3::new(v.x as f32, v.y as f32, v.z as f32) + } + + fn current(end: &Self::Current) -> Vec3 { + let v = end.0.extend(0.0); + Vec3::new(v.x as f32, v.y as f32, v.z as f32) + } +} +impl VelocitySource for AngularVelocitySource { + type Previous = PreviousAngularVelocity; + type Current = AngularVelocity; + + fn previous(start: &Self::Previous) -> Vec3 { + Vec3::Z * start.0 as f32 + } + + fn current(end: &Self::Current) -> Vec3 { + Vec3::Z * end.0 as f32 + } +} +fn update_previous_velocities( + mut entities: Query<(&mut PreviousAngularVelocity, &AngularVelocity, &mut PreviousLinearVelocity, &LinearVelocity)> +) { + for mut entity in entities.iter_mut() { + *entity.0 = PreviousAngularVelocity(**entity.1); + *entity.2 = PreviousLinearVelocity(**entity.3); + } } \ No newline at end of file diff --git a/crates/unified/src/client/net/incoming_parts.rs b/crates/unified/src/client/net/incoming_parts.rs index dacd1d225f049bbd959b191cd47c3a413ea58379..840176bdd861c9ae26a139e45ae243e3d5483f17 100644 --- a/crates/unified/src/client/net/incoming_parts.rs +++ b/crates/unified/src/client/net/incoming_parts.rs @@ -1,5 +1,9 @@ +use avian2d::prelude::{AngularVelocity, LinearVelocity}; use bevy::log::{debug, warn}; use bevy::prelude::{Commands, MessageReader, ResMut, Transform}; +use bevy_transform_interpolation::hermite::TransformHermiteEasing; +use bevy_transform_interpolation::interpolation::TransformInterpolation; +use crate::client::net::AngularVelocitySource; use crate::prelude::Query; use crate::shared::ecs::{Part, Temperature}; use crate::shared::net::part::{PartDto}; @@ -8,25 +12,31 @@ use crate::shared::net::ServerEntityMap; pub fn handle_incoming_parts( mut msgs: MessageReader, - mut q_parts: Query<(&mut Part, &mut Transform, &mut Temperature)>, + mut q_parts: Query<(&mut Part, &mut Transform, &mut Temperature, &mut LinearVelocity, &mut AngularVelocity)>, mut entity_map: ResMut, mut commands: Commands ) { 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 { + let Ok((mut part_data, mut transform, mut temperature, mut linvel, mut angvel)) = 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); + part.linvel.update(linvel); + part.angvel.update(angvel); } else { // Spawn new part let e = commands.spawn(( part.part.data().clone(), *part.transform.data(), *part.temperature.data(), + *part.linvel.data(), + *part.angvel.data(), + TransformInterpolation, + //TransformHermiteEasing )).id(); entity_map.server_to_client.insert(part.server_entity, e.clone()); entity_map.client_to_server.insert(e.clone(), part.server_entity); diff --git a/crates/unified/src/client/net/incoming_planets.rs b/crates/unified/src/client/net/incoming_planets.rs index 6749970fd64e42bef1098a2c44a2861a8e28f2c4..6b0a2822c4ff8e84e32714fe1927301da2947aa6 100644 --- a/crates/unified/src/client/net/incoming_planets.rs +++ b/crates/unified/src/client/net/incoming_planets.rs @@ -1,5 +1,9 @@ +use avian2d::prelude::{AngularVelocity, LinearVelocity}; use bevy::log::{debug, warn}; use bevy::prelude::{Commands, MessageReader, ResMut, Transform}; +use bevy_transform_interpolation::hermite::TransformHermiteEasing; +use bevy_transform_interpolation::interpolation::TransformInterpolation; +use crate::client::net::AngularVelocitySource; use crate::prelude::Query; use crate::shared::config::planet::Planet; use crate::shared::net::planet::{PlanetDto}; @@ -8,23 +12,29 @@ use crate::shared::net::ServerEntityMap; pub fn handle_incoming_planets( mut msgs: MessageReader, - mut q_planets: Query<(&mut Planet, &mut Transform)>, + mut q_planets: Query<(&mut Planet, &mut Transform, &mut LinearVelocity, &mut AngularVelocity)>, mut entity_map: ResMut, mut commands: Commands ) { 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 { + let Ok((mut planet_data, mut transform, mut linvel, mut angvel)) = 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); + planet.linvel.update(linvel); + planet.angvel.update(angvel); } else { // Spawn new planet let e = commands.spawn(( planet.planet.data().clone(), *planet.transform.data(), + *planet.linvel.data(), + *planet.angvel.data(), + TransformInterpolation, + //TransformHermiteEasing )).id(); entity_map.server_to_client.insert(planet.server_entity, e.clone()); entity_map.client_to_server.insert(e.clone(), planet.server_entity); diff --git a/crates/unified/src/client/plugins.rs b/crates/unified/src/client/plugins.rs index 504791261c185b6eef081c14a327a1b18fedcaaa..8325942ffa6389091d94c2107524ae529f7a9b6c 100644 --- a/crates/unified/src/client/plugins.rs +++ b/crates/unified/src/client/plugins.rs @@ -10,8 +10,11 @@ use bevy::input_focus::InputDispatchPlugin; use bevy::log::LogPlugin; use bevy::state::app::StatesPlugin; use bevy::time::TimePlugin; +use bevy_transform_interpolation::hermite::TransformHermiteEasingPlugin; +use bevy_transform_interpolation::prelude::TransformInterpolationPlugin; use crate::prelude::*; use leafwing_input_manager::plugin::InputManagerPlugin; +use crate::client::net::{AngularVelocitySource, LinearVelocitySource}; pub struct ClientPluginGroup; @@ -33,6 +36,8 @@ impl PluginGroup for ClientPluginGroup { .add(InputDispatchPlugin) .add(InputManagerPlugin::::default()) .add(WebSocketClientPlugin) + .add(TransformInterpolationPlugin::interpolate_all()) + .add(TransformHermiteEasingPlugin::::default()) //.add(bevy_replicon::client::ClientPlugin) //.add(bevy_replicon::client::message::ClientMessagePlugin) //.add(AeronetRepliconClientPlugin) diff --git a/crates/unified/src/server/net/update_parts.rs b/crates/unified/src/server/net/update_parts.rs index 25cb111cd89da69a76b3bd767794cd85b3d8ce5e..1748a536e1fe2df87713a6458e3aaa3a2a533fda 100644 --- a/crates/unified/src/server/net/update_parts.rs +++ b/crates/unified/src/server/net/update_parts.rs @@ -1,4 +1,5 @@ use std::collections::BTreeSet; +use avian2d::prelude::{AngularVelocity, LinearVelocity}; use bevy::prelude::{Added, Changed, Commands, MessageWriter, Query, Ref}; use crate::prelude::{debug, Entity, ParamSet, Transform}; use crate::shared::ecs::{Part, Temperature}; @@ -6,7 +7,7 @@ use crate::shared::net::part::{PartDto}; use crate::shared::net::staged_transform::LastStagedTransform; use crate::shared::net::{SendTargets, ToClients}; pub fn send_updated_parts( - parts: Query<(Entity, Ref, Ref, Ref)>, + parts: Query<(Entity, Ref, Ref, Ref, Ref, Ref)>, mut messages: MessageWriter> ) { for part in parts { @@ -15,7 +16,9 @@ pub fn send_updated_parts( server_entity: part.0, part: part.1.into(), transform: part.2.into(), - temperature: part.3.into() + temperature: part.3.into(), + linvel: part.4.into(), + angvel: part.5.into() }, targets: SendTargets::All }); diff --git a/crates/unified/src/server/net/update_planets.rs b/crates/unified/src/server/net/update_planets.rs index 0a662ce36bde6580c0adef11e69bd5ca02f569cd..8a7616588ffd6236cb80231e4662128e90e1d86d 100644 --- a/crates/unified/src/server/net/update_planets.rs +++ b/crates/unified/src/server/net/update_planets.rs @@ -1,4 +1,5 @@ use std::collections::BTreeSet; +use avian2d::prelude::{AngularVelocity, LinearVelocity}; use bevy::prelude::{Added, Changed, Commands, MessageWriter, Query}; use crate::prelude::{Entity, ParamSet, Ref, Transform}; use crate::shared::config::planet::Planet; @@ -9,7 +10,7 @@ use crate::shared::net::{SendTargets, ToClients}; use crate::shared::net::part::PartDto; pub fn send_updated_planets( - planets: Query<(Entity, Ref, Ref)>, + planets: Query<(Entity, Ref, Ref, Ref, Ref)>, mut messages: MessageWriter> ) { for planet in planets { @@ -18,6 +19,8 @@ pub fn send_updated_planets( server_entity: planet.0, planet: planet.1.into(), transform: planet.2.into(), + linvel: planet.3.into(), + angvel: planet.4.into(), }, targets: SendTargets::All }); diff --git a/crates/unified/src/shared/net/part.rs b/crates/unified/src/shared/net/part.rs index 4294245a18eed6f528db25003fbd53cc8962534d..d5e8205b9991bcbfd3fcd758901090faa4b29d41 100644 --- a/crates/unified/src/shared/net/part.rs +++ b/crates/unified/src/shared/net/part.rs @@ -1,3 +1,4 @@ +use avian2d::prelude::{AngularVelocity, LinearVelocity}; use bevy::prelude::{Entity, Message, Transform, TypePath}; use serde::{Deserialize, Serialize}; use crate::shared::config::planet::Planet; @@ -11,4 +12,6 @@ pub struct PartDto { pub part: WasUpdated, pub transform: WasUpdated, pub temperature: WasUpdated, + pub linvel: WasUpdated, + pub angvel: WasUpdated, } \ No newline at end of file diff --git a/crates/unified/src/shared/net/planet.rs b/crates/unified/src/shared/net/planet.rs index d74f667be143269aeaa68b3984463e1f657ffcc6..cfaec7024b40f365698c45de5c49f2d38191a4da 100644 --- a/crates/unified/src/shared/net/planet.rs +++ b/crates/unified/src/shared/net/planet.rs @@ -1,3 +1,4 @@ +use avian2d::prelude::{AngularVelocity, LinearVelocity}; use bevy::prelude::{Entity, Message, Transform, TypePath}; use serde::{Deserialize, Serialize}; use crate::shared::config::planet::Planet; @@ -8,5 +9,7 @@ pub struct PlanetDto { pub server_entity: Entity, pub planet: WasUpdated, - pub transform: WasUpdated + pub transform: WasUpdated, + pub linvel: WasUpdated, + pub angvel: WasUpdated, } \ No newline at end of file