first commit
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* EventBus.js
|
||||
* Simple publish/subscribe event system for decoupled communication
|
||||
* between game systems.
|
||||
*/
|
||||
|
||||
class EventBus {
|
||||
constructor() {
|
||||
/** @type {Map<string, Array<{fn: Function, once: boolean}>>} */
|
||||
this._listeners = new Map();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribe to an event.
|
||||
* @param {string} event
|
||||
* @param {Function} fn
|
||||
* @returns {Function} Unsubscribe function.
|
||||
*/
|
||||
on(event, fn) {
|
||||
if (!this._listeners.has(event)) {
|
||||
this._listeners.set(event, []);
|
||||
}
|
||||
const entry = { fn, once: false };
|
||||
this._listeners.get(event).push(entry);
|
||||
return () => this.off(event, fn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribe to an event, but only fire once.
|
||||
* @param {string} event
|
||||
* @param {Function} fn
|
||||
*/
|
||||
once(event, fn) {
|
||||
if (!this._listeners.has(event)) {
|
||||
this._listeners.set(event, []);
|
||||
}
|
||||
this._listeners.get(event).push({ fn, once: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribe from an event.
|
||||
* @param {string} event
|
||||
* @param {Function} fn
|
||||
*/
|
||||
off(event, fn) {
|
||||
const list = this._listeners.get(event);
|
||||
if (!list) return;
|
||||
const idx = list.findIndex((entry) => entry.fn === fn);
|
||||
if (idx !== -1) list.splice(idx, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit an event with optional data.
|
||||
* @param {string} event
|
||||
* @param {*} [data]
|
||||
*/
|
||||
emit(event, data) {
|
||||
const list = this._listeners.get(event);
|
||||
if (!list || list.length === 0) return;
|
||||
|
||||
// Iterate in reverse so we can safely remove "once" entries
|
||||
for (let i = list.length - 1; i >= 0; i--) {
|
||||
const entry = list[i];
|
||||
entry.fn(data);
|
||||
if (entry.once) {
|
||||
list.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all listeners for a specific event, or all events.
|
||||
* @param {string} [event]
|
||||
*/
|
||||
clear(event) {
|
||||
if (event) {
|
||||
this._listeners.delete(event);
|
||||
} else {
|
||||
this._listeners.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = EventBus;
|
||||
Reference in New Issue
Block a user