From 51c12c5cf6e9ded2a8d8c85f67b8b09015c10a40 Mon Sep 17 00:00:00 2001 From: c86ec23b-fef1-4979-b2fa-b9adc351b8cc <87239823+c86ec23b-fef1-4979-b2fa-b9adc351b8cc@users.noreply.github.com> Date: Fri, 4 Sep 2026 09:04:38 +0300 Subject: [PATCH 1/2] store all games on GameServer --- src/Game.ts | 4 ++++ src/index.ts | 12 ++++-------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Game.ts b/src/Game.ts index 853a9682..d944db4e 100644 --- a/src/Game.ts +++ b/src/Game.ts @@ -73,6 +73,8 @@ const GamemodeToArenaClass: Record * Used for determining which endpoints go to the default. */ export default class GameServer { + /** All game servers. */ + public static games: GameServer[] = []; /** Stores total player count. */ public static globalPlayerCount = 0; /** Whether or not the game server is running. */ @@ -152,6 +154,8 @@ export default class GameServer { this._tickInterval = setInterval(() => { if (this.clients.size) this.tickLoop(); // Don't tick empty games }, config.mspt); + + GameServer.games.push(this); } /** Returns a WebSocketServer Writer Broadcast Stream. */ diff --git a/src/index.ts b/src/index.ts index aef74bb9..a85b8eff 100644 --- a/src/index.ts +++ b/src/index.ts @@ -41,7 +41,6 @@ export const bannedClients = new Set(); const connections = new Map(); const allClients = new Set(); const app = App({}); -const games: GameServer[] = []; app.ws("/*", { compression: SHARED_COMPRESSOR, @@ -63,7 +62,7 @@ app.ws("/*", { return ws.close(); } connections.set(ipAddress, conns + 1); - const game = games.find(({ gamemode }) => gamemode === ws.getUserData().gamemode); + const game = GameServer.games.find(({ gamemode }) => gamemode === ws.getUserData().gamemode); if (!game) { return ws.close(); } @@ -99,7 +98,7 @@ app.get("/*", (res, req) => { res.writeStatus("200 OK").end(JSON.stringify(TankDefinitions)); return; case "/servers": - res.writeStatus("200 OK").end(JSON.stringify(games.map(({ gamemode, name }) => ({ gamemode, name })))); + res.writeStatus("200 OK").end(JSON.stringify(GameServer.games.map(({ gamemode, name }) => ({ gamemode, name })))); return; case "/commands": res.writeStatus("200 OK").end(JSON.stringify(config.enableCommands ? Object.values(commandDefinitions) : [])); @@ -160,14 +159,11 @@ app.listen(PORT, (success) => { // // NOTES(0): As of now, both servers run on the same process (and thread) here const ffa = new GameServer(FFAArena, "FFA"); - const sbx = new GameServer(SandboxArena, "Sandbox"); - - games.push(ffa, sbx); - + const sandbox = new GameServer(SandboxArena, "Sandbox"); util.saveToLog("Servers up", "All servers booted up.", 0x37F554); util.log("Dumping endpoint -> gamemode routing table"); - for (const game of games) console.log("> " + `localhost:${config.serverPort}/${game.gamemode}`.padEnd(40, " ") + " -> " + game.name); + for (const game of GameServer.games) console.log("> " + `localhost:${config.serverPort}/${game.gamemode}`.padEnd(40, " ") + " -> " + game.name); }); process.on("uncaughtException", (error) => { From fb60bc9ad4d1738f39611ca6ec2c185bc3d2d8fb Mon Sep 17 00:00:00 2001 From: c86ec23b-fef1-4979-b2fa-b9adc351b8cc <87239823+c86ec23b-fef1-4979-b2fa-b9adc351b8cc@users.noreply.github.com> Date: Fri, 4 Sep 2026 09:09:11 +0300 Subject: [PATCH 2/2] Fix player count updates --- src/Game.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Game.ts b/src/Game.ts index d944db4e..afa03e0e 100644 --- a/src/Game.ts +++ b/src/Game.ts @@ -121,7 +121,7 @@ export default class GameServer { const _add = this.clients.add; this.clients.add = (client: Client) => { GameServer.globalPlayerCount += 1; - this.broadcastPlayerCount(); + GameServer.broadcastPlayerCount(); return _add.call(this.clients, client); } @@ -130,7 +130,7 @@ export default class GameServer { let success = _delete.call(this.clients, client); if (success) { GameServer.globalPlayerCount -= 1; - this.broadcastPlayerCount(); + GameServer.broadcastPlayerCount(); this.clientsAwaitingSpawn.delete(client); } @@ -139,7 +139,7 @@ export default class GameServer { const _clear = this.clients.clear; this.clients.clear = () => { GameServer.globalPlayerCount -= this.clients.size; - this.broadcastPlayerCount(); + GameServer.broadcastPlayerCount(); this.clientsAwaitingSpawn.clear(); return _clear.call(this.clients); @@ -162,10 +162,14 @@ export default class GameServer { public broadcast() { return new WSSWriterStream(this); } + /** Broadcasts a player count packet. */ - public broadcastPlayerCount() { - this.broadcast().vu(ClientBound.PlayerCount).vu(GameServer.globalPlayerCount).send(); + public static broadcastPlayerCount() { + for (const game of GameServer.games) { + game.broadcast().vu(ClientBound.PlayerCount).vu(GameServer.globalPlayerCount).send(); + } } + /** Sends a notification to all clients connected to this game server. */ public broadcastMessage(text: string, color = 0x000000, time = 5000, id = "") { this.broadcast().u8(ClientBound.Notification).stringNT(text).u32(color).float(time).stringNT(id).send();