2024-01-11 11:28:11 -08:00

99 lines
2.4 KiB
Rust

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<GxShipHandle, GxShip>,
/// Ships indexed by the system they're in.
/// A ship must always be in exactly one system.
system_ship_table: HashMap<SystemHandle, Vec<GxShipHandle>>,
/// Systems indexed by which ships they contain.
/// A ship must always be in exactly one system.
ship_system_table: HashMap<GxShipHandle, SystemHandle>,
}
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<Item = &GxShip> {
self.ships.values()
}
}