@@ -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); | |||||
} | } | ||||
} | } | ||||