Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

137 wiersze
4.6 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::{FleetOrbiting, MeetingPoint, Player, PlayerOwned},
  9. misc::{ComponentEvent, StorageHelper, StorageHelperMut},
  10. };
  11. pub struct FleetOrbitingUpdate {
  12. meeting_point_ids: BitSet,
  13. fleet_orbiting_ids: BitSet,
  14. old_meeting_point_ids: HashMap<Index, Entity>,
  15. fleet_orbiting_event_id: ReaderId<crate::misc::ComponentEvent<FleetOrbiting>>,
  16. }
  17. #[derive(SystemData)]
  18. pub struct FleetOrbitingUpdateData<'a> {
  19. entities: Entities<'a>,
  20. players: ReadStorage<'a, Player>,
  21. player_owned: ReadStorage<'a, PlayerOwned>,
  22. fleet_orbiting: ReadStorage<'a, FleetOrbiting>,
  23. meeting_points: WriteStorage<'a, MeetingPoint>,
  24. }
  25. impl FleetOrbitingUpdate {
  26. pub fn new(world: &mut World) -> Self {
  27. WriteStorage::<FleetOrbiting>::setup(world);
  28. let meeting_point_ids = BitSet::new();
  29. let fleet_orbiting_ids = BitSet::new();
  30. let old_meeting_point_ids = HashMap::new();
  31. let fleet_orbiting_event_id = world
  32. .system_data::<WriteStorage<FleetOrbiting>>()
  33. .register_event_reader();
  34. Self {
  35. meeting_point_ids,
  36. fleet_orbiting_ids,
  37. old_meeting_point_ids,
  38. fleet_orbiting_event_id,
  39. }
  40. }
  41. }
  42. impl<'a> System<'a> for FleetOrbitingUpdate {
  43. type SystemData = FleetOrbitingUpdateData<'a>;
  44. fn run(&mut self, data: Self::SystemData) {
  45. let FleetOrbitingUpdateData {
  46. entities,
  47. players,
  48. player_owned,
  49. fleet_orbiting,
  50. mut meeting_points,
  51. } = data;
  52. self.meeting_point_ids.clear();
  53. self.fleet_orbiting_ids.clear();
  54. self.old_meeting_point_ids.clear();
  55. /* handle events */
  56. let events = fleet_orbiting
  57. .channel()
  58. .read(&mut self.fleet_orbiting_event_id);
  59. for event in events {
  60. match event {
  61. ComponentEvent::Inserted(id, fleet_orbiting) => {
  62. self.meeting_point_ids
  63. .add(fleet_orbiting.meeting_point().id());
  64. self.fleet_orbiting_ids.add(*id);
  65. }
  66. ComponentEvent::Modified(id, fleet_orbiting) => {
  67. self.meeting_point_ids
  68. .add(fleet_orbiting.meeting_point().id());
  69. self.fleet_orbiting_ids.add(*id);
  70. *self
  71. .old_meeting_point_ids
  72. .entry(*id)
  73. .or_insert_with(|| fleet_orbiting.meeting_point()) =
  74. fleet_orbiting.meeting_point();
  75. }
  76. ComponentEvent::Removed(id, fleet_orbiting) => {
  77. self.meeting_point_ids
  78. .add(fleet_orbiting.meeting_point().id());
  79. self.fleet_orbiting_ids.add(*id);
  80. *self
  81. .old_meeting_point_ids
  82. .entry(*id)
  83. .or_insert_with(|| fleet_orbiting.meeting_point()) =
  84. fleet_orbiting.meeting_point();
  85. }
  86. }
  87. }
  88. /* find new meeting_point ids */
  89. for (fleet_orbiting, _) in (&fleet_orbiting, &self.fleet_orbiting_ids).join() {
  90. self.meeting_point_ids
  91. .add(fleet_orbiting.meeting_point().id());
  92. }
  93. /* update meeting_points */
  94. for (meeting_point_id, meeting_point, _) in
  95. (&entities, &mut meeting_points, &self.meeting_point_ids).join()
  96. {
  97. let data = (
  98. &entities,
  99. &fleet_orbiting,
  100. &player_owned,
  101. &self.fleet_orbiting_ids,
  102. );
  103. for (fleet_id, fleet_orbiting, player_owned, _) in data.join() {
  104. let new_match = meeting_point_id == fleet_orbiting.meeting_point();
  105. let old_match = match self.old_meeting_point_ids.get(&fleet_id.id()) {
  106. Some(old_meeting_point_id) => meeting_point_id == *old_meeting_point_id,
  107. None => false,
  108. };
  109. let player_id = player_owned.owner();
  110. let player = players.get(player_id).unwrap();
  111. let player_index = player.index();
  112. if old_match && !new_match {
  113. meeting_point.remove_fleet(player_index);
  114. } else if !old_match && new_match {
  115. meeting_point.add_fleet(player_index, fleet_id);
  116. }
  117. }
  118. }
  119. }
  120. }