Skip to content

Commit

Permalink
fix: Move session commands into Sessions.
Browse files Browse the repository at this point in the history
  • Loading branch information
MaxCWhitehead committed Apr 14, 2024
1 parent 4160c9f commit e8fd8cb
Showing 1 changed file with 28 additions and 27 deletions.
55 changes: 28 additions & 27 deletions framework_crates/bones_lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub use bones_ecs as ecs;
/// Bones lib prelude
pub mod prelude {
pub use crate::{
ecs::prelude::*, instant::Instant, time::*, Game, GamePlugin, Session, SessionCommands,
ecs::prelude::*, instant::Instant, time::*, Game, GamePlugin, Session, SessionCommand,
SessionOptions, SessionPlugin, SessionRunner, Sessions,
};
}
Expand All @@ -22,19 +22,6 @@ pub mod time;
use std::{collections::VecDeque, fmt::Debug, sync::Arc};

use crate::prelude::*;

/// Commands that operate on [`Sessions`], called after all sessions update.
/// These may be used to add/delete/modify sessions.
///
/// `SessionCommands` must be installed as a shared resource to take effect.
/// This may be achieved while installing a [`GamePlugin`].
///
/// `SessionCommands` is useful in a situation where you want to remove / recreate
/// a session from within it's own system. You cannot do this while the `Session` is running
#[derive(HasSchema, Default, Deref, DerefMut)]
#[schema(no_clone)]
pub struct SessionCommands(VecDeque<Box<dyn FnOnce(&mut Sessions) + Sync + Send>>);

/// A bones game. This includes all of the game worlds, and systems.
#[derive(Deref, DerefMut)]
pub struct Session {
Expand Down Expand Up @@ -412,18 +399,6 @@ impl Game {
self.sessions.map.insert(session_name, current_session);
}

// Extract `SessionCommands` from optional shared resource
// (Swap to avoid double borrow of self)
let mut session_commands = SessionCommands::default();
if let Some(mut new_commands) = self.shared_resource_mut::<SessionCommands>() {
std::mem::swap(&mut session_commands.0, &mut new_commands.0);
}

// Execute Session Commands
for command in session_commands.0.drain(..) {
command(&mut self.sessions);
}

// Run any after session game systems
if let Some(systems) = game_systems.after_session.get_mut(&session_name) {
for system in systems {
Expand All @@ -432,6 +407,15 @@ impl Game {
}
}

// Execute Session Commands
{
let mut session_commands: VecDeque<Box<SessionCommand>> = default();
std::mem::swap(&mut session_commands, &mut self.sessions.commands);
for command in session_commands.drain(..) {
command(&mut self.sessions);
}
}

// Run after systems
for system in &mut game_systems.after {
system(self)
Expand Down Expand Up @@ -520,12 +504,24 @@ impl GameSystems {
}
}

/// Type of session command
pub type SessionCommand = dyn FnOnce(&mut Sessions) + Sync + Send;

/// Container for multiple game sessions.
///
/// Each session shares the same [`Entities`].
#[derive(HasSchema, Default, Debug)]
#[derive(HasSchema, Default)]
pub struct Sessions {
map: UstrMap<Session>,

/// Commands that operate on [`Sessions`], called after all sessions update.
/// These may be used to add/delete/modify sessions.
///
/// Commands are useful in a situation where you want to remove / recreate
/// a session from within it's own system. You cannot do this while the `Session` is running.
///
/// Commands added inside a session command will not be executed until next frame.
commands: VecDeque<Box<SessionCommand>>,
}

/// Resource that allows you to configure the current session.
Expand Down Expand Up @@ -597,6 +593,11 @@ impl Sessions {
pub fn iter(&self) -> std::collections::hash_map::Iter<Ustr, Session> {
self.map.iter()
}

/// Add a [`SessionCommand`] to queue.
pub fn add_command(&mut self, command: Box<SessionCommand>) {
self.commands.push_back(command);
}
}

// We implement `Clone` so that the world can still be snapshot with this resouce in it, but we
Expand Down

0 comments on commit e8fd8cb

Please sign in to comment.