[Linux-only] basically bloxstap for sober
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();