use crate::ids::GroupId;
use crate::world::World;
use std::collections::HashMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum Phase {
AdvanceTransient,
Dispatch,
Movement,
Doors,
Loading,
Reposition,
AdvanceQueue,
Metrics,
}
pub(crate) type PhaseHook = Box<dyn Fn(&mut World) + Send + Sync>;
#[derive(Default)]
pub(crate) struct PhaseHooks {
before: HashMap<Phase, Vec<PhaseHook>>,
after: HashMap<Phase, Vec<PhaseHook>>,
before_group: HashMap<(Phase, GroupId), Vec<PhaseHook>>,
after_group: HashMap<(Phase, GroupId), Vec<PhaseHook>>,
}
impl PhaseHooks {
pub(crate) fn run_before(&self, phase: Phase, world: &mut World) {
if let Some(hooks) = self.before.get(&phase) {
for hook in hooks {
hook(world);
}
}
}
pub(crate) fn run_after(&self, phase: Phase, world: &mut World) {
if let Some(hooks) = self.after.get(&phase) {
for hook in hooks {
hook(world);
}
}
}
pub(crate) fn add_before(&mut self, phase: Phase, hook: PhaseHook) {
self.before.entry(phase).or_default().push(hook);
}
pub(crate) fn add_after(&mut self, phase: Phase, hook: PhaseHook) {
self.after.entry(phase).or_default().push(hook);
}
pub(crate) fn run_before_group(&self, phase: Phase, group: GroupId, world: &mut World) {
if let Some(hooks) = self.before_group.get(&(phase, group)) {
for hook in hooks {
hook(world);
}
}
}
pub(crate) fn run_after_group(&self, phase: Phase, group: GroupId, world: &mut World) {
if let Some(hooks) = self.after_group.get(&(phase, group)) {
for hook in hooks {
hook(world);
}
}
}
pub(crate) fn add_before_group(&mut self, phase: Phase, group: GroupId, hook: PhaseHook) {
self.before_group
.entry((phase, group))
.or_default()
.push(hook);
}
pub(crate) fn add_after_group(&mut self, phase: Phase, group: GroupId, hook: PhaseHook) {
self.after_group
.entry((phase, group))
.or_default()
.push(hook);
}
}