mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 15:10:21 +00:00
refactor: move worker into worker file
This commit is contained in:
@@ -13,7 +13,7 @@ import { SendAttackIntentEvent, SendSpawnIntentEvent, Transport } from "./Transp
|
||||
import { createCanvas } from "./graphics/Utils";
|
||||
import { DisplayMessageEvent, MessageType } from "./graphics/layers/EventsDisplay";
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { AsyncPathFinderCreator } from "../core/pathfinding/AsyncPathFinding";
|
||||
import { WorkerClient } from "../core/worker/WorkerClient";
|
||||
|
||||
|
||||
export interface LobbyConfig {
|
||||
@@ -72,9 +72,9 @@ export async function createClientGame(gameConfig: GameConfig, eventBus: EventBu
|
||||
|
||||
let game = createGame(terrainMap, eventBus, config)
|
||||
|
||||
const pathFinder = new AsyncPathFinderCreator(game, gameConfig.map)
|
||||
const worker = new WorkerClient(game, gameConfig.map)
|
||||
console.log('going to init path finder')
|
||||
await pathFinder.initialize()
|
||||
await worker.initialize()
|
||||
console.log('inited path finder')
|
||||
const canvas = createCanvas()
|
||||
let gameRenderer = createRenderer(canvas, game, eventBus, gameConfig.clientID)
|
||||
@@ -88,7 +88,7 @@ export async function createClientGame(gameConfig: GameConfig, eventBus: EventBu
|
||||
game,
|
||||
gameRenderer,
|
||||
new InputHandler(canvas, eventBus),
|
||||
new Executor(game, gameConfig.difficulty, gameConfig.gameID, pathFinder),
|
||||
new Executor(game, gameConfig.difficulty, gameConfig.gameID, worker),
|
||||
transport,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ import { DestroyerExecution } from "./DestroyerExecution";
|
||||
import { PortExecution } from "./PortExecution";
|
||||
import { MissileSiloExecution } from "./MissileSiloExecution";
|
||||
import { BattleshipExecution } from "./BattleshipExecution";
|
||||
import { AsyncPathFinderCreator } from "../pathfinding/AsyncPathFinding";
|
||||
import { PathFinder } from "../pathfinding/PathFinding";
|
||||
import { WorkerClient } from "../worker/WorkerClient";
|
||||
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ export class Executor {
|
||||
// private random = new PseudoRandom(999)
|
||||
private random: PseudoRandom = null
|
||||
|
||||
constructor(private gs: Game, private difficulty: Difficulty, private gameID: GameID, private asyncPathFinder: AsyncPathFinderCreator) {
|
||||
constructor(private gs: Game, private difficulty: Difficulty, private gameID: GameID, private workerClient: WorkerClient) {
|
||||
// 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.asyncPathFinder)
|
||||
return new PortExecution(intent.player, new Cell(intent.x, intent.y), this.workerClient)
|
||||
case UnitType.MissileSilo:
|
||||
return new MissileSiloExecution(intent.player, new Cell(intent.x, intent.y))
|
||||
default:
|
||||
@@ -113,7 +113,7 @@ export class Executor {
|
||||
const execs = []
|
||||
for (const nation of this.gs.nations()) {
|
||||
execs.push(new FakeHumanExecution(
|
||||
this.asyncPathFinder,
|
||||
this.workerClient,
|
||||
new PlayerInfo(
|
||||
nation.name,
|
||||
PlayerType.FakeHuman,
|
||||
|
||||
@@ -5,7 +5,7 @@ import { AttackExecution } from "./AttackExecution";
|
||||
import { TransportShipExecution } from "./TransportShipExecution";
|
||||
import { SpawnExecution } from "./SpawnExecution";
|
||||
import { PortExecution } from "./PortExecution";
|
||||
import { ParallelAStar, AsyncPathFinderCreator } from "../pathfinding/AsyncPathFinding";
|
||||
import { ParallelAStar, WorkerClient } from "../worker/WorkerClient";
|
||||
import { PathFinder } from "../pathfinding/PathFinding";
|
||||
|
||||
export class FakeHumanExecution implements Execution {
|
||||
@@ -23,7 +23,7 @@ export class FakeHumanExecution implements Execution {
|
||||
|
||||
private relations = new Map<Player, number>()
|
||||
|
||||
constructor(private asyncPathFinder: AsyncPathFinderCreator, private playerInfo: PlayerInfo, private cell: Cell, private strength: number) {
|
||||
constructor(private worker: WorkerClient, private playerInfo: PlayerInfo, private cell: Cell, private strength: number) {
|
||||
this.random = new PseudoRandom(simpleHash(playerInfo.id))
|
||||
}
|
||||
|
||||
@@ -153,7 +153,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.asyncPathFinder))
|
||||
this.mg.addExecution(new PortExecution(this.player.id(), buildTile.cell(), this.worker))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { SerialAStar } from "../pathfinding/SerialAStar";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
import { bfs, dist, manhattanDist } from "../Util";
|
||||
import { TradeShipExecution } from "./TradeShipExecution";
|
||||
import { ParallelAStar, AsyncPathFinderCreator } from "../pathfinding/AsyncPathFinding";
|
||||
import { ParallelAStar, WorkerClient } from "../worker/WorkerClient";
|
||||
|
||||
export class PortExecution implements Execution {
|
||||
|
||||
@@ -19,7 +19,7 @@ export class PortExecution implements Execution {
|
||||
constructor(
|
||||
private _owner: PlayerID,
|
||||
private cell: Cell,
|
||||
private asyncPathFinderCreator: AsyncPathFinderCreator
|
||||
private worker: WorkerClient
|
||||
) { }
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ export class PortExecution implements Execution {
|
||||
}
|
||||
continue
|
||||
}
|
||||
const asyncPF = this.asyncPathFinderCreator.createParallelAStar(this.port.tile(), port.tile(), 100)
|
||||
const asyncPF = this.worker.createParallelAStar(this.port.tile(), port.tile(), 100)
|
||||
// console.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)
|
||||
}
|
||||
@@ -96,7 +96,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.asyncPathFinderCreator, 30)
|
||||
const pf = PathFinder.Parallel(this.worker, 30)
|
||||
this.mg.addExecution(new TradeShipExecution(this.player().id(), this.port, port, pf, path))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import { PathFindResultType } from "../pathfinding/AStar";
|
||||
import { SerialAStar } from "../pathfinding/SerialAStar";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
import { bfs, dist, distSortUnit, manhattanDist } from "../Util";
|
||||
import { AsyncPathFinderCreator } from "../pathfinding/AsyncPathFinding";
|
||||
|
||||
export class TradeShipExecution implements Execution {
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Game, Tile } from "../game/Game";
|
||||
import { manhattanDist } from "../Util";
|
||||
import { AStar, PathFindResultType, TileResult } from "./AStar";
|
||||
import { AsyncPathFinderCreator, ParallelAStar } from "./AsyncPathFinding";
|
||||
import { ParallelAStar, WorkerClient } from "../worker/WorkerClient";
|
||||
import { SerialAStar } from "./SerialAStar";
|
||||
|
||||
export class PathFinder {
|
||||
@@ -29,10 +29,10 @@ export class PathFinder {
|
||||
)
|
||||
}
|
||||
|
||||
public static Parallel(creator: AsyncPathFinderCreator, numTicks: number): PathFinder {
|
||||
public static Parallel(worker: WorkerClient, numTicks: number): PathFinder {
|
||||
return new PathFinder(
|
||||
(curr: Tile, dst: Tile) => {
|
||||
return creator.createParallelAStar(curr, dst, numTicks)
|
||||
return worker.createParallelAStar(curr, dst, numTicks)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
// pathfinding.ts
|
||||
import { Cell, GameMap, TerrainMap, TerrainTile, TerrainType } from "../game/Game";
|
||||
import { SearchNode } from "./AStar";
|
||||
import { PathFindResultType } from "./AStar";
|
||||
import { SerialAStar } from "./SerialAStar";
|
||||
import { loadTerrainMap } from "../game/TerrainMapLoader";
|
||||
import { PriorityQueue } from "@datastructures-js/priority-queue";
|
||||
import { SerialAStar } from "../pathfinding/SerialAStar";
|
||||
import { PathFindResultType, SearchNode } from "../pathfinding/AStar";
|
||||
|
||||
let terrainMapPromise: Promise<TerrainMap>;
|
||||
let searches = new PriorityQueue<Search>((a: Search, b: Search) => (a.deadline - b.deadline))
|
||||
@@ -98,4 +97,4 @@ function computeSearches() {
|
||||
} finally {
|
||||
isProcessingSearch = false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,15 @@
|
||||
import { TerrainTile, Tile, Game, GameMap, Cell } from "../game/Game";
|
||||
import { AStar, PathFindResultType } from "./AStar";
|
||||
import { Cell, Game, GameMap, Tile } from "../game/Game";
|
||||
import { AStar, PathFindResultType } from "../pathfinding/AStar";
|
||||
|
||||
export class AsyncPathFinderCreator {
|
||||
|
||||
export class WorkerClient {
|
||||
private worker: Worker;
|
||||
private isInitialized = false;
|
||||
|
||||
constructor(private game: Game, private gameMap: GameMap) {
|
||||
// Create a new worker using webpack worker-loader
|
||||
// The import.meta.url ensures webpack can properly bundle the worker
|
||||
this.worker = new Worker(new URL('./PathFinder.worker.ts', import.meta.url));
|
||||
this.worker = new Worker(new URL('./Worker.worker.ts', import.meta.url));
|
||||
}
|
||||
|
||||
initialize(): Promise<void> {
|
||||
@@ -44,7 +45,6 @@ export class AsyncPathFinderCreator {
|
||||
this.worker.terminate();
|
||||
}
|
||||
}
|
||||
|
||||
export class ParallelAStar implements AStar {
|
||||
private path: Tile[] | 'NOT_FOUND' | null = null;
|
||||
private promise: Promise<void>;
|
||||
@@ -58,15 +58,15 @@ export class ParallelAStar implements AStar {
|
||||
) { }
|
||||
|
||||
findPath(): Promise<void> {
|
||||
const requestId = crypto.randomUUID()
|
||||
const requestId = crypto.randomUUID();
|
||||
this.promise = new Promise((resolve, reject) => {
|
||||
const timeout = setTimeout(() => {
|
||||
reject("Path timeout");
|
||||
}, 100_000);
|
||||
}, 100000);
|
||||
|
||||
const handler = (e: MessageEvent) => {
|
||||
if (e.data.requestId != requestId) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
clearTimeout(timeout);
|
||||
this.worker.removeEventListener('message', handler);
|
||||
@@ -75,7 +75,7 @@ export class ParallelAStar implements AStar {
|
||||
this.path = e.data.path.map(pos => this.game.tile(new Cell(pos.x, pos.y)));
|
||||
resolve();
|
||||
} else if (e.data.type === 'pathNotFound') {
|
||||
this.path = 'NOT_FOUND'
|
||||
this.path = 'NOT_FOUND';
|
||||
} else {
|
||||
reject(e.data.reason || "Path not found");
|
||||
}
|
||||
@@ -98,26 +98,27 @@ export class ParallelAStar implements AStar {
|
||||
// TODO: rename to poll?
|
||||
compute(): PathFindResultType {
|
||||
if (this.promise == null) {
|
||||
this.findPath()
|
||||
this.findPath();
|
||||
}
|
||||
this.numTicks--;
|
||||
if (this.numTicks <= 0) {
|
||||
if (this.path == 'NOT_FOUND') {
|
||||
return PathFindResultType.PathNotFound
|
||||
return PathFindResultType.PathNotFound;
|
||||
}
|
||||
if (this.path != null) {
|
||||
return PathFindResultType.Completed;
|
||||
}
|
||||
throw new Error(`path not completed in time`)
|
||||
throw new Error(`path not completed in time`);
|
||||
}
|
||||
return PathFindResultType.Pending;
|
||||
}
|
||||
|
||||
reconstructPath(): Tile[] {
|
||||
if (this.path == "NOT_FOUND" || this.path == null) {
|
||||
throw Error(`cannot reconstruct path: ${this.path}`)
|
||||
throw Error(`cannot reconstruct path: ${this.path}`);
|
||||
}
|
||||
return this.path as Tile[]
|
||||
return this.path as Tile[];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user