diff --git a/src/client/ClientGameRunner.ts b/src/client/ClientGameRunner.ts index 65eed6d28..36c575ae6 100644 --- a/src/client/ClientGameRunner.ts +++ b/src/client/ClientGameRunner.ts @@ -1,5 +1,5 @@ import { Executor } from "../core/execution/ExecutionManager"; -import { Cell, MutableGame, PlayerID, MutablePlayer, TileEvent, Player, Game, UnitEvent, Tile, PlayerType, GameMap, Difficulty, GameType } from "../core/game/Game"; +import { Cell, MutableGame, PlayerID, GameMap, Difficulty, GameType } from "../core/game/Game"; import { createGame } from "../core/game/GameImpl"; import { EventBus } from "../core/EventBus"; import { createRenderer, GameRenderer } from "./graphics/GameRenderer"; diff --git a/src/client/graphics/layers/EventsDisplay.ts b/src/client/graphics/layers/EventsDisplay.ts index 14283f96b..a7e6e592e 100644 --- a/src/client/graphics/layers/EventsDisplay.ts +++ b/src/client/graphics/layers/EventsDisplay.ts @@ -2,15 +2,8 @@ import { LitElement, html, css } from 'lit'; import { customElement, property, state } from 'lit/decorators.js'; import { EventBus } from "../../../core/EventBus"; import { - AllianceExpiredEvent, - AllianceRequestEvent, - AllianceRequestReplyEvent, AllPlayers, - BrokeAllianceEvent, DisplayMessageEvent, EmojiMessageEvent, - Game, MessageType, - Player, TargetPlayerEvent, - UnitEvent } from "../../../core/game/Game"; import { ClientID } from "../../../core/Schemas"; import { Layer } from "./Layer"; diff --git a/src/client/graphics/layers/UILayer.ts b/src/client/graphics/layers/UILayer.ts index 9bf976eb2..85a040dd2 100644 --- a/src/client/graphics/layers/UILayer.ts +++ b/src/client/graphics/layers/UILayer.ts @@ -1,6 +1,6 @@ import { EventBus } from "../../../core/EventBus"; import { WinEvent } from "../../../core/execution/WinCheckExecution"; -import { AllianceRequest, AllianceRequestReplyEvent, Game, Player } from "../../../core/game/Game"; +import { Player } from "../../../core/game/Game"; import { ClientID } from "../../../core/Schemas"; import { Layer } from "./Layer"; import { TransformHandler } from "../TransformHandler"; diff --git a/src/client/graphics/layers/UnitLayer.ts b/src/client/graphics/layers/UnitLayer.ts index e6588b40b..034616d1b 100644 --- a/src/client/graphics/layers/UnitLayer.ts +++ b/src/client/graphics/layers/UnitLayer.ts @@ -1,6 +1,6 @@ import { Colord } from "colord"; import { Theme } from "../../../core/configuration/Config"; -import { Unit, UnitEvent, Cell, Game, Tile, UnitType, Player } from "../../../core/game/Game"; +import { Unit, Cell, Game, Tile, UnitType, Player } from "../../../core/game/Game"; import { bfs, dist, euclDist } from "../../../core/Util"; import { Layer } from "./Layer"; import { EventBus } from "../../../core/EventBus"; @@ -76,7 +76,7 @@ export class UnitLayer implements Layer { this.canvas.width = this.game.width(); this.canvas.height = this.game.height(); for (const unit of this.game.units()) { - this.onUnitEvent(new UnitEvent(unit, unit.tile())) + // this.onUnitEvent(new UnitEvent(unit, unit.tile())) } } @@ -176,22 +176,22 @@ export class UnitLayer implements Layer { } - private handleTradeShipEvent(event: UnitEvent) { - const rel = this.relationship(event.unit) - bfs(event.oldTile, euclDist(event.oldTile, 3)).forEach(t => { + private handleTradeShipEvent(unit: Unit) { + const rel = this.relationship(unit) + bfs(unit.oldTile, euclDist(unit.oldTile, 3)).forEach(t => { this.clearCell(t.cell()); }); - if (event.unit.isActive()) { - bfs(event.unit.tile(), dist(event.unit.tile(), 2)) - .forEach(t => this.paintCell(t.cell(), rel, this.theme.territoryColor(event.unit.owner().info()), 255)); + if (unit.isActive()) { + bfs(unit.tile(), dist(unit.tile(), 2)) + .forEach(t => this.paintCell(t.cell(), rel, this.theme.territoryColor(unit.owner().info()), 255)); } - if (event.unit.isActive()) { - bfs(event.unit.tile(), dist(event.unit.tile(), 1)) - .forEach(t => this.paintCell(t.cell(), rel, this.theme.borderColor(event.unit.owner().info()), 255)); + if (unit.isActive()) { + bfs(unit.tile(), dist(unit.tile(), 1)) + .forEach(t => this.paintCell(t.cell(), rel, this.theme.borderColor(unit.owner().info()), 255)); } } - private handleBoatEvent(event: UnitEvent) { + private handleBoatEvent(event: Unit) { const rel = this.relationship(event.unit) if (!this.boatToTrail.has(event.unit)) { this.boatToTrail.set(event.unit, new Set()); diff --git a/src/core/GameRunner.ts b/src/core/GameRunner.ts index d6c23b558..ac406af7a 100644 --- a/src/core/GameRunner.ts +++ b/src/core/GameRunner.ts @@ -3,7 +3,7 @@ import { getConfig } from "./configuration/Config"; import { EventBus } from "./EventBus"; import { Executor } from "./execution/ExecutionManager"; import { WinCheckExecution } from "./execution/WinCheckExecution"; -import { Cell, DisplayMessageEvent, Game, MessageType, MutableGame, MutableTile, Player, PlayerID, Tile, TileEvent, UnitType } from "./game/Game"; +import { Cell, DisplayMessageEvent, Game, MessageType, MutableGame, MutableTile, Player, PlayerID, Tile, UnitType } from "./game/Game"; import { createGame } from "./game/GameImpl"; import { loadTerrainMap } from "./game/TerrainMapLoader"; import { GameUpdateViewData, NameViewData, packTileData, PlayerActions, PlayerViewData } from "./GameView"; @@ -13,9 +13,8 @@ import { and, bfs, dist, targetTransportTile } from "./Util"; export async function createGameRunner(gameID: string, gameConfig: GameConfig, callBack: (gu: GameUpdateViewData) => void): Promise { const config = getConfig(gameConfig) const terrainMap = await loadTerrainMap(gameConfig.gameMap); - const eventBus = new EventBus() - const game = createGame(terrainMap.map, terrainMap.miniMap, eventBus, config) - const gr = new GameRunner(game as MutableGame, eventBus, new Executor(game, gameID), callBack) + const game = createGame(terrainMap.map, terrainMap.miniMap, config) + const gr = new GameRunner(game as MutableGame, new Executor(game, gameID), callBack) gr.init() return gr } @@ -31,21 +30,17 @@ export class GameRunner { constructor( public game: MutableGame, - private eventBus: EventBus, private execManager: Executor, private callBack: (gu: GameUpdateViewData) => void ) { } init() { - this.eventBus.on(TileEvent, (e) => { - this.updatedTiles.add(e.tile as MutableTile) - }) this.game.addExecution(...this.execManager.spawnBots(this.game.config().numBots())) if (this.game.config().spawnNPCs()) { this.game.addExecution(...this.execManager.fakeHumanExecutions()) } - this.game.addExecution(new WinCheckExecution(this.eventBus)) + this.game.addExecution(new WinCheckExecution()) this.tickInterval = setInterval(() => this.executeNextTick(), 10) } @@ -169,7 +164,7 @@ export class GameRunner { } // TODO: fix event bus if (tile.owner().isPlayer() && myPlayer.isAlliedWith(tile.owner() as Player)) { - this.eventBus.emit(new DisplayMessageEvent("Cannot attack ally", MessageType.WARN)) + // this.eventBus.emit(new DisplayMessageEvent("Cannot attack ally", MessageType.WARN)) return false } if (!tile.terrain().isLand()) { diff --git a/src/core/execution/BotSpawner.ts b/src/core/execution/BotSpawner.ts index 7580a01d7..d10ba59ba 100644 --- a/src/core/execution/BotSpawner.ts +++ b/src/core/execution/BotSpawner.ts @@ -1,5 +1,5 @@ import { consolex } from "../Consolex"; -import {Cell, Game, PlayerType, Tile, TileEvent} from "../game/Game"; +import {Cell, Game, PlayerType, Tile} from "../game/Game"; import {PseudoRandom} from "../PseudoRandom"; import {GameID, SpawnIntent} from "../Schemas"; import {bfs, dist as dist, manhattanDist, simpleHash} from "../Util"; diff --git a/src/core/execution/ExecutionManager.ts b/src/core/execution/ExecutionManager.ts index 74e569537..d2058633b 100644 --- a/src/core/execution/ExecutionManager.ts +++ b/src/core/execution/ExecutionManager.ts @@ -1,4 +1,4 @@ -import { Cell, Execution, MutableGame, Game, MutablePlayer, PlayerInfo, TerraNullius, Tile, PlayerType, Alliance, AllianceRequestReplyEvent, Difficulty, UnitType } from "../game/Game"; +import { Cell, Execution, MutableGame, Game, MutablePlayer, PlayerInfo, TerraNullius, Tile, PlayerType, Alliance, UnitType } from "../game/Game"; import { AttackIntent, BoatAttackIntentSchema, GameID, Intent, Turn } from "../Schemas"; import { AttackExecution } from "./AttackExecution"; import { SpawnExecution } from "./SpawnExecution"; diff --git a/src/core/execution/TransportShipExecution.ts b/src/core/execution/TransportShipExecution.ts index 34a0e40f1..0a0183406 100644 --- a/src/core/execution/TransportShipExecution.ts +++ b/src/core/execution/TransportShipExecution.ts @@ -1,4 +1,4 @@ -import { Unit, Cell, Execution, MutableUnit, MutableGame, MutablePlayer, Player, PlayerID, TerraNullius, Tile, TileEvent, UnitType, TerrainType } from "../game/Game"; +import { Unit, Cell, Execution, MutableUnit, MutableGame, MutablePlayer, Player, PlayerID, TerraNullius, Tile, UnitType, TerrainType } from "../game/Game"; import { and, bfs, manhattanDistWrapped, sourceDstOceanShore, targetTransportTile } from "../Util"; import { AttackExecution } from "./AttackExecution"; import { MessageType } from '../game/Game'; diff --git a/src/core/execution/WinCheckExecution.ts b/src/core/execution/WinCheckExecution.ts index 08ac55e8a..512ce4ddd 100644 --- a/src/core/execution/WinCheckExecution.ts +++ b/src/core/execution/WinCheckExecution.ts @@ -11,7 +11,7 @@ export class WinCheckExecution implements Execution { private mg: MutableGame - constructor(private eventBus: EventBus) { + constructor() { } init(mg: MutableGame, ticks: number) { @@ -28,7 +28,7 @@ export class WinCheckExecution implements Execution { } const max = sorted[0] if (max.numTilesOwned() / this.mg.terrainMap().numLandTiles() * 100 > this.mg.config().percentageTilesOwnedToWin()) { - this.eventBus.emit(new WinEvent(max)) + this.mg.setWinner(max) this.active = false } } diff --git a/src/core/game/AllianceRequestImpl.ts b/src/core/game/AllianceRequestImpl.ts index 696aef8fa..eec388ad7 100644 --- a/src/core/game/AllianceRequestImpl.ts +++ b/src/core/game/AllianceRequestImpl.ts @@ -1,4 +1,4 @@ -import { MutableAllianceRequest, MutablePlayer, Player, Tick } from "./Game"; +import { AllianceRequestUpdate, GameUpdateType, MutableAllianceRequest, MutablePlayer, Player, Tick } from "./Game"; import { GameImpl } from "./GameImpl"; @@ -25,4 +25,13 @@ export class AllianceRequestImpl implements MutableAllianceRequest { this.game.rejectAllianceRequest(this) } + toUpdate(): AllianceRequestUpdate { + return { + type: GameUpdateType.AllianceRequest, + requestorID: this.requestor_.smallID(), + recipientID: this.recipient_.smallID(), + createdAt: this.tickCreated, + } + } + } diff --git a/src/core/game/Game.ts b/src/core/game/Game.ts index 684ffd81d..2ce9c56ca 100644 --- a/src/core/game/Game.ts +++ b/src/core/game/Game.ts @@ -10,6 +10,11 @@ export type Gold = number export const AllPlayers = "AllPlayers" as const; +export interface MapPos { + x: number + y: number +} + export enum Difficulty { Easy = "Easy", Medium = "Medium", @@ -89,6 +94,13 @@ export class Cell { this.strRepr = `Cell[${this.x},${this.y}]` } + pos(): MapPos { + return { + x: this.x, + y: this.y + } + } + toString(): string { return this.strRepr } } @@ -150,6 +162,7 @@ export class PlayerInfo { public readonly playerType: PlayerType, // null if bot. public readonly clientID: ClientID | null, + // TODO: make player id the small id public readonly id: PlayerID ) { } } @@ -199,6 +212,7 @@ export interface MutableTile extends Tile, ViewSerializable { borders(other: Player | TerraNullius): boolean neighborsWrapped(): Tile[] defenseBonuses(): DefenseBonus[] + toUpdate(isBorderOnly: boolean): TileUpdate } export interface Unit { @@ -354,47 +368,105 @@ export interface MutableGame extends Game { units(...types: UnitType[]): MutableUnit[] addTileDefenseBonus(tile: Tile, unit: Unit, amount: number): DefenseBonus removeTileDefenseBonus(bonus: DefenseBonus): void - addFallout(tile: Tile) + addFallout(tile: Tile): void + setWinner(winner: Player): void } -export class TileEvent implements GameEvent { - constructor(public readonly tile: Tile, public readonly borderOnlyChange: boolean = false) { } +export enum GameUpdateType { + Tile, + Unit, + DisplayEvent, + AllianceRequest, + AllianceRequestReply, + BrokeAlliance, + AllianceExpired, + TargetPlayer, + EmojiUpdate, + WinUpdate } -export class UnitEvent implements GameEvent { - constructor(public readonly unit: Unit, public oldTile: Tile) { } +export type GameUpdate = TileUpdate + | UnitUpdate + | AllianceRequestUpdate + | AllianceRequestReplyUpdate + | BrokeAllianceUpdate + | AllianceExpiredUpdate + | DisplayMessageEvent + | TargetPlayerUpdate + | EmojiUpdate + | WinUpdate + +export interface TileUpdate { + type: GameUpdateType.Tile + owner: number + pos: MapPos + isBorder: boolean + borderOnlyChange: boolean + hasFallout: boolean + hasDefenseBonus: boolean } -export class AllianceRequestEvent implements GameEvent { - constructor(public readonly allianceRequest: AllianceRequest) { } +export interface UnitUpdate { + type: GameUpdateType.Unit + unitType: UnitType + troops: number + id: number + ownerID: number + pos: MapPos + oldPos: MapPos + isActive: boolean + health?: boolean } -export class AllianceRequestReplyEvent implements GameEvent { - constructor(public readonly allianceRequest: AllianceRequest, public readonly accepted: boolean) { } +export interface AllianceRequestUpdate { + type: GameUpdateType.AllianceRequest + requestorID: number, + recipientID: number, + createdAt: Tick, } -export class BrokeAllianceEvent implements GameEvent { - constructor(public readonly traitor: Player, public readonly betrayed: Player) { } +export interface AllianceRequestReplyUpdate { + type: GameUpdateType.AllianceRequestReply + request: AllianceRequestUpdate + accepted: boolean } -export class AllianceExpiredEvent implements GameEvent { - constructor(public readonly player1: Player, public readonly player2: Player) { } +export interface BrokeAllianceUpdate { + type: GameUpdateType.BrokeAlliance + traitorID: number + betrayedID: number } -export class TargetPlayerEvent implements GameEvent { - constructor(public readonly player: Player, public readonly target: Player) { } +export interface AllianceExpiredUpdate { + type: GameUpdateType.AllianceExpired + player1: number + player2: number } -export class EmojiMessageEvent implements GameEvent { - constructor(public readonly message: EmojiMessage) { } +export interface TargetPlayerUpdate { + type: GameUpdateType.TargetPlayer + playerID: number + targetID: number } -export class DisplayMessageEvent implements GameEvent { - constructor( - public readonly message: string, - public readonly type: MessageType, - public readonly playerID: PlayerID | null = null - ) { } +export interface EmojiUpdate { + type: GameUpdateType.EmojiUpdate + message: string + senderID: number + recipientID: number | typeof AllPlayers + createdAt: Tick +} + +export interface DisplayMessageEvent { + type: GameUpdateType.DisplayEvent + message: string + messageType: MessageType + playerID: number | null +} + +export interface WinUpdate { + type: GameUpdateType.WinUpdate + winnerID: number, } export enum MessageType { diff --git a/src/core/game/GameImpl.ts b/src/core/game/GameImpl.ts index dfe3cebc1..890aab31d 100644 --- a/src/core/game/GameImpl.ts +++ b/src/core/game/GameImpl.ts @@ -1,7 +1,5 @@ -import { info } from "console"; import { Config } from "../configuration/Config"; -import { EventBus } from "../EventBus"; -import { Cell, Execution, MutableGame, Game, MutablePlayer, PlayerID, PlayerInfo, Player, TerraNullius, Tile, TileEvent, Unit, UnitEvent as UnitEvent, PlayerType, MutableAllianceRequest, AllianceRequestReplyEvent, AllianceRequestEvent, BrokeAllianceEvent, MutableAlliance, Alliance, AllianceExpiredEvent, Nation, UnitType, UnitInfo, TerrainMap, DefenseBonus, MutableTile } from "./Game"; +import { Cell, Execution, MutableGame, Game, MutablePlayer, PlayerID, PlayerInfo, Player, TerraNullius, Tile, Unit, MutableAllianceRequest, Alliance, Nation, UnitType, UnitInfo, TerrainMap, DefenseBonus, MutableTile, GameUpdate, GameUpdateType, AllPlayers } from "./Game"; import { TerrainMapImpl } from "./TerrainMapLoader"; import { PlayerImpl } from "./PlayerImpl"; import { TerraNulliusImpl } from "./TerraNulliusImpl"; @@ -10,12 +8,12 @@ import { AllianceRequestImpl } from "./AllianceRequestImpl"; import { AllianceImpl } from "./AllianceImpl"; import { ClientID, GameConfig } from "../Schemas"; import { MessageType } from './Game'; -import { DisplayMessageEvent } from './Game'; import { UnitImpl } from "./UnitImpl"; import { consolex } from "../Consolex"; +import { string } from "zod"; -export function createGame(terrainMap: TerrainMapImpl, miniMap: TerrainMap, eventBus: EventBus, config: Config): Game { - return new GameImpl(terrainMap, miniMap, eventBus, config) +export function createGame(terrainMap: TerrainMapImpl, miniMap: TerrainMap, config: Config): Game { + return new GameImpl(terrainMap, miniMap, config) } export type CellString = string @@ -43,11 +41,11 @@ export class GameImpl implements MutableGame { private nextPlayerID = 1 private _nextUnitID = 1 + private updates: GameUpdate[] = [] constructor( private _terrainMap: TerrainMapImpl, private _miniMap: TerrainMap, - public eventBus: EventBus, private _config: Config, ) { this._terraNullius = new TerraNulliusImpl() @@ -81,20 +79,20 @@ export class GameImpl implements MutableGame { throw Error(`cannot set fallout, tile ${tile} has owner`) } ti._hasFallout = true - this.eventBus.emit(new TileEvent(tile)) + this.updates.push(ti.toUpdate(false)) } addTileDefenseBonus(tile: Tile, unit: Unit, amount: number): DefenseBonus { const df = { unit: unit, tile: tile, amount: amount }; (tile as TileImpl)._defenseBonuses.push(df) - this.eventBus.emit(new TileEvent(tile)) + this.updates.push((tile as TileImpl).toUpdate()) return df } removeTileDefenseBonus(bonus: DefenseBonus): void { const t = bonus.tile as TileImpl t._defenseBonuses = t._defenseBonuses.filter(db => db != bonus) - this.eventBus.emit(new TileEvent(bonus.tile)) + this.updates.push(t.toUpdate()) } units(...types: UnitType[]): UnitImpl[] { @@ -124,7 +122,7 @@ export class GameImpl implements MutableGame { } const ar = new AllianceRequestImpl(requestor, recipient, this._ticks, this) this.allianceRequests.push(ar) - this.eventBus.emit(new AllianceRequestEvent(ar)) + this.updates.push(ar.toUpdate()) return ar } @@ -133,13 +131,22 @@ export class GameImpl implements MutableGame { const alliance = new AllianceImpl(this, request.requestor() as PlayerImpl, request.recipient() as PlayerImpl, this._ticks) this.alliances_.push(alliance); (request.requestor() as PlayerImpl).pastOutgoingAllianceRequests.push(request) - this.eventBus.emit(new AllianceRequestReplyEvent(request, true)) + this.updates.push({ + type: GameUpdateType.AllianceRequestReply, + request: request.toUpdate(), + accepted: true, + + }) } rejectAllianceRequest(request: AllianceRequestImpl) { this.allianceRequests = this.allianceRequests.filter(ar => ar != request); (request.requestor() as PlayerImpl).pastOutgoingAllianceRequests.push(request) - this.eventBus.emit(new AllianceRequestReplyEvent(request, false)) + this.updates.push({ + type: GameUpdateType.AllianceRequestReply, + request: request.toUpdate(), + accepted: true + }) } hasPlayer(id: PlayerID): boolean { @@ -348,7 +355,7 @@ export class GameImpl implements MutableGame { owner._lastTileChange = this._ticks this.updateBorders(tile) tileImpl._hasFallout = false - this.eventBus.emit(new TileEvent(tile)) + this.updates.push((tile as TileImpl).toUpdate()) } relinquish(tile: Tile) { @@ -368,7 +375,9 @@ export class GameImpl implements MutableGame { tileImpl._owner = this._terraNullius this.updateBorders(tile) - this.eventBus.emit(new TileEvent(tile)) + this.updates.push( + (tile as TileImpl).toUpdate() + ) } private updateBorders(tile: Tile) { @@ -377,7 +386,7 @@ export class GameImpl implements MutableGame { tile.neighbors().forEach(t => tiles.push(t as TileImpl)) for (const t of tiles) { - this.eventBus.emit(new TileEvent(t, true)) + this.updates.push(t.toUpdate(true)) if (!t.hasOwner()) { t._isBorder = false continue @@ -405,8 +414,16 @@ export class GameImpl implements MutableGame { return false } - public fireUnitUpdateEvent(boat: Unit, oldTile: Tile) { - this.eventBus.emit(new UnitEvent(boat, oldTile)) + public fireUnitUpdateEvent(unit: Unit, oldTile: Tile) { + this.updates.push((unit as UnitImpl).toUpdate(oldTile)) + } + + target(targeter: Player, target: Player) { + this.updates.push({ + type: GameUpdateType.TargetPlayer, + playerID: targeter.smallID(), + targetID: target.smallID(), + }) } public breakAlliance(breaker: Player, alliance: Alliance) { @@ -429,7 +446,12 @@ export class GameImpl implements MutableGame { throw new Error(`must have exactly one alliance, have ${alliances.length}`) } this.alliances_ = this.alliances_.filter(a => a != alliances[0]) - this.eventBus.emit(new BrokeAllianceEvent(breaker, other)) + this.updates.push({ + type: GameUpdateType.BrokeAlliance, + traitorID: breaker.smallID(), + betrayedID: other.smallID() + + }) } public expireAlliance(alliance: Alliance) { @@ -439,7 +461,30 @@ export class GameImpl implements MutableGame { throw new Error(`cannot expire alliance: must have exactly one alliance, have ${alliances.length}`) } this.alliances_ = this.alliances_.filter(a => a != alliances[0]) - this.eventBus.emit(new AllianceExpiredEvent(alliance.requestor(), alliance.recipient())) + this.updates.push({ + type: GameUpdateType.AllianceExpired, + player1: alliance.requestor().smallID(), + player2: alliance.recipient().smallID() + }) + } + + sendEmojiUpdate(sender: Player, recipient: Player | typeof AllPlayers, emoji: string): void { + const recipientID = recipient === AllPlayers ? recipient : recipient.smallID(); + + this.updates.push({ + type: GameUpdateType.EmojiUpdate, + message: emoji, + senderID: sender.smallID(), + recipientID: recipientID, + createdAt: this._ticks + }) + } + + setWinner(winner: Player): void { + this.updates.push({ + type: GameUpdateType.WinUpdate, + winnerID: winner.smallID() + }) } public terrainMap(): TerrainMapImpl { @@ -451,7 +496,15 @@ export class GameImpl implements MutableGame { } displayMessage(message: string, type: MessageType, playerID: PlayerID | null): void { - this.eventBus.emit(new DisplayMessageEvent(message, type, playerID)) + let id = null + if (playerID != null) { + id = this.player(playerID).smallID() + } + this.updates.push({ + type: GameUpdateType.DisplayEvent, + messageType: type, + message: message, + playerID: id + }) } - } \ No newline at end of file diff --git a/src/core/game/PlayerImpl.ts b/src/core/game/PlayerImpl.ts index 8644d50e6..85eca3ca6 100644 --- a/src/core/game/PlayerImpl.ts +++ b/src/core/game/PlayerImpl.ts @@ -1,4 +1,4 @@ -import { MutablePlayer, Tile, PlayerInfo, PlayerID, PlayerType, Player, TerraNullius, Cell, Execution, AllianceRequest, MutableAllianceRequest, MutableAlliance, Alliance, Tick, TargetPlayerEvent, EmojiMessage, EmojiMessageEvent, AllPlayers, Gold, UnitType, Unit, MutableUnit, Relation, MutableTile } from "./Game"; +import { MutablePlayer, Tile, PlayerInfo, PlayerID, PlayerType, Player, TerraNullius, Cell, Execution, AllianceRequest, MutableAllianceRequest, MutableAlliance, Alliance, Tick, EmojiMessage, AllPlayers, Gold, UnitType, Unit, MutableUnit, Relation, MutableTile } from "./Game"; import { ClientID } from "../Schemas"; import { assertNever, bfs, closestOceanShoreFromPlayer, dist, distSortUnit, manhattanDist, manhattanDistWrapped, processName, simpleHash, sourceDstOceanShore, within } from "../Util"; import { CellString, GameImpl } from "./GameImpl"; @@ -6,7 +6,7 @@ import { UnitImpl } from "./UnitImpl"; import { TileImpl } from "./TileImpl"; import { MessageType } from './Game'; import { renderTroops } from "../../client/Utils"; -import { PlayerViewData, ViewData, ViewSerializable } from "../GameView"; +import { PlayerViewData } from "../GameView"; interface Target { tick: Tick @@ -291,7 +291,7 @@ export class PlayerImpl implements MutablePlayer { target(other: Player): void { this.targets_.push({ tick: this.gs.ticks(), target: other }) - this.gs.eventBus.emit(new TargetPlayerEvent(this, other)) + this.gs.target(this, other) } targets(): PlayerImpl[] { @@ -312,7 +312,7 @@ export class PlayerImpl implements MutablePlayer { } const msg = new EmojiMessage(this, recipient, emoji, this.gs.ticks()) this.outgoingEmojis_.push(msg) - this.gs.eventBus.emit(new EmojiMessageEvent(msg)) + this.gs.sendEmojiUpdate(this, recipient, emoji) } outgoingEmojis(): EmojiMessage[] { diff --git a/src/core/game/TileImpl.ts b/src/core/game/TileImpl.ts index 5cf699e21..72bbe5383 100644 --- a/src/core/game/TileImpl.ts +++ b/src/core/game/TileImpl.ts @@ -1,4 +1,4 @@ -import { Tile, Cell, TerrainType, Player, TerraNullius, MutablePlayer, TerrainTile, DefenseBonus, MutableTile } from "./Game"; +import { Tile, Cell, TerrainType, Player, TerraNullius, MutablePlayer, TerrainTile, DefenseBonus, MutableTile, TileUpdate, GameUpdateType } from "./Game"; import { SearchNode } from "../pathfinding/AStar"; import { TerrainTileImpl } from "./TerrainMapLoader"; import { GameImpl } from "./GameImpl"; @@ -24,13 +24,21 @@ export class TileImpl implements MutableTile { ) { } toViewData(): TileViewData { + throw new Error("Method not implemented."); + } + + toUpdate(borderOnlyChange: boolean = false): TileUpdate { return { - x: this._cell.x, - y: this._cell.y, - smallID: this._owner.isPlayer() ? this._owner.smallID() : 0, + type: GameUpdateType.Tile, + pos: { + x: this._cell.x, + y: this._cell.y + }, + owner: this._owner.isPlayer() ? this._owner.smallID() : 0, hasFallout: this._hasFallout, hasDefenseBonus: this.hasDefenseBonus(), isBorder: this.isBorder(), + borderOnlyChange: borderOnlyChange } } diff --git a/src/core/game/UnitImpl.ts b/src/core/game/UnitImpl.ts index a21e69d8c..273f84793 100644 --- a/src/core/game/UnitImpl.ts +++ b/src/core/game/UnitImpl.ts @@ -1,4 +1,4 @@ -import { MessageType } from './Game'; +import { GameUpdateType, MessageType, UnitUpdate } from './Game'; import { UnitViewData, ViewData, ViewSerializable } from "../GameView"; import { simpleHash, within } from "../Util"; import { MutableUnit, Tile, TerraNullius, UnitType, Player, UnitInfo } from "./Game"; @@ -22,6 +22,19 @@ export class UnitImpl implements MutableUnit { this._health = (this.g.unitInfo(_type).maxHealth ?? 2) / 2 } + toUpdate(oldTile: Tile): UnitUpdate { + return { + type: GameUpdateType.Unit, + unitType: this._type, + id: this._id, + troops: this._troops, + ownerID: this._owner.smallID(), + isActive: this._active, + pos: this._tile.cell().pos(), + oldPos: oldTile.cell().pos() + } + } + toViewData(): UnitViewData { return { id: this._id,