2019-11-04 00:57:36 +00:00
|
|
|
use super::SysTimer;
|
|
|
|
use common::{
|
|
|
|
comp::{
|
|
|
|
Body, CanBuild, Gravity, Item, LightEmitter, Mass, MountState, Mounting, Player,
|
|
|
|
Projectile, Scale, Stats, Sticky,
|
|
|
|
},
|
|
|
|
msg::{EcsCompPacket, EcsResPacket},
|
2019-11-29 06:04:37 +00:00
|
|
|
state::TimeOfDay,
|
2019-11-24 20:12:03 +00:00
|
|
|
sync::{
|
|
|
|
CompPacket, EntityPackage, ResSyncPackage, StatePackage, SyncPackage, Uid, UpdateTracker,
|
|
|
|
WorldSyncExt,
|
2019-11-04 00:57:36 +00:00
|
|
|
},
|
|
|
|
};
|
2019-11-29 06:04:37 +00:00
|
|
|
use hashbrown::HashMap;
|
2019-11-04 00:57:36 +00:00
|
|
|
use shred_derive::SystemData;
|
|
|
|
use specs::{
|
|
|
|
Entity as EcsEntity, Join, ReadExpect, ReadStorage, System, World, Write, WriteExpect,
|
|
|
|
};
|
|
|
|
use std::ops::Deref;
|
2019-11-29 06:04:37 +00:00
|
|
|
use vek::*;
|
2019-11-04 00:57:36 +00:00
|
|
|
|
|
|
|
/// Always watching
|
|
|
|
/// This system will monitor specific components for insertion, removal, and modification
|
|
|
|
pub struct Sys;
|
|
|
|
impl<'a> System<'a> for Sys {
|
|
|
|
type SystemData = (
|
|
|
|
Write<'a, SysTimer<Self>>,
|
|
|
|
TrackedComps<'a>,
|
|
|
|
WriteTrackers<'a>,
|
|
|
|
);
|
|
|
|
|
|
|
|
fn run(&mut self, (mut timer, comps, mut trackers): Self::SystemData) {
|
|
|
|
timer.start();
|
|
|
|
|
|
|
|
record_changes(&comps, &mut trackers);
|
|
|
|
|
|
|
|
timer.end();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Probably more difficult than it needs to be :p
|
|
|
|
#[derive(SystemData)]
|
|
|
|
pub struct TrackedComps<'a> {
|
2019-11-29 06:04:37 +00:00
|
|
|
pub uid: ReadStorage<'a, Uid>,
|
|
|
|
pub body: ReadStorage<'a, Body>,
|
|
|
|
pub player: ReadStorage<'a, Player>,
|
|
|
|
pub stats: ReadStorage<'a, Stats>,
|
|
|
|
pub can_build: ReadStorage<'a, CanBuild>,
|
|
|
|
pub light_emitter: ReadStorage<'a, LightEmitter>,
|
|
|
|
pub item: ReadStorage<'a, Item>,
|
|
|
|
pub scale: ReadStorage<'a, Scale>,
|
|
|
|
pub mounting: ReadStorage<'a, Mounting>,
|
|
|
|
pub mount_state: ReadStorage<'a, MountState>,
|
|
|
|
pub mass: ReadStorage<'a, Mass>,
|
|
|
|
pub sticky: ReadStorage<'a, Sticky>,
|
|
|
|
pub gravity: ReadStorage<'a, Gravity>,
|
|
|
|
pub projectile: ReadStorage<'a, Projectile>,
|
2019-11-04 00:57:36 +00:00
|
|
|
}
|
|
|
|
impl<'a> TrackedComps<'a> {
|
|
|
|
pub fn create_entity_package(&self, entity: EcsEntity) -> EntityPackage<EcsCompPacket> {
|
|
|
|
let uid = self
|
|
|
|
.uid
|
|
|
|
.get(entity)
|
|
|
|
.copied()
|
|
|
|
.expect("No uid to create an entity package")
|
|
|
|
.0;
|
|
|
|
let mut packets = Vec::new();
|
|
|
|
self.body
|
|
|
|
.get(entity)
|
|
|
|
.copied()
|
|
|
|
.map(|c| packets.push(c.into()));
|
|
|
|
self.player
|
|
|
|
.get(entity)
|
|
|
|
.cloned()
|
|
|
|
.map(|c| packets.push(c.into()));
|
|
|
|
self.stats
|
|
|
|
.get(entity)
|
|
|
|
.cloned()
|
|
|
|
.map(|c| packets.push(c.into()));
|
|
|
|
self.can_build
|
|
|
|
.get(entity)
|
|
|
|
.cloned()
|
|
|
|
.map(|c| packets.push(c.into()));
|
|
|
|
self.light_emitter
|
|
|
|
.get(entity)
|
|
|
|
.copied()
|
|
|
|
.map(|c| packets.push(c.into()));
|
|
|
|
self.item
|
|
|
|
.get(entity)
|
|
|
|
.cloned()
|
|
|
|
.map(|c| packets.push(c.into()));
|
|
|
|
self.scale
|
|
|
|
.get(entity)
|
|
|
|
.copied()
|
|
|
|
.map(|c| packets.push(c.into()));
|
|
|
|
self.mounting
|
|
|
|
.get(entity)
|
|
|
|
.cloned()
|
|
|
|
.map(|c| packets.push(c.into()));
|
|
|
|
self.mount_state
|
|
|
|
.get(entity)
|
|
|
|
.cloned()
|
|
|
|
.map(|c| packets.push(c.into()));
|
|
|
|
self.mass
|
|
|
|
.get(entity)
|
|
|
|
.copied()
|
|
|
|
.map(|c| packets.push(c.into()));
|
|
|
|
self.sticky
|
|
|
|
.get(entity)
|
|
|
|
.copied()
|
|
|
|
.map(|c| packets.push(c.into()));
|
|
|
|
self.gravity
|
|
|
|
.get(entity)
|
|
|
|
.copied()
|
|
|
|
.map(|c| packets.push(c.into()));
|
|
|
|
self.projectile
|
|
|
|
.get(entity)
|
|
|
|
.cloned()
|
|
|
|
.map(|c| packets.push(c.into()));
|
|
|
|
|
|
|
|
EntityPackage(uid, packets)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#[derive(SystemData)]
|
|
|
|
pub struct ReadTrackers<'a> {
|
2019-11-29 06:04:37 +00:00
|
|
|
pub uid: ReadExpect<'a, UpdateTracker<Uid>>,
|
|
|
|
pub body: ReadExpect<'a, UpdateTracker<Body>>,
|
|
|
|
pub player: ReadExpect<'a, UpdateTracker<Player>>,
|
|
|
|
pub stats: ReadExpect<'a, UpdateTracker<Stats>>,
|
|
|
|
pub can_build: ReadExpect<'a, UpdateTracker<CanBuild>>,
|
|
|
|
pub light_emitter: ReadExpect<'a, UpdateTracker<LightEmitter>>,
|
|
|
|
pub item: ReadExpect<'a, UpdateTracker<Item>>,
|
|
|
|
pub scale: ReadExpect<'a, UpdateTracker<Scale>>,
|
|
|
|
pub mounting: ReadExpect<'a, UpdateTracker<Mounting>>,
|
|
|
|
pub mount_state: ReadExpect<'a, UpdateTracker<MountState>>,
|
|
|
|
pub mass: ReadExpect<'a, UpdateTracker<Mass>>,
|
|
|
|
pub sticky: ReadExpect<'a, UpdateTracker<Sticky>>,
|
|
|
|
pub gravity: ReadExpect<'a, UpdateTracker<Gravity>>,
|
|
|
|
pub projectile: ReadExpect<'a, UpdateTracker<Projectile>>,
|
2019-11-04 00:57:36 +00:00
|
|
|
}
|
|
|
|
impl<'a> ReadTrackers<'a> {
|
|
|
|
pub fn create_sync_package(
|
|
|
|
&self,
|
|
|
|
comps: &TrackedComps,
|
|
|
|
filter: impl Join + Copy,
|
2019-11-29 06:04:37 +00:00
|
|
|
deleted_entities: Vec<u64>,
|
2019-11-04 00:57:36 +00:00
|
|
|
) -> SyncPackage<EcsCompPacket> {
|
2019-11-29 06:04:37 +00:00
|
|
|
SyncPackage::new(&comps.uid, &self.uid, filter, deleted_entities)
|
|
|
|
.with_component(&comps.uid, self.body.deref(), &comps.body, filter)
|
|
|
|
.with_component(&comps.uid, self.player.deref(), &comps.player, filter)
|
|
|
|
.with_component(&comps.uid, self.stats.deref(), &comps.stats, filter)
|
|
|
|
.with_component(&comps.uid, self.can_build.deref(), &comps.can_build, filter)
|
2019-11-04 00:57:36 +00:00
|
|
|
.with_component(
|
|
|
|
&comps.uid,
|
|
|
|
self.light_emitter.deref(),
|
|
|
|
&comps.light_emitter,
|
|
|
|
filter,
|
|
|
|
)
|
2019-11-29 06:04:37 +00:00
|
|
|
.with_component(&comps.uid, self.item.deref(), &comps.item, filter)
|
|
|
|
.with_component(&comps.uid, self.scale.deref(), &comps.scale, filter)
|
|
|
|
.with_component(&comps.uid, self.mounting.deref(), &comps.mounting, filter)
|
2019-11-04 00:57:36 +00:00
|
|
|
.with_component(
|
|
|
|
&comps.uid,
|
|
|
|
self.mount_state.deref(),
|
|
|
|
&comps.mount_state,
|
|
|
|
filter,
|
|
|
|
)
|
2019-11-29 06:04:37 +00:00
|
|
|
.with_component(&comps.uid, self.mass.deref(), &comps.mass, filter)
|
|
|
|
.with_component(&comps.uid, self.sticky.deref(), &comps.sticky, filter)
|
|
|
|
.with_component(&comps.uid, self.gravity.deref(), &comps.gravity, filter)
|
2019-11-04 00:57:36 +00:00
|
|
|
.with_component(
|
|
|
|
&comps.uid,
|
|
|
|
self.projectile.deref(),
|
|
|
|
&comps.projectile,
|
|
|
|
filter,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(SystemData)]
|
|
|
|
pub struct WriteTrackers<'a> {
|
|
|
|
uid: WriteExpect<'a, UpdateTracker<Uid>>,
|
|
|
|
body: WriteExpect<'a, UpdateTracker<Body>>,
|
|
|
|
player: WriteExpect<'a, UpdateTracker<Player>>,
|
|
|
|
stats: WriteExpect<'a, UpdateTracker<Stats>>,
|
|
|
|
can_build: WriteExpect<'a, UpdateTracker<CanBuild>>,
|
|
|
|
light_emitter: WriteExpect<'a, UpdateTracker<LightEmitter>>,
|
|
|
|
item: WriteExpect<'a, UpdateTracker<Item>>,
|
|
|
|
scale: WriteExpect<'a, UpdateTracker<Scale>>,
|
|
|
|
mounting: WriteExpect<'a, UpdateTracker<Mounting>>,
|
|
|
|
mount_state: WriteExpect<'a, UpdateTracker<MountState>>,
|
|
|
|
mass: WriteExpect<'a, UpdateTracker<Mass>>,
|
|
|
|
sticky: WriteExpect<'a, UpdateTracker<Sticky>>,
|
|
|
|
gravity: WriteExpect<'a, UpdateTracker<Gravity>>,
|
|
|
|
projectile: WriteExpect<'a, UpdateTracker<Projectile>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) {
|
|
|
|
// Update trackers
|
|
|
|
trackers.uid.record_changes(&comps.uid);
|
|
|
|
trackers.body.record_changes(&comps.body);
|
|
|
|
trackers.player.record_changes(&comps.player);
|
|
|
|
trackers.stats.record_changes(&comps.stats);
|
|
|
|
trackers.can_build.record_changes(&comps.can_build);
|
|
|
|
trackers.light_emitter.record_changes(&comps.light_emitter);
|
|
|
|
trackers.item.record_changes(&comps.item);
|
|
|
|
trackers.scale.record_changes(&comps.scale);
|
|
|
|
trackers.mounting.record_changes(&comps.mounting);
|
|
|
|
trackers.mount_state.record_changes(&comps.mount_state);
|
|
|
|
trackers.mass.record_changes(&comps.mass);
|
|
|
|
trackers.sticky.record_changes(&comps.sticky);
|
|
|
|
trackers.gravity.record_changes(&comps.gravity);
|
|
|
|
trackers.projectile.record_changes(&comps.projectile);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn register_trackers(world: &mut World) {
|
|
|
|
world.register_tracker::<Uid>();
|
|
|
|
world.register_tracker::<Body>();
|
|
|
|
world.register_tracker::<Player>();
|
|
|
|
world.register_tracker::<Stats>();
|
|
|
|
world.register_tracker::<CanBuild>();
|
|
|
|
world.register_tracker::<LightEmitter>();
|
|
|
|
world.register_tracker::<Item>();
|
|
|
|
world.register_tracker::<Scale>();
|
|
|
|
world.register_tracker::<Mounting>();
|
|
|
|
world.register_tracker::<MountState>();
|
|
|
|
world.register_tracker::<Mass>();
|
|
|
|
world.register_tracker::<Sticky>();
|
|
|
|
world.register_tracker::<Gravity>();
|
|
|
|
world.register_tracker::<Projectile>();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(SystemData)]
|
|
|
|
pub struct TrackedResources<'a> {
|
|
|
|
time_of_day: ReadExpect<'a, TimeOfDay>,
|
|
|
|
}
|
|
|
|
impl<'a> TrackedResources<'a> {
|
|
|
|
pub fn create_res_sync_package(&self) -> ResSyncPackage<EcsResPacket> {
|
2019-11-29 06:04:37 +00:00
|
|
|
ResSyncPackage::new().with_res(self.time_of_day.deref())
|
2019-11-04 00:57:36 +00:00
|
|
|
}
|
|
|
|
/// Create state package with resources included
|
2019-11-24 20:12:03 +00:00
|
|
|
pub fn state_package<C: CompPacket>(&self) -> StatePackage<C, EcsResPacket> {
|
2019-11-29 06:04:37 +00:00
|
|
|
StatePackage::new().with_res(self.time_of_day.deref())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Deleted entities grouped by region
|
|
|
|
pub struct DeletedEntities {
|
|
|
|
map: HashMap<Vec2<i32>, Vec<u64>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for DeletedEntities {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
map: HashMap::new(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DeletedEntities {
|
|
|
|
pub fn record_deleted_entity(&mut self, uid: Uid, region_key: Vec2<i32>) {
|
|
|
|
self.map
|
|
|
|
.entry(region_key)
|
|
|
|
.or_insert(Vec::new())
|
|
|
|
.push(uid.into());
|
|
|
|
}
|
|
|
|
pub fn take_deleted_in_region(&mut self, key: Vec2<i32>) -> Option<Vec<u64>> {
|
|
|
|
self.map.remove(&key)
|
|
|
|
}
|
|
|
|
pub fn get_deleted_in_region(&mut self, key: Vec2<i32>) -> Option<&Vec<u64>> {
|
|
|
|
self.map.get(&key)
|
|
|
|
}
|
|
|
|
pub fn take_remaining_deleted(&mut self) -> Vec<(Vec2<i32>, Vec<u64>)> {
|
|
|
|
// TODO: don't allocate
|
|
|
|
self.map.drain().collect()
|
2019-11-04 00:57:36 +00:00
|
|
|
}
|
|
|
|
}
|