1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//! A typed in-process message bus for participant-to-participant signals that
//! are not engine events: a quest system telling the HUD, an AI telling the
//! audio director. Broadcast a value of any type, drain values of that type
//! elsewhere this frame or next. It stays in process, so the payload is a live
//! value and never serializes, which is why this is a Rust-only api with no
//! command form.
use std::any::Any;
use std::collections::VecDeque;
use nightshade::ecs::event_bus::commands::publish_app_event;
use nightshade::ecs::event_bus::resources::Message;
use nightshade::prelude::*;
/// Broadcasts a typed message onto the bus. Any system can drain it with
/// [`drain_messages`] of the same type.
pub fn broadcast<T: Any + Send + Sync>(world: &mut World, message: T) {
publish_app_event(world, message);
}
/// Drains every message of type `T` from the bus, returning them in order and
/// leaving messages of other types in place.
pub fn drain_messages<T: Any + Send + Sync>(world: &mut World) -> Vec<T> {
let mut kept: VecDeque<Message> = VecDeque::new();
let mut drained: Vec<T> = Vec::new();
while let Some(message) = world.resources.event_bus.messages.pop_front() {
match message {
Message::App { type_name, payload } => match payload.downcast::<T>() {
Ok(value) => drained.push(*value),
Err(payload) => kept.push_back(Message::App { type_name, payload }),
},
other => kept.push_back(other),
}
}
world.resources.event_bus.messages = kept;
drained
}