Skip to content

Commit

Permalink
feat: Add Session commands to modify sessions from game code (#379)
Browse files Browse the repository at this point in the history
Add SessionCommands which may be inserted as shared resource. Runs after
session execution, before the "after_session" GameSystems.

One thing I don't like about this is it only works as shared resource,
if user does not insert shared resource, and tries to do ResMutInit,
they run into trouble. Not sure what the best way to avoid that is.
  • Loading branch information
MaxCWhitehead committed Apr 14, 2024
1 parent c40262a commit 8be1965
Showing 1 changed file with 30 additions and 5 deletions.
35 changes: 30 additions & 5 deletions framework_crates/bones_lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,17 @@ pub use bones_ecs as ecs;
/// Bones lib prelude
pub mod prelude {
pub use crate::{
ecs::prelude::*, instant::Instant, time::*, Game, GamePlugin, Session, SessionOptions,
SessionPlugin, SessionRunner, Sessions,
ecs::prelude::*, instant::Instant, time::*, Game, GamePlugin, Session, SessionCommand,
SessionOptions, SessionPlugin, SessionRunner, Sessions,
};
}

pub use instant;
pub mod time;

use std::{fmt::Debug, sync::Arc};
use std::{collections::VecDeque, fmt::Debug, sync::Arc};

use crate::prelude::*;

/// A bones game. This includes all of the game worlds, and systems.
#[derive(Deref, DerefMut)]
pub struct Session {
Expand Down Expand Up @@ -408,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 @@ -496,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 @@ -573,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 8be1965

Please sign in to comment.