use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum EventType {
PlayerDied,
EnemyKilled,
CoinCollected,
LevelComplete,
GameOver,
Custom(String),
}
#[derive(Debug, Clone)]
pub struct EventData {
pub event_type: EventType,
pub data: HashMap<String, String>,
}
impl EventData {
pub fn new(event_type: EventType) -> Self {
Self {
event_type,
data: HashMap::new(),
}
}
pub fn with_data(mut self, key: &str, value: &str) -> Self {
self.data.insert(key.to_string(), value.to_string());
self
}
pub fn get(&self, key: &str) -> Option<&String> {
self.data.get(key)
}
}
pub type EventCallback = Box<dyn FnMut(&EventData)>;
pub struct EventSystem {
listeners: HashMap<EventType, Vec<EventCallback>>,
event_queue: Vec<EventData>,
}
impl EventSystem {
pub fn new() -> Self {
Self {
listeners: HashMap::new(),
event_queue: Vec::new(),
}
}
pub fn on<F>(&mut self, event_type: EventType, callback: F)
where
F: FnMut(&EventData) + 'static,
{
self.listeners
.entry(event_type)
.or_insert_with(Vec::new)
.push(Box::new(callback));
}
pub fn emit(&mut self, event: EventData) {
if let Some(callbacks) = self.listeners.get_mut(&event.event_type) {
for callback in callbacks {
callback(&event);
}
}
}
pub fn queue(&mut self, event: EventData) {
self.event_queue.push(event);
}
pub fn process_queue(&mut self) {
let events: Vec<EventData> = self.event_queue.drain(..).collect();
for event in events {
self.emit(event);
}
}
pub fn clear_listeners(&mut self, event_type: &EventType) {
self.listeners.remove(event_type);
}
pub fn clear_all_listeners(&mut self) {
self.listeners.clear();
}
}
impl Default for EventSystem {
fn default() -> Self {
Self::new()
}
}