M Cargo.lock => Cargo.lock +1 -7
@@ 5570,12 5570,6 @@ 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"
@@ 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",
M Cargo.toml => Cargo.toml +1 -1
@@ 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
M crates/unified/Cargo.toml => crates/unified/Cargo.toml +1 -1
@@ 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 }
M crates/unified/src/client/net.rs => crates/unified/src/client/net.rs +47 -1
@@ 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
M crates/unified/src/client/net/incoming_parts.rs => crates/unified/src/client/net/incoming_parts.rs +12 -2
@@ 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<PartDto>,
- 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<ServerEntityMap>,
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);
M crates/unified/src/client/net/incoming_planets.rs => crates/unified/src/client/net/incoming_planets.rs +12 -2
@@ 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<PlanetDto>,
- mut q_planets: Query<(&mut Planet, &mut Transform)>,
+ mut q_planets: Query<(&mut Planet, &mut Transform, &mut LinearVelocity, &mut AngularVelocity)>,
mut entity_map: ResMut<ServerEntityMap>,
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);
M crates/unified/src/client/plugins.rs => crates/unified/src/client/plugins.rs +5 -0
@@ 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::<crate::client::input::ClientAction>::default())
.add(WebSocketClientPlugin)
+ .add(TransformInterpolationPlugin::interpolate_all())
+ .add(TransformHermiteEasingPlugin::<LinearVelocitySource, AngularVelocitySource>::default())
//.add(bevy_replicon::client::ClientPlugin)
//.add(bevy_replicon::client::message::ClientMessagePlugin)
//.add(AeronetRepliconClientPlugin)
M crates/unified/src/server/net/update_parts.rs => crates/unified/src/server/net/update_parts.rs +5 -2
@@ 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<Part>, Ref<Transform>, Ref<Temperature>)>,
+ parts: Query<(Entity, Ref<Part>, Ref<Transform>, Ref<Temperature>, Ref<LinearVelocity>, Ref<AngularVelocity>)>,
mut messages: MessageWriter<ToClients<PartDto>>
) {
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
});
M crates/unified/src/server/net/update_planets.rs => crates/unified/src/server/net/update_planets.rs +4 -1
@@ 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<Planet>, Ref<Transform>)>,
+ planets: Query<(Entity, Ref<Planet>, Ref<Transform>, Ref<LinearVelocity>, Ref<AngularVelocity>)>,
mut messages: MessageWriter<ToClients<PlanetDto>>
) {
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
});
M crates/unified/src/shared/net/part.rs => crates/unified/src/shared/net/part.rs +3 -0
@@ 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<Part>,
pub transform: WasUpdated<Transform>,
pub temperature: WasUpdated<Temperature>,
+ pub linvel: WasUpdated<LinearVelocity>,
+ pub angvel: WasUpdated<AngularVelocity>,
}=
\ No newline at end of file
M crates/unified/src/shared/net/planet.rs => crates/unified/src/shared/net/planet.rs +4 -1
@@ 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<Planet>,
- pub transform: WasUpdated<Transform>
+ pub transform: WasUpdated<Transform>,
+ pub linvel: WasUpdated<LinearVelocity>,
+ pub angvel: WasUpdated<AngularVelocity>,
}=
\ No newline at end of file