|
- use shrev::{EventChannel, ReaderId};
- use specs::{
- prelude::*, saveload::MarkedBuilder, Entities, Entity, LazyUpdate, ReadExpect, ReadStorage,
- System, World, WriteStorage,
- };
-
- use crate::{
- components::{
- Fleet, FleetOwned, Orbit, OrbitOwned, Player, PlayerOwned, Ship, ShipCount, ShipType,
- },
- continue_if_none,
- misc::{LogResult, PersistWorld, Persistence, WorldHelper},
- Error,
- };
-
- pub struct FleetControl {
- fleet_control_event_id: ReaderId<FleetControlEvent>,
- }
-
- #[derive(Debug)]
- pub enum FleetControlEvent {
- Move(MoveArgs),
- }
-
- #[derive(Debug)]
- pub struct MoveArgs {
- player: Entity,
- target: Entity,
- fleet: Entity,
- count: ShipCount,
- }
-
- #[derive(SystemData)]
- pub struct FleetControlData<'a> {
- lazy: Read<'a, LazyUpdate>,
- entities: Entities<'a>,
- fleet_control_events: ReadExpect<'a, EventChannel<FleetControlEvent>>,
- player_owned: WriteStorage<'a, PlayerOwned>,
- orbit_owned: WriteStorage<'a, OrbitOwned>,
- fleet_owned: WriteStorage<'a, FleetOwned>,
- orbits: WriteStorage<'a, Orbit>,
- fleets: WriteStorage<'a, Fleet>,
- players: ReadStorage<'a, Player>,
- ships: ReadStorage<'a, Ship>,
- }
-
- impl FleetControl {
- pub fn new(world: &mut World) -> Result<Self, Error> {
- world.insert(EventChannel::<FleetControlEvent>::default());
-
- let fleet_control_event_id = world.register_event_reader::<FleetControlEvent>()?;
-
- Ok(Self {
- fleet_control_event_id,
- })
- }
- }
-
- impl<'a> System<'a> for FleetControl {
- type SystemData = FleetControlData<'a>;
-
- fn run(&mut self, data: Self::SystemData) {
- let FleetControlData {
- lazy,
- entities,
- fleet_control_events,
- mut player_owned,
- mut orbit_owned,
- mut fleet_owned,
- mut orbits,
- mut fleets,
- players,
- ships,
- } = data;
-
- let events = fleet_control_events.read(&mut self.fleet_control_event_id);
- for event in events {
- match event {
- FleetControlEvent::Move(args) if args.count.is_all() => {
- let orbit_owned = continue_if_none!(orbit_owned.get_mut(args.fleet));
- orbit_owned.set_owner(args.target);
- }
- FleetControlEvent::Move(args) => {
- let target_orbit = continue_if_none!(orbits.get_mut(args.target));
- let player = continue_if_none!(players.get(args.player));
- let mut count = args.count;
-
- let target_fleet = match target_orbit.fleet_mut(player.index()) {
- Some(fleet) => *fleet,
- f @ None => {
- let fleet = lazy
- .create_entity(&entities)
- .marked::<<PersistWorld as Persistence>::Marker>()
- .build();
-
- player_owned
- .insert(fleet, PlayerOwned::new(args.player))
- .error("Unable to insert component: PlayerOwned");
- orbit_owned
- .insert(fleet, OrbitOwned::new(args.target))
- .error("Unable to insert component: OrbitOwned");
- fleets
- .insert(fleet, Fleet::default())
- .error("Unable to insert component: Fleet");
-
- *f = Some(fleet);
-
- fleet
- }
- };
-
- let source_fleet = continue_if_none!(fleets.get(args.fleet));
- let data = (&mut fleet_owned, &ships, source_fleet.owned());
- for (fleet_owned, ship, _) in data.join() {
- match ship.type_() {
- ShipType::Fighter if count.fighter > 0 => {
- count.fighter -= 1;
- fleet_owned.set_owner(target_fleet);
- }
- ShipType::Bomber if count.bomber > 0 => {
- count.bomber -= 1;
- fleet_owned.set_owner(target_fleet);
- }
- ShipType::Transporter if count.transporter > 0 => {
- count.transporter -= 1;
- fleet_owned.set_owner(target_fleet);
- }
- _ => (),
- }
- }
- }
- }
- }
- }
- }
-
- impl FleetControlEvent {
- pub fn move_(player: Entity, target: Entity, fleet: Entity, count: ShipCount) -> Self {
- Self::Move(MoveArgs {
- player,
- target,
- fleet,
- count,
- })
- }
- }
|