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.

130 rivejä
4.1 KiB

  1. use std::collections::HashMap;
  2. use shrev::ReaderId;
  3. use specs::{
  4. hibitset::BitSet, prelude::*, world::Index, Entities, Entity, ReadStorage, System, World,
  5. WriteStorage,
  6. };
  7. use crate::{
  8. components::{Orbit, OrbitOwned, PlayerOwned},
  9. misc::ComponentEvent,
  10. };
  11. pub struct OrbitOwnedUpdate {
  12. orbit_ids: BitSet,
  13. orbit_owned_ids: BitSet,
  14. old_orbit_ids: HashMap<Index, Entity>,
  15. orbit_owned_event_id: ReaderId<crate::misc::ComponentEvent<OrbitOwned>>,
  16. }
  17. impl OrbitOwnedUpdate {
  18. pub fn new(world: &mut World) -> Self {
  19. let orbit_ids = BitSet::new();
  20. let orbit_owned_ids = BitSet::new();
  21. let old_orbit_ids = HashMap::new();
  22. let orbit_owned_event_id = unsafe {
  23. WriteStorage::<OrbitOwned>::setup(world);
  24. let mut orbit_owned = world.system_data::<WriteStorage<OrbitOwned>>();
  25. orbit_owned
  26. .unprotected_storage_mut()
  27. .channel_mut()
  28. .register_reader()
  29. };
  30. Self {
  31. orbit_ids,
  32. orbit_owned_ids,
  33. old_orbit_ids,
  34. orbit_owned_event_id,
  35. }
  36. }
  37. }
  38. #[derive(SystemData)]
  39. pub struct OrbitOwnedUpdateData<'a> {
  40. entities: Entities<'a>,
  41. orbits: WriteStorage<'a, Orbit>,
  42. player_owned: ReadStorage<'a, PlayerOwned>,
  43. orbit_owned: ReadStorage<'a, OrbitOwned>,
  44. }
  45. impl<'a> System<'a> for OrbitOwnedUpdate {
  46. type SystemData = OrbitOwnedUpdateData<'a>;
  47. fn run(&mut self, data: Self::SystemData) {
  48. let OrbitOwnedUpdateData {
  49. entities,
  50. mut orbits,
  51. player_owned,
  52. orbit_owned,
  53. } = data;
  54. self.orbit_ids.clear();
  55. self.orbit_owned_ids.clear();
  56. self.old_orbit_ids.clear();
  57. /* handle events */
  58. let events = orbit_owned
  59. .unprotected_storage()
  60. .channel()
  61. .read(&mut self.orbit_owned_event_id);
  62. for event in events {
  63. match event {
  64. ComponentEvent::Inserted(id, orbit_owned) => {
  65. self.orbit_ids.add(orbit_owned.owner().id());
  66. self.orbit_owned_ids.add(*id);
  67. }
  68. ComponentEvent::Modified(id, orbit_owned) => {
  69. self.orbit_ids.add(orbit_owned.owner().id());
  70. self.orbit_owned_ids.add(*id);
  71. *self
  72. .old_orbit_ids
  73. .entry(*id)
  74. .or_insert_with(|| orbit_owned.owner()) = orbit_owned.owner();
  75. }
  76. ComponentEvent::Removed(id, orbit_owned) => {
  77. self.orbit_ids.add(orbit_owned.owner().id());
  78. self.orbit_owned_ids.add(*id);
  79. *self
  80. .old_orbit_ids
  81. .entry(*id)
  82. .or_insert_with(|| orbit_owned.owner()) = orbit_owned.owner();
  83. }
  84. }
  85. }
  86. /* update orbits */
  87. for (orbit_id, orbit, _) in (&entities, &mut orbits, &self.orbit_ids).join() {
  88. let data = (
  89. &entities,
  90. &orbit_owned,
  91. &player_owned,
  92. &self.orbit_owned_ids,
  93. );
  94. for (fleet_id, orbit_owned, player_owned, _) in data.join() {
  95. let new_match = orbit_id == orbit_owned.owner();
  96. let old_match = match self.old_orbit_ids.get(&fleet_id.id()) {
  97. Some(old_orbit_id) => orbit_id == *old_orbit_id,
  98. None => false,
  99. };
  100. let player_id = player_owned.owner().id() as usize;
  101. if old_match && !new_match {
  102. if let Some(fleet) = orbit.fleets_mut().get_mut(player_id) {
  103. *fleet = None;
  104. }
  105. } else if !old_match && new_match {
  106. orbit
  107. .fleets_mut()
  108. .resize_with(player_id + 1, Default::default);
  109. orbit.fleets_mut()[player_id] = Some(fleet_id);
  110. }
  111. }
  112. }
  113. }
  114. }