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.

121 lines
3.9 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, StorageHelper, StorageHelperMut},
  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. WriteStorage::<FleetOwned>::setup(world);
  17. let fleet_ids = BitSet::new();
  18. let fleet_owned_ids = BitSet::new();
  19. let old_fleet_ids = HashMap::new();
  20. let fleet_owned_event_id = world
  21. .system_data::<WriteStorage<FleetOwned>>()
  22. .register_event_reader();
  23. Self {
  24. fleet_ids,
  25. fleet_owned_ids,
  26. old_fleet_ids,
  27. fleet_owned_event_id,
  28. }
  29. }
  30. }
  31. #[derive(SystemData)]
  32. pub struct FleetOwnedUpdateData<'a> {
  33. entities: Entities<'a>,
  34. ships: ReadStorage<'a, Ship>,
  35. fleets: WriteStorage<'a, Fleet>,
  36. fleet_owned: ReadStorage<'a, FleetOwned>,
  37. }
  38. impl<'a> System<'a> for FleetOwnedUpdate {
  39. type SystemData = FleetOwnedUpdateData<'a>;
  40. fn run(&mut self, data: Self::SystemData) {
  41. let FleetOwnedUpdateData {
  42. entities,
  43. ships,
  44. mut fleets,
  45. fleet_owned,
  46. } = data;
  47. self.fleet_ids.clear();
  48. self.fleet_owned_ids.clear();
  49. self.old_fleet_ids.clear();
  50. /* handle events */
  51. let events = fleet_owned.channel().read(&mut self.fleet_owned_event_id);
  52. for event in events {
  53. match event {
  54. ComponentEvent::Inserted(id, fleet_owned) => {
  55. self.fleet_ids.add(fleet_owned.owner().id());
  56. self.fleet_owned_ids.add(*id);
  57. }
  58. ComponentEvent::Modified(id, fleet_owned) => {
  59. self.fleet_ids.add(fleet_owned.owner().id());
  60. self.fleet_owned_ids.add(*id);
  61. *self
  62. .old_fleet_ids
  63. .entry(*id)
  64. .or_insert_with(|| fleet_owned.owner()) = fleet_owned.owner();
  65. }
  66. ComponentEvent::Removed(id, fleet_owned) => {
  67. self.fleet_ids.add(fleet_owned.owner().id());
  68. self.fleet_owned_ids.add(*id);
  69. *self
  70. .old_fleet_ids
  71. .entry(*id)
  72. .or_insert_with(|| fleet_owned.owner()) = fleet_owned.owner();
  73. }
  74. }
  75. }
  76. /* find new fleet ids */
  77. for (fleet_owned, _) in (&fleet_owned, &self.fleet_owned_ids).join() {
  78. self.fleet_ids.add(fleet_owned.owner().id());
  79. }
  80. /* update fleets */
  81. for (fleet_id, fleet, _) in (&entities, &mut fleets, &self.fleet_ids).join() {
  82. let data = (&entities, &ships, &fleet_owned, &self.fleet_owned_ids);
  83. for (ship_id, ship, fleet_owned, _) in data.join() {
  84. let new_match = fleet_id == fleet_owned.owner();
  85. let old_match = match self.old_fleet_ids.get(&ship_id.id()) {
  86. Some(old_fleet_id) => fleet_id == *old_fleet_id,
  87. None => false,
  88. };
  89. if old_match && !new_match {
  90. let count = fleet.count_mut();
  91. let count = &mut count[ship.type_()];
  92. *count = count.saturating_sub(1);
  93. fleet.owned_mut().remove(ship_id.id());
  94. } else if !old_match && new_match {
  95. let count = fleet.count_mut();
  96. let count = &mut count[ship.type_()];
  97. *count += 1;
  98. fleet.owned_mut().add(ship_id.id());
  99. }
  100. }
  101. }
  102. }
  103. }