type Listener = (...args: any[]) => void; /** * 轻量事件总线(可替换):默认本地发布订阅 * - 迁移到有全局 EventBus 的项目时,可替换为项目总线 */ export class PortableEventBus { private listeners: Map> = new Map(); on(event: string, listener: Listener) { if (!this.listeners.has(event)) this.listeners.set(event, new Set()); this.listeners.get(event)!.add(listener); } once(event: string, listener: Listener) { const wrap: Listener = (...args: any[]) => { this.off(event, wrap); listener(...args); }; this.on(event, wrap); } off(event: string, listener: Listener) { this.listeners.get(event)?.delete(listener); } emit(event: string, ...args: any[]) { const set = this.listeners.get(event); if (!set) return; for (const l of Array.from(set)) { try { l(...args); } catch { /* swallow */ } } } } export const BulletEvents = { BULLET_CREATE_REQUEST: 'BULLET_CREATE_REQUEST', BULLET_HIT: 'BULLET_HIT', BULLET_DESTROY: 'BULLET_DESTROY' } as const;