use std::collections::HashMap; use crate::{handles::GxShipHandle, ship::GxShip, ship::ShipPersonality}; use galactica_content::{Content, FactionHandle, ShipHandle, SystemHandle}; /// Keeps track of all objects in the galaxy. /// This struct does NO physics, it keeps track of data exclusively. #[derive(Debug, Clone)] pub struct Galaxy { /// Universal counter. /// Used to create unique handles for game objects. index: u64, /// All ships in the galaxy ships: HashMap, /// Ships indexed by the system they're in. /// A ship must always be in exactly one system. system_ship_table: HashMap>, /// Systems indexed by which ships they contain. /// A ship must always be in exactly one system. ship_system_table: HashMap, } impl Galaxy { pub fn new(ct: &Content) -> Self { Self { system_ship_table: ct.iter_systems().map(|s| (s, Vec::new())).collect(), ship_system_table: HashMap::new(), index: 0, ships: HashMap::new(), } } /// Spawn a ship pub fn create_ship( &mut self, ct: &Content, ship: ShipHandle, faction: FactionHandle, personality: ShipPersonality, system: &SystemHandle, ) -> GxShipHandle { let handle = GxShipHandle { index: self.index, content: ship, }; self.index += 1; self.ships .insert(handle, GxShip::new(ct, handle, ship, faction, personality)); self.system_ship_table.get_mut(system).unwrap().push(handle); self.ship_system_table.insert(handle, *system); return handle; } pub fn step(&mut self, t: f32) { // TODO: don't allocate on step, need a better // way to satisfy the borrow checker. // Same needs to be done in the `systemsim` crate. let mut to_remove = Vec::new(); for (_, s) in &mut self.ships { s.step(t); if s.is_dead() { to_remove.push(s.get_handle()); } } // Remove dead ships // No fancy animation here, that's handled by the physics system. for i in to_remove { let system = self.ship_system_table.remove(&i).unwrap(); self.system_ship_table .get_mut(&system) .unwrap() .retain(|x| *x != i); self.ships.remove(&i); } } } // Public getters impl Galaxy { pub fn get_ship(&self, handle: GxShipHandle) -> Option<&GxShip> { self.ships.get(&handle) } pub fn get_ship_mut(&mut self, handle: GxShipHandle) -> Option<&mut GxShip> { self.ships.get_mut(&handle) } pub fn iter_ships(&self) -> impl Iterator { self.ships.values() } }