|
- use shrev::{EventChannel, ReaderId};
- use specs::{
- prelude::*, Entities, Entity, LazyUpdate, ReadExpect, ReadStorage, System, World, WriteStorage,
- };
-
- use crate::{
- components::{
- Fleet, FleetMoving, FleetOrbiting, FleetOwned, MeetingPoint, Player, PlayerOwned,
- ShipMoving, ShipOrbiting,
- },
- misc::{LogResult, WorldHelper},
- Error,
- };
-
- pub struct ShipControl {
- ship_control_event_id: ReaderId<ShipControlEvent>,
- }
-
- #[derive(Debug)]
- pub enum ShipControlEvent {
- SetMoving { ship: Entity, fleet: Entity },
- SetOrbiting { ship: Entity, target: Entity },
- }
-
- #[derive(SystemData)]
- pub struct ShipControlData<'a> {
- ship_control_events: ReadExpect<'a, EventChannel<ShipControlEvent>>,
-
- lazy: Read<'a, LazyUpdate>,
- entities: Entities<'a>,
-
- players: ReadStorage<'a, Player>,
- player_owned: WriteStorage<'a, PlayerOwned>,
-
- fleets: WriteStorage<'a, Fleet>,
- fleets_moving: WriteStorage<'a, FleetMoving>,
- fleets_orbiting: WriteStorage<'a, FleetOrbiting>,
-
- meeting_points: WriteStorage<'a, MeetingPoint>,
-
- ships_orbiting: WriteStorage<'a, ShipOrbiting>,
- ships_moving: WriteStorage<'a, ShipMoving>,
- fleet_owned: WriteStorage<'a, FleetOwned>,
- }
-
- struct Processor<'a> {
- lazy: Read<'a, LazyUpdate>,
- entities: Entities<'a>,
-
- players: ReadStorage<'a, Player>,
- player_owned: WriteStorage<'a, PlayerOwned>,
-
- fleets: WriteStorage<'a, Fleet>,
- fleets_moving: WriteStorage<'a, FleetMoving>,
- fleets_orbiting: WriteStorage<'a, FleetOrbiting>,
-
- meeting_points: WriteStorage<'a, MeetingPoint>,
-
- ships_orbiting: WriteStorage<'a, ShipOrbiting>,
- ships_moving: WriteStorage<'a, ShipMoving>,
- fleet_owned: WriteStorage<'a, FleetOwned>,
- }
-
- impl ShipControl {
- pub fn new(world: &mut World) -> Result<Self, Error> {
- world.insert(EventChannel::<ShipControlEvent>::default());
-
- let ship_control_event_id = world.register_event_reader::<ShipControlEvent>()?;
-
- Ok(Self {
- ship_control_event_id,
- })
- }
- }
-
- impl<'a> System<'a> for ShipControl {
- type SystemData = ShipControlData<'a>;
-
- fn run(&mut self, data: Self::SystemData) {
- let ShipControlData {
- ship_control_events,
- lazy,
- entities,
- players,
- player_owned,
- fleets,
- fleets_moving,
- fleets_orbiting,
- meeting_points,
- ships_orbiting,
- ships_moving,
- fleet_owned,
- } = data;
-
- let mut processor = Processor {
- lazy,
- entities,
- players,
- player_owned,
- fleets,
- fleets_moving,
- fleets_orbiting,
- meeting_points,
- ships_orbiting,
- ships_moving,
- fleet_owned,
- };
-
- let events = ship_control_events.read(&mut self.ship_control_event_id);
- for event in events {
- match event {
- ShipControlEvent::SetMoving { ship, fleet } => processor.set_moving(*ship, *fleet),
- ShipControlEvent::SetOrbiting { ship, target } => {
- processor.set_orbiting(*ship, *target)
- }
- }
- }
- }
- }
-
- impl Processor<'_> {
- fn set_moving(&mut self, ship_id: Entity, fleet_id: Entity) {
- let fleet_owned = self.fleet_owned.get_mut(ship_id).unwrap();
- fleet_owned.set_owner(fleet_id);
-
- self.ships_orbiting.remove(ship_id);
- self.ships_moving
- .insert(ship_id, ShipMoving::new())
- .panic("Unable to create component 'ShipsMoving'");
- }
-
- fn set_orbiting(&mut self, ship_id: Entity, target_id: Entity) {
- let player_owned = self.player_owned.get(ship_id).unwrap();
- let player_id = player_owned.owner();
- let player = self.players.get(player_id).unwrap();
- let meeting_point = self.meeting_points.get_mut(target_id).unwrap();
- let fleet_id = match meeting_point.fleet(player.index()) {
- Some(fleet_id) => fleet_id,
- None => {
- let fleet_id = Fleet::builder()
- .player(player_id)
- .orbiting(target_id)
- .lazy(
- &self.lazy,
- &self.entities,
- &mut self.player_owned,
- &mut self.fleets,
- &mut self.fleets_moving,
- &mut self.fleets_orbiting,
- )
- .panic("Unable to create new entitiy: Fleet");
- meeting_point.add_fleet(player.index(), fleet_id);
-
- fleet_id
- }
- };
-
- let fleet_owned = self.fleet_owned.get_mut(ship_id).unwrap();
- fleet_owned.set_owner(fleet_id);
-
- self.ships_moving.remove(ship_id);
- self.ships_orbiting
- .insert(ship_id, ShipOrbiting::new())
- .panic("Unable to create component 'ShipOrbiting'");
- }
- }
|