diff --git a/src/client/Client.ts b/src/client/Client.ts index 08705d023..f00137dd4 100644 --- a/src/client/Client.ts +++ b/src/client/Client.ts @@ -22,7 +22,6 @@ class Client { constructor() { this.lobbiesContainer = document.getElementById('lobbies-container'); - } initialize(): void { diff --git a/src/client/ClientGame.ts b/src/client/ClientGame.ts index 2fba196c5..af97e383b 100644 --- a/src/client/ClientGame.ts +++ b/src/client/ClientGame.ts @@ -35,15 +35,14 @@ export class ClientGame { private socket: WebSocket private isActive = false - private ticksPerTurn = 1 - - private ticksThisTurn = 0 private currTurn = 0 private spawned = false private intervalID: NodeJS.Timeout + private isProcessingTurn = false + constructor( private playerName: string, private id: ClientID, @@ -76,6 +75,7 @@ export class ClientGame { const message: ServerMessage = ServerMessageSchema.parse(JSON.parse(event.data)) if (message.type == "start") { console.log("starting game!") + this.turns = message.turns if (!this.isActive) { this.start() } @@ -122,21 +122,22 @@ export class ClientGame { } public addTurn(turn: Turn): void { + if (this.turns.length != turn.turnNumber) { + console.error(`got wrong turn have turns ${this.turns.length}, received turn ${turn.turnNumber}`) + } this.turns.push(turn) } public tick() { - if (this.ticksThisTurn >= this.ticksPerTurn) { - if (this.currTurn >= this.turns.length) { - return - } - this.executor.addTurn(this.turns[this.currTurn]) - this.currTurn++ - this.ticksThisTurn = 0 + if (this.currTurn >= this.turns.length || this.isProcessingTurn) { + return } - this.ticksThisTurn++ + this.isProcessingTurn = true + this.gs.addExecution(...this.executor.createExecs(this.turns[this.currTurn])) this.gs.tick() this.renderer.tick() + this.currTurn++ + this.isProcessingTurn = false } private playerEvent(event: PlayerEvent) { diff --git a/src/core/GameImpl.ts b/src/core/GameImpl.ts index 363690899..38df7cb92 100644 --- a/src/core/GameImpl.ts +++ b/src/core/GameImpl.ts @@ -217,7 +217,7 @@ export class GameImpl implements MutableGame { this.execs.push(...this.unInitExecs) this.unInitExecs = [] this.ticks++ - if (this.ticks % 10) { + if (this.ticks % 100 == 0) { let hash = 1; this._players.forEach(p => { hash += p.hash() diff --git a/src/core/Schemas.ts b/src/core/Schemas.ts index de18e18e9..a6745f40c 100644 --- a/src/core/Schemas.ts +++ b/src/core/Schemas.ts @@ -77,6 +77,8 @@ export const ServerTurnMessageSchema = ServerBaseMessageSchema.extend({ export const ServerStartGameMessageSchema = ServerBaseMessageSchema.extend({ type: z.literal('start'), + // Turns the client missed if they are late to the game. + turns: z.array(TurnSchema) }) diff --git a/src/core/execution/BotExecution.ts b/src/core/execution/BotExecution.ts index f3aa26691..ce05c8d8b 100644 --- a/src/core/execution/BotExecution.ts +++ b/src/core/execution/BotExecution.ts @@ -29,6 +29,7 @@ export class BotExecution implements Execution { if (ticks < this.ticksUntilStart) { return } + return if (!this.bot.isAlive()) { this.active = false diff --git a/src/core/execution/Executor.ts b/src/core/execution/Executor.ts index c976bbb64..ff55b5eb2 100644 --- a/src/core/execution/Executor.ts +++ b/src/core/execution/Executor.ts @@ -14,38 +14,32 @@ export class Executor { } - addTurn(turn: Turn) { - turn.intents.forEach(i => this.addIntent(i)) + createExecs(turn: Turn): Execution[] { + return turn.intents.map(i => this.createExec(i)) } - addIntent(intent: Intent) { + createExec(intent: Intent) { if (intent.type == "attack") { - this.gs.addExecution( - new AttackExecution( - intent.troops, - intent.attackerID, - intent.targetID, - new Cell(intent.targetX, intent.targetY), - this.playerConfig - ) + return new AttackExecution( + intent.troops, + intent.attackerID, + intent.targetID, + new Cell(intent.targetX, intent.targetY), + this.playerConfig ) } else if (intent.type == "spawn") { - this.gs.addExecution( - new SpawnExecution( - new PlayerInfo(intent.name, intent.isBot, intent.clientID), - new Cell(intent.x, intent.y), - this.playerConfig - ) + return new SpawnExecution( + new PlayerInfo(intent.name, intent.isBot, intent.clientID), + new Cell(intent.x, intent.y), + this.playerConfig ) } else if (intent.type == "boat") { - this.gs.addExecution( - new BoatAttackExecution( - intent.attackerID, - intent.targetID, - new Cell(intent.x, intent.y), - intent.troops, - this.playerConfig - ) + return new BoatAttackExecution( + intent.attackerID, + intent.targetID, + new Cell(intent.x, intent.y), + intent.troops, + this.playerConfig ) } else { throw new Error(`intent type ${intent} not found`) @@ -54,6 +48,6 @@ export class Executor { spawnBots(numBots: number): void { - new BotSpawner(this.gs).spawnBots(numBots).forEach(i => this.addIntent(i)) + new BotSpawner(this.gs).spawnBots(numBots).forEach(i => this.createExec(i)) } } \ No newline at end of file diff --git a/src/server/GameServer.ts b/src/server/GameServer.ts index d4ec587b4..be91206ce 100644 --- a/src/server/GameServer.ts +++ b/src/server/GameServer.ts @@ -66,7 +66,9 @@ export class GameServer { private sendStartGameMsg(ws: WebSocket) { ws.send(JSON.stringify(ServerStartGameMessageSchema.parse( { - type: "start" + type: "start", + // TODO: this could get large + turns: this.turns } ))) }