[Linux-only] basically bloxstap for sober
at dev 161 lines 3.7 kB view raw
1import type { 2 PlrJoinLeaveAction, 3 GameJoinAction, 4 BloxstrapRPCAction, 5 GameState, 6 TeleportAction 7} from "./types"; 8import { currentStateManager } from "./CurrentState"; 9 10export type EventType = 11 | "GAME_JOIN" 12 | "GAME_LEAVE" 13 | "PLAYER_JOIN" 14 | "PLAYER_LEAVE" 15 | "TELEPORT" 16 | "BLOXSTRAP_RPC" 17 | "STATE_CHANGE"; 18 19export type EventData = { 20 GAME_JOIN: GameJoinAction; 21 GAME_LEAVE: void; 22 PLAYER_JOIN: PlrJoinLeaveAction; 23 PLAYER_LEAVE: PlrJoinLeaveAction; 24 BLOXSTRAP_RPC: BloxstrapRPCAction; 25 STATE_CHANGE: GameState; 26 TELEPORT: TeleportAction; 27}; 28 29export type EventCallback<T extends EventType> = (data: EventData[T]) => void; 30 31export type EventSubscription = { 32 unsubscribe: () => void; 33}; 34 35class EventCollector { 36 private listeners: Map<EventType, Set<EventCallback<any>>> = new Map(); 37 38 /** 39 * Subscribe to an event type 40 */ 41 public on<T extends EventType>( 42 eventType: T, 43 callback: EventCallback<T> 44 ): EventSubscription { 45 if (!this.listeners.has(eventType)) { 46 this.listeners.set(eventType, new Set()); 47 } 48 49 const eventListeners = this.listeners.get(eventType)!; 50 eventListeners.add(callback); 51 52 return { 53 unsubscribe: () => { 54 eventListeners.delete(callback); 55 if (eventListeners.size === 0) { 56 this.listeners.delete(eventType); 57 } 58 } 59 }; 60 } 61 62 /** 63 * Emit an event to all subscribed listeners 64 */ 65 public emit<T extends EventType>(eventType: T, data: EventData[T]): void { 66 const eventListeners = this.listeners.get(eventType); 67 if (eventListeners) { 68 eventListeners.forEach((callback) => { 69 try { 70 callback(data); 71 } catch (error) { 72 console.error( 73 `Error in event listener for ${eventType}:`, 74 error 75 ); 76 } 77 }); 78 } 79 } 80 81 /** 82 * Emit a game join event 83 */ 84 public emitGameJoin(gameData: GameJoinAction): void { 85 this.emit("GAME_JOIN", gameData); 86 currentStateManager.handleGameJoin(gameData); 87 this.emit("STATE_CHANGE", currentStateManager.getCurrentState()); 88 } 89 90 /** 91 * Emit a game leave event 92 */ 93 public emitGameLeave(): void { 94 this.emit("GAME_LEAVE", undefined); 95 currentStateManager.handleGameLeave(); 96 this.emit("STATE_CHANGE", currentStateManager.getCurrentState()); 97 } 98 99 /** 100 * Emit a player join event 101 */ 102 public emitPlayerJoin(playerData: PlrJoinLeaveAction): void { 103 this.emit("PLAYER_JOIN", playerData); 104 currentStateManager.handlePlayerAction(playerData); 105 this.emit("STATE_CHANGE", currentStateManager.getCurrentState()); 106 } 107 108 /** 109 * Emit a player leave event 110 */ 111 public emitPlayerLeave(playerData: PlrJoinLeaveAction): void { 112 this.emit("PLAYER_LEAVE", playerData); 113 currentStateManager.handlePlayerAction(playerData); 114 this.emit("STATE_CHANGE", currentStateManager.getCurrentState()); 115 } 116 117 /** 118 * Emit a Bloxstrap RPC event 119 */ 120 public emitBloxstrapRPC(rpcData: BloxstrapRPCAction): void { 121 this.emit("BLOXSTRAP_RPC", rpcData); 122 } 123 124 /** 125 * Emit a teleport event 126 */ 127 public emitTeleport(data: TeleportAction): void { 128 this.emit("TELEPORT", data); 129 } 130 131 /** 132 * Get the number of listeners for a specific event type 133 */ 134 public getListenerCount(eventType: EventType): number { 135 return this.listeners.get(eventType)?.size || 0; 136 } 137 138 /** 139 * Get all registered event types 140 */ 141 public getRegisteredEvents(): EventType[] { 142 return Array.from(this.listeners.keys()); 143 } 144 145 /** 146 * Clear all listeners for a specific event type 147 */ 148 public clearListeners(eventType: EventType): void { 149 this.listeners.delete(eventType); 150 } 151 152 /** 153 * Clear all listeners for all event types 154 */ 155 public clearAllListeners(): void { 156 this.listeners.clear(); 157 } 158} 159 160// Export a singleton instance 161export const eventCollector = new EventCollector();