slime/src/core/EventBus.ts

101 lines
2.4 KiB
TypeScript

/**
* Enum for game-wide event types.
*/
export enum Events {
DAMAGE_DEALT = 'combat:damage_dealt',
ENTITY_DIED = 'combat:entity_died',
EVOLVED = 'evolution:evolved',
MUTATION_GAINED = 'evolution:mutation_gained',
EXP_GAINED = 'stats:exp_gained',
LEVEL_UP = 'stats:level_up',
SKILL_LEARNED = 'skills:learned',
ATTACK_PERFORMED = 'combat:attack_performed',
SKILL_COOLDOWN_STARTED = 'skills:cooldown_started',
}
/**
* Event data types
*/
export interface DamageDealtEvent {
x: number;
y: number;
value: number;
color: string;
}
export interface MutationGainedEvent {
name: string;
description?: string;
}
export interface SkillLearnedEvent {
id: string;
}
export interface EntityDiedEvent {
entity: unknown;
}
export interface AttackPerformedEvent {
entity: unknown;
angle: number;
}
type EventCallback = (data?: unknown) => void;
/**
* Lightweight EventBus for pub/sub communication between systems.
*/
export class EventBus {
private listeners: Map<string, EventCallback[]>;
constructor() {
this.listeners = new Map();
}
/**
* Subscribe to an event with a callback.
* @param event - The event name from the Events enum
* @param callback - The function to call when the event is emitted
* @returns An unsubscribe function
*/
on(event: string, callback: EventCallback): () => void {
if (!this.listeners.has(event)) {
this.listeners.set(event, []);
}
const callbacks = this.listeners.get(event);
if (callbacks) {
callbacks.push(callback);
}
return () => this.off(event, callback);
}
/**
* Unsubscribe a specific callback from an event.
* @param event - The event name
* @param callback - The original callback function to remove
*/
off(event: string, callback: EventCallback): void {
if (!this.listeners.has(event)) return;
const callbacks = this.listeners.get(event);
if (callbacks) {
const index = callbacks.indexOf(callback);
if (index > -1) {
callbacks.splice(index, 1);
}
}
}
/**
* Emit an event to all subscribers.
* @param event - The event name
* @param data - Data to pass to the callbacks
*/
emit(event: string, data?: unknown): void {
if (!this.listeners.has(event)) return;
const callbacks = this.listeners.get(event);
if (callbacks) {
callbacks.forEach((callback) => callback(data));
}
}
}