Delete Vel and Ori on the client when they are removed on the server

This commit is contained in:
Imbris 2020-03-18 17:00:07 -04:00
parent 038f655269
commit 1a484410ca
10 changed files with 219 additions and 228 deletions

View File

@ -629,8 +629,15 @@ impl Client {
ServerMsg::TimeOfDay(time_of_day) => { ServerMsg::TimeOfDay(time_of_day) => {
*self.state.ecs_mut().write_resource() = time_of_day; *self.state.ecs_mut().write_resource() = time_of_day;
}, },
ServerMsg::EcsSync(sync_package) => { ServerMsg::EntitySync(entity_sync_package) => {
self.state.ecs_mut().apply_sync_package(sync_package); self.state
.ecs_mut()
.apply_entity_sync_package(entity_sync_package);
},
ServerMsg::CompSync(comp_sync_package) => {
self.state
.ecs_mut()
.apply_comp_sync_package(comp_sync_package);
}, },
ServerMsg::CreateEntity(entity_package) => { ServerMsg::CreateEntity(entity_package) => {
self.state.ecs_mut().apply_entity_package(entity_package); self.state.ecs_mut().apply_entity_package(entity_package);
@ -667,29 +674,6 @@ impl Client {
.allocate(entity_builder.entity, Some(client_uid)); .allocate(entity_builder.entity, Some(client_uid));
self.entity = entity_builder.with(uid).build(); self.entity = entity_builder.with(uid).build();
}, },
ServerMsg::EntityPos { entity, pos } => {
if let Some(entity) = self.state.ecs().entity_from_uid(entity) {
self.state.write_component(entity, pos);
}
},
ServerMsg::EntityVel { entity, vel } => {
if let Some(entity) = self.state.ecs().entity_from_uid(entity) {
self.state.write_component(entity, vel);
}
},
ServerMsg::EntityOri { entity, ori } => {
if let Some(entity) = self.state.ecs().entity_from_uid(entity) {
self.state.write_component(entity, ori);
}
},
ServerMsg::EntityCharacterState {
entity,
character_state,
} => {
if let Some(entity) = self.state.ecs().entity_from_uid(entity) {
self.state.write_component(entity, character_state);
}
},
ServerMsg::InventoryUpdate(inventory, event) => { ServerMsg::InventoryUpdate(inventory, event) => {
match event { match event {
InventoryUpdateEvent::CollectFailed => { InventoryUpdateEvent::CollectFailed => {

View File

@ -25,6 +25,9 @@ sum_type! {
Loadout(comp::Loadout), Loadout(comp::Loadout),
Attacking(comp::Attacking), Attacking(comp::Attacking),
CharacterState(comp::CharacterState), CharacterState(comp::CharacterState),
Pos(comp::Pos),
Vel(comp::Vel),
Ori(comp::Ori),
} }
} }
// Automatically derive From<T> for EcsCompPhantom // Automatically derive From<T> for EcsCompPhantom
@ -49,6 +52,9 @@ sum_type! {
Loadout(PhantomData<comp::Loadout>), Loadout(PhantomData<comp::Loadout>),
Attacking(PhantomData<comp::Attacking>), Attacking(PhantomData<comp::Attacking>),
CharacterState(PhantomData<comp::CharacterState>), CharacterState(PhantomData<comp::CharacterState>),
Pos(PhantomData<comp::Pos>),
Vel(PhantomData<comp::Vel>),
Ori(PhantomData<comp::Ori>),
} }
} }
impl sync::CompPacket for EcsCompPacket { impl sync::CompPacket for EcsCompPacket {
@ -73,6 +79,9 @@ impl sync::CompPacket for EcsCompPacket {
EcsCompPacket::Loadout(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Loadout(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::Attacking(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Attacking(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::CharacterState(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::CharacterState(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::Pos(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::Vel(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::Ori(comp) => sync::handle_insert(comp, entity, world),
} }
} }
@ -95,6 +104,9 @@ impl sync::CompPacket for EcsCompPacket {
EcsCompPacket::Loadout(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Loadout(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::Attacking(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Attacking(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::CharacterState(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::CharacterState(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::Pos(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::Vel(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::Ori(comp) => sync::handle_modify(comp, entity, world),
} }
} }
@ -123,6 +135,9 @@ impl sync::CompPacket for EcsCompPacket {
EcsCompPhantom::CharacterState(_) => { EcsCompPhantom::CharacterState(_) => {
sync::handle_remove::<comp::CharacterState>(entity, world) sync::handle_remove::<comp::CharacterState>(entity, world)
}, },
EcsCompPhantom::Pos(_) => sync::handle_remove::<comp::Pos>(entity, world),
EcsCompPhantom::Vel(_) => sync::handle_remove::<comp::Vel>(entity, world),
EcsCompPhantom::Ori(_) => sync::handle_remove::<comp::Ori>(entity, world),
} }
} }
} }

View File

@ -46,25 +46,10 @@ pub enum ServerMsg {
}, },
SetPlayerEntity(u64), SetPlayerEntity(u64),
TimeOfDay(state::TimeOfDay), TimeOfDay(state::TimeOfDay),
EcsSync(sync::SyncPackage<EcsCompPacket>), EntitySync(sync::EntitySyncPackage),
CompSync(sync::CompSyncPackage<EcsCompPacket>),
CreateEntity(sync::EntityPackage<EcsCompPacket>), CreateEntity(sync::EntityPackage<EcsCompPacket>),
DeleteEntity(u64), DeleteEntity(u64),
EntityPos {
entity: u64,
pos: comp::Pos,
},
EntityVel {
entity: u64,
vel: comp::Vel,
},
EntityOri {
entity: u64,
ori: comp::Ori,
},
EntityCharacterState {
entity: u64,
character_state: comp::CharacterState,
},
InventoryUpdate(comp::Inventory, comp::InventoryUpdateEvent), InventoryUpdate(comp::Inventory, comp::InventoryUpdateEvent),
TerrainChunkUpdate { TerrainChunkUpdate {
key: Vec2<i32>, key: Vec2<i32>,

View File

@ -7,8 +7,8 @@ mod uid;
// Reexports // Reexports
pub use packet::{ pub use packet::{
handle_insert, handle_modify, handle_remove, CompPacket, EntityPackage, StatePackage, handle_insert, handle_modify, handle_remove, CompPacket, CompSyncPackage, EntityPackage,
SyncPackage, EntitySyncPackage, StatePackage,
}; };
pub use sync_ext::WorldSyncExt; pub use sync_ext::WorldSyncExt;
pub use track::UpdateTracker; pub use track::UpdateTracker;

View File

@ -23,18 +23,22 @@ pub trait CompPacket: Clone + Debug + Send + 'static {
pub fn handle_insert<C: Component>(comp: C, entity: Entity, world: &World) { pub fn handle_insert<C: Component>(comp: C, entity: Entity, world: &World) {
if let Err(err) = world.write_storage::<C>().insert(entity, comp) { if let Err(err) = world.write_storage::<C>().insert(entity, comp) {
error!("Error inserting component: {:?}", err); error!("Error inserting component: {:?}", err);
}; }
} }
/// Useful for implementing CompPacket trait /// Useful for implementing CompPacket trait
pub fn handle_modify<C: Component>(comp: C, entity: Entity, world: &World) { pub fn handle_modify<C: Component>(comp: C, entity: Entity, world: &World) {
let _ = world if world
.write_storage::<C>() .write_storage::<C>()
.get_mut(entity) .get_mut(entity)
.map(|c| *c = comp); .map(|c| *c = comp)
.is_none()
{
error!("Error modifying synced component, it doesn't seem to exist");
}
} }
/// Useful for implementing CompPacket trait /// Useful for implementing CompPacket trait
pub fn handle_remove<C: Component>(entity: Entity, world: &World) { pub fn handle_remove<C: Component>(entity: Entity, world: &World) {
let _ = world.write_storage::<C>().remove(entity); world.write_storage::<C>().remove(entity);
} }
#[derive(Copy, Clone, Debug, Serialize, Deserialize)] #[derive(Copy, Clone, Debug, Serialize, Deserialize)]
@ -81,12 +85,11 @@ impl<P: CompPacket> StatePackage<P> {
} }
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SyncPackage<P: CompPacket> { pub struct EntitySyncPackage {
pub comp_updates: Vec<(u64, CompUpdateKind<P>)>,
pub created_entities: Vec<u64>, pub created_entities: Vec<u64>,
pub deleted_entities: Vec<u64>, pub deleted_entities: Vec<u64>,
} }
impl<P: CompPacket> SyncPackage<P> { impl EntitySyncPackage {
pub fn new<'a>( pub fn new<'a>(
uids: &ReadStorage<'a, Uid>, uids: &ReadStorage<'a, Uid>,
uid_tracker: &UpdateTracker<Uid>, uid_tracker: &UpdateTracker<Uid>,
@ -100,11 +103,48 @@ impl<P: CompPacket> SyncPackage<P> {
.collect(); .collect();
Self { Self {
comp_updates: Vec::new(),
created_entities, created_entities,
deleted_entities, deleted_entities,
} }
} }
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct CompSyncPackage<P: CompPacket> {
// TODO: this can be made to take less space by clumping updates for the same entity together
pub comp_updates: Vec<(u64, CompUpdateKind<P>)>,
}
impl<P: CompPacket> CompSyncPackage<P> {
pub fn new() -> Self {
Self {
comp_updates: Vec::new(),
}
}
pub fn comp_inserted<C>(&mut self, uid: Uid, comp: C)
where
P: From<C>,
{
self.comp_updates
.push((uid.into(), CompUpdateKind::Inserted(comp.into())));
}
pub fn comp_modified<C>(&mut self, uid: Uid, comp: C)
where
P: From<C>,
{
self.comp_updates
.push((uid.into(), CompUpdateKind::Modified(comp.into())));
}
pub fn comp_removed<C>(&mut self, uid: Uid)
where
P::Phantom: From<PhantomData<C>>,
{
self.comp_updates
.push((uid.into(), CompUpdateKind::Removed(PhantomData::<C>.into())));
}
pub fn with_component<'a, C: Component + Clone + Send + Sync>( pub fn with_component<'a, C: Component + Clone + Send + Sync>(
mut self, mut self,

View File

@ -1,5 +1,7 @@
use super::{ use super::{
packet::{CompPacket, CompUpdateKind, EntityPackage, StatePackage, SyncPackage}, packet::{
CompPacket, CompSyncPackage, CompUpdateKind, EntityPackage, EntitySyncPackage, StatePackage,
},
track::UpdateTracker, track::UpdateTracker,
uid::{Uid, UidAllocator}, uid::{Uid, UidAllocator},
}; };
@ -27,7 +29,8 @@ pub trait WorldSyncExt {
entity_package: EntityPackage<P>, entity_package: EntityPackage<P>,
) -> specs::Entity; ) -> specs::Entity;
fn apply_state_package<P: CompPacket>(&mut self, state_package: StatePackage<P>); fn apply_state_package<P: CompPacket>(&mut self, state_package: StatePackage<P>);
fn apply_sync_package<P: CompPacket>(&mut self, package: SyncPackage<P>); fn apply_entity_sync_package(&mut self, package: EntitySyncPackage);
fn apply_comp_sync_package<P: CompPacket>(&mut self, package: CompSyncPackage<P>);
} }
impl WorldSyncExt for specs::World { impl WorldSyncExt for specs::World {
@ -106,24 +109,30 @@ impl WorldSyncExt for specs::World {
//self.maintain(); //self.maintain();
} }
fn apply_sync_package<P: CompPacket>(&mut self, package: SyncPackage<P>) { fn apply_entity_sync_package(&mut self, package: EntitySyncPackage) {
// Take ownership of the fields // Take ownership of the fields
let SyncPackage { let EntitySyncPackage {
comp_updates,
created_entities, created_entities,
deleted_entities, deleted_entities,
} = package; } = package;
// Attempt to create entities // Attempt to create entities
for entity_uid in created_entities { created_entities.into_iter().for_each(|uid| {
create_entity_with_uid(self, entity_uid); create_entity_with_uid(self, uid);
} });
// Attempt to delete entities that were marked for deletion
deleted_entities.into_iter().for_each(|uid| {
self.delete_entity_and_clear_from_uid_allocator(uid);
});
}
fn apply_comp_sync_package<P: CompPacket>(&mut self, package: CompSyncPackage<P>) {
// Update components // Update components
for (entity_uid, update) in comp_updates { package.comp_updates.into_iter().for_each(|(uid, update)| {
if let Some(entity) = self if let Some(entity) = self
.read_resource::<UidAllocator>() .read_resource::<UidAllocator>()
.retrieve_entity_internal(entity_uid) .retrieve_entity_internal(uid)
{ {
match update { match update {
CompUpdateKind::Inserted(packet) => { CompUpdateKind::Inserted(packet) => {
@ -137,12 +146,7 @@ impl WorldSyncExt for specs::World {
}, },
} }
} }
} });
// Attempt to delete entities that were marked for deletion
for entity_uid in deleted_entities {
self.delete_entity_and_clear_from_uid_allocator(entity_uid);
}
} }
} }

View File

@ -468,7 +468,7 @@ impl Server {
.notify(ServerMsg::InitialSync { .notify(ServerMsg::InitialSync {
// Send client their entity // Send client their entity
entity_package: TrackedComps::fetch(&self.state.ecs()) entity_package: TrackedComps::fetch(&self.state.ecs())
.create_entity_package(entity), .create_entity_package(entity, None, None, None),
server_info: self.server_info.clone(), server_info: self.server_info.clone(),
time_of_day: *self.state.ecs().read_resource(), time_of_day: *self.state.ecs().read_resource(),
world_map: (WORLD_SIZE.map(|e| e as u32), self.map.clone()), world_map: (WORLD_SIZE.map(|e| e as u32), self.map.clone()),

View File

@ -11,7 +11,7 @@ use common::{
msg::ServerMsg, msg::ServerMsg,
region::{Event as RegionEvent, RegionMap}, region::{Event as RegionEvent, RegionMap},
state::TimeOfDay, state::TimeOfDay,
sync::Uid, sync::{CompSyncPackage, Uid},
}; };
use specs::{ use specs::{
Entities, Entity as EcsEntity, Join, Read, ReadExpect, ReadStorage, System, Write, WriteStorage, Entities, Entity as EcsEntity, Join, Read, ReadExpect, ReadStorage, System, Write, WriteStorage,
@ -30,13 +30,11 @@ impl<'a> System<'a> for Sys {
ReadStorage<'a, Pos>, ReadStorage<'a, Pos>,
ReadStorage<'a, Vel>, ReadStorage<'a, Vel>,
ReadStorage<'a, Ori>, ReadStorage<'a, Ori>,
ReadStorage<'a, CharacterState>,
ReadStorage<'a, Inventory>, ReadStorage<'a, Inventory>,
ReadStorage<'a, RegionSubscription>, ReadStorage<'a, RegionSubscription>,
WriteStorage<'a, Last<Pos>>, WriteStorage<'a, Last<Pos>>,
WriteStorage<'a, Last<Vel>>, WriteStorage<'a, Last<Vel>>,
WriteStorage<'a, Last<Ori>>, WriteStorage<'a, Last<Ori>>,
WriteStorage<'a, Last<CharacterState>>,
WriteStorage<'a, Client>, WriteStorage<'a, Client>,
WriteStorage<'a, ForceUpdate>, WriteStorage<'a, ForceUpdate>,
WriteStorage<'a, InventoryUpdate>, WriteStorage<'a, InventoryUpdate>,
@ -57,13 +55,11 @@ impl<'a> System<'a> for Sys {
positions, positions,
velocities, velocities,
orientations, orientations,
character_states,
inventories, inventories,
subscriptions, subscriptions,
mut last_pos, mut last_pos,
mut last_vel, mut last_vel,
mut last_ori, mut last_ori,
mut last_character_state,
mut clients, mut clients,
mut force_updates, mut force_updates,
mut inventory_updates, mut inventory_updates,
@ -116,22 +112,18 @@ impl<'a> System<'a> for Sys {
continue; continue;
} }
let entity = entities.entity(*id); let entity = entities.entity(*id);
if let Some((uid, pos, vel, ori, character_state)) = if let Some((uid, pos, vel, ori)) = uids.get(entity).and_then(|uid| {
uids.get(entity).and_then(|uid| { positions.get(entity).map(|pos| {
positions.get(entity).map(|pos| { (uid, pos, velocities.get(entity), orientations.get(entity))
(
uid,
pos,
velocities.get(entity),
orientations.get(entity),
character_states.get(entity),
)
})
}) })
{ }) {
let create_msg = ServerMsg::CreateEntity( let create_msg =
tracked_comps.create_entity_package(entity), ServerMsg::CreateEntity(tracked_comps.create_entity_package(
); entity,
Some(*pos),
vel.copied(),
ori.copied(),
));
for (client, regions, client_entity, _) in &mut subscribers { for (client, regions, client_entity, _) in &mut subscribers {
if maybe_key if maybe_key
.as_ref() .as_ref()
@ -141,14 +133,6 @@ impl<'a> System<'a> for Sys {
&& *client_entity != entity && *client_entity != entity
{ {
client.notify(create_msg.clone()); client.notify(create_msg.clone());
send_initial_unsynced_components(
client,
uid,
pos,
vel,
ori,
character_state,
);
} }
} }
} }
@ -172,18 +156,19 @@ impl<'a> System<'a> for Sys {
// Sync tracked components // Sync tracked components
// Get deleted entities in this region from DeletedEntities // Get deleted entities in this region from DeletedEntities
let sync_msg = ServerMsg::EcsSync( let (entity_sync_package, comp_sync_package) = trackers.create_sync_packages(
trackers.create_sync_package( &tracked_comps,
&tracked_comps, region.entities(),
region.entities(), deleted_entities
deleted_entities .take_deleted_in_region(key)
.take_deleted_in_region(key) .unwrap_or_else(|| Vec::new()),
.unwrap_or_else(|| Vec::new()),
),
); );
for (client, _, _, _) in &mut subscribers { let entity_sync_msg = ServerMsg::EntitySync(entity_sync_package);
client.notify(sync_msg.clone()); let comp_sync_msg = ServerMsg::CompSync(comp_sync_package);
} subscribers.iter_mut().for_each(move |(client, _, _, _)| {
client.notify(entity_sync_msg.clone());
client.notify(comp_sync_msg.clone());
});
let mut send_msg = |msg: ServerMsg, let mut send_msg = |msg: ServerMsg,
entity: EcsEntity, entity: EcsEntity,
@ -191,117 +176,112 @@ impl<'a> System<'a> for Sys {
force_update: Option<&ForceUpdate>, force_update: Option<&ForceUpdate>,
throttle: bool| { throttle: bool| {
for (client, _, client_entity, client_pos) in &mut subscribers { for (client, _, client_entity, client_pos) in &mut subscribers {
let update = if client_entity == &entity { if if client_entity == &entity {
// Don't send client physics updates about itself unless force update is set // Don't send client physics updates about itself unless force update is set
force_update.is_some() force_update.is_some()
} else if !throttle { } else if !throttle {
// Update rate not thottled by distance // Send the message if not throttling
true true
} else { } else {
// Throttle update rate based on distance to client // Throttle update rate based on distance to client
let distance_sq = client_pos.0.distance_squared(pos.0); let distance_sq = client_pos.0.distance_squared(pos.0);
let id_staggered_tick = tick + entity.id() as u64;
// More entities farther away so checks start there // More entities farther away so checks start there
if distance_sq > 300.0f32.powi(2) { if distance_sq > 300.0f32.powi(2) {
(tick + entity.id() as u64) % 32 == 0 id_staggered_tick % 32 == 0
} else if distance_sq > 250.0f32.powi(2) { } else if distance_sq > 250.0f32.powi(2) {
(tick + entity.id() as u64) % 16 == 0 id_staggered_tick % 16 == 0
} else if distance_sq > 200.0f32.powi(2) { } else if distance_sq > 200.0f32.powi(2) {
(tick + entity.id() as u64) % 8 == 0 id_staggered_tick % 8 == 0
} else if distance_sq > 150.0f32.powi(2) { } else if distance_sq > 150.0f32.powi(2) {
(tick + entity.id() as u64) % 4 == 0 id_staggered_tick % 4 == 0
} else if distance_sq > 100.0f32.powi(2) { } else if distance_sq > 100.0f32.powi(2) {
(tick + entity.id() as u64) % 2 == 0 id_staggered_tick % 2 == 0
} else { } else {
true // Closer than 100 blocks true // Closer than 100 blocks
} }
}; } {
if update {
client.notify(msg.clone()); client.notify(msg.clone());
} }
} }
}; };
// Sync physics components // Sync physics components
for (_, entity, &uid, &pos, maybe_vel, maybe_ori, character_state, force_update) in ( for (_, entity, &uid, &pos, maybe_vel, maybe_ori, force_update) in (
region.entities(), region.entities(),
&entities, &entities,
&uids, &uids,
&positions, &positions,
velocities.maybe(), velocities.maybe(),
orientations.maybe(), orientations.maybe(),
character_states.maybe(),
force_updates.maybe(), force_updates.maybe(),
) )
.join() .join()
{ {
let mut comp_sync_package = CompSyncPackage::new();
let mut throttle = true;
// TODO: An entity that stoppped moving on a tick that it wasn't sent to the // TODO: An entity that stoppped moving on a tick that it wasn't sent to the
// player will never have it's position updated // player will never have it's position updated
if last_pos.get(entity).map(|&l| l.0 != pos).unwrap_or(true) { match last_pos.get(entity).map(|&l| l.0 != pos) {
let _ = last_pos.insert(entity, Last(pos)); Some(false) => {},
send_msg( Some(true) => {
ServerMsg::EntityPos { let _ = last_pos.insert(entity, Last(pos));
entity: uid.into(), comp_sync_package.comp_modified(uid, pos);
pos, },
}, None => {
entity, let _ = last_pos.insert(entity, Last(pos));
pos, throttle = false;
force_update, comp_sync_package.comp_inserted(uid, pos);
true, },
);
} }
if let Some(&vel) = maybe_vel { if let Some(&vel) = maybe_vel {
if last_vel.get(entity).map(|&l| l.0 != vel).unwrap_or(true) { match last_vel.get(entity).map(|&l| l.0 != vel) {
let _ = last_vel.insert(entity, Last(vel)); Some(false) => {},
send_msg( Some(true) => {
ServerMsg::EntityVel { let _ = last_vel.insert(entity, Last(vel));
entity: uid.into(), comp_sync_package.comp_modified(uid, vel);
vel, },
}, None => {
entity, let _ = last_vel.insert(entity, Last(vel));
pos, throttle = false;
force_update, comp_sync_package.comp_inserted(uid, vel);
true, },
);
} }
} else if last_vel.remove(entity).is_some() {
// Send removal message if Vel was removed
// Note: we don't have to handle this for position because the entity will be
// removed from the client by the region system
throttle = false;
comp_sync_package.comp_removed::<Vel>(uid);
} }
if let Some(&ori) = maybe_ori { if let Some(&ori) = maybe_ori {
if last_ori.get(entity).map(|&l| l.0 != ori).unwrap_or(true) { match last_ori.get(entity).map(|&l| l.0 != ori) {
let _ = last_ori.insert(entity, Last(ori)); Some(false) => {},
send_msg( Some(true) => {
ServerMsg::EntityOri { let _ = last_ori.insert(entity, Last(ori));
entity: uid.into(), comp_sync_package.comp_modified(uid, ori);
ori, },
}, None => {
entity, let _ = last_ori.insert(entity, Last(ori));
pos, throttle = false;
force_update, comp_sync_package.comp_inserted(uid, ori);
true, },
);
} }
} else if last_ori.remove(entity).is_some() {
// Send removal message if Ori was removed
throttle = false;
comp_sync_package.comp_removed::<Ori>(uid);
} }
if let Some(&character_state) = character_state.as_ref() { send_msg(
if last_character_state ServerMsg::CompSync(comp_sync_package),
.get(entity) entity,
.map(|l| !character_state.equals(&l.0)) pos,
.unwrap_or(true) force_update,
{ throttle,
let _ = last_character_state.insert(entity, Last(character_state.clone())); );
send_msg(
ServerMsg::EntityCharacterState {
entity: uid.into(),
character_state: character_state.clone(),
},
entity,
pos,
force_update,
false,
);
}
}
} }
} }
@ -350,27 +330,3 @@ impl<'a> System<'a> for Sys {
timer.end(); timer.end();
} }
} }
pub fn send_initial_unsynced_components(
client: &mut Client,
uid: &Uid,
pos: &Pos,
vel: Option<&Vel>,
ori: Option<&Ori>,
character_state: Option<&CharacterState>,
) {
let entity = (*uid).into();
client.notify(ServerMsg::EntityPos { entity, pos: *pos });
if let Some(&vel) = vel {
client.notify(ServerMsg::EntityVel { entity, vel });
}
if let Some(&ori) = ori {
client.notify(ServerMsg::EntityOri { entity, ori });
}
if let Some(character_state) = character_state.cloned() {
client.notify(ServerMsg::EntityCharacterState {
entity,
character_state,
});
}
}

View File

@ -2,10 +2,10 @@ use super::SysTimer;
use common::{ use common::{
comp::{ comp::{
Body, CanBuild, CharacterState, Energy, Gravity, Item, LightEmitter, Loadout, Mass, Body, CanBuild, CharacterState, Energy, Gravity, Item, LightEmitter, Loadout, Mass,
MountState, Mounting, Player, Scale, Stats, Sticky, MountState, Mounting, Ori, Player, Pos, Scale, Stats, Sticky, Vel,
}, },
msg::EcsCompPacket, msg::EcsCompPacket,
sync::{EntityPackage, SyncPackage, Uid, UpdateTracker, WorldSyncExt}, sync::{CompSyncPackage, EntityPackage, EntitySyncPackage, Uid, UpdateTracker, WorldSyncExt},
}; };
use hashbrown::HashMap; use hashbrown::HashMap;
use specs::{ use specs::{
@ -55,7 +55,13 @@ pub struct TrackedComps<'a> {
pub character_state: ReadStorage<'a, CharacterState>, pub character_state: ReadStorage<'a, CharacterState>,
} }
impl<'a> TrackedComps<'a> { impl<'a> TrackedComps<'a> {
pub fn create_entity_package(&self, entity: EcsEntity) -> EntityPackage<EcsCompPacket> { pub fn create_entity_package(
&self,
entity: EcsEntity,
pos: Option<Pos>,
vel: Option<Vel>,
ori: Option<Ori>,
) -> EntityPackage<EcsCompPacket> {
let uid = self let uid = self
.uid .uid
.get(entity) .get(entity)
@ -114,6 +120,10 @@ impl<'a> TrackedComps<'a> {
.get(entity) .get(entity)
.cloned() .cloned()
.map(|c| comps.push(c.into())); .map(|c| comps.push(c.into()));
// Add untracked comps
pos.map(|c| comps.push(c.into()));
vel.map(|c| comps.push(c.into()));
ori.map(|c| comps.push(c.into()));
EntityPackage { uid, comps } EntityPackage { uid, comps }
} }
@ -138,13 +148,15 @@ pub struct ReadTrackers<'a> {
pub character_state: ReadExpect<'a, UpdateTracker<CharacterState>>, pub character_state: ReadExpect<'a, UpdateTracker<CharacterState>>,
} }
impl<'a> ReadTrackers<'a> { impl<'a> ReadTrackers<'a> {
pub fn create_sync_package( pub fn create_sync_packages(
&self, &self,
comps: &TrackedComps, comps: &TrackedComps,
filter: impl Join + Copy, filter: impl Join + Copy,
deleted_entities: Vec<u64>, deleted_entities: Vec<u64>,
) -> SyncPackage<EcsCompPacket> { ) -> (EntitySyncPackage, CompSyncPackage<EcsCompPacket>) {
SyncPackage::new(&comps.uid, &self.uid, filter, deleted_entities) let entity_sync_package =
EntitySyncPackage::new(&comps.uid, &self.uid, filter, deleted_entities);
let comp_sync_package = CompSyncPackage::new()
.with_component(&comps.uid, &*self.body, &comps.body, filter) .with_component(&comps.uid, &*self.body, &comps.body, filter)
.with_component(&comps.uid, &*self.player, &comps.player, filter) .with_component(&comps.uid, &*self.player, &comps.player, filter)
.with_component(&comps.uid, &*self.stats, &comps.stats, filter) .with_component(&comps.uid, &*self.stats, &comps.stats, filter)
@ -169,7 +181,9 @@ impl<'a> ReadTrackers<'a> {
&*self.character_state, &*self.character_state,
&comps.character_state, &comps.character_state,
filter, filter,
) );
(entity_sync_package, comp_sync_package)
} }
} }

View File

@ -194,19 +194,16 @@ impl<'a> System<'a> for Sys {
.join() .join()
.filter(|(_, _, _, _, _, _, e)| *e != client_entity) .filter(|(_, _, _, _, _, _, e)| *e != client_entity)
{ {
// Send message to create entity and tracked components // Send message to create entity and tracked components and physics
// components
client.notify(ServerMsg::CreateEntity( client.notify(ServerMsg::CreateEntity(
tracked_comps.create_entity_package(entity), tracked_comps.create_entity_package(
entity,
Some(*pos),
vel.copied(),
ori.copied(),
),
)); ));
// Send message to create physics components
super::entity_sync::send_initial_unsynced_components(
client,
uid,
pos,
vel,
ori,
character_state,
);
} }
} }
} }
@ -253,19 +250,15 @@ pub fn initialize_region_subscription(world: &World, entity: specs::Entity) {
) )
.join() .join()
{ {
// Send message to create entity and tracked components // Send message to create entity and tracked components and physics components
client.notify(ServerMsg::CreateEntity( client.notify(ServerMsg::CreateEntity(
tracked_comps.create_entity_package(entity), tracked_comps.create_entity_package(
entity,
Some(*pos),
vel.copied(),
ori.copied(),
),
)); ));
// Send message to create physics components
super::entity_sync::send_initial_unsynced_components(
client,
uid,
pos,
vel,
ori,
character_state,
);
} }
} }
} }