mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 09:30:45 +00:00
websocket reconnect on failure
This commit is contained in:
@@ -17,8 +17,12 @@
|
||||
* upload and start server DONE 8/13/2024
|
||||
* fix multiplayer DONE 8/14/2024
|
||||
* fix server resource leak DONE 8/14/2024
|
||||
* fix bug where game stops after 10s (websocket disconnection) DONE 8/16/2024
|
||||
* fix server memory leak
|
||||
* balance attacks/expansions better
|
||||
* Bug: boats not going to destination, coast not being recognized
|
||||
* double attack add troops
|
||||
* Have some time for spawning before game starts
|
||||
* delete players when territories too small
|
||||
* better algorithm for name render placement
|
||||
* make boats larger
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {defaultConfig} from "../core/configuration/DefaultConfig";
|
||||
import {TerrainMap} from "../core/Game";
|
||||
import {PseudoRandom} from "../core/PseudoRandom";
|
||||
import {ServerMessage, ServerMessageSchema} from "../core/Schemas";
|
||||
import {GameID, ServerMessage, ServerMessageSchema} from "../core/Schemas";
|
||||
import {loadTerrainMap} from "../core/TerrainMapLoader";
|
||||
import {ClientGame, createClientGame} from "./ClientGame";
|
||||
import {v4 as uuidv4} from 'uuid';
|
||||
@@ -44,15 +44,15 @@ class Client {
|
||||
}
|
||||
}
|
||||
|
||||
private updateLobbiesDisplay(lobbies: Array<{id: string}>): void {
|
||||
private updateLobbiesDisplay(lobbies: GameID[]): void {
|
||||
if (!this.lobbiesContainer) return;
|
||||
|
||||
this.lobbiesContainer.innerHTML = ''; // Clear existing lobbies
|
||||
|
||||
lobbies.forEach(lobby => {
|
||||
const button = document.createElement('button');
|
||||
button.textContent = `Join Lobby ${lobby.id}`;
|
||||
button.onclick = () => this.joinLobby(lobby.id);
|
||||
button.textContent = `Join Lobby ${lobby}`;
|
||||
button.onclick = () => this.joinLobby(lobby);
|
||||
this.lobbiesContainer.appendChild(button);
|
||||
});
|
||||
|
||||
@@ -88,7 +88,7 @@ class Client {
|
||||
}
|
||||
// TODO make id more random, if two player join same millisecond get same id.
|
||||
this.game = createClientGame(getUsername(), new PseudoRandom(Date.now()).nextID(), lobbyID, defaultConfig, map)
|
||||
this.game.joinLobby()
|
||||
this.game.join()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+53
-70
@@ -1,16 +1,16 @@
|
||||
import {Executor} from "../core/execution/Executor";
|
||||
import {Cell, ClientID, MutableGame, LobbyID, PlayerEvent, PlayerID, PlayerInfo, MutablePlayer, TerrainMap, TileEvent, Player, Game, BoatEvent, TerrainTypes} from "../core/Game";
|
||||
import {Cell, MutableGame, PlayerEvent, PlayerID, PlayerInfo, MutablePlayer, TerrainMap, TileEvent, Player, Game, BoatEvent, TerrainTypes} from "../core/Game";
|
||||
import {createGame} from "../core/GameImpl";
|
||||
import {Ticker, TickEvent} from "../core/Ticker";
|
||||
import {EventBus} from "../core/EventBus";
|
||||
import {Config} from "../core/configuration/Config";
|
||||
import {GameRenderer} from "./graphics/GameRenderer";
|
||||
import {InputHandler, MouseUpEvent, ZoomEvent, DragEvent, MouseDownEvent} from "./InputHandler"
|
||||
import {ClientIntentMessageSchema, ClientJoinMessageSchema, ClientMessageSchema, ServerMessage, ServerMessageSchema, ServerSyncMessage, Turn} from "../core/Schemas";
|
||||
import {ClientID, ClientIntentMessageSchema, ClientJoinMessageSchema, ClientMessageSchema, GameID, Intent, ServerMessage, ServerMessageSchema, ServerSyncMessage, Turn} from "../core/Schemas";
|
||||
|
||||
|
||||
|
||||
export function createClientGame(name: string, clientID: ClientID, lobbyID: LobbyID, config: Config, terrainMap: TerrainMap): ClientGame {
|
||||
export function createClientGame(name: string, clientID: ClientID, gameID: GameID, config: Config, terrainMap: TerrainMap): ClientGame {
|
||||
let eventBus = new EventBus()
|
||||
let gs = createGame(terrainMap, eventBus)
|
||||
let gameRenderer = new GameRenderer(gs, config.theme(), document.createElement("canvas"))
|
||||
@@ -18,7 +18,7 @@ export function createClientGame(name: string, clientID: ClientID, lobbyID: Lobb
|
||||
return new ClientGame(
|
||||
name,
|
||||
clientID,
|
||||
lobbyID,
|
||||
gameID,
|
||||
eventBus,
|
||||
gs,
|
||||
gameRenderer,
|
||||
@@ -47,7 +47,7 @@ export class ClientGame {
|
||||
constructor(
|
||||
private playerName: string,
|
||||
private id: ClientID,
|
||||
private gameID: LobbyID,
|
||||
private gameID: GameID,
|
||||
private eventBus: EventBus,
|
||||
private gs: Game,
|
||||
private renderer: GameRenderer,
|
||||
@@ -56,16 +56,17 @@ export class ClientGame {
|
||||
private config: Config
|
||||
) { }
|
||||
|
||||
public joinLobby() {
|
||||
public join() {
|
||||
const wsHost = process.env.WEBSOCKET_URL || window.location.host;
|
||||
this.socket = new WebSocket(`ws://${wsHost}`)
|
||||
const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
this.socket = new WebSocket(`${wsProtocol}//${wsHost}`)
|
||||
this.socket.onopen = () => {
|
||||
console.log('Connected to game server!');
|
||||
this.socket.send(
|
||||
JSON.stringify(
|
||||
ClientJoinMessageSchema.parse({
|
||||
type: "join",
|
||||
lobbyID: this.gameID,
|
||||
gameID: this.gameID,
|
||||
clientID: this.id
|
||||
})
|
||||
)
|
||||
@@ -81,6 +82,15 @@ export class ClientGame {
|
||||
this.addTurn(message.turn)
|
||||
}
|
||||
};
|
||||
this.socket.onerror = (err) => {
|
||||
console.error('Socket encountered error: ', err, 'Closing socket');
|
||||
this.socket.close();
|
||||
};
|
||||
this.socket.onclose = (event: CloseEvent) => {
|
||||
console.log(`WebSocket closed. Code: ${event.code}, Reason: ${event.reason}`);
|
||||
this.join()
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public start() {
|
||||
@@ -128,7 +138,7 @@ export class ClientGame {
|
||||
|
||||
private playerEvent(event: PlayerEvent) {
|
||||
console.log('received new player event!')
|
||||
if (event.player.info().clientID == this.id) {
|
||||
if (event.player.info().gameID == this.id) {
|
||||
console.log('setting name')
|
||||
this.myPlayer = event.player
|
||||
}
|
||||
@@ -167,79 +177,52 @@ export class ClientGame {
|
||||
}
|
||||
|
||||
private sendSpawnIntent(cell: Cell) {
|
||||
const spawn = JSON.stringify(
|
||||
ClientIntentMessageSchema.parse({
|
||||
type: "intent",
|
||||
clientID: this.id,
|
||||
gameID: this.gameID,
|
||||
intent: {
|
||||
type: "spawn",
|
||||
clientID: this.id,
|
||||
name: this.playerName,
|
||||
isBot: false,
|
||||
x: cell.x,
|
||||
y: cell.y
|
||||
}
|
||||
})
|
||||
)
|
||||
console.log(spawn)
|
||||
if (this.socket.readyState === WebSocket.OPEN) {
|
||||
console.log(`seding spawn intent: ${spawn}`)
|
||||
this.socket.send(spawn)
|
||||
} else {
|
||||
console.log('WebSocket is not open. Current state:', this.socket.readyState);
|
||||
}
|
||||
this.sendIntent({
|
||||
type: "spawn",
|
||||
clientID: this.id,
|
||||
name: this.playerName,
|
||||
isBot: false,
|
||||
x: cell.x,
|
||||
y: cell.y
|
||||
})
|
||||
}
|
||||
|
||||
private sendAttackIntent(targetID: PlayerID, cell: Cell, troops: number) {
|
||||
const attack = JSON.stringify(
|
||||
ClientIntentMessageSchema.parse({
|
||||
type: "intent",
|
||||
clientID: this.id,
|
||||
gameID: this.gameID,
|
||||
intent: {
|
||||
type: "attack",
|
||||
clientID: this.id,
|
||||
attackerID: this.myPlayer.id(),
|
||||
targetID: targetID,
|
||||
troops: troops,
|
||||
targetX: cell.x,
|
||||
targetY: cell.y
|
||||
}
|
||||
})
|
||||
)
|
||||
console.log(attack)
|
||||
if (this.socket.readyState === WebSocket.OPEN) {
|
||||
console.log(`sending attack intent: ${attack}`)
|
||||
this.socket.send(attack)
|
||||
} else {
|
||||
console.log('WebSocket is not open. Current state:', this.socket.readyState);
|
||||
}
|
||||
this.sendIntent({
|
||||
type: "attack",
|
||||
clientID: this.id,
|
||||
attackerID: this.myPlayer.id(),
|
||||
targetID: targetID,
|
||||
troops: troops,
|
||||
targetX: cell.x,
|
||||
targetY: cell.y
|
||||
})
|
||||
}
|
||||
|
||||
private sendBoatAttackIntent(targetID: PlayerID, cell: Cell, troops: number) {
|
||||
const attack = JSON.stringify(
|
||||
ClientIntentMessageSchema.parse({
|
||||
this.sendIntent({
|
||||
type: "boat",
|
||||
clientID: this.id,
|
||||
attackerID: this.myPlayer.id(),
|
||||
targetID: targetID,
|
||||
troops: troops,
|
||||
x: cell.x,
|
||||
y: cell.y,
|
||||
})
|
||||
}
|
||||
|
||||
private sendIntent(intent: Intent) {
|
||||
if (this.socket.readyState === WebSocket.OPEN) {
|
||||
const msg = ClientIntentMessageSchema.parse({
|
||||
type: "intent",
|
||||
clientID: this.id,
|
||||
gameID: this.gameID,
|
||||
intent: {
|
||||
type: "boat",
|
||||
clientID: this.id,
|
||||
attackerID: this.myPlayer.id(),
|
||||
targetID: targetID,
|
||||
troops: troops,
|
||||
x: cell.x,
|
||||
y: cell.y,
|
||||
}
|
||||
intent: intent
|
||||
})
|
||||
)
|
||||
console.log(attack)
|
||||
if (this.socket.readyState === WebSocket.OPEN) {
|
||||
console.log(`sending boat attack intent: ${attack}`)
|
||||
this.socket.send(attack)
|
||||
this.socket.send(JSON.stringify(msg))
|
||||
} else {
|
||||
console.log('WebSocket is not open. Current state:', this.socket.readyState);
|
||||
console.log('attempting reconnect')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-9
@@ -1,13 +1,8 @@
|
||||
import {GameEvent} from "./EventBus"
|
||||
|
||||
export type ClientID = string
|
||||
import {GameID} from "./Schemas"
|
||||
|
||||
export type PlayerID = number // TODO: make string?
|
||||
|
||||
export type GameID = string
|
||||
|
||||
export type LobbyID = string
|
||||
|
||||
export class Cell {
|
||||
|
||||
private strRepr: string
|
||||
@@ -38,7 +33,7 @@ export class PlayerInfo {
|
||||
public readonly name: string,
|
||||
public readonly isBot: boolean,
|
||||
// null if bot.
|
||||
public readonly clientID: ClientID | null
|
||||
public readonly gameID: GameID | null
|
||||
) { }
|
||||
}
|
||||
|
||||
@@ -133,8 +128,8 @@ export interface Game {
|
||||
forEachTile(fn: (tile: Tile) => void): void
|
||||
executions(): ExecutionView[]
|
||||
terraNullius(): TerraNullius
|
||||
tick()
|
||||
addExecution(...exec: Execution[])
|
||||
tick(): void
|
||||
addExecution(...exec: Execution[]): void
|
||||
}
|
||||
|
||||
export interface MutableGame extends Game {
|
||||
|
||||
+4
-1
@@ -1,5 +1,8 @@
|
||||
import {z} from 'zod';
|
||||
|
||||
export type GameID = string
|
||||
export type ClientID = string
|
||||
|
||||
export type Intent = SpawnIntent | AttackIntent | BoatAttackIntent
|
||||
|
||||
export type AttackIntent = z.infer<typeof AttackIntentSchema>
|
||||
@@ -96,7 +99,7 @@ export const ClientIntentMessageSchema = ClientBaseMessageSchema.extend({
|
||||
export const ClientJoinMessageSchema = ClientBaseMessageSchema.extend({
|
||||
type: z.literal('join'),
|
||||
clientID: z.string(),
|
||||
lobbyID: z.string()
|
||||
gameID: z.string()
|
||||
})
|
||||
|
||||
export const ClientMessageSchema = z.union([ClientIntentMessageSchema, ClientJoinMessageSchema]);
|
||||
@@ -6,7 +6,7 @@ export interface Config {
|
||||
theme(): Theme;
|
||||
player(): PlayerConfig
|
||||
turnIntervalMs(): number
|
||||
lobbyCreationRate(): number
|
||||
gameCreationRate(): number
|
||||
lobbyLifetime(): number
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ export const defaultConfig = new class implements Config {
|
||||
turnIntervalMs(): number {
|
||||
return 100
|
||||
}
|
||||
lobbyCreationRate(): number {
|
||||
gameCreationRate(): number {
|
||||
return 2 * 1000
|
||||
}
|
||||
lobbyLifetime(): number {
|
||||
|
||||
@@ -26,7 +26,6 @@ export class SpawnExecution implements Execution {
|
||||
}
|
||||
const player = this.gs.addPlayer(this.playerInfo, this.playerConfig.startTroops(this.playerInfo))
|
||||
getSpawnCells(this.gs, this.cell).forEach(c => {
|
||||
console.log('conquering cell')
|
||||
player.conquer(this.gs.tile(c))
|
||||
})
|
||||
this.gs.addExecution(new PlayerExecution(player.id(), this.playerConfig))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {ClientID} from "../core/Game";
|
||||
import WebSocket from 'ws';
|
||||
import {ClientID} from '../core/Schemas';
|
||||
|
||||
|
||||
export class Client {
|
||||
|
||||
+31
-51
@@ -1,73 +1,53 @@
|
||||
import {GameID, LobbyID} from "../core/Game";
|
||||
import {Client} from "./Client";
|
||||
import {Lobby} from "./Lobby";
|
||||
import {GameServer} from "./GameServer";
|
||||
import {GamePhase, GameServer} from "./GameServer";
|
||||
import {Config} from "../core/configuration/Config";
|
||||
import {defaultConfig} from "../core/configuration/DefaultConfig";
|
||||
import {PseudoRandom} from "../core/PseudoRandom";
|
||||
import WebSocket from 'ws';
|
||||
import {ClientID, GameID} from "../core/Schemas";
|
||||
import {Client} from "./Client";
|
||||
|
||||
|
||||
export class GameManager {
|
||||
|
||||
private lastNewLobby: number = 0
|
||||
|
||||
private _lobbies: Map<LobbyID, Lobby> = new Map()
|
||||
|
||||
private games: Map<GameID, GameServer> = new Map()
|
||||
private games: GameServer[] = []
|
||||
|
||||
private random = new PseudoRandom(123)
|
||||
|
||||
constructor(private settings: Config) { }
|
||||
constructor(private config: Config) { }
|
||||
|
||||
|
||||
public hasLobby(lobbyID: LobbyID): boolean {
|
||||
return this._lobbies.has(lobbyID)
|
||||
gamesByPhase(phase: GamePhase): GameServer[] {
|
||||
return this.games.filter(g => g.phase() == phase)
|
||||
}
|
||||
|
||||
public addClientToLobby(client: Client, lobbyID: LobbyID) {
|
||||
this._lobbies.get(lobbyID).addClient(client)
|
||||
}
|
||||
|
||||
addLobby(lobby: Lobby) {
|
||||
this._lobbies.set(lobby.id, lobby)
|
||||
}
|
||||
|
||||
lobby(id: LobbyID): Lobby {
|
||||
return this._lobbies.get(id)
|
||||
}
|
||||
|
||||
lobbies(): Lobby[] {
|
||||
return Array.from(this._lobbies.values())
|
||||
}
|
||||
|
||||
addGame(game: GameServer) {
|
||||
this.games.set(game.id, game)
|
||||
addClient(client: Client, gameID: GameID) {
|
||||
const game = this.games.find(g => g.id == gameID)
|
||||
if (!game) {
|
||||
console.log(`game id ${gameID} not found`)
|
||||
return
|
||||
}
|
||||
game.addClient(client)
|
||||
}
|
||||
|
||||
tick() {
|
||||
const lobbies = this.gamesByPhase(GamePhase.Lobby)
|
||||
const active = this.gamesByPhase(GamePhase.Active)
|
||||
const finished = this.gamesByPhase(GamePhase.Finished)
|
||||
|
||||
const now = Date.now()
|
||||
|
||||
const active = this.lobbies().filter(l => !l.isExpired(now - 2000))
|
||||
const expired = this.lobbies().filter(l => l.isExpired(now - 2000))
|
||||
this._lobbies = new Map(active.map(lobby => [lobby.id, lobby]));
|
||||
expired.forEach(lobby => {
|
||||
const game = new GameServer(lobby.id, now, lobby.clients, this.settings)
|
||||
this.games.set(game.id, game)
|
||||
game.start()
|
||||
})
|
||||
|
||||
if (now > this.lastNewLobby + this.settings.lobbyCreationRate()) {
|
||||
if (now > this.lastNewLobby + this.config.gameCreationRate()) {
|
||||
this.lastNewLobby = now
|
||||
this.addLobby(new Lobby(this.random.nextID(), this.settings.lobbyLifetime()))
|
||||
const id = this.random.nextID()
|
||||
console.log(`creating game ${id}`)
|
||||
lobbies.push(new GameServer(id, now, this.config))
|
||||
}
|
||||
|
||||
const activeGames: Map<GameID, GameServer> = new Map()
|
||||
for (const [id, game] of this.games) {
|
||||
if (game.isActive()) {
|
||||
activeGames.set(id, game)
|
||||
} else {
|
||||
game.endGame()
|
||||
}
|
||||
}
|
||||
//this.games = activeGames
|
||||
active.filter(g => !g.hasStarted()).forEach(g => {
|
||||
g.start()
|
||||
})
|
||||
finished.forEach(g => {
|
||||
g.endGame()
|
||||
})
|
||||
this.games = [...lobbies, ...active]
|
||||
}
|
||||
}
|
||||
+52
-27
@@ -1,50 +1,64 @@
|
||||
import {EventBus} from "../core/EventBus";
|
||||
import {ClientID, GameID} from "../core/Game";
|
||||
import {ClientMessage, ClientMessageSchema, Intent, ServerStartGameMessage, ServerStartGameMessageSchema, ServerTurnMessageSchema, Turn} from "../core/Schemas";
|
||||
import {Config} from "../core/configuration/Config";
|
||||
import {Ticker, TickEvent} from "../core/Ticker";
|
||||
import {Client} from "./Client";
|
||||
|
||||
export enum GamePhase {
|
||||
Lobby = 'LOBBY',
|
||||
Active = 'ACTIVE',
|
||||
Finished = 'FINISHED'
|
||||
}
|
||||
|
||||
export class GameServer {
|
||||
|
||||
|
||||
private gameDuration = 5 * 60 * 1000 // TODO!!! fix this
|
||||
|
||||
private turns: Turn[] = []
|
||||
private intents: Intent[] = []
|
||||
private lastUpdate = 0;
|
||||
private clients: Client[] = []
|
||||
private _hasStarted = false
|
||||
|
||||
constructor(
|
||||
public readonly id: GameID,
|
||||
private startTime: number,
|
||||
private clients: Map<ClientID, Client>,
|
||||
public readonly id: string,
|
||||
public readonly createdAt: number,
|
||||
private settings: Config,
|
||||
) {
|
||||
this.lastUpdate = Date.now()
|
||||
) { }
|
||||
|
||||
public addClient(client: Client) {
|
||||
console.log(`game ${this.id} adding client ${client.id}`)
|
||||
// Remove stale client if this is a reconnect
|
||||
this.clients = this.clients.filter(c => c.id != client.id)
|
||||
this.clients.push(client)
|
||||
client.ws.on('message', (message: string) => {
|
||||
const clientMsg: ClientMessage = ClientMessageSchema.parse(JSON.parse(message))
|
||||
if (clientMsg.type == "intent") {
|
||||
if (clientMsg.gameID == this.id) {
|
||||
this.addIntent(clientMsg.intent)
|
||||
} else {
|
||||
console.warn(`client ${clientMsg.clientID} sent to wrong game`)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
public start() {
|
||||
this.clients.forEach(c => {
|
||||
c.ws.on('message', (message: string) => {
|
||||
this.lastUpdate = Date.now()
|
||||
const clientMsg: ClientMessage = ClientMessageSchema.parse(JSON.parse(message))
|
||||
if (clientMsg.type == "intent") {
|
||||
if (clientMsg.gameID == this.id) {
|
||||
this.addIntent(clientMsg.intent)
|
||||
} else {
|
||||
console.warn(`client ${clientMsg.clientID} sent to wrong game`)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
this._hasStarted = true
|
||||
const startGame = JSON.stringify(ServerStartGameMessageSchema.parse(
|
||||
{
|
||||
type: "start"
|
||||
}
|
||||
))
|
||||
this.clients.forEach(c => {
|
||||
console.log(`game ${this.id} sending start message to ${c.id}`)
|
||||
c.ws.send(startGame)
|
||||
})
|
||||
setInterval(() => this.endTurn(), this.settings.turnIntervalMs());
|
||||
|
||||
// setInterval(() => {
|
||||
// this.clients.forEach(c => {
|
||||
// c.ws.close(1011, 'Intentional error for testing');
|
||||
// })
|
||||
// }, 1000)
|
||||
}
|
||||
|
||||
private addIntent(intent: Intent) {
|
||||
@@ -69,10 +83,7 @@ export class GameServer {
|
||||
this.clients.forEach(c => {
|
||||
c.ws.send(msg)
|
||||
})
|
||||
}
|
||||
|
||||
public isActive(): boolean {
|
||||
return Date.now() - this.lastUpdate < 1000 * 60 * 5 // 5 minutes
|
||||
}
|
||||
|
||||
endGame() {
|
||||
@@ -85,4 +96,18 @@ export class GameServer {
|
||||
});
|
||||
}
|
||||
|
||||
phase(): GamePhase {
|
||||
if (Date.now() - this.createdAt < this.settings.lobbyLifetime()) {
|
||||
return GamePhase.Lobby
|
||||
}
|
||||
if (Date.now() - this.createdAt < this.settings.lobbyLifetime() + this.gameDuration) {
|
||||
return GamePhase.Active
|
||||
}
|
||||
return GamePhase.Finished
|
||||
}
|
||||
|
||||
hasStarted(): boolean {
|
||||
return this._hasStarted
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import {ClientID} from "../core/Game";
|
||||
import {Client} from "./Client";
|
||||
|
||||
export class Lobby {
|
||||
|
||||
public clients: Map<ClientID, Client> = new Map()
|
||||
private startGameTs: number
|
||||
|
||||
|
||||
constructor(public readonly id: string, durationMs: number) {
|
||||
this.startGameTs = Date.now() + durationMs
|
||||
}
|
||||
|
||||
public addClient(client: Client) {
|
||||
this.clients.set(client.id, client)
|
||||
}
|
||||
|
||||
public isExpired(now: number): boolean {
|
||||
return now > this.startGameTs
|
||||
}
|
||||
}
|
||||
+3
-12
@@ -6,8 +6,8 @@ import {fileURLToPath} from 'url';
|
||||
import {GameManager} from './GameManager';
|
||||
import {Client} from './Client';
|
||||
import {ClientMessage, ClientMessageSchema} from '../core/Schemas';
|
||||
import {Lobby} from './Lobby';
|
||||
import {defaultConfig} from '../core/configuration/DefaultConfig';
|
||||
import {GamePhase} from './GameServer';
|
||||
|
||||
|
||||
|
||||
@@ -27,12 +27,8 @@ const gm = new GameManager(defaultConfig)
|
||||
|
||||
// New GET endpoint to list lobbies
|
||||
app.get('/lobbies', (req, res) => {
|
||||
const lobbyList = Array.from(gm.lobbies()).filter(l => !l.isExpired(Date.now())).map(lobby => ({
|
||||
id: lobby.id,
|
||||
}));
|
||||
|
||||
res.json({
|
||||
lobbies: lobbyList,
|
||||
lobbies: gm.gamesByPhase(GamePhase.Lobby).map(g => g.id),
|
||||
});
|
||||
});
|
||||
|
||||
@@ -43,12 +39,7 @@ wss.on('connection', (ws) => {
|
||||
const clientMsg: ClientMessage = ClientMessageSchema.parse(JSON.parse(message))
|
||||
if (clientMsg.type == "join") {
|
||||
console.log('got join request')
|
||||
if (gm.hasLobby(clientMsg.lobbyID)) {
|
||||
console.log('client joining lobby')
|
||||
gm.addClientToLobby(new Client(clientMsg.clientID, ws), clientMsg.lobbyID)
|
||||
} else {
|
||||
console.log('lobby not found')
|
||||
}
|
||||
gm.addClient(new Client(clientMsg.clientID, ws), clientMsg.gameID)
|
||||
}
|
||||
// TODO: send error message
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user