Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

120 linhas
4.0 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, FleetMoving, FleetOwned, Ship},
  6. misc::{ComponentEvent, LogResult, 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. fleets_moving: ReadStorage<'a, FleetMoving>,
  37. fleet_owned: ReadStorage<'a, FleetOwned>,
  38. }
  39. impl<'a> System<'a> for FleetOwnedUpdate {
  40. type SystemData = FleetOwnedUpdateData<'a>;
  41. fn run(&mut self, data: Self::SystemData) {
  42. let FleetOwnedUpdateData {
  43. entities,
  44. ships,
  45. mut fleets,
  46. fleets_moving,
  47. fleet_owned,
  48. } = data;
  49. self.fleet_ids.clear();
  50. self.fleet_owned_ids.clear();
  51. self.old_fleet_ids.clear();
  52. /* handle events */
  53. let events = fleet_owned.channel().read(&mut self.fleet_owned_event_id);
  54. for event in events {
  55. match event {
  56. ComponentEvent::Inserted(id, fleet_owned) => {
  57. self.fleet_ids.add(fleet_owned.owner().id());
  58. self.fleet_owned_ids.add(*id);
  59. }
  60. ComponentEvent::Modified(id, fleet_owned) => {
  61. self.fleet_ids.add(fleet_owned.owner().id());
  62. self.fleet_owned_ids.add(*id);
  63. *self
  64. .old_fleet_ids
  65. .entry(*id)
  66. .or_insert_with(|| fleet_owned.owner()) = fleet_owned.owner();
  67. }
  68. ComponentEvent::Removed(id, fleet_owned) => {
  69. self.fleet_ids.add(fleet_owned.owner().id());
  70. self.fleet_owned_ids.add(*id);
  71. *self
  72. .old_fleet_ids
  73. .entry(*id)
  74. .or_insert_with(|| fleet_owned.owner()) = fleet_owned.owner();
  75. }
  76. }
  77. }
  78. /* find new fleet ids */
  79. for (fleet_owned, _) in (&fleet_owned, &self.fleet_owned_ids).join() {
  80. self.fleet_ids.add(fleet_owned.owner().id());
  81. }
  82. /* update fleets */
  83. for (fleet_id, fleet, _) in (&entities, &mut fleets, &self.fleet_ids).join() {
  84. let data = (&entities, &ships, &fleet_owned, &self.fleet_owned_ids);
  85. for (ship_id, ship, fleet_owned, _) in data.join() {
  86. let new_match = fleet_id == fleet_owned.owner();
  87. let old_match = match self.old_fleet_ids.get(&ship_id.id()) {
  88. Some(old_fleet_id) => fleet_id == *old_fleet_id,
  89. None => false,
  90. };
  91. if old_match && !new_match {
  92. fleet.remove_ship(ship_id, ship);
  93. if fleet.is_empty() && fleets_moving.contains(fleet_id) {
  94. entities
  95. .delete(fleet_id)
  96. .panic("Unable to delete entity for moving fleet!");
  97. }
  98. } else if !old_match && new_match {
  99. fleet.add_ship(ship_id, ship);
  100. }
  101. }
  102. }
  103. }
  104. }