Apply ForcedUpdate messages to the interpolation system, potentially improving the handling of teleports.

This commit is contained in:
Avi Weinstock 2021-03-16 11:55:01 -04:00
parent f4fa1e9cd3
commit 62de0816e0
4 changed files with 62 additions and 25 deletions

View File

@ -76,7 +76,7 @@ sum_type! {
impl sync::CompPacket for EcsCompPacket {
type Phantom = EcsCompPhantom;
fn apply_insert(self, entity: specs::Entity, world: &specs::World) {
fn apply_insert(self, entity: specs::Entity, world: &specs::World, force_update: bool) {
match self {
EcsCompPacket::Body(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::Player(comp) => sync::handle_insert(comp, entity, world),
@ -100,15 +100,21 @@ impl sync::CompPacket for EcsCompPacket {
EcsCompPacket::Gravity(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::Sticky(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::CharacterState(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::Pos(comp) => sync::handle_interp_insert(comp, entity, world),
EcsCompPacket::Vel(comp) => sync::handle_interp_insert(comp, entity, world),
EcsCompPacket::Ori(comp) => sync::handle_interp_insert(comp, entity, world),
EcsCompPacket::Pos(comp) => {
sync::handle_interp_insert(comp, entity, world, force_update)
},
EcsCompPacket::Vel(comp) => {
sync::handle_interp_insert(comp, entity, world, force_update)
},
EcsCompPacket::Ori(comp) => {
sync::handle_interp_insert(comp, entity, world, force_update)
},
EcsCompPacket::Shockwave(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::BeamSegment(comp) => sync::handle_insert(comp, entity, world),
}
}
fn apply_modify(self, entity: specs::Entity, world: &specs::World) {
fn apply_modify(self, entity: specs::Entity, world: &specs::World, force_update: bool) {
match self {
EcsCompPacket::Body(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::Player(comp) => sync::handle_modify(comp, entity, world),
@ -132,9 +138,15 @@ impl sync::CompPacket for EcsCompPacket {
EcsCompPacket::Gravity(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::Sticky(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::CharacterState(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::Pos(comp) => sync::handle_interp_modify(comp, entity, world),
EcsCompPacket::Vel(comp) => sync::handle_interp_modify(comp, entity, world),
EcsCompPacket::Ori(comp) => sync::handle_interp_modify(comp, entity, world),
EcsCompPacket::Pos(comp) => {
sync::handle_interp_modify(comp, entity, world, force_update)
},
EcsCompPacket::Vel(comp) => {
sync::handle_interp_modify(comp, entity, world, force_update)
},
EcsCompPacket::Ori(comp) => {
sync::handle_interp_modify(comp, entity, world, force_update)
},
EcsCompPacket::Shockwave(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::BeamSegment(comp) => sync::handle_modify(comp, entity, world),
}

View File

@ -14,7 +14,7 @@ pub struct InterpBuffer<T> {
pub i: usize,
}
impl<T> InterpBuffer<T> {
impl<T: Clone> InterpBuffer<T> {
fn push(&mut self, time: f64, x: T) {
let InterpBuffer {
ref mut buf,
@ -24,6 +24,20 @@ impl<T> InterpBuffer<T> {
*i %= buf.len();
buf[*i] = (time, x);
}
fn force_update(&mut self, time: f64, x: T) {
for i in 0..self.buf.len() {
self.buf[i] = (time, x.clone());
}
}
fn update(&mut self, time: f64, x: T, force_update: bool) {
if force_update {
self.force_update(time, x);
} else {
self.push(time, x);
}
}
}
impl<T: 'static + Send + Sync> Component for InterpBuffer<T> {
@ -40,8 +54,8 @@ impl InterpolatableComponent for Pos {
type InterpData = InterpBuffer<Pos>;
type ReadData = InterpBuffer<Vel>;
fn update_component(&self, interp_data: &mut Self::InterpData, time: f64) {
interp_data.push(time, *self);
fn update_component(&self, interp_data: &mut Self::InterpData, time: f64, force_update: bool) {
interp_data.update(time, *self, force_update);
}
fn interpolate(self, interp_data: &Self::InterpData, t2: f64, vel: &InterpBuffer<Vel>) -> Self {
@ -94,8 +108,8 @@ impl InterpolatableComponent for Vel {
type InterpData = InterpBuffer<Vel>;
type ReadData = ();
fn update_component(&self, interp_data: &mut Self::InterpData, time: f64) {
interp_data.push(time, *self);
fn update_component(&self, interp_data: &mut Self::InterpData, time: f64, force_update: bool) {
interp_data.update(time, *self, force_update);
}
fn interpolate(self, interp_data: &Self::InterpData, t2: f64, _: &()) -> Self {
@ -129,8 +143,8 @@ impl InterpolatableComponent for Ori {
type InterpData = InterpBuffer<Ori>;
type ReadData = ();
fn update_component(&self, interp_data: &mut Self::InterpData, time: f64) {
interp_data.push(time, *self);
fn update_component(&self, interp_data: &mut Self::InterpData, time: f64, force_update: bool) {
interp_data.update(time, *self, force_update);
}
fn interpolate(self, interp_data: &Self::InterpData, t2: f64, _: &()) -> Self {

View File

@ -19,8 +19,8 @@ use tracing::error;
pub trait CompPacket: Clone + Debug + Send + 'static {
type Phantom: Clone + Debug + Serialize + DeserializeOwned;
fn apply_insert(self, entity: Entity, world: &World);
fn apply_modify(self, entity: Entity, world: &World);
fn apply_insert(self, entity: Entity, world: &World, force_update: bool);
fn apply_modify(self, entity: Entity, world: &World, force_update: bool);
fn apply_remove(phantom: Self::Phantom, entity: Entity, world: &World);
}
@ -50,14 +50,19 @@ pub trait InterpolatableComponent: Component {
type InterpData: Component + Default;
type ReadData;
fn update_component(&self, data: &mut Self::InterpData, time: f64);
fn update_component(&self, data: &mut Self::InterpData, time: f64, force_update: bool);
fn interpolate(self, data: &Self::InterpData, time: f64, read_data: &Self::ReadData) -> Self;
}
pub fn handle_interp_insert<C: InterpolatableComponent>(comp: C, entity: Entity, world: &World) {
pub fn handle_interp_insert<C: InterpolatableComponent>(
comp: C,
entity: Entity,
world: &World,
force_update: bool,
) {
let mut interp_data = C::InterpData::default();
let time = world.read_resource::<Time>().0;
comp.update_component(&mut interp_data, time);
comp.update_component(&mut interp_data, time, force_update);
handle_insert(comp, entity, world);
handle_insert(interp_data, entity, world);
}
@ -66,10 +71,11 @@ pub fn handle_interp_modify<C: InterpolatableComponent + Debug>(
comp: C,
entity: Entity,
world: &World,
force_update: bool,
) {
if let Some(mut interp_data) = world.write_storage::<C::InterpData>().get_mut(entity) {
let time = world.read_resource::<Time>().0;
comp.update_component(&mut interp_data, time);
comp.update_component(&mut interp_data, time, force_update);
handle_modify(comp, entity, world);
} else {
error!(

View File

@ -4,7 +4,10 @@ use super::{
},
track::UpdateTracker,
};
use common::uid::{Uid, UidAllocator};
use common::{
resources::PlayerEntity,
uid::{Uid, UidAllocator},
};
use specs::{
saveload::{MarkedBuilder, MarkerAllocator},
world::Builder,
@ -80,7 +83,7 @@ impl WorldSyncExt for specs::World {
let entity = create_entity_with_uid(self, uid);
for packet in comps {
packet.apply_insert(entity, self)
packet.apply_insert(entity, self, true)
}
entity
@ -129,17 +132,19 @@ impl WorldSyncExt for specs::World {
fn apply_comp_sync_package<P: CompPacket>(&mut self, package: CompSyncPackage<P>) {
// Update components
let player_entity = self.read_resource::<PlayerEntity>().0;
package.comp_updates.into_iter().for_each(|(uid, update)| {
if let Some(entity) = self
.read_resource::<UidAllocator>()
.retrieve_entity_internal(uid)
{
let force_update = player_entity == Some(entity);
match update {
CompUpdateKind::Inserted(packet) => {
packet.apply_insert(entity, self);
packet.apply_insert(entity, self, force_update);
},
CompUpdateKind::Modified(packet) => {
packet.apply_modify(entity, self);
packet.apply_modify(entity, self, force_update);
},
CompUpdateKind::Removed(phantom) => {
P::apply_remove(phantom, entity, self);