|
- 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, StorageHelper, StorageHelperMut},
- };
-
- 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 {
- 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 = world
- .system_data::<WriteStorage<OrbitOwned>>()
- .register_event_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.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_with(|| 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_with(|| orbit_owned.owner()) = orbit_owned.owner();
- }
- }
- }
-
- /* find new orbit ids */
- for (orbit_owned, _) in (&orbit_owned, &self.orbit_owned_ids).join() {
- self.orbit_ids.add(orbit_owned.owner().id());
- }
-
- /* 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_mut().get_mut(player_id) {
- *fleet = None;
- }
- } else if !old_match && new_match {
- orbit
- .fleets_mut()
- .resize_with(player_id + 1, Default::default);
- // TODO: merge fleets if player already have a fleet on this orbit
- orbit.fleets_mut()[player_id] = Some(fleet_id);
- }
- }
- }
- }
- }
|