| @@ -5,6 +5,8 @@ use glc::vector::Vector2f; | |||||
| use serde::{Deserialize, Serialize}; | use serde::{Deserialize, Serialize}; | ||||
| use specs::{Component, Entity, VecStorage}; | use specs::{Component, Entity, VecStorage}; | ||||
| use crate::misc::FlaggedStorage; | |||||
| #[derive(Clone, Debug, Serialize, Deserialize)] | #[derive(Clone, Debug, Serialize, Deserialize)] | ||||
| pub struct Ship { | pub struct Ship { | ||||
| type_: Type, | type_: Type, | ||||
| @@ -84,7 +86,7 @@ impl Ship { | |||||
| } | } | ||||
| impl Component for Ship { | impl Component for Ship { | ||||
| type Storage = VecStorage<Self>; | |||||
| type Storage = FlaggedStorage<Self, VecStorage<Self>>; | |||||
| } | } | ||||
| impl Default for Obstacle { | impl Default for Obstacle { | ||||
| @@ -1,59 +1,53 @@ | |||||
| #![allow(dead_code)] | #![allow(dead_code)] | ||||
| use std::ops::{Deref, DerefMut}; | |||||
| use hibitset::BitSetLike; | use hibitset::BitSetLike; | ||||
| use shrev::EventChannel; | |||||
| use shrev::{Event, EventChannel, ReaderId}; | |||||
| use specs::{ | use specs::{ | ||||
| storage::{TryDefault, UnprotectedStorage}, | |||||
| storage::{DistinctStorage, MaskedStorage, Storage, TryDefault, UnprotectedStorage}, | |||||
| world::Index, | world::Index, | ||||
| Component, DenseVecStorage, | Component, DenseVecStorage, | ||||
| }; | }; | ||||
| /* FlaggedStorage */ | |||||
| pub struct FlaggedStorage<C, T = DenseVecStorage<C>> | pub struct FlaggedStorage<C, T = DenseVecStorage<C>> | ||||
| where | where | ||||
| C: Send + Sync + 'static, | |||||
| C: Event, | |||||
| { | { | ||||
| event_emission: bool, | |||||
| channel: EventChannel<ComponentEvent<C>>, | channel: EventChannel<ComponentEvent<C>>, | ||||
| storage: T, | storage: T, | ||||
| } | } | ||||
| pub enum ComponentEvent<C> | pub enum ComponentEvent<C> | ||||
| where | where | ||||
| C: Send + Sync + 'static, | |||||
| C: Event, | |||||
| { | { | ||||
| Inserted(Index, C), | Inserted(Index, C), | ||||
| Modified(Index, C), | Modified(Index, C), | ||||
| Removed(Index, C), | Removed(Index, C), | ||||
| } | } | ||||
| impl<C, T> FlaggedStorage<C, T> | |||||
| where | |||||
| C: Send + Sync + 'static, | |||||
| { | |||||
| pub fn channel(&self) -> &EventChannel<ComponentEvent<C>> { | |||||
| &self.channel | |||||
| } | |||||
| pub fn channel_mut(&mut self) -> &mut EventChannel<ComponentEvent<C>> { | |||||
| &mut self.channel | |||||
| } | |||||
| } | |||||
| impl<C, T> Default for FlaggedStorage<C, T> | impl<C, T> Default for FlaggedStorage<C, T> | ||||
| where | where | ||||
| C: Send + Sync + 'static, | |||||
| C: Event, | |||||
| T: TryDefault, | T: TryDefault, | ||||
| { | { | ||||
| fn default() -> Self { | fn default() -> Self { | ||||
| FlaggedStorage { | FlaggedStorage { | ||||
| event_emission: true, | |||||
| channel: EventChannel::new(), | channel: EventChannel::new(), | ||||
| storage: T::unwrap_default(), | storage: T::unwrap_default(), | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| impl<C: Component + Clone, T: UnprotectedStorage<C>> UnprotectedStorage<C> for FlaggedStorage<C, T> | |||||
| impl<C, T> UnprotectedStorage<C> for FlaggedStorage<C, T> | |||||
| where | where | ||||
| C: Send + Sync + 'static, | |||||
| C: Component + Event + Clone, | |||||
| T: UnprotectedStorage<C>, | |||||
| { | { | ||||
| unsafe fn clean<B>(&mut self, has: B) | unsafe fn clean<B>(&mut self, has: B) | ||||
| where | where | ||||
| @@ -91,3 +85,88 @@ where | |||||
| component | component | ||||
| } | } | ||||
| } | } | ||||
| unsafe impl<C, T> DistinctStorage for FlaggedStorage<C, T> | |||||
| where | |||||
| C: Component + Event + Clone, | |||||
| T: DistinctStorage, | |||||
| { | |||||
| } | |||||
| /* Tracked */ | |||||
| pub trait Tracked<C: Event> { | |||||
| fn channel(&self) -> &EventChannel<ComponentEvent<C>>; | |||||
| fn channel_mut(&mut self) -> &mut EventChannel<ComponentEvent<C>>; | |||||
| fn event_emission(&self) -> bool; | |||||
| fn set_event_emission(&mut self, value: bool); | |||||
| } | |||||
| impl<C, T> Tracked<C> for FlaggedStorage<C, T> | |||||
| where | |||||
| C: Component + Event, | |||||
| { | |||||
| fn channel(&self) -> &EventChannel<ComponentEvent<C>> { | |||||
| &self.channel | |||||
| } | |||||
| fn channel_mut(&mut self) -> &mut EventChannel<ComponentEvent<C>> { | |||||
| &mut self.channel | |||||
| } | |||||
| fn event_emission(&self) -> bool { | |||||
| self.event_emission | |||||
| } | |||||
| fn set_event_emission(&mut self, value: bool) { | |||||
| self.event_emission = value; | |||||
| } | |||||
| } | |||||
| /* StorageHelper */ | |||||
| pub trait StorageHelper<C: Event> { | |||||
| fn event_emission(&self) -> bool; | |||||
| fn channel(&self) -> &EventChannel<ComponentEvent<C>>; | |||||
| } | |||||
| pub trait StorageHelperMut<C: Event> { | |||||
| fn set_event_emission(&mut self, value: bool); | |||||
| fn channel_mut(&mut self) -> &mut EventChannel<ComponentEvent<C>>; | |||||
| fn register_event_reader(&mut self) -> ReaderId<ComponentEvent<C>>; | |||||
| } | |||||
| impl<'e, T, D> StorageHelper<T> for Storage<'e, T, D> | |||||
| where | |||||
| T: Component + Event, | |||||
| T::Storage: Tracked<T>, | |||||
| D: Deref<Target = MaskedStorage<T>>, | |||||
| { | |||||
| fn event_emission(&self) -> bool { | |||||
| self.unprotected_storage().event_emission() | |||||
| } | |||||
| fn channel(&self) -> &EventChannel<ComponentEvent<T>> { | |||||
| self.unprotected_storage().channel() | |||||
| } | |||||
| } | |||||
| impl<'e, T, D> StorageHelperMut<T> for Storage<'e, T, D> | |||||
| where | |||||
| T: Component + Event, | |||||
| T::Storage: Tracked<T>, | |||||
| D: DerefMut<Target = MaskedStorage<T>>, | |||||
| { | |||||
| fn set_event_emission(&mut self, value: bool) { | |||||
| unsafe { self.unprotected_storage_mut().set_event_emission(value) }; | |||||
| } | |||||
| fn channel_mut(&mut self) -> &mut EventChannel<ComponentEvent<T>> { | |||||
| unsafe { self.unprotected_storage_mut().channel_mut() } | |||||
| } | |||||
| fn register_event_reader(&mut self) -> ReaderId<ComponentEvent<T>> { | |||||
| self.channel_mut().register_reader() | |||||
| } | |||||
| } | |||||
| @@ -7,7 +7,9 @@ mod world; | |||||
| pub use self::log::init as init_logger; | pub use self::log::init as init_logger; | ||||
| pub use self::vfs::{Vfs, VfsError}; | pub use self::vfs::{Vfs, VfsError}; | ||||
| pub use flagged_storage::{ComponentEvent, FlaggedStorage}; | |||||
| pub use flagged_storage::{ | |||||
| ComponentEvent, FlaggedStorage, StorageHelper, StorageHelperMut, Tracked, | |||||
| }; | |||||
| pub use log_result::LogResult; | pub use log_result::LogResult; | ||||
| pub use persistence::{PersistWorld, Persistence}; | pub use persistence::{PersistWorld, Persistence}; | ||||
| pub use world::WorldHelper; | pub use world::WorldHelper; | ||||
| @@ -5,7 +5,7 @@ use specs::{prelude::*, world::Index, Entities, ReadStorage, System, World, Writ | |||||
| use crate::{ | use crate::{ | ||||
| components::{Fleet, FleetOwned, Ship}, | components::{Fleet, FleetOwned, Ship}, | ||||
| misc::ComponentEvent, | |||||
| misc::{ComponentEvent, StorageHelper, StorageHelperMut}, | |||||
| }; | }; | ||||
| pub struct FleetOwnedUpdate { | pub struct FleetOwnedUpdate { | ||||
| @@ -17,19 +17,14 @@ pub struct FleetOwnedUpdate { | |||||
| impl FleetOwnedUpdate { | impl FleetOwnedUpdate { | ||||
| pub fn new(world: &mut World) -> Self { | pub fn new(world: &mut World) -> Self { | ||||
| WriteStorage::<FleetOwned>::setup(world); | |||||
| let fleet_ids = BitSet::new(); | let fleet_ids = BitSet::new(); | ||||
| let fleet_owned_ids = BitSet::new(); | let fleet_owned_ids = BitSet::new(); | ||||
| let old_fleet_ids = HashMap::new(); | let old_fleet_ids = HashMap::new(); | ||||
| let fleet_owned_event_id = unsafe { | |||||
| WriteStorage::<FleetOwned>::setup(world); | |||||
| let mut fleet_owned = world.system_data::<WriteStorage<FleetOwned>>(); | |||||
| fleet_owned | |||||
| .unprotected_storage_mut() | |||||
| .channel_mut() | |||||
| .register_reader() | |||||
| }; | |||||
| let fleet_owned_event_id = world | |||||
| .system_data::<WriteStorage<FleetOwned>>() | |||||
| .register_event_reader(); | |||||
| Self { | Self { | ||||
| fleet_ids, | fleet_ids, | ||||
| @@ -64,10 +59,7 @@ impl<'a> System<'a> for FleetOwnedUpdate { | |||||
| self.old_fleet_ids.clear(); | self.old_fleet_ids.clear(); | ||||
| /* handle events */ | /* handle events */ | ||||
| let events = fleet_owned | |||||
| .unprotected_storage() | |||||
| .channel() | |||||
| .read(&mut self.fleet_owned_event_id); | |||||
| let events = fleet_owned.channel().read(&mut self.fleet_owned_event_id); | |||||
| for event in events { | for event in events { | ||||
| match event { | match event { | ||||
| ComponentEvent::Inserted(id, fleet_owned) => { | ComponentEvent::Inserted(id, fleet_owned) => { | ||||
| @@ -8,7 +8,7 @@ use specs::{ | |||||
| use crate::{ | use crate::{ | ||||
| components::{Orbit, OrbitOwned, PlayerOwned}, | components::{Orbit, OrbitOwned, PlayerOwned}, | ||||
| misc::ComponentEvent, | |||||
| misc::{ComponentEvent, StorageHelper, StorageHelperMut}, | |||||
| }; | }; | ||||
| pub struct OrbitOwnedUpdate { | pub struct OrbitOwnedUpdate { | ||||
| @@ -20,19 +20,14 @@ pub struct OrbitOwnedUpdate { | |||||
| impl OrbitOwnedUpdate { | impl OrbitOwnedUpdate { | ||||
| pub fn new(world: &mut World) -> Self { | pub fn new(world: &mut World) -> Self { | ||||
| WriteStorage::<OrbitOwned>::setup(world); | |||||
| let orbit_ids = BitSet::new(); | let orbit_ids = BitSet::new(); | ||||
| let orbit_owned_ids = BitSet::new(); | let orbit_owned_ids = BitSet::new(); | ||||
| let old_orbit_ids = HashMap::new(); | let old_orbit_ids = HashMap::new(); | ||||
| let orbit_owned_event_id = unsafe { | |||||
| WriteStorage::<OrbitOwned>::setup(world); | |||||
| let mut orbit_owned = world.system_data::<WriteStorage<OrbitOwned>>(); | |||||
| orbit_owned | |||||
| .unprotected_storage_mut() | |||||
| .channel_mut() | |||||
| .register_reader() | |||||
| }; | |||||
| let orbit_owned_event_id = world | |||||
| .system_data::<WriteStorage<OrbitOwned>>() | |||||
| .register_event_reader(); | |||||
| Self { | Self { | ||||
| orbit_ids, | orbit_ids, | ||||
| @@ -67,10 +62,7 @@ impl<'a> System<'a> for OrbitOwnedUpdate { | |||||
| self.old_orbit_ids.clear(); | self.old_orbit_ids.clear(); | ||||
| /* handle events */ | /* handle events */ | ||||
| let events = orbit_owned | |||||
| .unprotected_storage() | |||||
| .channel() | |||||
| .read(&mut self.orbit_owned_event_id); | |||||
| let events = orbit_owned.channel().read(&mut self.orbit_owned_event_id); | |||||
| for event in events { | for event in events { | ||||
| match event { | match event { | ||||
| ComponentEvent::Inserted(id, orbit_owned) => { | ComponentEvent::Inserted(id, orbit_owned) => { | ||||
| @@ -16,7 +16,7 @@ use crate::{ | |||||
| SHIP_ORBIT_AGILITY, SHIP_ORBIT_ANGLE_DELTA_MIN, SHIP_ORBIT_ANGLE_DELTA_RND, | SHIP_ORBIT_AGILITY, SHIP_ORBIT_ANGLE_DELTA_MIN, SHIP_ORBIT_ANGLE_DELTA_RND, | ||||
| SHIP_ORBIT_DISTANCE_MAX, VECTOR_2F_POS_X, | SHIP_ORBIT_DISTANCE_MAX, VECTOR_2F_POS_X, | ||||
| }, | }, | ||||
| misc::ComponentEvent, | |||||
| misc::{ComponentEvent, StorageHelper, StorageHelperMut}, | |||||
| resources::Global, | resources::Global, | ||||
| return_if_none, | return_if_none, | ||||
| }; | }; | ||||
| @@ -51,16 +51,12 @@ struct Processor<'a> { | |||||
| impl Ships { | impl Ships { | ||||
| pub fn new(world: &mut World) -> Self { | pub fn new(world: &mut World) -> Self { | ||||
| WriteStorage::<FleetOwned>::setup(world); | |||||
| let need_update = BitSet::new(); | let need_update = BitSet::new(); | ||||
| let fleet_owned_id = unsafe { | |||||
| WriteStorage::<FleetOwned>::setup(world); | |||||
| let mut fleet_owned = world.system_data::<WriteStorage<FleetOwned>>(); | |||||
| fleet_owned | |||||
| .unprotected_storage_mut() | |||||
| .channel_mut() | |||||
| .register_reader() | |||||
| }; | |||||
| let fleet_owned_id = world | |||||
| .system_data::<WriteStorage<FleetOwned>>() | |||||
| .register_event_reader(); | |||||
| Self { | Self { | ||||
| need_update, | need_update, | ||||
| @@ -70,10 +66,7 @@ impl Ships { | |||||
| fn progress_events(&mut self, fleet_owned: &ReadStorage<'_, FleetOwned>) { | fn progress_events(&mut self, fleet_owned: &ReadStorage<'_, FleetOwned>) { | ||||
| self.need_update.clear(); | self.need_update.clear(); | ||||
| let events = fleet_owned | |||||
| .unprotected_storage() | |||||
| .channel() | |||||
| .read(&mut self.fleet_owned_id); | |||||
| let events = fleet_owned.channel().read(&mut self.fleet_owned_id); | |||||
| for event in events { | for event in events { | ||||
| let id = match event { | let id = match event { | ||||
| ComponentEvent::Inserted(id, _) => id, | ComponentEvent::Inserted(id, _) => id, | ||||
| @@ -115,6 +108,8 @@ impl<'a> System<'a> for Ships { | |||||
| delta: global.delta * global.world_speed, | delta: global.delta * global.world_speed, | ||||
| }; | }; | ||||
| ships.set_event_emission(false); | |||||
| let data = ( | let data = ( | ||||
| positions.mask(), | positions.mask(), | ||||
| &mut ships, | &mut ships, | ||||
| @@ -127,6 +122,8 @@ impl<'a> System<'a> for Ships { | |||||
| .for_each(|(id, ship, velocity, position, fleet_owned)| { | .for_each(|(id, ship, velocity, position, fleet_owned)| { | ||||
| processor.progress_ship(id, ship, velocity, position, fleet_owned); | processor.progress_ship(id, ship, velocity, position, fleet_owned); | ||||
| }); | }); | ||||
| ships.set_event_emission(true); | |||||
| } | } | ||||
| } | } | ||||