|
- use std::collections::HashMap;
-
- use shrev::ReaderId;
- use space_crush_common::{
- components::{FleetOwned, PlayerOwned, Ship},
- misc::ComponentEvent,
- };
- use specs::{
- hibitset::BitSetLike, prelude::*, world::Index, Entities, ReadExpect, ReadStorage, System,
- World, WriteStorage,
- };
-
- use crate::{components::FleetInfo, resources::PlayerState};
-
- pub struct FleetInfoUpdate {
- modified: HashMap<Index, Modified>,
- need_update: BitSet,
- fleet_owned_id: ReaderId<ComponentEvent<FleetOwned>>,
- player_owned_id: ReaderId<ComponentEvent<PlayerOwned>>,
- }
-
- #[derive(Default)]
- struct Modified {
- old_fleet_id: Option<Entity>,
- old_player_id: Option<Entity>,
- }
-
- impl FleetInfoUpdate {
- pub fn new(world: &mut World) -> Self {
- let modified = HashMap::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 player_owned_id = unsafe {
- WriteStorage::<PlayerOwned>::setup(world);
-
- let mut player_owned = world.system_data::<WriteStorage<PlayerOwned>>();
- player_owned
- .unprotected_storage_mut()
- .channel_mut()
- .register_reader()
- };
-
- Self {
- modified,
- need_update,
- fleet_owned_id,
- player_owned_id,
- }
- }
- }
-
- #[derive(SystemData)]
- pub struct FleetInfoUpdateData<'a> {
- entities: Entities<'a>,
- player_state: ReadExpect<'a, PlayerState>,
- ships: ReadStorage<'a, Ship>,
- fleet_infos: WriteStorage<'a, FleetInfo>,
- fleet_owned: ReadStorage<'a, FleetOwned>,
- player_owned: ReadStorage<'a, PlayerOwned>,
- }
-
- impl<'a> System<'a> for FleetInfoUpdate {
- type SystemData = FleetInfoUpdateData<'a>;
-
- fn run(&mut self, data: Self::SystemData) {
- let FleetInfoUpdateData {
- entities,
- player_state,
- ships,
- mut fleet_infos,
- fleet_owned,
- player_owned,
- } = data;
-
- self.modified.clear();
- self.need_update.clear();
-
- /* player owned events */
- let events = player_owned
- .unprotected_storage()
- .channel()
- .read(&mut self.player_owned_id);
- for event in events {
- match event {
- ComponentEvent::Inserted(id) => {
- self.need_update.add(*id);
- }
- ComponentEvent::Modified(id, player_owned)
- | ComponentEvent::Removed(id, player_owned) => {
- self.need_update.add(*id);
- self.modified.entry(*id).or_default().old_player_id = Some(player_owned.owner);
- }
- }
- }
-
- /* fleet owned events */
- let events = fleet_owned
- .unprotected_storage()
- .channel()
- .read(&mut self.fleet_owned_id);
- for event in events {
- match event {
- ComponentEvent::Inserted(id) => {
- self.need_update.add(*id);
- }
- ComponentEvent::Modified(id, fleet_owned)
- | ComponentEvent::Removed(id, fleet_owned) => {
- self.need_update.add(*id);
- self.modified.entry(*id).or_default().old_fleet_id = Some(fleet_owned.owner);
- }
- }
- }
-
- if self.need_update.is_empty() {
- return;
- }
-
- /* update fleets */
- let player_id = player_state.player_id;
- for (fleet_id, fleet_info) in (&entities, &mut fleet_infos).join() {
- for (ship_id, ship, fleet_owned, player_owned, _) in (
- &entities,
- &ships,
- &fleet_owned,
- &player_owned,
- &self.need_update,
- )
- .join()
- {
- let new_match = fleet_owned.owner == fleet_id && player_owned.owner == player_id;
- let old_match = match self.modified.get(&ship_id.id()) {
- None => false,
- Some(modified) => match (modified.old_fleet_id, modified.old_player_id) {
- (Some(old_fleet_id), Some(old_player_id)) => {
- old_fleet_id != fleet_id && old_player_id == player_id
- }
- (Some(old_fleet_id), None) => {
- old_fleet_id != fleet_id && player_owned.owner == player_id
- }
- (None, Some(old_player_id)) => {
- fleet_owned.owner != fleet_id && old_player_id == player_id
- }
- (None, None) => false,
- },
- };
-
- if old_match && !new_match {
- fleet_info.count[ship.type_] = fleet_info.count[ship.type_].saturating_sub(1);
- } else if !old_match && new_match {
- fleet_info.count[ship.type_] += 1;
- }
- }
- }
- }
- }
|