create game runner

This commit is contained in:
Evan
2025-01-02 13:25:36 -08:00
parent 8a4644637a
commit 8443095d89
10 changed files with 100 additions and 32 deletions
@@ -69,16 +69,14 @@ export function joinLobby(lobbyConfig: LobbyConfig, onjoin: () => void): () => v
}
export async function createClientGame(lobbyConfig: LobbyConfig, gameConfig: GameConfig, eventBus: EventBus, transport: Transport): Promise<GameRunner> {
export async function createClientGame(lobbyConfig: LobbyConfig, gameConfig: GameConfig, eventBus: EventBus, transport: Transport): Promise<ClientGameRunner> {
const config = getConfig(gameConfig)
const terrainMap = await loadTerrainMap(gameConfig.gameMap);
let game = createGame(terrainMap.map, terrainMap.miniMap, eventBus, config)
const worker = new WorkerClient(game, gameConfig.gameMap)
consolex.log('going to init path finder')
await worker.initialize()
consolex.log('inited path finder')
const canvas = createCanvas()
let gameRenderer = createRenderer(canvas, game, eventBus, lobbyConfig.clientID)
@@ -86,18 +84,18 @@ export async function createClientGame(lobbyConfig: LobbyConfig, gameConfig: Gam
consolex.log(`creating private game got difficulty: ${gameConfig.difficulty}`)
return new GameRunner(
return new ClientGameRunner(
lobbyConfig.clientID,
eventBus,
game,
gameRenderer,
new InputHandler(canvas, eventBus),
new Executor(game, lobbyConfig.gameID, worker),
new Executor(game, lobbyConfig.gameID),
transport,
)
}
export class GameRunner {
export class ClientGameRunner {
private myPlayer: Player
private turns: Turn[] = []
private isActive = false
+1 -1
View File
@@ -3,7 +3,7 @@ import { consolex } from "../core/Consolex";
import { GameEvent } from "../core/EventBus";
import { ClientID, ClientMessage, ClientMessageSchema, GameConfig, GameID, GameRecordSchema, Intent, PlayerRecord, ServerMessage, ServerStartGameMessageSchema, ServerTurnMessageSchema, Turn } from "../core/Schemas";
import { CreateGameRecord, generateID } from "../core/Util";
import { LobbyConfig } from "./GameRunner";
import { LobbyConfig } from "./ClientGameRunner";
import { getPersistentIDFromCookie } from "./Main";
+1 -1
View File
@@ -1,4 +1,4 @@
import { GameRunner, joinLobby } from "./GameRunner";
import { ClientGameRunner, joinLobby } from "./ClientGameRunner";
import backgroundImage from '../../resources/images/TerrainMapFrontPage.png';
import favicon from '../../resources/images/Favicon.svg';
+1 -1
View File
@@ -3,7 +3,7 @@ import { SendLogEvent } from "../core/Consolex"
import { EventBus, GameEvent } from "../core/EventBus"
import { AllianceRequest, AllPlayers, Cell, GameType, Player, PlayerID, PlayerType, Tile, UnitType } from "../core/game/Game"
import { ClientID, ClientIntentMessageSchema, ClientJoinMessageSchema, GameID, Intent, ServerMessage, ServerMessageSchema, ClientPingMessageSchema, GameConfig, ClientLogMessageSchema } from "../core/Schemas"
import { LobbyConfig } from "./GameRunner"
import { LobbyConfig } from "./ClientGameRunner"
import { LocalServer } from "./LocalServer"
import { UsernameInput } from "./UsernameInput";
import { HostLobbyModal as HostPrivateLobbyModal } from "./HostLobbyModal";
+50
View File
@@ -0,0 +1,50 @@
import { getConfig } from "./configuration/Config";
import { EventBus } from "./EventBus";
import { Executor } from "./execution/ExecutionManager";
import { Game } from "./game/Game";
import { createGame } from "./game/GameImpl";
import { loadTerrainMap } from "./game/TerrainMapLoader";
import { GameConfig, Turn } from "./Schemas";
export interface GameUpdate {
players: PlayerUpdate[]
units: UnitUpdate[]
}
export interface PlayerUpdate {
}
export interface UnitUpdate {
}
export interface TileUpdate {
x: number
y: number
isBorder: boolean
}
export async function createGameRunner(gameID: string, gameConfig: GameConfig): Promise<GameRunner> {
const config = getConfig(gameConfig)
const terrainMap = await loadTerrainMap(gameConfig.gameMap);
const eventBus = new EventBus()
const game = createGame(terrainMap.map, terrainMap.miniMap, eventBus, config)
return new GameRunner(game, eventBus, new Executor(game, gameID))
}
export class GameRunner {
constructor(private game: Game, private eventBus: EventBus, private execManager: Executor) {
}
public executeNextTick(turn: Turn): GameUpdate {
this.game.executeNextTick()
return null
}
}
+26
View File
@@ -0,0 +1,26 @@
import { Cell, PlayerID } from "./game/Game";
import { GameUpdate } from "./GameRunner";
export class TileView {
}
export class PlayerView {
}
export class GameView {
public update(gu: GameUpdate) {
}
tile(cell: Cell): TileView {
return null
}
player(id: PlayerID): PlayerView {
return null
}
}
+2 -3
View File
@@ -32,7 +32,7 @@ export class Executor {
// private random = new PseudoRandom(999)
private random: PseudoRandom = null
constructor(private gs: Game, private gameID: GameID, private workerClient: WorkerClient) {
constructor(private gs: Game, private gameID: GameID) {
// Add one to avoid id collisions with bots.
this.random = new PseudoRandom(simpleHash(gameID) + 1)
}
@@ -94,7 +94,7 @@ export class Executor {
case UnitType.Battleship:
return new BattleshipExecution(intent.player, new Cell(intent.x, intent.y))
case UnitType.Port:
return new PortExecution(intent.player, new Cell(intent.x, intent.y), this.workerClient)
return new PortExecution(intent.player, new Cell(intent.x, intent.y))
case UnitType.MissileSilo:
return new MissileSiloExecution(intent.player, new Cell(intent.x, intent.y))
case UnitType.DefensePost:
@@ -118,7 +118,6 @@ export class Executor {
for (const nation of this.gs.nations()) {
execs.push(new FakeHumanExecution(
this.gameID,
this.workerClient,
new PlayerInfo(
nation.name,
PlayerType.FakeHuman,
+2 -2
View File
@@ -33,7 +33,7 @@ export class FakeHumanExecution implements Execution {
private lastEmojiSent = new Map<Player, Tick>()
constructor(gameID: GameID, private worker: WorkerClient, private playerInfo: PlayerInfo, private cell: Cell, private strength: number) {
constructor(gameID: GameID, private playerInfo: PlayerInfo, private cell: Cell, private strength: number) {
this.random = new PseudoRandom(simpleHash(playerInfo.id) + simpleHash(gameID))
}
@@ -265,7 +265,7 @@ export class FakeHumanExecution implements Execution {
const oceanTiles = Array.from(this.player.borderTiles()).filter(t => t.isOceanShore())
if (oceanTiles.length > 0) {
const buildTile = this.random.randElement(oceanTiles)
this.mg.addExecution(new PortExecution(this.player.id(), buildTile.cell(), this.worker))
this.mg.addExecution(new PortExecution(this.player.id(), buildTile.cell()))
}
return
}
+13 -6
View File
@@ -7,6 +7,7 @@ import { bfs, dist, manhattanDist } from "../Util";
import { TradeShipExecution } from "./TradeShipExecution";
import { ParallelAStar, WorkerClient } from "../worker/WorkerClient";
import { consolex } from "../Consolex";
import { MiniAStar } from "../pathfinding/MiniAStar";
export class PortExecution implements Execution {
@@ -15,12 +16,11 @@ export class PortExecution implements Execution {
private port: MutableUnit
private random: PseudoRandom
private portPaths = new Map<MutableUnit, Tile[]>()
private computingPaths = new Map<MutableUnit, ParallelAStar>()
private computingPaths = new Map<MutableUnit, MiniAStar>()
constructor(
private _owner: PlayerID,
private cell: Cell,
private worker: WorkerClient
) { }
@@ -84,9 +84,16 @@ export class PortExecution implements Execution {
}
continue
}
const asyncPF = this.worker.createParallelAStar(this.port.tile(), port.tile(), 25, [TerrainType.Ocean])
// consolex.log(`adding new port path from ${this.player().name()}:${this.port.tile().cell()} to ${port.owner().name()}:${port.tile().cell()}`)
this.computingPaths.set(port, asyncPF)
const pf = new MiniAStar(
this.mg.terrainMap(),
this.mg.terrainMiniMap(),
this.port.tile(), port.tile(),
sn => sn.terrainType() == TerrainType.Ocean,
10_000,
25
)
this.computingPaths.set(port, pf)
}
for (const port of this.portPaths.keys()) {
@@ -102,7 +109,7 @@ export class PortExecution implements Execution {
const port = this.random.randElement(portConnections)
const path = this.portPaths.get(port)
if (path != null) {
const pf = PathFinder.Parallel(this.mg, this.worker, 10)
const pf = PathFinder.Mini(this.mg, 10, (sn) => sn.terrainType() == TerrainType.Ocean)
this.mg.addExecution(new TradeShipExecution(this.player().id(), this.port, port, pf, path))
}
}
-12
View File
@@ -52,18 +52,6 @@ export class PathFinder {
)
}
public static Parallel(game: Game, worker: WorkerClient, numTicks: number, ...types: TerrainType[]): PathFinder {
if (types.length == 0) {
types = [TerrainType.Ocean]
}
return new PathFinder(
game,
(curr: Tile, dst: Tile) => {
return worker.createParallelAStar(curr, dst, numTicks, types)
}
)
}
nextTile(curr: Tile, dst: Tile, dist: number = 1): TileResult {
if (curr == null) {
consolex.error('curr is null')