[Linux-only] basically bloxstap for sober
at dev 150 lines 3.2 kB view raw
1import type { 2 GameState, 3 PlayerInfo, 4 GameJoinAction, 5 PlrJoinLeaveAction 6} from "./types"; 7import { ServerType } from "./types"; 8 9export class CurrentStateManager { 10 private currentState: GameState = { 11 placeId: "", 12 jobId: "", 13 ipAddr: "", 14 ipAddrUdmux: undefined, 15 serverType: ServerType.PUBLIC, 16 isInGame: false, 17 joinTime: undefined, 18 players: [] 19 }; 20 21 private stateChangeCallbacks: Array<(state: GameState) => void> = []; 22 23 /** 24 * Get the current game state 25 */ 26 getCurrentState(): GameState { 27 return { ...this.currentState }; 28 } 29 30 /** 31 * Subscribe to state changes 32 * @param callback Function to call when state changes 33 * @returns Unsubscribe function 34 */ 35 onStateChange(callback: (state: GameState) => void): () => void { 36 this.stateChangeCallbacks.push(callback); 37 38 // Return unsubscribe function 39 return () => { 40 const index = this.stateChangeCallbacks.indexOf(callback); 41 if (index > -1) { 42 this.stateChangeCallbacks.splice(index, 1); 43 } 44 }; 45 } 46 47 /** 48 * Check if currently in a game 49 */ 50 isInGame(): boolean { 51 return this.currentState.isInGame; 52 } 53 54 /** 55 * Get the current place ID 56 */ 57 getPlaceId(): string | null { 58 return this.currentState.isInGame ? this.currentState.placeId : null; 59 } 60 61 /** 62 * Get the current job ID 63 */ 64 getJobId(): string | null { 65 return this.currentState.isInGame ? this.currentState.jobId : null; 66 } 67 68 /** 69 * Update state when joining a game 70 */ 71 handleGameJoin(gameData: GameJoinAction): void { 72 this.currentState = { 73 placeId: gameData.placeId, 74 jobId: gameData.jobId, 75 ipAddr: gameData.ipAddr, 76 ipAddrUdmux: gameData.ipAddrUdmux, 77 serverType: gameData.serverType, 78 isInGame: true, 79 joinTime: Date.now(), 80 players: [] 81 }; 82 83 this.notifyStateChange(); 84 } 85 86 /** 87 * Update state when leaving a game 88 */ 89 handleGameLeave(): void { 90 this.currentState = { 91 placeId: "", 92 jobId: "", 93 ipAddr: "", 94 ipAddrUdmux: undefined, 95 serverType: ServerType.PUBLIC, 96 isInGame: false, 97 joinTime: undefined, 98 players: [] 99 }; 100 101 this.notifyStateChange(); 102 } 103 104 /** 105 * Handle player join/leave events 106 */ 107 handlePlayerAction(action: PlrJoinLeaveAction): void { 108 if (!this.currentState.isInGame) return; 109 110 if (action.action === "JOIN") { 111 const playerInfo: PlayerInfo = { 112 name: action.name, 113 id: action.id, 114 joinTime: Date.now() 115 }; 116 117 // Check if player already exists 118 const existingPlayerIndex = this.currentState.players.findIndex( 119 (p) => p.id === action.id 120 ); 121 if (existingPlayerIndex === -1) { 122 this.currentState.players.push(playerInfo); 123 this.notifyStateChange(); 124 } 125 } else if (action.action === "LEAVE") { 126 // Remove player from the list 127 this.currentState.players = this.currentState.players.filter( 128 (p) => p.id !== action.id 129 ); 130 this.notifyStateChange(); 131 } 132 } 133 134 /** 135 * Notify all subscribers of state changes 136 */ 137 private notifyStateChange(): void { 138 const stateCopy = this.getCurrentState(); 139 this.stateChangeCallbacks.forEach((callback) => { 140 try { 141 callback(stateCopy); 142 } catch (error) { 143 console.error("Error in state change callback:", error); 144 } 145 }); 146 } 147} 148 149// Create a singleton instance 150export const currentStateManager = new CurrentStateManager();