Cutout unnecessary Resource syncing machinery and Tracker trait

This commit is contained in:
Imbris 2019-12-18 00:22:52 -05:00
parent 5813f626d1
commit b2752d2419
12 changed files with 102 additions and 222 deletions

View File

@ -79,9 +79,9 @@ impl Client {
// Wait for initial sync
let (state, entity, server_info, world_map) = match postbox.next_message() {
Some(ServerMsg::InitialSync {
ecs_state,
entity_uid,
entity_package,
server_info,
time_of_day,
// world_map: /*(map_size, world_map)*/map_size,
}) => {
// TODO: Voxygen should display this.
@ -95,12 +95,10 @@ impl Client {
);
}
// Initialize `State`
let mut state = State::default();
state.ecs_mut().apply_state_package(ecs_state);
let entity = state
.ecs()
.entity_from_uid(entity_uid)
.ok_or(Error::ServerWentMad)?;
let entity = state.ecs_mut().apply_entity_package(entity_package);
*state.ecs_mut().write_resource() = time_of_day;
// assert_eq!(world_map.len(), map_size.x * map_size.y);
let map_size = Vec2::new(1024, 1024);
@ -539,7 +537,7 @@ impl Client {
self.last_ping_delta = Instant::now()
.duration_since(self.last_server_ping)
.as_secs_f64()
.as_secs_f64();
}
ServerMsg::ChatMsg { chat_type, message } => {
frontend_events.push(Event::Chat { chat_type, message })
@ -551,15 +549,14 @@ impl Client {
return Err(Error::Other("Failed to find entity from uid.".to_owned()));
}
}
ServerMsg::EcsSync(sync_package) => {
self.state.ecs_mut().apply_sync_package(sync_package)
ServerMsg::TimeOfDay(time_of_day) => {
*self.state.ecs_mut().write_resource() = time_of_day;
}
ServerMsg::EcsSync(sync_package) => {
self.state.ecs_mut().apply_sync_package(sync_package);
}
ServerMsg::EcsResSync(res_sync_package) => self
.state
.ecs_mut()
.apply_res_sync_package(res_sync_package),
ServerMsg::CreateEntity(entity_package) => {
self.state.ecs_mut().apply_entity_package(entity_package)
self.state.ecs_mut().apply_entity_package(entity_package);
}
ServerMsg::DeleteEntity(entity) => {
if self

View File

@ -1,29 +1,8 @@
use crate::{comp, state, sync};
use crate::{comp, sync};
use serde_derive::{Deserialize, Serialize};
use std::marker::PhantomData;
use sum_type::sum_type;
// TODO: remove me
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum MustHaveMoreThanOneVariant {}
// Automatically derive From<T> for EcsResPacket
// for each variant EcsResPacket::T(T).
sum_type! {
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum EcsResPacket {
MustHaveMoreThanOneVariant(MustHaveMoreThanOneVariant),
TimeOfDay(state::TimeOfDay),
}
}
impl sync::ResPacket for EcsResPacket {
fn apply(self, world: &specs::World) {
match self {
EcsResPacket::MustHaveMoreThanOneVariant(_) => unimplemented!(),
EcsResPacket::TimeOfDay(time_of_day) => sync::handle_res_update(time_of_day, world),
}
}
}
// Automatically derive From<T> for EcsCompPacket
// for each variant EcsCompPacket::T(T.)
sum_type! {

View File

@ -4,7 +4,7 @@ pub mod server;
// Reexports
pub use self::client::ClientMsg;
pub use self::ecs_packet::{EcsCompPacket, EcsResPacket};
pub use self::ecs_packet::EcsCompPacket;
pub use self::server::{RequestStateError, ServerError, ServerInfo, ServerMsg};
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]

View File

@ -1,6 +1,6 @@
use super::{ClientState, EcsCompPacket, EcsResPacket};
use super::{ClientState, EcsCompPacket};
use crate::{
comp, sync,
comp, state, sync,
terrain::{Block, TerrainChunk},
ChatType,
};
@ -26,9 +26,9 @@ pub struct ServerInfo {
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ServerMsg {
InitialSync {
ecs_state: sync::StatePackage<EcsCompPacket, EcsResPacket>,
entity_uid: u64,
entity_package: sync::EntityPackage<EcsCompPacket>,
server_info: ServerInfo,
time_of_day: state::TimeOfDay,
// world_map: Vec2<usize>, /*, Vec<u32>)*/
},
StateAnswer(Result<ClientState, (RequestStateError, ClientState)>),
@ -40,8 +40,8 @@ pub enum ServerMsg {
message: String,
},
SetPlayerEntity(u64),
TimeOfDay(state::TimeOfDay),
EcsSync(sync::SyncPackage<EcsCompPacket>),
EcsResSync(sync::ResSyncPackage<EcsResPacket>),
CreateEntity(sync::EntityPackage<EcsCompPacket>),
DeleteEntity(u64),
EntityPos {

View File

@ -23,7 +23,7 @@ use vek::*;
const DAY_CYCLE_FACTOR: f64 = 24.0 * 2.0;
/// A resource that stores the time of day.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
pub struct TimeOfDay(pub f64);
/// A resource that stores the tick (i.e: physics) time.

View File

@ -6,9 +6,9 @@ mod uid;
// Reexports
pub use packet::{
handle_insert, handle_modify, handle_remove, handle_res_update, CompPacket, EntityPackage,
ResPacket, ResSyncPackage, StatePackage, SyncPackage,
handle_insert, handle_modify, handle_remove, CompPacket, EntityPackage, StatePackage,
SyncPackage,
};
pub use sync_ext::WorldSyncExt;
pub use track::{Tracker, UpdateTracker};
pub use track::UpdateTracker;
pub use uid::{Uid, UidAllocator};

View File

@ -1,10 +1,7 @@
use super::{
track::{Tracker, UpdateTracker},
uid::Uid,
};
use super::{track::UpdateTracker, uid::Uid};
use log::error;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use specs::{shred::Resource, Component, Entity, Join, ReadStorage, World, WorldExt};
use specs::{Component, Entity, Join, ReadStorage, World, WorldExt};
use std::{
convert::{TryFrom, TryInto},
fmt::Debug,
@ -19,10 +16,6 @@ pub trait CompPacket: Clone + Debug + Send + 'static {
fn apply_remove(phantom: Self::Phantom, entity: Entity, world: &World);
}
pub trait ResPacket: Clone + Debug + Send + 'static {
fn apply(self, world: &World);
}
/// Useful for implementing CompPacket trait
pub fn handle_insert<C: Component>(comp: C, entity: Entity, world: &World) {
if let Err(err) = world.write_storage::<C>().insert(entity, comp) {
@ -40,10 +33,6 @@ pub fn handle_modify<C: Component>(comp: C, entity: Entity, world: &World) {
pub fn handle_remove<C: Component>(entity: Entity, world: &World) {
let _ = world.write_storage::<C>().remove(entity);
}
/// Useful for implementing ResPacket trait
pub fn handle_res_update<R: Resource>(res: R, world: &World) {
*world.write_resource::<R>() = res;
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
pub enum CompUpdateKind<P: CompPacket> {
@ -53,24 +42,25 @@ pub enum CompUpdateKind<P: CompPacket> {
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct EntityPackage<P: CompPacket>(pub u64, pub Vec<P>);
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct StatePackage<P: CompPacket, R: ResPacket> {
pub entities: Vec<EntityPackage<P>>,
pub resources: Vec<R>,
pub struct EntityPackage<P: CompPacket> {
pub uid: u64,
pub comps: Vec<P>,
}
impl<P: CompPacket, R: ResPacket> Default for StatePackage<P, R> {
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct StatePackage<P: CompPacket> {
pub entities: Vec<EntityPackage<P>>,
}
impl<P: CompPacket> Default for StatePackage<P> {
fn default() -> Self {
Self {
entities: Vec::new(),
resources: Vec::new(),
}
}
}
impl<P: CompPacket, R: ResPacket> StatePackage<P, R> {
impl<P: CompPacket> StatePackage<P> {
pub fn new() -> Self {
Self::default()
}
@ -85,13 +75,6 @@ impl<P: CompPacket, R: ResPacket> StatePackage<P, R> {
self.entities.push(entry);
self
}
pub fn with_res<C: Resource + Clone + Send + Sync>(mut self, res: &C) -> Self
where
R: From<C>,
{
self.resources.push(R::from(res.clone()));
self
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
@ -122,7 +105,7 @@ impl<P: CompPacket> SyncPackage<P> {
pub fn with_component<'a, C: Component + Clone + Send + Sync>(
mut self,
uids: &ReadStorage<'a, Uid>,
tracker: &impl Tracker<C, P>,
tracker: &UpdateTracker<C>,
storage: &ReadStorage<'a, C>,
filter: impl Join + Copy,
) -> Self
@ -137,22 +120,3 @@ impl<P: CompPacket> SyncPackage<P> {
self
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ResSyncPackage<R: ResPacket> {
pub resources: Vec<R>,
}
impl<R: ResPacket> ResSyncPackage<R> {
pub fn new() -> Self {
Self {
resources: Vec::new(),
}
}
pub fn with_res<C: Resource + Clone + Send + Sync>(mut self, res: &C) -> Self
where
R: From<C>,
{
self.resources.push(R::from(res.clone()));
self
}
}

View File

@ -1,8 +1,5 @@
use super::{
packet::{
CompPacket, CompUpdateKind, EntityPackage, ResPacket, ResSyncPackage, StatePackage,
SyncPackage,
},
packet::{CompPacket, CompUpdateKind, EntityPackage, StatePackage, SyncPackage},
track::UpdateTracker,
uid::{Uid, UidAllocator},
};
@ -25,13 +22,12 @@ pub trait WorldSyncExt {
fn delete_entity_and_clear_from_uid_allocator(&mut self, uid: u64);
fn uid_from_entity(&self, entity: specs::Entity) -> Option<Uid>;
fn entity_from_uid(&self, uid: u64) -> Option<specs::Entity>;
fn apply_entity_package<P: CompPacket>(&mut self, entity_package: EntityPackage<P>);
fn apply_state_package<P: CompPacket, R: ResPacket>(
fn apply_entity_package<P: CompPacket>(
&mut self,
state_package: StatePackage<P, R>,
);
entity_package: EntityPackage<P>,
) -> specs::Entity;
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_res_sync_package<R: ResPacket>(&mut self, package: ResSyncPackage<R>);
}
impl WorldSyncExt for specs::World {
@ -71,13 +67,18 @@ impl WorldSyncExt for specs::World {
.retrieve_entity_internal(uid)
}
fn apply_entity_package<P: CompPacket>(&mut self, entity_package: EntityPackage<P>) {
let EntityPackage(entity_uid, packets) = entity_package;
fn apply_entity_package<P: CompPacket>(
&mut self,
entity_package: EntityPackage<P>,
) -> specs::Entity {
let EntityPackage { uid, comps } = entity_package;
let entity = create_entity_with_uid(self, entity_uid);
for packet in packets {
let entity = create_entity_with_uid(self, uid);
for packet in comps {
packet.apply_insert(entity, self)
}
entity
}
fn delete_entity_and_clear_from_uid_allocator(&mut self, uid: u64) {
@ -90,25 +91,15 @@ impl WorldSyncExt for specs::World {
}
}
fn apply_state_package<P: CompPacket, R: ResPacket>(
&mut self,
state_package: StatePackage<P, R>,
) {
let StatePackage {
entities,
resources,
} = state_package;
// Apply state package resources
for res_packet in resources {
res_packet.apply(self);
}
fn apply_state_package<P: CompPacket>(&mut self, state_package: StatePackage<P>) {
let StatePackage { entities } = state_package;
// Apply state package entities
for entity_package in entities {
self.apply_entity_package(entity_package);
}
// TODO: determine if this is needed
// Initialize entities
//self.maintain();
}
@ -151,12 +142,6 @@ impl WorldSyncExt for specs::World {
self.delete_entity_and_clear_from_uid_allocator(entity_uid);
}
}
fn apply_res_sync_package<R: ResPacket>(&mut self, package: ResSyncPackage<R>) {
// Update resources
for res_packet in package.resources {
res_packet.apply(self);
}
}
}
// Private utilities

View File

@ -8,29 +8,6 @@ use std::{
marker::PhantomData,
};
pub trait Tracker<C: Component + Clone + Send + Sync, P: CompPacket>: Send + 'static
where
P: From<C>,
C: TryFrom<P>,
P::Phantom: From<PhantomData<C>>,
P::Phantom: TryInto<PhantomData<C>>,
C::Storage: specs::storage::Tracked,
{
fn add_packet_for<'a>(
&self,
storage: &specs::ReadStorage<'a, C>,
entity: specs::Entity,
packets: &mut Vec<P>,
);
fn get_updates_for<'a>(
&self,
uids: &specs::ReadStorage<'a, Uid>,
storage: &specs::ReadStorage<'a, C>,
filter: impl Join + Copy,
buf: &mut Vec<(u64, CompUpdateKind<P>)>,
);
}
pub struct UpdateTracker<C: Component> {
reader_id: specs::ReaderId<specs::storage::ComponentEvent>,
inserted: BitSet,
@ -92,32 +69,39 @@ where
}
}
impl<C: Component + Clone + Send + Sync, P: CompPacket> Tracker<C, P> for UpdateTracker<C>
where
P: From<C>,
C: TryFrom<P>,
P::Phantom: From<PhantomData<C>>,
P::Phantom: TryInto<PhantomData<C>>,
C::Storage: specs::storage::Tracked,
{
fn add_packet_for<'a>(
impl<C: Component + Clone + Send + Sync> UpdateTracker<C> {
pub fn add_packet_for<'a, P>(
&self,
storage: &ReadStorage<'a, C>,
entity: Entity,
packets: &mut Vec<P>,
) {
) where
P: CompPacket,
P: From<C>,
C: TryFrom<P>,
P::Phantom: From<PhantomData<C>>,
P::Phantom: TryInto<PhantomData<C>>,
C::Storage: specs::storage::Tracked,
{
if let Some(comp) = storage.get(entity) {
packets.push(P::from(comp.clone()));
}
}
fn get_updates_for<'a>(
pub fn get_updates_for<'a, P>(
&self,
uids: &specs::ReadStorage<'a, Uid>,
storage: &specs::ReadStorage<'a, C>,
entity_filter: impl Join + Copy,
buf: &mut Vec<(u64, CompUpdateKind<P>)>,
) {
) where
P: CompPacket,
P: From<C>,
C: TryFrom<P>,
P::Phantom: From<PhantomData<C>>,
P::Phantom: TryInto<PhantomData<C>>,
C::Storage: specs::storage::Tracked,
{
// Generate inserted updates
for (uid, comp, _, _) in (uids, storage, &self.inserted, entity_filter).join() {
buf.push((

View File

@ -19,7 +19,7 @@ use crate::{
chunk_generator::ChunkGenerator,
client::{Client, RegionSubscription},
cmd::CHAT_COMMANDS,
sys::sentinel::{DeletedEntities, TrackedComps, TrackedResources},
sys::sentinel::{DeletedEntities, TrackedComps},
};
use common::{
assets, comp,
@ -992,7 +992,8 @@ impl Server {
.create_entity_synced()
.with(client)
.build();
// Return the state of the current world (all of the components that Sphynx tracks).
// Send client all the tracked components currently attached to its entity as well
// as synced resources (currently only `TimeOfDay`)
log::debug!("Starting initial sync with client.");
self.state
.ecs()
@ -1000,15 +1001,11 @@ impl Server {
.get_mut(entity)
.unwrap()
.notify(ServerMsg::InitialSync {
ecs_state: TrackedResources::fetch(&self.state.ecs())
.state_package()
// Send client their entity
.with_entity(
TrackedComps::fetch(&self.state.ecs())
.create_entity_package(entity),
),
entity_uid: self.state.ecs().uid_from_entity(entity).unwrap().into(), // Can't fail.
// Send client their entity
entity_package: TrackedComps::fetch(&self.state.ecs())
.create_entity_package(entity),
server_info: self.server_info.clone(),
time_of_day: *self.state.ecs().read_resource(),
// world_map: (WORLD_SIZE/*, self.world.sim().get_map()*/),
});
log::debug!("Done initial sync with client.");

View File

@ -1,5 +1,5 @@
use super::{
sentinel::{DeletedEntities, ReadTrackers, TrackedComps, TrackedResources},
sentinel::{DeletedEntities, ReadTrackers, TrackedComps},
SysTimer,
};
use crate::{
@ -10,6 +10,7 @@ use common::{
comp::{CharacterState, ForceUpdate, Inventory, InventoryUpdate, Last, Ori, Pos, Vel},
msg::ServerMsg,
region::{Event as RegionEvent, RegionMap},
state::TimeOfDay,
sync::Uid,
};
use specs::{
@ -22,6 +23,7 @@ impl<'a> System<'a> for Sys {
type SystemData = (
Entities<'a>,
Read<'a, Tick>,
ReadExpect<'a, TimeOfDay>,
ReadExpect<'a, RegionMap>,
Write<'a, SysTimer<Self>>,
ReadStorage<'a, Uid>,
@ -41,7 +43,6 @@ impl<'a> System<'a> for Sys {
Write<'a, DeletedEntities>,
TrackedComps<'a>,
ReadTrackers<'a>,
TrackedResources<'a>,
);
fn run(
@ -49,6 +50,7 @@ impl<'a> System<'a> for Sys {
(
entities,
tick,
time_of_day,
region_map,
mut timer,
uids,
@ -68,7 +70,6 @@ impl<'a> System<'a> for Sys {
mut deleted_entities,
tracked_comps,
trackers,
tracked_resources,
): Self::SystemData,
) {
timer.start();
@ -329,10 +330,10 @@ impl<'a> System<'a> for Sys {
inventory_updates.clear();
// Sync resources
// TODO: doesn't really belong in this system
let res_msg = ServerMsg::EcsResSync(tracked_resources.create_res_sync_package());
// TODO: doesn't really belong in this system (rename system or create another system?)
let tof_msg = ServerMsg::TimeOfDay(*time_of_day);
for client in (&mut clients).join() {
client.notify(res_msg.clone());
client.notify(tof_msg.clone());
}
timer.end();

View File

@ -4,12 +4,8 @@ use common::{
Body, CanBuild, Gravity, Item, LightEmitter, Mass, MountState, Mounting, Player, Scale,
Stats, Sticky,
},
msg::{EcsCompPacket, EcsResPacket},
state::TimeOfDay,
sync::{
CompPacket, EntityPackage, ResSyncPackage, StatePackage, SyncPackage, Uid, UpdateTracker,
WorldSyncExt,
},
msg::EcsCompPacket,
sync::{EntityPackage, SyncPackage, Uid, UpdateTracker, WorldSyncExt},
};
use hashbrown::HashMap;
use specs::{
@ -62,57 +58,48 @@ impl<'a> TrackedComps<'a> {
.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()));
let mut comps = Vec::new();
self.body.get(entity).copied().map(|c| comps.push(c.into()));
self.player
.get(entity)
.cloned()
.map(|c| packets.push(c.into()));
.map(|c| comps.push(c.into()));
self.stats
.get(entity)
.cloned()
.map(|c| packets.push(c.into()));
.map(|c| comps.push(c.into()));
self.can_build
.get(entity)
.cloned()
.map(|c| packets.push(c.into()));
.map(|c| comps.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()));
.map(|c| comps.push(c.into()));
self.item.get(entity).cloned().map(|c| comps.push(c.into()));
self.scale
.get(entity)
.copied()
.map(|c| packets.push(c.into()));
.map(|c| comps.push(c.into()));
self.mounting
.get(entity)
.cloned()
.map(|c| packets.push(c.into()));
.map(|c| comps.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()));
.map(|c| comps.push(c.into()));
self.mass.get(entity).copied().map(|c| comps.push(c.into()));
self.sticky
.get(entity)
.copied()
.map(|c| packets.push(c.into()));
.map(|c| comps.push(c.into()));
self.gravity
.get(entity)
.copied()
.map(|c| packets.push(c.into()));
.map(|c| comps.push(c.into()));
EntityPackage(uid, packets)
EntityPackage { uid, comps }
}
}
#[derive(SystemData)]
@ -209,20 +196,6 @@ pub fn register_trackers(world: &mut World) {
world.register_tracker::<Gravity>();
}
#[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> {
ResSyncPackage::new().with_res(&*self.time_of_day)
}
/// Create state package with resources included
pub fn state_package<C: CompPacket>(&self) -> StatePackage<C, EcsResPacket> {
StatePackage::new().with_res(&*self.time_of_day)
}
}
/// Deleted entities grouped by region
pub struct DeletedEntities {
map: HashMap<Vec2<i32>, Vec<u64>>,