diff --git a/client/src/lib.rs b/client/src/lib.rs index 5310576629..56caab05b2 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -16,12 +16,9 @@ use std::{ }; use vek::*; use threadpool; -use specs::{ - Builder, - saveload::MarkerAllocator, -}; +use specs::Builder; use common::{ - comp::{self, Uid}, + comp, state::State, terrain::TerrainChunk, net::PostBox, @@ -104,30 +101,6 @@ impl Client { #[allow(dead_code)] pub fn state_mut(&mut self) -> &mut State { &mut self.state } - /// Get an entity from its UID, creating it if it does not exists - pub fn get_or_create_entity_from_uid(&mut self, uid: Uid) -> EcsEntity { - // Find the ECS entity from its UID - let ecs_entity = self.state().ecs_world() - .read_resource::() - .retrieve_entity_internal(uid.into()); - - // Return the entity or create it - if let Some(ecs_entity) = ecs_entity { - ecs_entity - } else { - let ecs_entity = self.state.ecs_world_mut().create_entity() - .build(); - - // Allocate it the specific UID given - self.state - .ecs_world_mut() - .write_resource::() - .allocate(ecs_entity, Some(uid.into())); - - ecs_entity - } - } - /// Get the player entity #[allow(dead_code)] pub fn player(&self) -> Option { @@ -222,11 +195,17 @@ impl Client { ServerMsg::Pong => {}, ServerMsg::Chat(msg) => frontend_events.push(Event::Chat(msg)), ServerMsg::SetPlayerEntity(uid) => { - let ecs_entity = self.get_or_create_entity_from_uid(uid); + let ecs_entity = self.state + .get_entity(uid) + .unwrap_or_else(|| self.state.build_uid_entity_with_uid(uid).build()); + self.player = Some(ecs_entity); }, ServerMsg::EntityPhysics { uid, pos, vel, dir } => { - let ecs_entity = self.get_or_create_entity_from_uid(uid); + let ecs_entity = self.state + .get_entity(uid) + .unwrap_or_else(|| self.state.build_uid_entity_with_uid(uid).build()); + self.state.write_component(ecs_entity, pos); self.state.write_component(ecs_entity, vel); self.state.write_component(ecs_entity, dir); diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs index 684d6b1798..776a67485c 100644 --- a/common/src/comp/mod.rs +++ b/common/src/comp/mod.rs @@ -1,5 +1,6 @@ pub mod phys; pub mod uid; +pub mod util; // Reexports pub use uid::{Uid, UidAllocator}; @@ -10,6 +11,8 @@ pub fn register_local_components(ecs_world: &mut EcsWorld) { ecs_world.register::(); ecs_world.add_resource(UidAllocator::new()); + ecs_world.register::(); + ecs_world.register::(); ecs_world.register::(); ecs_world.register::(); diff --git a/common/src/comp/util.rs b/common/src/comp/util.rs new file mode 100644 index 0000000000..0ea2d35ebc --- /dev/null +++ b/common/src/comp/util.rs @@ -0,0 +1,12 @@ +// Library +use specs::{Component, NullStorage}; +use vek::*; + +// Pos + +#[derive(Copy, Clone, Debug, Default)] +pub struct New; + +impl Component for New { + type Storage = NullStorage; +} diff --git a/common/src/state.rs b/common/src/state.rs index 232c9d6645..b395dd35de 100644 --- a/common/src/state.rs +++ b/common/src/state.rs @@ -4,13 +4,14 @@ use specs::{ Builder, Component, DispatcherBuilder, + EntityBuilder as EcsEntityBuilder, Entity as EcsEntity, World as EcsWorld, storage::{ Storage as EcsStorage, MaskedStorage as EcsMaskedStorage, }, - saveload::MarkerAllocator, + saveload::{MarkedBuilder, MarkerAllocator}, }; use vek::*; use crate::{ @@ -90,6 +91,24 @@ impl State { self } + /// Build a new entity with a generated UID + pub fn build_uid_entity(&mut self) -> EcsEntityBuilder { + self.ecs_world.create_entity() + .with(comp::util::New) + .marked::() + } + + /// Build an entity with a specific UID + pub fn build_uid_entity_with_uid(&mut self, uid: comp::Uid) -> EcsEntityBuilder { + let builder = self.build_uid_entity(); + + builder.world + .write_resource::() + .allocate(builder.entity, Some(uid.into())); + + builder + } + /// Get an entity from its UID, if it exists pub fn get_entity(&self, uid: comp::Uid) -> Option { // Find the ECS entity from its UID @@ -168,6 +187,9 @@ impl State { /// Execute a single tick, simulating the game state by the given duration. pub fn tick(&mut self, dt: Duration) { + // First, wipe all temporary marker components + self.ecs_world.write_storage::().clear(); + // Change the time accordingly self.ecs_world.write_resource::().0 += dt.as_secs_f64() * DAY_CYCLE_FACTOR; self.ecs_world.write_resource::