|
- use std::collections::HashMap;
-
- use shrev::ReaderId;
- use specs::{
- hibitset::BitSet, prelude::*, world::Index, Entities, Entity, ReadStorage, System, World,
- WriteStorage,
- };
-
- use crate::{
- components::{Orbit, OrbitOwned, PlayerOwned},
- misc::ComponentEvent,
- };
-
- pub struct OrbitOwnedUpdate {
- orbit_ids: BitSet,
- orbit_owned_ids: BitSet,
- old_orbit_ids: HashMap<Index, Entity>,
- orbit_owned_event_id: ReaderId<crate::misc::ComponentEvent<OrbitOwned>>,
- }
-
- impl OrbitOwnedUpdate {
- pub fn new(world: &mut World) -> Self {
- 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()
- };
-
- Self {
- orbit_ids,
- orbit_owned_ids,
- old_orbit_ids,
- orbit_owned_event_id,
- }
- }
- }
-
- #[derive(SystemData)]
- pub struct OrbitOwnedUpdateData<'a> {
- entities: Entities<'a>,
- orbits: WriteStorage<'a, Orbit>,
- player_owned: ReadStorage<'a, PlayerOwned>,
- orbit_owned: ReadStorage<'a, OrbitOwned>,
- }
-
- impl<'a> System<'a> for OrbitOwnedUpdate {
- type SystemData = OrbitOwnedUpdateData<'a>;
-
- fn run(&mut self, data: Self::SystemData) {
- let OrbitOwnedUpdateData {
- entities,
- mut orbits,
- player_owned,
- orbit_owned,
- } = data;
-
- self.orbit_ids.clear();
- self.orbit_owned_ids.clear();
- self.old_orbit_ids.clear();
-
- /* handle events */
- let events = orbit_owned
- .unprotected_storage()
- .channel()
- .read(&mut self.orbit_owned_event_id);
- for event in events {
- match event {
- ComponentEvent::Inserted(id, orbit_owned) => {
- self.orbit_ids.add(orbit_owned.owner.id());
- self.orbit_owned_ids.add(*id);
- }
- ComponentEvent::Modified(id, orbit_owned) => {
- self.orbit_ids.add(orbit_owned.owner.id());
- self.orbit_owned_ids.add(*id);
- *self.old_orbit_ids.entry(*id).or_insert(orbit_owned.owner) = orbit_owned.owner;
- }
- ComponentEvent::Removed(id, orbit_owned) => {
- self.orbit_ids.add(orbit_owned.owner.id());
- self.orbit_owned_ids.add(*id);
- *self.old_orbit_ids.entry(*id).or_insert(orbit_owned.owner) = orbit_owned.owner;
- }
- }
- }
-
- /* update orbits */
- for (orbit_id, orbit, _) in (&entities, &mut orbits, &self.orbit_ids).join() {
- let data = (
- &entities,
- &orbit_owned,
- &player_owned,
- &self.orbit_owned_ids,
- );
-
- for (fleet_id, orbit_owned, player_owned, _) in data.join() {
- let new_match = orbit_id == orbit_owned.owner;
- let old_match = match self.old_orbit_ids.get(&fleet_id.id()) {
- Some(old_orbit_id) => orbit_id == *old_orbit_id,
- None => false,
- };
-
- let player_id = player_owned.owner.id() as usize;
- if old_match && !new_match {
- if let Some(fleet) = orbit.fleets.get_mut(player_id) {
- *fleet = None;
- }
- } else if !old_match && new_match {
- orbit.fleets.resize_with(player_id + 1, Default::default);
- orbit.fleets[player_id] = Some(fleet_id);
- }
- }
- }
- }
- }
|