use super::*;
use crate::world::World;
#[derive(Debug, Default)]
pub struct Universe {
worlds: Option<HashMap<String, World>>,
world_tasks: Option<Vec<Result<World, JoinError>>>,
}
impl Universe {
pub fn new() -> Self {
Self {
worlds: Some(HashMap::new()),
world_tasks: None,
}
}
pub fn add_world(&mut self, world: World) {
if let Some(worlds) = self.worlds.as_mut() {
worlds.insert(world.id.clone(), world);
}
}
pub async fn run_worlds(&mut self) -> Result<(), ArbiterEngineError> {
if self.is_online() {
return Err(ArbiterEngineError::UniverseError(
"Universe is already running.".to_owned(),
));
}
let mut tasks = Vec::new();
for (_, mut world) in self.worlds.take().unwrap().drain() {
tasks.push(spawn(async move {
world.run().await.unwrap();
world
}));
}
self.world_tasks = Some(join_all(tasks.into_iter()).await);
Ok(())
}
pub fn is_online(&self) -> bool {
self.world_tasks.is_some()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn run_universe() {
let mut universe = Universe::new();
let world = World::new("test");
universe.add_world(world);
universe.run_worlds().await.unwrap();
universe.world_tasks.unwrap().remove(0).unwrap();
}
#[tokio::test]
#[should_panic(expected = "Universe is already running.")]
async fn cant_run_twice() {
let mut universe = Universe::new();
let world1 = World::new("test");
universe.add_world(world1);
universe.run_worlds().await.unwrap();
universe.run_worlds().await.unwrap();
}
}