mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-22 03:43:48 +00:00
multithreading: radial menu works
This commit is contained in:
@@ -190,45 +190,17 @@ export class ClientGameRunner {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
const owner = tile.owner()
|
||||
const targetID = owner.isPlayer() ? owner.id() : null;
|
||||
|
||||
if (tile.owner() == this.myPlayer) {
|
||||
return
|
||||
}
|
||||
if (tile.owner().isPlayer() && this.myPlayer.isAlliedWith(tile.owner() as Player)) {
|
||||
this.eventBus.emit(new DisplayMessageEvent("Cannot attack ally", MessageType.WARN))
|
||||
return
|
||||
}
|
||||
|
||||
if (tile.terrain().isLand()) {
|
||||
if (tile.hasOwner()) {
|
||||
this.myPlayer.sharesBorderWithAsync(tile.owner()).then(sharesBorder => {
|
||||
if (sharesBorder) {
|
||||
this.eventBus.emit(
|
||||
|
||||
new SendAttackIntentEvent(
|
||||
targetID,
|
||||
this.myPlayer.troops() * this.renderer.uiState.attackRatio
|
||||
)
|
||||
)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
outer_loop: for (const t of bfs(tile, and(t => !t.hasOwner() && t.terrain().isLand(), dist(tile, 200)))) {
|
||||
for (const n of t.neighbors()) {
|
||||
if (n.owner().isPlayer()) {
|
||||
console.log(`owner: ${(n.owner() as PlayerView).name()}`)
|
||||
}
|
||||
if (n.owner() == this.myPlayer) {
|
||||
this.eventBus.emit(new SendAttackIntentEvent(targetID, this.myPlayer.troops() * this.renderer.uiState.attackRatio))
|
||||
break outer_loop
|
||||
}
|
||||
}
|
||||
}
|
||||
this.myPlayer.actions(tile).then(actions => {
|
||||
console.log(`got actions: ${JSON.stringify(actions)}`)
|
||||
if (actions.canAttack) {
|
||||
this.eventBus.emit(
|
||||
new SendAttackIntentEvent(
|
||||
tile.owner().id(),
|
||||
this.myPlayer.troops() * this.renderer.uiState.attackRatio
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { EventBus } from "../../../../core/EventBus";
|
||||
import { AllPlayers, Cell, Game, Player, UnitType } from "../../../../core/game/Game";
|
||||
import { AllPlayers, Cell, Game, Player, Tile, UnitType } from "../../../../core/game/Game";
|
||||
import { ClientID } from "../../../../core/Schemas";
|
||||
import { and, bfs, dist, manhattanDist, manhattanDistWrapped, sourceDstOceanShore, targetTransportTile } from "../../../../core/Util";
|
||||
import { ContextMenuEvent, MouseUpEvent, ShowBuildMenuEvent } from "../../../InputHandler";
|
||||
@@ -20,7 +20,7 @@ import { EmojiTable } from "./EmojiTable";
|
||||
import { UIState } from "../../UIState";
|
||||
import { BuildMenu } from "./BuildMenu";
|
||||
import { consolex } from "../../../../core/Consolex";
|
||||
import { GameView } from "../../../../core/GameView";
|
||||
import { GameView, PlayerActions, PlayerView } from "../../../../core/GameView";
|
||||
|
||||
|
||||
enum Slot {
|
||||
@@ -237,7 +237,6 @@ export class RadialMenu implements Layer {
|
||||
return
|
||||
}
|
||||
const tile = this.game.tile(this.clickedCell)
|
||||
const other = tile.owner()
|
||||
|
||||
if (this.game.inSpawnPhase()) {
|
||||
if (tile.terrain().isLand() && !tile.hasOwner()) {
|
||||
@@ -246,134 +245,82 @@ export class RadialMenu implements Layer {
|
||||
return
|
||||
}
|
||||
|
||||
const myPlayer = this.game.players().find(p => p.clientID() == this.clientID)
|
||||
const myPlayer = this.game.playerViews().find(p => p.clientID() == this.clientID)
|
||||
if (!myPlayer) {
|
||||
consolex.warn('my player not found')
|
||||
return
|
||||
}
|
||||
myPlayer.actions(tile).then(actions => {
|
||||
this.handlePlayerActions(myPlayer, actions, tile)
|
||||
})
|
||||
}
|
||||
|
||||
private handlePlayerActions(myPlayer: PlayerView, actions: PlayerActions, tile: Tile) {
|
||||
this.activateMenuElement(Slot.Build, "#ebe250", buildIcon, () => {
|
||||
this.buildMenu.showMenu(myPlayer, this.clickedCell)
|
||||
})
|
||||
|
||||
if (tile.hasOwner()) {
|
||||
const target = tile.owner() == myPlayer ? AllPlayers : (tile.owner() as Player)
|
||||
if (myPlayer.canSendEmoji(target)) {
|
||||
this.activateMenuElement(Slot.Emoji, "#00a6a4", emojiIcon, () => {
|
||||
this.emojiTable.onEmojiClicked = (emoji: string) => {
|
||||
this.emojiTable.hideTable()
|
||||
this.eventBus.emit(new SendEmojiIntentEvent(target, emoji))
|
||||
}
|
||||
this.emojiTable.showTable()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (tile.owner() != myPlayer && tile.terrain().isLand() && myPlayer.sharesBorderWith(other)) {
|
||||
if (other.isPlayer()) {
|
||||
if (!myPlayer.isAlliedWith(other)) {
|
||||
this.enableCenterButton(true)
|
||||
if (actions.interaction?.canSendEmoji) {
|
||||
this.activateMenuElement(Slot.Emoji, "#00a6a4", emojiIcon, () => {
|
||||
const target = tile.owner() == myPlayer ? AllPlayers : (tile.owner() as Player)
|
||||
this.emojiTable.onEmojiClicked = (emoji: string) => {
|
||||
this.emojiTable.hideTable()
|
||||
this.eventBus.emit(new SendEmojiIntentEvent(target, emoji))
|
||||
}
|
||||
} else {
|
||||
outer_loop: for (const t of bfs(tile, and(t => !t.hasOwner() && t.terrain().isLand(), dist(tile, 200)))) {
|
||||
for (const n of t.neighbors()) {
|
||||
if (n.owner() == myPlayer) {
|
||||
this.enableCenterButton(true)
|
||||
break outer_loop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.emojiTable.showTable()
|
||||
})
|
||||
}
|
||||
|
||||
if (tile.hasOwner()) {
|
||||
const other = tile.owner() as Player
|
||||
if (other.clientID() == this.clientID) {
|
||||
return
|
||||
}
|
||||
|
||||
if (myPlayer.canDonate(other)) {
|
||||
this.activateMenuElement(Slot.Target, "#53ac75", donateIcon, () => {
|
||||
this.eventBus.emit(
|
||||
new SendDonateIntentEvent(myPlayer, other, null)
|
||||
if (actions.canBoat) {
|
||||
this.activateMenuElement(Slot.Boat, "#3f6ab1", boatIcon, () => {
|
||||
this.eventBus.emit(
|
||||
new SendBoatAttackIntentEvent(
|
||||
myPlayer.id(),
|
||||
this.clickedCell,
|
||||
this.uiState.attackRatio * myPlayer.troops()
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
if (myPlayer.isAlliedWith(other)) {
|
||||
this.activateMenuElement(Slot.Alliance, "#c74848", traitorIcon, () => {
|
||||
this.eventBus.emit(
|
||||
new SendBreakAllianceIntentEvent(myPlayer, other)
|
||||
)
|
||||
})
|
||||
} else if (!myPlayer.recentOrPendingAllianceRequestWith(other)) {
|
||||
this.activateMenuElement(Slot.Alliance, "#53ac75", allianceIcon, () => {
|
||||
this.eventBus.emit(
|
||||
new SendAllianceRequestIntentEvent(myPlayer, other)
|
||||
)
|
||||
})
|
||||
}
|
||||
if (myPlayer.canTarget(other)) {
|
||||
this.activateMenuElement(Slot.Target, "#c74848", targetIcon, () => {
|
||||
this.eventBus.emit(
|
||||
new SendTargetPlayerIntentEvent(other.id())
|
||||
)
|
||||
})
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
if (actions.canAttack) {
|
||||
this.enableCenterButton(true)
|
||||
}
|
||||
|
||||
if (!tile.terrain().isLand()) {
|
||||
return
|
||||
}
|
||||
if (myPlayer.units(UnitType.TransportShip).length >= this.game.config().boatMaxNumber()) {
|
||||
return
|
||||
}
|
||||
|
||||
let myPlayerBordersOcean = false
|
||||
for (const bt of myPlayer.borderTiles()) {
|
||||
if (bt.terrain().isOceanShore()) {
|
||||
myPlayerBordersOcean = true
|
||||
break
|
||||
}
|
||||
}
|
||||
let otherPlayerBordersOcean = false
|
||||
if (!tile.hasOwner()) {
|
||||
otherPlayerBordersOcean = true
|
||||
} else {
|
||||
for (const bt of (other as Player).borderTiles()) {
|
||||
if (bt.terrain().isOceanShore()) {
|
||||
otherPlayerBordersOcean = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (other.isPlayer() && myPlayer.allianceWith(other)) {
|
||||
return
|
||||
}
|
||||
const other = tile.owner() as Player
|
||||
|
||||
let nearOcean = false
|
||||
for (const t of bfs(tile, and(t => t.owner() == tile.owner() && t.terrain().isLand(), dist(tile, 25)))) {
|
||||
if (t.terrain().isOceanShore()) {
|
||||
nearOcean = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!nearOcean) {
|
||||
return
|
||||
|
||||
if (actions?.interaction.canDonate) {
|
||||
this.activateMenuElement(Slot.Target, "#53ac75", donateIcon, () => {
|
||||
this.eventBus.emit(
|
||||
new SendDonateIntentEvent(myPlayer, other, null)
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
if (myPlayerBordersOcean && otherPlayerBordersOcean) {
|
||||
const dst = targetTransportTile(this.game.width(), tile)
|
||||
if (dst != null) {
|
||||
if (myPlayer.canBuild(UnitType.TransportShip, dst)) {
|
||||
this.activateMenuElement(Slot.Boat, "#3f6ab1", boatIcon, () => {
|
||||
this.eventBus.emit(
|
||||
new SendBoatAttackIntentEvent(other.id(), this.clickedCell, this.uiState.attackRatio * myPlayer.troops())
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
if (actions?.interaction.canTarget) {
|
||||
this.activateMenuElement(Slot.Target, "#c74848", targetIcon, () => {
|
||||
this.eventBus.emit(
|
||||
new SendTargetPlayerIntentEvent(other.id())
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
if (actions?.interaction.canSendAllianceRequest) {
|
||||
this.activateMenuElement(Slot.Alliance, "#53ac75", allianceIcon, () => {
|
||||
this.eventBus.emit(
|
||||
new SendAllianceRequestIntentEvent(myPlayer, other)
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
if (actions?.interaction.canBreakAlliance) {
|
||||
this.activateMenuElement(Slot.Alliance, "#c74848", traitorIcon, () => {
|
||||
this.eventBus.emit(
|
||||
new SendBreakAllianceIntentEvent(myPlayer, other)
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,11 +355,9 @@ export class RadialMenu implements Layer {
|
||||
if (this.game.inSpawnPhase()) {
|
||||
this.eventBus.emit(new SendSpawnIntentEvent(this.clickedCell))
|
||||
} else {
|
||||
if (clicked.owner().clientID() != this.clientID) {
|
||||
const myPlayer = this.game.players().find(p => p.clientID() == this.clientID)
|
||||
if (myPlayer != null) {
|
||||
this.eventBus.emit(new SendAttackIntentEvent(clicked.owner().id(), this.uiState.attackRatio * myPlayer.troops()))
|
||||
}
|
||||
const myPlayer = this.game.players().find(p => p.clientID() == this.clientID)
|
||||
if (myPlayer != null && clicked.owner() != myPlayer) {
|
||||
this.eventBus.emit(new SendAttackIntentEvent(clicked.owner().id(), this.uiState.attackRatio * myPlayer.troops()))
|
||||
}
|
||||
}
|
||||
this.hideRadialMenu();
|
||||
|
||||
+103
-3
@@ -3,11 +3,12 @@ import { getConfig } from "./configuration/Config";
|
||||
import { EventBus } from "./EventBus";
|
||||
import { Executor } from "./execution/ExecutionManager";
|
||||
import { WinCheckExecution } from "./execution/WinCheckExecution";
|
||||
import { Game, MutableGame, MutableTile, PlayerID, Tile, TileEvent } from "./game/Game";
|
||||
import { Cell, DisplayMessageEvent, Game, MessageType, MutableGame, MutableTile, Player, PlayerID, Tile, TileEvent, UnitType } from "./game/Game";
|
||||
import { createGame } from "./game/GameImpl";
|
||||
import { loadTerrainMap } from "./game/TerrainMapLoader";
|
||||
import { GameUpdateViewData, NameViewData, packTileData, PlayerViewData } from "./GameView";
|
||||
import { GameUpdateViewData, NameViewData, packTileData, PlayerActions, PlayerViewData } from "./GameView";
|
||||
import { GameConfig, Turn } from "./Schemas";
|
||||
import { and, bfs, dist, targetTransportTile } from "./Util";
|
||||
|
||||
export async function createGameRunner(gameID: string, gameConfig: GameConfig, callBack: (gu: GameUpdateViewData) => void): Promise<GameRunner> {
|
||||
const config = getConfig(gameConfig)
|
||||
@@ -90,4 +91,103 @@ export class GameRunner {
|
||||
this.isExecuting = false
|
||||
}
|
||||
|
||||
}
|
||||
public playerActions(playerID: PlayerID, x: number, y: number): PlayerActions {
|
||||
const player = this.game.player(playerID)
|
||||
const tile = this.game.tile(new Cell(x, y))
|
||||
const actions = {
|
||||
canBoat: this.canBoat(player, tile),
|
||||
canAttack: this.canAttack(player, tile),
|
||||
buildableUnits: Object.values(UnitType).filter(ut => player.canBuild(ut, tile) != false)
|
||||
} as PlayerActions
|
||||
|
||||
if (tile.hasOwner()) {
|
||||
const other = tile.owner() as Player
|
||||
actions.interaction = {
|
||||
sharedBorder: player.sharesBorderWith(other),
|
||||
canSendEmoji: player.canSendEmoji(other),
|
||||
canTarget: player.canTarget(other),
|
||||
canSendAllianceRequest: !player.recentOrPendingAllianceRequestWith(other),
|
||||
canBreakAlliance: player.isAlliedWith(other),
|
||||
canDonate: player.canDonate(other)
|
||||
}
|
||||
}
|
||||
|
||||
return actions
|
||||
}
|
||||
|
||||
private canBoat(myPlayer: Player, tile: Tile): boolean {
|
||||
const other = tile.owner()
|
||||
if (myPlayer.units(UnitType.TransportShip).length >= this.game.config().boatMaxNumber()) {
|
||||
return false
|
||||
}
|
||||
|
||||
let myPlayerBordersOcean = false
|
||||
for (const bt of myPlayer.borderTiles()) {
|
||||
if (bt.terrain().isOceanShore()) {
|
||||
myPlayerBordersOcean = true
|
||||
break
|
||||
}
|
||||
}
|
||||
let otherPlayerBordersOcean = false
|
||||
if (!tile.hasOwner()) {
|
||||
otherPlayerBordersOcean = true
|
||||
} else {
|
||||
for (const bt of (other as Player).borderTiles()) {
|
||||
if (bt.terrain().isOceanShore()) {
|
||||
otherPlayerBordersOcean = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (other.isPlayer() && myPlayer.allianceWith(other)) {
|
||||
return false
|
||||
}
|
||||
|
||||
let nearOcean = false
|
||||
for (const t of bfs(tile, and(t => t.owner() == tile.owner() && t.terrain().isLand(), dist(tile, 25)))) {
|
||||
if (t.terrain().isOceanShore()) {
|
||||
nearOcean = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!nearOcean) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (myPlayerBordersOcean && otherPlayerBordersOcean) {
|
||||
const dst = targetTransportTile(this.game.width(), tile)
|
||||
if (dst != null) {
|
||||
if (myPlayer.canBuild(UnitType.TransportShip, dst)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private canAttack(myPlayer: Player, tile: Tile): boolean {
|
||||
if (tile.owner() == myPlayer) {
|
||||
return false
|
||||
}
|
||||
// TODO: fix event bus
|
||||
if (tile.owner().isPlayer() && myPlayer.isAlliedWith(tile.owner() as Player)) {
|
||||
this.eventBus.emit(new DisplayMessageEvent("Cannot attack ally", MessageType.WARN))
|
||||
return false
|
||||
}
|
||||
if (!tile.terrain().isLand()) {
|
||||
return false
|
||||
}
|
||||
if (tile.hasOwner()) {
|
||||
return myPlayer.sharesBorderWith(tile.owner())
|
||||
} else {
|
||||
for (const t of bfs(tile, and(t => !t.hasOwner() && t.terrain().isLand(), dist(tile, 200)))) {
|
||||
for (const n of t.neighbors()) {
|
||||
if (n.owner() == myPlayer) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+21
-5
@@ -124,9 +124,29 @@ export interface PlayerViewData extends ViewData<PlayerViewData> {
|
||||
targetTroopRatio: number
|
||||
}
|
||||
|
||||
export interface PlayerActions {
|
||||
canBoat: boolean
|
||||
canAttack: boolean
|
||||
buildableUnits: UnitType[]
|
||||
interaction?: PlayerInteraction
|
||||
}
|
||||
|
||||
export interface PlayerInteraction {
|
||||
sharedBorder: boolean
|
||||
canSendEmoji: boolean
|
||||
canSendAllianceRequest: boolean
|
||||
canBreakAlliance: boolean
|
||||
canTarget: boolean
|
||||
canDonate: boolean
|
||||
}
|
||||
|
||||
export class PlayerView implements Player {
|
||||
constructor(private game: GameView, public data: PlayerViewData) { }
|
||||
|
||||
async actions(tile: Tile): Promise<PlayerActions> {
|
||||
return this.game.worker.playerInteraction(this.id(), tile)
|
||||
}
|
||||
|
||||
nameLocation(): NameViewData {
|
||||
return this.data.nameViewData
|
||||
}
|
||||
@@ -196,10 +216,6 @@ export class PlayerView implements Player {
|
||||
return false
|
||||
}
|
||||
|
||||
async sharesBorderWithAsync(other: Player | TerraNullius): Promise<boolean> {
|
||||
return this.game.worker.sharesBorderWith(this.id(), other.id())
|
||||
}
|
||||
|
||||
incomingAllianceRequests(): AllianceRequest[] {
|
||||
return []
|
||||
}
|
||||
@@ -325,7 +341,7 @@ export class GameView {
|
||||
return false
|
||||
}
|
||||
playerViews(): PlayerView[] {
|
||||
return Object.values(this.lastUpdate.players).map(data => new PlayerView(this, data))
|
||||
return Array.from(this._players.values())
|
||||
}
|
||||
|
||||
players(): Player[] {
|
||||
|
||||
@@ -19,8 +19,6 @@ import { DestroyerExecution } from "./DestroyerExecution";
|
||||
import { PortExecution } from "./PortExecution";
|
||||
import { MissileSiloExecution } from "./MissileSiloExecution";
|
||||
import { BattleshipExecution } from "./BattleshipExecution";
|
||||
import { PathFinder } from "../pathfinding/PathFinding";
|
||||
import { WorkerClient } from "../worker/WorkerClient";
|
||||
import { DefensePostExecution } from "./DefensePostExecution";
|
||||
import { CityExecution } from "./CityExecution";
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
MainThreadMessage,
|
||||
WorkerMessage,
|
||||
InitializedMessage,
|
||||
SharesBorderResultMessage
|
||||
PlayerActionsResultMessage,
|
||||
} from './WorkerMessages';
|
||||
|
||||
const ctx: Worker = self as any;
|
||||
@@ -58,21 +58,18 @@ ctx.addEventListener('message', async (e: MessageEvent<MainThreadMessage>) => {
|
||||
}
|
||||
break;
|
||||
|
||||
case 'shares_border':
|
||||
case 'player_actions':
|
||||
if (!gameRunner) {
|
||||
throw new Error('Game runner not initialized');
|
||||
}
|
||||
|
||||
try {
|
||||
const game = (await gameRunner).game
|
||||
const result = game.player(message.player1)
|
||||
.sharesBorderWith(game.player(message.player2))
|
||||
|
||||
const actions = (await gameRunner).playerActions(message.playerID, message.x, message.y)
|
||||
sendMessage({
|
||||
type: 'shares_border_result',
|
||||
type: 'player_actions_result',
|
||||
id: message.id,
|
||||
result
|
||||
} as SharesBorderResultMessage);
|
||||
result: actions
|
||||
} as PlayerActionsResultMessage);
|
||||
} catch (error) {
|
||||
console.error('Failed to check borders:', error);
|
||||
throw error;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { PlayerID } from "../game/Game";
|
||||
import { GameUpdateViewData } from "../GameView";
|
||||
import { PlayerID, Tile } from "../game/Game";
|
||||
import { GameUpdateViewData, PlayerActions, PlayerInteraction } from "../GameView";
|
||||
import { GameConfig, GameID, Turn } from "../Schemas";
|
||||
import { generateID } from "../Util";
|
||||
import { WorkerMessage } from "./WorkerMessages";
|
||||
@@ -29,7 +29,7 @@ export class WorkerClient {
|
||||
break;
|
||||
|
||||
case 'initialized':
|
||||
case 'shares_border_result':
|
||||
case 'player_actions_result':
|
||||
if (message.id && this.messageHandlers.has(message.id)) {
|
||||
const handler = this.messageHandlers.get(message.id)!;
|
||||
handler(message);
|
||||
@@ -85,7 +85,7 @@ export class WorkerClient {
|
||||
});
|
||||
}
|
||||
|
||||
sharesBorderWith(p1: PlayerID, p2: PlayerID): Promise<boolean> {
|
||||
playerInteraction(playerID: PlayerID, tile: Tile): Promise<PlayerActions> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!this.isInitialized) {
|
||||
reject(new Error('Worker not initialized'));
|
||||
@@ -95,21 +95,23 @@ export class WorkerClient {
|
||||
const messageId = generateID()
|
||||
|
||||
this.messageHandlers.set(messageId, (message) => {
|
||||
if (message.type === 'shares_border_result' && message.result !== undefined) {
|
||||
if (message.type === 'player_actions_result' && message.result !== undefined) {
|
||||
resolve(message.result);
|
||||
}
|
||||
});
|
||||
|
||||
this.worker.postMessage({
|
||||
type: 'shares_border',
|
||||
type: 'player_actions',
|
||||
id: messageId,
|
||||
player1: p1,
|
||||
player2: p2
|
||||
playerID: playerID,
|
||||
x: tile.cell().x,
|
||||
y: tile.cell().y
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
cleanup() {
|
||||
this.worker.terminate();
|
||||
this.messageHandlers.clear();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { GameUpdateViewData } from "../GameView";
|
||||
import { GameUpdateViewData, PlayerActions, PlayerInteraction } from "../GameView";
|
||||
import { GameConfig, GameID, Turn } from "../Schemas";
|
||||
import { PlayerID } from "../game/Game";
|
||||
|
||||
@@ -7,8 +7,8 @@ export type WorkerMessageType =
|
||||
| 'initialized'
|
||||
| 'turn'
|
||||
| 'game_update'
|
||||
| 'shares_border'
|
||||
| 'shares_border_result';
|
||||
| 'player_actions'
|
||||
| 'player_actions_result';
|
||||
|
||||
// Base interface for all messages
|
||||
interface BaseWorkerMessage {
|
||||
@@ -28,12 +28,6 @@ export interface TurnMessage extends BaseWorkerMessage {
|
||||
turn: Turn;
|
||||
}
|
||||
|
||||
export interface SharesBorderMessage extends BaseWorkerMessage {
|
||||
type: 'shares_border';
|
||||
player1: PlayerID;
|
||||
player2: PlayerID;
|
||||
}
|
||||
|
||||
// Messages from worker to main thread
|
||||
export interface InitializedMessage extends BaseWorkerMessage {
|
||||
type: 'initialized';
|
||||
@@ -44,11 +38,20 @@ export interface GameUpdateMessage extends BaseWorkerMessage {
|
||||
gameUpdate: GameUpdateViewData;
|
||||
}
|
||||
|
||||
export interface SharesBorderResultMessage extends BaseWorkerMessage {
|
||||
type: 'shares_border_result';
|
||||
result: boolean;
|
||||
export interface PlayerActionsMessage extends BaseWorkerMessage {
|
||||
type: 'player_actions'
|
||||
playerID: PlayerID
|
||||
x: number,
|
||||
y: number
|
||||
}
|
||||
|
||||
export interface PlayerActionsResultMessage extends BaseWorkerMessage {
|
||||
type: 'player_actions_result';
|
||||
result: PlayerActions;
|
||||
}
|
||||
|
||||
// Union types for type safety
|
||||
export type MainThreadMessage = InitMessage | TurnMessage | SharesBorderMessage;
|
||||
export type WorkerMessage = InitializedMessage | GameUpdateMessage | SharesBorderResultMessage;
|
||||
export type MainThreadMessage = InitMessage | TurnMessage | PlayerActionsMessage
|
||||
|
||||
// Message send from worker
|
||||
export type WorkerMessage = InitializedMessage | GameUpdateMessage | PlayerActionsResultMessage;
|
||||
Reference in New Issue
Block a user