mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Add sync_me
parameter to Presence
that must be set to true
for
entities with the `Presence` component to be synced to other clients.
This commit is contained in:
@ -13,16 +13,23 @@ pub struct Presence {
|
|||||||
/// updated!
|
/// updated!
|
||||||
pub kind: PresenceKind,
|
pub kind: PresenceKind,
|
||||||
pub lossy_terrain_compression: bool,
|
pub lossy_terrain_compression: bool,
|
||||||
|
/// Controls whether this entity is synced to other clients.
|
||||||
|
///
|
||||||
|
/// Note, if it ends up being useful this could be generalized to an
|
||||||
|
/// independent component that is required for any entity to be synced
|
||||||
|
/// (as an independent component it could use NullStorage).
|
||||||
|
pub sync_me: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Presence {
|
impl Presence {
|
||||||
pub fn new(view_distances: ViewDistances, kind: PresenceKind) -> Self {
|
pub fn new(view_distances: ViewDistances, kind: PresenceKind, sync_me: bool) -> Self {
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
Self {
|
Self {
|
||||||
terrain_view_distance: ViewDistance::new(view_distances.terrain, now),
|
terrain_view_distance: ViewDistance::new(view_distances.terrain, now),
|
||||||
entity_view_distance: ViewDistance::new(view_distances.entity, now),
|
entity_view_distance: ViewDistance::new(view_distances.entity, now),
|
||||||
kind,
|
kind,
|
||||||
lossy_terrain_compression: false,
|
lossy_terrain_compression: false,
|
||||||
|
sync_me,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::comp::{Pos, Vel};
|
use crate::comp::{Pos, Presence, Vel};
|
||||||
use common_base::span;
|
use common_base::span;
|
||||||
use hashbrown::{hash_map::DefaultHashBuilder, HashSet};
|
use hashbrown::{hash_map::DefaultHashBuilder, HashSet};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
@ -69,7 +69,12 @@ const NEIGHBOR_OFFSETS: [Vec2<i32>; 8] = [
|
|||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
// TODO generic region size (16x16 for now)
|
// TODO generic region size (16x16 for now)
|
||||||
// TODO compare to sweep and prune approach
|
// TODO compare to sweep and prune approach
|
||||||
/// A region system that tracks where entities are
|
/// A region system that tracks where entities are.
|
||||||
|
///
|
||||||
|
/// Note, this structure is primarily intended for tracking which entities need
|
||||||
|
/// to be synchronized to which clients (and as part of that what entities are
|
||||||
|
/// already synchronized). If an entity is marked to not be synchronized to
|
||||||
|
/// other clients it may not appear here.
|
||||||
pub struct RegionMap {
|
pub struct RegionMap {
|
||||||
// Tree?
|
// Tree?
|
||||||
// Sorted Vec? (binary search lookup)
|
// Sorted Vec? (binary search lookup)
|
||||||
@ -92,7 +97,13 @@ impl RegionMap {
|
|||||||
|
|
||||||
// TODO maintain within a system?
|
// TODO maintain within a system?
|
||||||
// TODO special case large entities
|
// TODO special case large entities
|
||||||
pub fn tick(&mut self, pos: ReadStorage<Pos>, vel: ReadStorage<Vel>, entities: Entities) {
|
pub fn tick(
|
||||||
|
&mut self,
|
||||||
|
pos: ReadStorage<Pos>,
|
||||||
|
vel: ReadStorage<Vel>,
|
||||||
|
presence: ReadStorage<Presence>,
|
||||||
|
entities: Entities,
|
||||||
|
) {
|
||||||
span!(_guard, "tick", "Region::tick");
|
span!(_guard, "tick", "Region::tick");
|
||||||
self.tick += 1;
|
self.tick += 1;
|
||||||
// Clear events within each region
|
// Clear events within each region
|
||||||
@ -101,9 +112,10 @@ impl RegionMap {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Add any untracked entities
|
// Add any untracked entities
|
||||||
for (pos, id) in (&pos, &entities, !&self.tracked_entities)
|
for (pos, id) in (&pos, &entities, presence.maybe(), !&self.tracked_entities)
|
||||||
.join()
|
.join()
|
||||||
.map(|(pos, e, _)| (pos, e.id()))
|
.filter(|(_, _, presence, _)| presence.map_or(true, |p| p.sync_me))
|
||||||
|
.map(|(pos, e, _, _)| (pos, e.id()))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
{
|
{
|
||||||
// Add entity
|
// Add entity
|
||||||
@ -123,15 +135,21 @@ impl RegionMap {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.for_each(|(i, (¤t_region, region_data))| {
|
.for_each(|(i, (¤t_region, region_data))| {
|
||||||
for (maybe_pos, _maybe_vel, id) in
|
for (maybe_pos, _maybe_vel, maybe_presence, id) in (
|
||||||
(pos.maybe(), vel.maybe(), ®ion_data.bitset).join()
|
pos.maybe(),
|
||||||
|
vel.maybe(),
|
||||||
|
presence.maybe(),
|
||||||
|
®ion_data.bitset,
|
||||||
|
)
|
||||||
|
.join()
|
||||||
{
|
{
|
||||||
|
let should_sync = maybe_presence.map_or(true, |p| p.sync_me);
|
||||||
match maybe_pos {
|
match maybe_pos {
|
||||||
// Switch regions for entities which need switching
|
// Switch regions for entities which need switching
|
||||||
// TODO don't check every tick (use velocity) (and use id to stagger)
|
// TODO don't check every tick (use velocity) (and use id to stagger)
|
||||||
// Starting parameters at v = 0 check every 100 ticks
|
// Starting parameters at v = 0 check every 100 ticks
|
||||||
// tether_length^2 / vel^2 (with a max of every tick)
|
// tether_length^2 / vel^2 (with a max of every tick)
|
||||||
Some(pos) => {
|
Some(pos) if should_sync => {
|
||||||
let pos = pos.0.map(|e| e as i32);
|
let pos = pos.0.map(|e| e as i32);
|
||||||
let key = Self::pos_key(pos);
|
let key = Self::pos_key(pos);
|
||||||
// Consider switching
|
// Consider switching
|
||||||
@ -148,7 +166,7 @@ impl RegionMap {
|
|||||||
},
|
},
|
||||||
// Remove any non-existant entities (or just ones that lost their position
|
// Remove any non-existant entities (or just ones that lost their position
|
||||||
// component) TODO: distribute this between ticks
|
// component) TODO: distribute this between ticks
|
||||||
None => {
|
None | Some(_) => {
|
||||||
// TODO: shouldn't there be a way to extract the bitset of entities with
|
// TODO: shouldn't there be a way to extract the bitset of entities with
|
||||||
// positions directly from specs? Yes, with `.mask()` on the component
|
// positions directly from specs? Yes, with `.mask()` on the component
|
||||||
// storage.
|
// storage.
|
||||||
|
@ -534,6 +534,7 @@ impl State {
|
|||||||
self.ecs.write_resource::<RegionMap>().tick(
|
self.ecs.write_resource::<RegionMap>().tick(
|
||||||
self.ecs.read_storage::<comp::Pos>(),
|
self.ecs.read_storage::<comp::Pos>(),
|
||||||
self.ecs.read_storage::<comp::Vel>(),
|
self.ecs.read_storage::<comp::Vel>(),
|
||||||
|
self.ecs.read_storage::<comp::Presence>(),
|
||||||
self.ecs.entities(),
|
self.ecs.entities(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -418,6 +418,7 @@ pub fn handle_possess(server: &mut Server, possessor_uid: Uid, possessee_uid: Ui
|
|||||||
// from overwriting original character info with stuff from the new character.
|
// from overwriting original character info with stuff from the new character.
|
||||||
kind: PresenceKind::Possessor,
|
kind: PresenceKind::Possessor,
|
||||||
lossy_terrain_compression: presence.lossy_terrain_compression,
|
lossy_terrain_compression: presence.lossy_terrain_compression,
|
||||||
|
sync_me: presence.sync_me,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -604,6 +604,7 @@ impl StateExt for State {
|
|||||||
entity: view_distance,
|
entity: view_distance,
|
||||||
},
|
},
|
||||||
PresenceKind::Spectator,
|
PresenceKind::Spectator,
|
||||||
|
false,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -644,7 +645,11 @@ impl StateExt for State {
|
|||||||
|
|
||||||
self.write_component_ignore_entity_dead(
|
self.write_component_ignore_entity_dead(
|
||||||
entity,
|
entity,
|
||||||
Presence::new(view_distances, PresenceKind::LoadingCharacter(character_id)),
|
Presence::new(
|
||||||
|
view_distances,
|
||||||
|
PresenceKind::LoadingCharacter(character_id),
|
||||||
|
false,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Tell the client its request was successful.
|
// Tell the client its request was successful.
|
||||||
@ -669,7 +674,7 @@ impl StateExt for State {
|
|||||||
|
|
||||||
self.write_component_ignore_entity_dead(
|
self.write_component_ignore_entity_dead(
|
||||||
entity,
|
entity,
|
||||||
Presence::new(view_distances, PresenceKind::Spectator),
|
Presence::new(view_distances, PresenceKind::Spectator, false),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Tell the client its request was successful.
|
// Tell the client its request was successful.
|
||||||
@ -704,6 +709,7 @@ impl StateExt for State {
|
|||||||
self.ecs()
|
self.ecs()
|
||||||
.write_resource::<IdMaps>()
|
.write_resource::<IdMaps>()
|
||||||
.add_character(id, entity);
|
.add_character(id, entity);
|
||||||
|
presence.sync_me = true;
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err("PresenceKind is not LoadingCharacter")
|
Err("PresenceKind is not LoadingCharacter")
|
||||||
|
Reference in New Issue
Block a user