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