You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
3.6 KiB

  1. use std::collections::HashMap;
  2. use shrev::ReaderId;
  3. use specs::{prelude::*, world::Index, Entities, ReadStorage, System, World, WriteStorage};
  4. use crate::{
  5. components::{Fleet, FleetOwned, Ship},
  6. misc::ComponentEvent,
  7. };
  8. pub struct FleetOwnedUpdate {
  9. fleet_ids: BitSet,
  10. fleet_owned_ids: BitSet,
  11. old_fleet_ids: HashMap<Index, Entity>,
  12. fleet_owned_event_id: ReaderId<ComponentEvent<FleetOwned>>,
  13. }
  14. impl FleetOwnedUpdate {
  15. pub fn new(world: &mut World) -> Self {
  16. let fleet_ids = BitSet::new();
  17. let fleet_owned_ids = BitSet::new();
  18. let old_fleet_ids = HashMap::new();
  19. let fleet_owned_event_id = unsafe {
  20. WriteStorage::<FleetOwned>::setup(world);
  21. let mut fleet_owned = world.system_data::<WriteStorage<FleetOwned>>();
  22. fleet_owned
  23. .unprotected_storage_mut()
  24. .channel_mut()
  25. .register_reader()
  26. };
  27. Self {
  28. fleet_ids,
  29. fleet_owned_ids,
  30. old_fleet_ids,
  31. fleet_owned_event_id,
  32. }
  33. }
  34. }
  35. #[derive(SystemData)]
  36. pub struct FleetOwnedUpdateData<'a> {
  37. entities: Entities<'a>,
  38. ships: ReadStorage<'a, Ship>,
  39. fleets: WriteStorage<'a, Fleet>,
  40. fleet_owned: ReadStorage<'a, FleetOwned>,
  41. }
  42. impl<'a> System<'a> for FleetOwnedUpdate {
  43. type SystemData = FleetOwnedUpdateData<'a>;
  44. fn run(&mut self, data: Self::SystemData) {
  45. let FleetOwnedUpdateData {
  46. entities,
  47. ships,
  48. mut fleets,
  49. fleet_owned,
  50. } = data;
  51. self.fleet_ids.clear();
  52. self.fleet_owned_ids.clear();
  53. self.old_fleet_ids.clear();
  54. /* handle events */
  55. let events = fleet_owned
  56. .unprotected_storage()
  57. .channel()
  58. .read(&mut self.fleet_owned_event_id);
  59. for event in events {
  60. match event {
  61. ComponentEvent::Inserted(id, fleet_owned) => {
  62. self.fleet_ids.add(fleet_owned.owner.id());
  63. self.fleet_owned_ids.add(*id);
  64. }
  65. ComponentEvent::Modified(id, fleet_owned) => {
  66. self.fleet_ids.add(fleet_owned.owner.id());
  67. self.fleet_owned_ids.add(*id);
  68. *self.old_fleet_ids.entry(*id).or_insert(fleet_owned.owner) = fleet_owned.owner;
  69. }
  70. ComponentEvent::Removed(id, fleet_owned) => {
  71. self.fleet_ids.add(fleet_owned.owner.id());
  72. self.fleet_owned_ids.add(*id);
  73. *self.old_fleet_ids.entry(*id).or_insert(fleet_owned.owner) = fleet_owned.owner;
  74. }
  75. }
  76. }
  77. /* update fleets */
  78. for (fleet_id, fleet_info, _) in (&entities, &mut fleets, &self.fleet_ids).join() {
  79. let data = (&entities, &ships, &fleet_owned, &self.fleet_owned_ids);
  80. for (ship_id, ship, fleet_owned, _) in data.join() {
  81. let new_match = fleet_id == fleet_owned.owner;
  82. let old_match = match self.old_fleet_ids.get(&ship_id.id()) {
  83. Some(old_fleet_id) => fleet_id == *old_fleet_id,
  84. None => false,
  85. };
  86. if old_match && !new_match {
  87. fleet_info.owned.remove(ship_id.id());
  88. fleet_info.count[ship.type_] = fleet_info.count[ship.type_].saturating_sub(1);
  89. } else if !old_match && new_match {
  90. fleet_info.owned.add(ship_id.id());
  91. fleet_info.count[ship.type_] += 1;
  92. }
  93. }
  94. }
  95. }
  96. }