mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Delete Vel and Ori on the client when they are removed on the server
This commit is contained in:
parent
038f655269
commit
1a484410ca
@ -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 => {
|
||||||
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>,
|
||||||
|
@ -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;
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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()),
|
||||||
|
@ -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,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user