| @@ -21,7 +21,7 @@ Player______________ \ \ \ \ \ \ \ \ \ \ \ \ \ | |||||
| +--------------------+---+---+---+---+---+---+---+---+---+---+---+---+---+ | +--------------------+---+---+---+---+---+---+---+---+---+---+---+---+---+ | ||||
| | Player | x | | | | | | | | | | | | x | | | Player | x | | | | | | | | | | | | x | | ||||
| | Ship | | x | x | x | x | | | | | | | | x | | | Ship | | x | x | x | x | | | | | | | | x | | ||||
| | Fleet | | | | | | x | x | | | | | | x | | |||||
| | Fleet | | x | | | | x | x | | | | | | x | | |||||
| | Asteroid | | o | x | | | | | x | x | x | x | | x | | | Asteroid | | o | x | | | | | x | x | x | x | | x | | ||||
| | Planet | | o | x | | | | | x | x | x | | x | x | | | Planet | | o | x | | | | | x | x | x | | x | x | | ||||
| | MeetingPoint | | | x | | | | | | | x | | | x | | | MeetingPoint | | | x | | | | | | | x | | | x | | ||||
| @@ -92,7 +92,11 @@ fn create_world(world: &mut World, player_id: Entity) { | |||||
| .unwrap(); | .unwrap(); | ||||
| } | } | ||||
| let fleet_id = Fleet::builder().owner(planets[1]).build(world).unwrap(); | |||||
| let fleet_id = Fleet::builder() | |||||
| .player(player_id) | |||||
| .meeting_point(planets[1]) | |||||
| .build(world) | |||||
| .unwrap(); | |||||
| for i in 0..9 { | for i in 0..9 { | ||||
| let r = 325.0 + 100.0 * random::<f32>(); | let r = 325.0 + 100.0 * random::<f32>(); | ||||
| @@ -1,7 +1,7 @@ | |||||
| use specs::{saveload::MarkedBuilder, Builder, Entity, World, WorldExt}; | use specs::{saveload::MarkedBuilder, Builder, Entity, World, WorldExt}; | ||||
| use crate::{ | use crate::{ | ||||
| components::{Fleet, MeetingPointOwned}, | |||||
| components::{Fleet, MeetingPointOwned, PlayerOwned}, | |||||
| misc::{Persistence, WorldPersistence}, | misc::{Persistence, WorldPersistence}, | ||||
| }; | }; | ||||
| @@ -9,28 +9,40 @@ use super::Error; | |||||
| #[derive(Default, Clone)] | #[derive(Default, Clone)] | ||||
| pub struct FleetBuilder { | pub struct FleetBuilder { | ||||
| owner: Option<Entity>, | |||||
| player: Option<Entity>, | |||||
| meeting_point: Option<Entity>, | |||||
| } | } | ||||
| impl FleetBuilder { | impl FleetBuilder { | ||||
| pub fn build(&self, world: &mut World) -> Result<Entity, Error> { | pub fn build(&self, world: &mut World) -> Result<Entity, Error> { | ||||
| let owner = self.owner.ok_or(Error::MissingValue("owner"))?; | |||||
| let player = self.player.ok_or(Error::MissingValue("player"))?; | |||||
| let meeting_point = self | |||||
| .meeting_point | |||||
| .ok_or(Error::MissingValue("meeting_point"))?; | |||||
| let meeting_point_owned = MeetingPointOwned::new(owner); | |||||
| let player_owned = PlayerOwned::new(player); | |||||
| let meeting_point_owned = MeetingPointOwned::new(meeting_point); | |||||
| let fleet = Fleet::new(); | let fleet = Fleet::new(); | ||||
| let entity = world | let entity = world | ||||
| .create_entity() | .create_entity() | ||||
| .marked::<<WorldPersistence as Persistence>::Marker>() | .marked::<<WorldPersistence as Persistence>::Marker>() | ||||
| .with(meeting_point_owned) | .with(meeting_point_owned) | ||||
| .with(player_owned) | |||||
| .with(fleet) | .with(fleet) | ||||
| .build(); | .build(); | ||||
| Ok(entity) | Ok(entity) | ||||
| } | } | ||||
| pub fn owner(mut self, meeting_point: Entity) -> Self { | |||||
| self.owner = Some(meeting_point); | |||||
| pub fn player(mut self, player: Entity) -> Self { | |||||
| self.player = Some(player); | |||||
| self | |||||
| } | |||||
| pub fn meeting_point(mut self, meeting_point: Entity) -> Self { | |||||
| self.meeting_point = Some(meeting_point); | |||||
| self | self | ||||
| } | } | ||||
| @@ -70,6 +70,17 @@ impl MeetingPoint { | |||||
| fleets: smallvec![], | fleets: smallvec![], | ||||
| } | } | ||||
| } | } | ||||
| pub(crate) fn add_fleet(&mut self, player: usize, fleet: Entity) { | |||||
| self.fleets.resize_with(player + 1, Default::default); | |||||
| self.fleets[player] = Some(fleet); | |||||
| } | |||||
| pub(crate) fn remove_fleet(&mut self, player: usize) { | |||||
| if let Some(fleet) = self.fleets.get_mut(player) { | |||||
| *fleet = None; | |||||
| } | |||||
| } | |||||
| } | } | ||||
| impl Component for MeetingPoint { | impl Component for MeetingPoint { | ||||
| @@ -3,7 +3,9 @@ use specs::{Dispatcher as Inner, DispatcherBuilder, World, WorldExt}; | |||||
| use crate::{ | use crate::{ | ||||
| components::Player, | components::Player, | ||||
| resources::Global, | resources::Global, | ||||
| systems::{FleetControl, FleetOwnedUpdate, Process, ShipMovement, Ships}, | |||||
| systems::{ | |||||
| FleetControl, FleetOwnedUpdate, MeetingPointOwnedUpdate, Process, ShipMovement, Ships, | |||||
| }, | |||||
| Error, | Error, | ||||
| }; | }; | ||||
| @@ -23,6 +25,11 @@ impl<'a, 'b> Dispatcher<'a, 'b> { | |||||
| .with(Ships::new(world), "ships", &[]) | .with(Ships::new(world), "ships", &[]) | ||||
| .with(FleetControl::new(world)?, "fleet_control", &[]) | .with(FleetControl::new(world)?, "fleet_control", &[]) | ||||
| .with(FleetOwnedUpdate::new(world), "fleet_owned_update", &[]) | .with(FleetOwnedUpdate::new(world), "fleet_owned_update", &[]) | ||||
| .with( | |||||
| MeetingPointOwnedUpdate::new(world), | |||||
| "meeting_point_owned_update", | |||||
| &[], | |||||
| ) | |||||
| .build(); | .build(); | ||||
| dispatcher.setup(world); | dispatcher.setup(world); | ||||
| @@ -0,0 +1,134 @@ | |||||
| use std::collections::HashMap; | |||||
| use shrev::ReaderId; | |||||
| use specs::{ | |||||
| hibitset::BitSet, prelude::*, world::Index, Entities, Entity, ReadStorage, System, World, | |||||
| WriteStorage, | |||||
| }; | |||||
| use crate::{ | |||||
| components::{MeetingPoint, MeetingPointOwned, Player, PlayerOwned}, | |||||
| continue_if_none, | |||||
| misc::{ComponentEvent, StorageHelper, StorageHelperMut}, | |||||
| }; | |||||
| pub struct MeetingPointOwnedUpdate { | |||||
| meeting_point_ids: BitSet, | |||||
| meeting_point_owned_ids: BitSet, | |||||
| old_meeting_point_ids: HashMap<Index, Entity>, | |||||
| meeting_point_owned_event_id: ReaderId<crate::misc::ComponentEvent<MeetingPointOwned>>, | |||||
| } | |||||
| #[derive(SystemData)] | |||||
| pub struct MeetingPointOwnedUpdateData<'a> { | |||||
| entities: Entities<'a>, | |||||
| players: ReadStorage<'a, Player>, | |||||
| player_owned: ReadStorage<'a, PlayerOwned>, | |||||
| meeting_point_owned: ReadStorage<'a, MeetingPointOwned>, | |||||
| meeting_points: WriteStorage<'a, MeetingPoint>, | |||||
| } | |||||
| impl MeetingPointOwnedUpdate { | |||||
| pub fn new(world: &mut World) -> Self { | |||||
| WriteStorage::<MeetingPointOwned>::setup(world); | |||||
| let meeting_point_ids = BitSet::new(); | |||||
| let meeting_point_owned_ids = BitSet::new(); | |||||
| let old_meeting_point_ids = HashMap::new(); | |||||
| let meeting_point_owned_event_id = world | |||||
| .system_data::<WriteStorage<MeetingPointOwned>>() | |||||
| .register_event_reader(); | |||||
| Self { | |||||
| meeting_point_ids, | |||||
| meeting_point_owned_ids, | |||||
| old_meeting_point_ids, | |||||
| meeting_point_owned_event_id, | |||||
| } | |||||
| } | |||||
| } | |||||
| impl<'a> System<'a> for MeetingPointOwnedUpdate { | |||||
| type SystemData = MeetingPointOwnedUpdateData<'a>; | |||||
| fn run(&mut self, data: Self::SystemData) { | |||||
| let MeetingPointOwnedUpdateData { | |||||
| entities, | |||||
| players, | |||||
| player_owned, | |||||
| meeting_point_owned, | |||||
| mut meeting_points, | |||||
| } = data; | |||||
| self.meeting_point_ids.clear(); | |||||
| self.meeting_point_owned_ids.clear(); | |||||
| self.old_meeting_point_ids.clear(); | |||||
| /* handle events */ | |||||
| let events = meeting_point_owned | |||||
| .channel() | |||||
| .read(&mut self.meeting_point_owned_event_id); | |||||
| for event in events { | |||||
| match event { | |||||
| ComponentEvent::Inserted(id, meeting_point_owned) => { | |||||
| self.meeting_point_ids.add(meeting_point_owned.owner().id()); | |||||
| self.meeting_point_owned_ids.add(*id); | |||||
| } | |||||
| ComponentEvent::Modified(id, meeting_point_owned) => { | |||||
| self.meeting_point_ids.add(meeting_point_owned.owner().id()); | |||||
| self.meeting_point_owned_ids.add(*id); | |||||
| *self | |||||
| .old_meeting_point_ids | |||||
| .entry(*id) | |||||
| .or_insert_with(|| meeting_point_owned.owner()) = | |||||
| meeting_point_owned.owner(); | |||||
| } | |||||
| ComponentEvent::Removed(id, meeting_point_owned) => { | |||||
| self.meeting_point_ids.add(meeting_point_owned.owner().id()); | |||||
| self.meeting_point_owned_ids.add(*id); | |||||
| *self | |||||
| .old_meeting_point_ids | |||||
| .entry(*id) | |||||
| .or_insert_with(|| meeting_point_owned.owner()) = | |||||
| meeting_point_owned.owner(); | |||||
| } | |||||
| } | |||||
| } | |||||
| /* find new meeting_point ids */ | |||||
| for (meeting_point_owned, _) in (&meeting_point_owned, &self.meeting_point_owned_ids).join() | |||||
| { | |||||
| self.meeting_point_ids.add(meeting_point_owned.owner().id()); | |||||
| } | |||||
| /* update meeting_points */ | |||||
| for (meeting_point_id, meeting_point, _) in | |||||
| (&entities, &mut meeting_points, &self.meeting_point_ids).join() | |||||
| { | |||||
| let data = ( | |||||
| &entities, | |||||
| &meeting_point_owned, | |||||
| &player_owned, | |||||
| &self.meeting_point_owned_ids, | |||||
| ); | |||||
| for (fleet_id, meeting_point_owned, player_owned, _) in data.join() { | |||||
| let new_match = meeting_point_id == meeting_point_owned.owner(); | |||||
| let old_match = match self.old_meeting_point_ids.get(&fleet_id.id()) { | |||||
| Some(old_meeting_point_id) => meeting_point_id == *old_meeting_point_id, | |||||
| None => false, | |||||
| }; | |||||
| let player_id = player_owned.owner(); | |||||
| let player = continue_if_none!(players.get(player_id)); | |||||
| let player_index = player.index(); | |||||
| if old_match && !new_match { | |||||
| meeting_point.remove_fleet(player_index); | |||||
| } else if !old_match && new_match { | |||||
| meeting_point.add_fleet(player_index, fleet_id); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,11 +1,13 @@ | |||||
| mod fleet_control; | mod fleet_control; | ||||
| mod fleet_owned_update; | mod fleet_owned_update; | ||||
| mod meeting_point_owned_update; | |||||
| mod process; | mod process; | ||||
| mod ship_movement; | mod ship_movement; | ||||
| mod ships; | mod ships; | ||||
| pub use fleet_control::{FleetControl, FleetControlEvent}; | pub use fleet_control::{FleetControl, FleetControlEvent}; | ||||
| pub use fleet_owned_update::FleetOwnedUpdate; | pub use fleet_owned_update::FleetOwnedUpdate; | ||||
| pub use meeting_point_owned_update::MeetingPointOwnedUpdate; | |||||
| pub use process::Process; | pub use process::Process; | ||||
| pub use ship_movement::ShipMovement; | pub use ship_movement::ShipMovement; | ||||
| pub use ships::Ships; | pub use ships::Ships; | ||||