"use strict"; const TARINAI_PUBLIC_EVENT_TYPES = new Set(["audio:play", "selection:changed", "tool:selected", "world:phase", "log:entry", "tool:placed"]); class TarinaiEventBus { constructor() { this.handlers = new Map(); } on(type, handler) { if (!type || typeof handler !== "function") return; let list = this.handlers.get(type); if (!list) { list = new Set(); this.handlers.set(type, list); } list.add(handler); } hasDirectListeners(type) { if (!type) return false; return Boolean(this.handlers.get(type)?.size || 0); } hasWildcardListeners(type) { if (!type || !TARINAI_PUBLIC_EVENT_TYPES.has(String(type))) return false; return Boolean(this.handlers.get("*")?.size || 0); } hasListeners(type) { if (!type) return false; return Boolean(this.hasDirectListeners(type) || this.hasWildcardListeners(type)); } emit(type, detail = {}) { if (!type) return null; const direct = this.handlers.get(type); const wildcard = TARINAI_PUBLIC_EVENT_TYPES.has(String(type)) ? this.handlers.get("*") : null; if (!(direct?.size || 0) && !(wildcard?.size || 0)) return null; const event = { type, detail: detail || {}, at: performance?.now?.() ?? Date.now() }; if (direct) for (const handler of [...direct]) this.safeCall(handler, event); if (wildcard) for (const handler of [...wildcard]) this.safeCall(handler, event); return event; } safeCall(handler, event) { try { handler(event); } catch (err) { console.error("event handler failed", event.type, err); } } } window.TarinaiEvents = window.TarinaiEvents || new TarinaiEventBus();