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.

122 lines
3.8 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.old_orbit_ids.entry(*id).or_insert(orbit_owned.owner) = orbit_owned.owner;
  72. }
  73. ComponentEvent::Removed(id, orbit_owned) => {
  74. self.orbit_ids.add(orbit_owned.owner.id());
  75. self.orbit_owned_ids.add(*id);
  76. *self.old_orbit_ids.entry(*id).or_insert(orbit_owned.owner) = orbit_owned.owner;
  77. }
  78. }
  79. }
  80. /* update orbits */
  81. for (orbit_id, orbit, _) in (&entities, &mut orbits, &self.orbit_ids).join() {
  82. let data = (
  83. &entities,
  84. &orbit_owned,
  85. &player_owned,
  86. &self.orbit_owned_ids,
  87. );
  88. for (fleet_id, orbit_owned, player_owned, _) in data.join() {
  89. let new_match = orbit_id == orbit_owned.owner;
  90. let old_match = match self.old_orbit_ids.get(&fleet_id.id()) {
  91. Some(old_orbit_id) => orbit_id == *old_orbit_id,
  92. None => false,
  93. };
  94. let player_id = player_owned.owner.id() as usize;
  95. if old_match && !new_match {
  96. if let Some(fleet) = orbit.fleets.get_mut(player_id) {
  97. *fleet = None;
  98. }
  99. } else if !old_match && new_match {
  100. orbit.fleets.resize_with(player_id + 1, Default::default);
  101. orbit.fleets[player_id] = Some(fleet_id);
  102. }
  103. }
  104. }
  105. }
  106. }