@@ -21,7 +21,7 @@ Player______________ \ \ \ \ \ \ \ \ \ \ \ \ \ | |||
+--------------------+---+---+---+---+---+---+---+---+---+---+---+---+---+ | |||
| Player | 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 | | |||
| Planet | | o | x | | | | | x | x | x | | x | x | | |||
| MeetingPoint | | | x | | | | | | | x | | | x | | |||
@@ -92,7 +92,11 @@ fn create_world(world: &mut World, player_id: Entity) { | |||
.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 { | |||
let r = 325.0 + 100.0 * random::<f32>(); | |||
@@ -1,7 +1,7 @@ | |||
use specs::{saveload::MarkedBuilder, Builder, Entity, World, WorldExt}; | |||
use crate::{ | |||
components::{Fleet, MeetingPointOwned}, | |||
components::{Fleet, MeetingPointOwned, PlayerOwned}, | |||
misc::{Persistence, WorldPersistence}, | |||
}; | |||
@@ -9,28 +9,40 @@ use super::Error; | |||
#[derive(Default, Clone)] | |||
pub struct FleetBuilder { | |||
owner: Option<Entity>, | |||
player: Option<Entity>, | |||
meeting_point: Option<Entity>, | |||
} | |||
impl FleetBuilder { | |||
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 entity = world | |||
.create_entity() | |||
.marked::<<WorldPersistence as Persistence>::Marker>() | |||
.with(meeting_point_owned) | |||
.with(player_owned) | |||
.with(fleet) | |||
.build(); | |||
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 | |||
} | |||
@@ -70,6 +70,17 @@ impl MeetingPoint { | |||
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 { | |||
@@ -3,7 +3,9 @@ use specs::{Dispatcher as Inner, DispatcherBuilder, World, WorldExt}; | |||
use crate::{ | |||
components::Player, | |||
resources::Global, | |||
systems::{FleetControl, FleetOwnedUpdate, Process, ShipMovement, Ships}, | |||
systems::{ | |||
FleetControl, FleetOwnedUpdate, MeetingPointOwnedUpdate, Process, ShipMovement, Ships, | |||
}, | |||
Error, | |||
}; | |||
@@ -23,6 +25,11 @@ impl<'a, 'b> Dispatcher<'a, 'b> { | |||
.with(Ships::new(world), "ships", &[]) | |||
.with(FleetControl::new(world)?, "fleet_control", &[]) | |||
.with(FleetOwnedUpdate::new(world), "fleet_owned_update", &[]) | |||
.with( | |||
MeetingPointOwnedUpdate::new(world), | |||
"meeting_point_owned_update", | |||
&[], | |||
) | |||
.build(); | |||
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_owned_update; | |||
mod meeting_point_owned_update; | |||
mod process; | |||
mod ship_movement; | |||
mod ships; | |||
pub use fleet_control::{FleetControl, FleetControlEvent}; | |||
pub use fleet_owned_update::FleetOwnedUpdate; | |||
pub use meeting_point_owned_update::MeetingPointOwnedUpdate; | |||
pub use process::Process; | |||
pub use ship_movement::ShipMovement; | |||
pub use ships::Ships; |