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, orbit_owned_event_id: ReaderId>, } 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::::setup(world); let mut orbit_owned = world.system_data::>(); 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); } } } } }