|
- use glc::vector::Vector2f;
- use shrev::{EventChannel, ReaderId};
- use specs::{
- prelude::*, Entities, Entity, LazyUpdate, ReadExpect, ReadStorage, System, World, WriteStorage,
- };
-
- use crate::{
- components::{
- Fleet, FleetMoving, FleetOrbiting, MeetingPoint, PlayerOwned, Position, Ship, ShipCount,
- ShipType,
- },
- misc::{LogResult, WorldHelper},
- systems::ShipControlEvent,
- Error,
- };
-
- pub struct FleetControl {
- fleet_control_event_id: ReaderId<FleetControlEvent>,
- }
-
- #[derive(Debug)]
- pub enum FleetControlEvent {
- MoveToMeetingPoint {
- fleet: Entity,
- count: ShipCount,
- target: Entity,
- },
- MoveToPosition {
- fleet: Entity,
- count: ShipCount,
- target: Vector2f,
- },
- }
-
- #[derive(SystemData)]
- pub struct FleetControlData<'a> {
- fleet_control_events: ReadExpect<'a, EventChannel<FleetControlEvent>>,
-
- lazy: Read<'a, LazyUpdate>,
- entities: Entities<'a>,
- player_owned: WriteStorage<'a, PlayerOwned>,
- ship_control: WriteExpect<'a, EventChannel<ShipControlEvent>>,
-
- fleets: WriteStorage<'a, Fleet>,
- fleets_moving: WriteStorage<'a, FleetMoving>,
- fleets_orbiting: WriteStorage<'a, FleetOrbiting>,
-
- positions: WriteStorage<'a, Position>,
- meeting_points: WriteStorage<'a, MeetingPoint>,
-
- ships: ReadStorage<'a, Ship>,
- }
-
- struct Processor<'a> {
- lazy: Read<'a, LazyUpdate>,
-
- entities: Entities<'a>,
- player_owned: WriteStorage<'a, PlayerOwned>,
- ship_control: WriteExpect<'a, EventChannel<ShipControlEvent>>,
-
- fleets: WriteStorage<'a, Fleet>,
- fleets_moving: WriteStorage<'a, FleetMoving>,
- fleets_orbiting: WriteStorage<'a, FleetOrbiting>,
-
- positions: WriteStorage<'a, Position>,
- meeting_points: WriteStorage<'a, MeetingPoint>,
-
- 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 {
- fleet_control_events,
- lazy,
- entities,
- player_owned,
- ship_control,
- fleets,
- fleets_moving,
- fleets_orbiting,
- positions,
- meeting_points,
- ships,
- } = data;
-
- let mut processor = Processor {
- lazy,
- entities,
- player_owned,
- ship_control,
- fleets,
- fleets_moving,
- fleets_orbiting,
- positions,
- meeting_points,
- ships,
- };
-
- let events = fleet_control_events.read(&mut self.fleet_control_event_id);
- for event in events {
- match event {
- FleetControlEvent::MoveToPosition {
- fleet,
- count,
- target,
- } => {
- processor.move_to_position(*fleet, *count, *target);
- }
- FleetControlEvent::MoveToMeetingPoint {
- fleet,
- count,
- target,
- } => {
- processor.move_to_meeting_point(*fleet, *count, *target);
- }
- }
- }
- }
- }
-
- impl Processor<'_> {
- fn move_to_position(&mut self, fleet: Entity, count: ShipCount, target: Vector2f) {
- let target = self.create_meeting_point(target);
-
- self.move_to_meeting_point(fleet, count, target);
- }
-
- fn move_to_meeting_point(&mut self, fleet: Entity, mut count: ShipCount, target: Entity) {
- let player_owned = self.player_owned.get(fleet).unwrap();
- let player_id = player_owned.owner();
- let target_fleet = self.create_fleet(player_id, target);
- let source_fleet = self.fleets.get(fleet).unwrap();
-
- let data = (&self.entities, source_fleet.owned(), &self.ships);
- for (id, _, ship) in data.join() {
- match ship.type_() {
- ShipType::Fighter if count.fighter > 0 => {
- count.fighter -= 1;
- }
- ShipType::Bomber if count.bomber > 0 => {
- count.bomber -= 1;
- }
- ShipType::Transporter if count.transporter > 0 => {
- count.transporter -= 1;
- }
- _ => continue,
- }
-
- let event = ShipControlEvent::SetMoving {
- ship: id,
- fleet: target_fleet,
- };
- self.ship_control.single_write(event);
- }
- }
-
- fn create_meeting_point(&mut self, pos: Vector2f) -> Entity {
- MeetingPoint::builder()
- .position(pos)
- .lazy(
- &self.lazy,
- &self.entities,
- &mut self.positions,
- &mut self.meeting_points,
- )
- .panic("Unable to create new entity: MeetingPoint")
- }
-
- fn create_fleet(&mut self, player: Entity, target: Entity) -> Entity {
- Fleet::builder()
- .player(player)
- .moving(target)
- .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")
- }
- }
|