From 0ea670d975ae85cc905594363a627f030c0c98fb Mon Sep 17 00:00:00 2001 From: evanpelle Date: Sat, 17 Aug 2024 12:42:18 -0700 Subject: [PATCH] better game join logic, create dev and prod configs --- TODO.txt | 11 +++++++---- src/client/Client.ts | 22 ++++++++++++---------- src/client/ClientGame.ts | 13 +++++++++++-- src/client/graphics/GameRenderer.ts | 5 +---- src/client/index.html | 4 ++-- src/core/Schemas.ts | 9 +++++++-- src/core/configuration/Config.ts | 11 +++++++++++ src/core/configuration/DefaultConfig.ts | 14 +++++++++----- src/core/configuration/DevConfig.ts | 10 ++++++++++ src/server/GameManager.ts | 4 ++-- src/server/GameServer.ts | 23 +++++++++++++---------- src/server/Server.ts | 7 ++++--- webpack.config.js | 3 +++ 13 files changed, 92 insertions(+), 44 deletions(-) create mode 100644 src/core/configuration/DevConfig.ts diff --git a/TODO.txt b/TODO.txt index 71b3403e8..31ffdd3e4 100644 --- a/TODO.txt +++ b/TODO.txt @@ -19,14 +19,16 @@ * fix server resource leak DONE 8/14/2024 * fix bug where game stops after 10s (websocket disconnection) DONE 8/16/2024 * balance attacks/expansions better DONE 8/16/2024 +* delete players when territories too small DONE 8/16/2024 +* double attack add troops DONE 8/16/2024 +* Have some time for spawning before game starts DONE 8/16/2024 +* only send delta turns on connect/reconnect DONE 8/17/2024 +* Create separate game config dev vs prod +* improve front page, only one game at a time every 30s * fix desync * fix server memory leak * BUG: boats not going to destination, coast not being recognized * BUG: boats freeze game on path calculation -* double attack add troops -* Create separate game config dev vs prod -* Have some time for spawning before game starts -* delete players when territories too small * better algorithm for name render placement * make boats larger * have boats not get close to shore @@ -36,3 +38,4 @@ * fix enemy islands when attacking * BUG: ocean is considered TerraNullius * on websocket connect server only send missing turns not all turns +* BUG: fix hotreload (priority queue breaks it) diff --git a/src/client/Client.ts b/src/client/Client.ts index f00137dd4..707919bbb 100644 --- a/src/client/Client.ts +++ b/src/client/Client.ts @@ -1,7 +1,9 @@ +import {getConfig} from "../core/configuration/Config"; import {defaultConfig} from "../core/configuration/DefaultConfig"; +import {devConfig} from "../core/configuration/DevConfig"; import {TerrainMap} from "../core/Game"; import {PseudoRandom} from "../core/PseudoRandom"; -import {GameID, ServerMessage, ServerMessageSchema} from "../core/Schemas"; +import {GameID, Lobby, ServerMessage, ServerMessageSchema} from "../core/Schemas"; import {loadTerrainMap} from "../core/TerrainMapLoader"; import {ClientGame, createClientGame} from "./ClientGame"; import {v4 as uuidv4} from 'uuid'; @@ -36,21 +38,21 @@ class Client { private async fetchAndUpdateLobbies(): Promise { try { - const data = await this.fetchLobbies(); - this.updateLobbiesDisplay(data.lobbies); + const lobbies = await this.fetchLobbies(); + this.updateLobbiesDisplay(lobbies); } catch (error) { console.error('Error fetching and updating lobbies:', error); } } - private updateLobbiesDisplay(lobbies: GameID[]): void { + private updateLobbiesDisplay(lobbies: Lobby[]): void { if (!this.lobbiesContainer) return; this.lobbiesContainer.innerHTML = ''; // Clear existing lobbies lobbies.forEach(lobby => { const button = document.createElement('button'); - button.textContent = `Join Lobby ${lobby}`; + button.textContent = `Join Lobby ${lobby.id} (${Math.floor((lobby.startTime - Date.now()) / 1000)}s)`; button.onclick = () => this.joinLobby(lobby); this.lobbiesContainer.appendChild(button); }); @@ -63,7 +65,7 @@ class Client { // } } - async fetchLobbies() { + async fetchLobbies(): Promise { const url = '/lobbies'; try { const response = await fetch(url); @@ -71,22 +73,22 @@ class Client { throw new Error(`HTTP error! status: ${response.status}, statusText: ${response.statusText}`); } const data = await response.json(); - return data; + return data.lobbies; } catch (error) { console.error('Error fetching lobbies:', error); throw error; } } - private async joinLobby(lobbyID: string) { + private async joinLobby(lobby: Lobby) { clearInterval(this.lobbiesInterval) - this.lobbiesContainer.innerHTML = 'Joining'; // Clear existing lobbies + this.lobbiesContainer.innerHTML = `Joining: ${lobby.id}`; // Clear existing lobbies this.terrainMap.then((map) => { if (this.game != null) { return } // 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 = createClientGame(getUsername(), new PseudoRandom(Date.now()).nextID(), lobby.id, getConfig(), map) this.game.join() }) } diff --git a/src/client/ClientGame.ts b/src/client/ClientGame.ts index e5ee2bab8..47616c68e 100644 --- a/src/client/ClientGame.ts +++ b/src/client/ClientGame.ts @@ -65,7 +65,8 @@ export class ClientGame { ClientJoinMessageSchema.parse({ type: "join", gameID: this.gameID, - clientID: this.id + clientID: this.id, + lastTurn: this.turns.length }) ) ) @@ -74,7 +75,12 @@ export class ClientGame { const message: ServerMessage = ServerMessageSchema.parse(JSON.parse(event.data)) if (message.type == "start") { console.log("starting game!") - this.turns = message.turns + for (const turn of message.turns) { + if (turn.turnNumber < this.turns.length) { + continue + } + this.turns.push(turn) + } if (!this.isActive) { this.start() } @@ -148,6 +154,9 @@ export class ClientGame { } private inputEvent(event: MouseDownEvent) { + if (this.turns.length < this.config.turnsUntilGameStart()) { + return + } if (!this.isActive) { return } diff --git a/src/client/graphics/GameRenderer.ts b/src/client/graphics/GameRenderer.ts index 5ff388d52..363b6907e 100644 --- a/src/client/graphics/GameRenderer.ts +++ b/src/client/graphics/GameRenderer.ts @@ -1,10 +1,7 @@ import {Colord} from "colord"; -import {Cell, MutableGame, Game, PlayerEvent, Tile, TileEvent, Player, Execution, BoatEvent} from "../../core/Game"; +import {Cell, Game, PlayerEvent, Tile, TileEvent, Player, Execution, BoatEvent} from "../../core/Game"; import {Theme} from "../../core/configuration/Config"; import {DragEvent, ZoomEvent} from "../InputHandler"; -import {calculateBoundingBox, placeName} from "../NameBoxCalculator"; -import {PseudoRandom} from "../../core/PseudoRandom"; -import {BoatAttackExecution} from "../../core/execution/BoatAttackExecution"; import {NameRenderer} from "./NameRenderer"; diff --git a/src/client/index.html b/src/client/index.html index c8787e00b..2dab6c4fd 100644 --- a/src/client/index.html +++ b/src/client/index.html @@ -4,7 +4,7 @@ - Warfront + OpenFront