Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

128 righe
4.2 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, StorageHelper, StorageHelperMut},
  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. WriteStorage::<OrbitOwned>::setup(world);
  20. let orbit_ids = BitSet::new();
  21. let orbit_owned_ids = BitSet::new();
  22. let old_orbit_ids = HashMap::new();
  23. let orbit_owned_event_id = world
  24. .system_data::<WriteStorage<OrbitOwned>>()
  25. .register_event_reader();
  26. Self {
  27. orbit_ids,
  28. orbit_owned_ids,
  29. old_orbit_ids,
  30. orbit_owned_event_id,
  31. }
  32. }
  33. }
  34. #[derive(SystemData)]
  35. pub struct OrbitOwnedUpdateData<'a> {
  36. entities: Entities<'a>,
  37. orbits: WriteStorage<'a, Orbit>,
  38. player_owned: ReadStorage<'a, PlayerOwned>,
  39. orbit_owned: ReadStorage<'a, OrbitOwned>,
  40. }
  41. impl<'a> System<'a> for OrbitOwnedUpdate {
  42. type SystemData = OrbitOwnedUpdateData<'a>;
  43. fn run(&mut self, data: Self::SystemData) {
  44. let OrbitOwnedUpdateData {
  45. entities,
  46. mut orbits,
  47. player_owned,
  48. orbit_owned,
  49. } = data;
  50. self.orbit_ids.clear();
  51. self.orbit_owned_ids.clear();
  52. self.old_orbit_ids.clear();
  53. /* handle events */
  54. let events = orbit_owned.channel().read(&mut self.orbit_owned_event_id);
  55. for event in events {
  56. match event {
  57. ComponentEvent::Inserted(id, orbit_owned) => {
  58. self.orbit_ids.add(orbit_owned.owner().id());
  59. self.orbit_owned_ids.add(*id);
  60. }
  61. ComponentEvent::Modified(id, orbit_owned) => {
  62. self.orbit_ids.add(orbit_owned.owner().id());
  63. self.orbit_owned_ids.add(*id);
  64. *self
  65. .old_orbit_ids
  66. .entry(*id)
  67. .or_insert_with(|| orbit_owned.owner()) = orbit_owned.owner();
  68. }
  69. ComponentEvent::Removed(id, orbit_owned) => {
  70. self.orbit_ids.add(orbit_owned.owner().id());
  71. self.orbit_owned_ids.add(*id);
  72. *self
  73. .old_orbit_ids
  74. .entry(*id)
  75. .or_insert_with(|| orbit_owned.owner()) = orbit_owned.owner();
  76. }
  77. }
  78. }
  79. /* find new orbit ids */
  80. for (orbit_owned, _) in (&orbit_owned, &self.orbit_owned_ids).join() {
  81. self.orbit_ids.add(orbit_owned.owner().id());
  82. }
  83. /* update orbits */
  84. for (orbit_id, orbit, _) in (&entities, &mut orbits, &self.orbit_ids).join() {
  85. let data = (
  86. &entities,
  87. &orbit_owned,
  88. &player_owned,
  89. &self.orbit_owned_ids,
  90. );
  91. for (fleet_id, orbit_owned, player_owned, _) in data.join() {
  92. let new_match = orbit_id == orbit_owned.owner();
  93. let old_match = match self.old_orbit_ids.get(&fleet_id.id()) {
  94. Some(old_orbit_id) => orbit_id == *old_orbit_id,
  95. None => false,
  96. };
  97. let player_id = player_owned.owner().id() as usize;
  98. if old_match && !new_match {
  99. if let Some(fleet) = orbit.fleets_mut().get_mut(player_id) {
  100. *fleet = None;
  101. }
  102. } else if !old_match && new_match {
  103. orbit
  104. .fleets_mut()
  105. .resize_with(player_id + 1, Default::default);
  106. // TODO: merge fleets if player already have a fleet on this orbit
  107. orbit.fleets_mut()[player_id] = Some(fleet_id);
  108. }
  109. }
  110. }
  111. }
  112. }