mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 12:00:44 +00:00
builds
This commit is contained in:
@@ -10,7 +10,7 @@ import { and, bfs, dist, generateID, manhattanDist } from "../core/Util";
|
||||
import { SendAttackIntentEvent, SendSpawnIntentEvent, Transport } from "./Transport";
|
||||
import { createCanvas } from "./Utils";
|
||||
import { MessageType } from '../core/game/Game';
|
||||
import { DisplayMessageEvent } from '../core/game/Game';
|
||||
import { DisplayMessageUpdate } from '../core/game/Game';
|
||||
import { WorkerClient } from "../core/worker/WorkerClient";
|
||||
import { consolex, initRemoteSender } from "../core/Consolex";
|
||||
import { getConfig, getServerConfig } from "../core/configuration/Config";
|
||||
|
||||
@@ -30,7 +30,9 @@ export class SendBreakAllianceIntentEvent implements GameEvent {
|
||||
|
||||
export class SendAllianceReplyIntentEvent implements GameEvent {
|
||||
constructor(
|
||||
public readonly allianceRequest: AllianceRequest,
|
||||
// The original alliance requestor
|
||||
public readonly requestor: Player,
|
||||
public readonly recipient: Player,
|
||||
public readonly accepted: boolean
|
||||
) { }
|
||||
}
|
||||
@@ -262,8 +264,8 @@ export class Transport {
|
||||
this.sendIntent({
|
||||
type: "allianceRequestReply",
|
||||
clientID: this.lobbyConfig.clientID,
|
||||
requestor: event.allianceRequest.requestor().id(),
|
||||
recipient: event.allianceRequest.recipient().id(),
|
||||
requestor: event.requestor.id(),
|
||||
recipient: event.recipient.id(),
|
||||
accept: event.accepted,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2,8 +2,13 @@ import { LitElement, html, css } from 'lit';
|
||||
import { customElement, property, state } from 'lit/decorators.js';
|
||||
import { EventBus } from "../../../core/EventBus";
|
||||
import {
|
||||
AllianceRequestReplyUpdate,
|
||||
AllianceRequestUpdate,
|
||||
AllPlayers,
|
||||
DisplayMessageUpdate,
|
||||
EmojiUpdate,
|
||||
MessageType,
|
||||
TargetPlayerUpdate,
|
||||
} from "../../../core/game/Game";
|
||||
import { ClientID } from "../../../core/Schemas";
|
||||
import { Layer } from "./Layer";
|
||||
@@ -140,13 +145,6 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
}
|
||||
|
||||
init() {
|
||||
this.eventBus.on(AllianceRequestEvent, a => this.onAllianceRequestEvent(a));
|
||||
this.eventBus.on(AllianceRequestReplyEvent, a => this.onAllianceRequestReplyEvent(a));
|
||||
this.eventBus.on(DisplayMessageEvent, e => this.onDisplayMessageEvent(e));
|
||||
this.eventBus.on(BrokeAllianceEvent, e => this.onBrokeAllianceEvent(e));
|
||||
this.eventBus.on(AllianceExpiredEvent, e => this.onAllianceExpiredEvent(e));
|
||||
this.eventBus.on(TargetPlayerEvent, e => this.onTargetPlayerEvent(e));
|
||||
this.eventBus.on(EmojiMessageEvent, e => this.onEmojiMessageEvent(e));
|
||||
}
|
||||
|
||||
tick() {
|
||||
@@ -186,9 +184,9 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
|
||||
renderLayer(): void { }
|
||||
|
||||
onDisplayMessageEvent(event: DisplayMessageEvent) {
|
||||
onDisplayMessageEvent(event: DisplayMessageUpdate) {
|
||||
const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
if (event.playerID != null && (!myPlayer || myPlayer.id() !== event.playerID)) {
|
||||
if (event.playerID != null && (!myPlayer || myPlayer.smallID() !== event.playerID)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -196,122 +194,137 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
description: event.message,
|
||||
createdAt: this.game.ticks(),
|
||||
highlight: true,
|
||||
type: event.type,
|
||||
type: event.messageType,
|
||||
unsafeDescription: true,
|
||||
});
|
||||
}
|
||||
|
||||
onAllianceRequestEvent(event: AllianceRequestEvent) {
|
||||
onAllianceRequestEvent(update: AllianceRequestUpdate) {
|
||||
const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
if (!myPlayer || event.allianceRequest.recipient() !== myPlayer) {
|
||||
if (!myPlayer || update.recipientID !== myPlayer.smallID()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const requestor = this.game.playerBySmallID(update.requestorID)
|
||||
const recipient = this.game.playerBySmallID(update.recipientID)
|
||||
|
||||
this.addEvent({
|
||||
description: `${event.allianceRequest.requestor().name()} requests an alliance!`,
|
||||
description: `${requestor.name()} requests an alliance!`,
|
||||
buttons: [
|
||||
{
|
||||
text: "Accept",
|
||||
className: "btn",
|
||||
action: () => this.eventBus.emit(new SendAllianceReplyIntentEvent(event.allianceRequest, true)),
|
||||
action: () => this.eventBus.emit(
|
||||
new SendAllianceReplyIntentEvent(requestor, recipient, true)
|
||||
),
|
||||
},
|
||||
{
|
||||
text: "Reject",
|
||||
className: "btn btn-info",
|
||||
action: () => this.eventBus.emit(new SendAllianceReplyIntentEvent(event.allianceRequest, false)),
|
||||
action: () => this.eventBus.emit(
|
||||
new SendAllianceReplyIntentEvent(requestor, recipient, false)
|
||||
),
|
||||
}
|
||||
],
|
||||
highlight: true,
|
||||
type: MessageType.INFO,
|
||||
createdAt: this.game.ticks(),
|
||||
onDelete: () => this.eventBus.emit(new SendAllianceReplyIntentEvent(event.allianceRequest, false))
|
||||
onDelete: () => this.eventBus.emit(
|
||||
new SendAllianceReplyIntentEvent(requestor, recipient, false)
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
onAllianceRequestReplyEvent(event: AllianceRequestReplyEvent) {
|
||||
const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
if (!myPlayer || event.allianceRequest.requestor() !== myPlayer) {
|
||||
return;
|
||||
}
|
||||
// onAllianceRequestReplyEvent(event: AllianceRequestReplyUpdate) {
|
||||
// const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
// if (!myPlayer || event.allianceRequest.requestor() !== myPlayer) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
this.addEvent({
|
||||
description: `${event.allianceRequest.recipient().name()} ${event.accepted ? "accepted" : "rejected"} your alliance request`,
|
||||
type: event.accepted ? MessageType.SUCCESS : MessageType.ERROR,
|
||||
highlight: true,
|
||||
createdAt: this.game.ticks(),
|
||||
});
|
||||
}
|
||||
// this.addEvent({
|
||||
// description: `${event.allianceRequest.recipient().name()} ${event.accepted ? "accepted" : "rejected"} your alliance request`,
|
||||
// type: event.accepted ? MessageType.SUCCESS : MessageType.ERROR,
|
||||
// highlight: true,
|
||||
// createdAt: this.game.ticks(),
|
||||
// });
|
||||
// }
|
||||
|
||||
onBrokeAllianceEvent(event: BrokeAllianceEvent) {
|
||||
const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
if (!myPlayer) return;
|
||||
// onBrokeAllianceEvent(event: BrokeAllianceEvent) {
|
||||
// const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
// if (!myPlayer) return;
|
||||
|
||||
if (!event.betrayed.isTraitor() && event.traitor === myPlayer) {
|
||||
this.addEvent({
|
||||
description: `You broke your alliance with ${event.betrayed.name()}, making you a TRAITOR`,
|
||||
type: MessageType.ERROR,
|
||||
highlight: true,
|
||||
createdAt: this.game.ticks(),
|
||||
});
|
||||
} else if (event.betrayed === myPlayer) {
|
||||
this.addEvent({
|
||||
description: `${event.traitor.name()}, broke their alliance with you`,
|
||||
type: MessageType.ERROR,
|
||||
highlight: true,
|
||||
createdAt: this.game.ticks(),
|
||||
});
|
||||
}
|
||||
}
|
||||
// if (!event.betrayed.isTraitor() && event.traitor === myPlayer) {
|
||||
// this.addEvent({
|
||||
// description: `You broke your alliance with ${event.betrayed.name()}, making you a TRAITOR`,
|
||||
// type: MessageType.ERROR,
|
||||
// highlight: true,
|
||||
// createdAt: this.game.ticks(),
|
||||
// });
|
||||
// } else if (event.betrayed === myPlayer) {
|
||||
// this.addEvent({
|
||||
// description: `${event.traitor.name()}, broke their alliance with you`,
|
||||
// type: MessageType.ERROR,
|
||||
// highlight: true,
|
||||
// createdAt: this.game.ticks(),
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
onAllianceExpiredEvent(event: AllianceExpiredEvent) {
|
||||
const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
if (!myPlayer) return;
|
||||
// onAllianceExpiredEvent(event: AllianceExpiredEvent) {
|
||||
// const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
// if (!myPlayer) return;
|
||||
|
||||
const other = event.player1 === myPlayer ? event.player2 : event.player2 === myPlayer ? event.player1 : null;
|
||||
if (!other || !myPlayer.isAlive() || !other.isAlive()) return;
|
||||
// const other = event.player1 === myPlayer ? event.player2 : event.player2 === myPlayer ? event.player1 : null;
|
||||
// if (!other || !myPlayer.isAlive() || !other.isAlive()) return;
|
||||
|
||||
this.addEvent({
|
||||
description: `Your alliance with ${other.name()} expired`,
|
||||
type: MessageType.WARN,
|
||||
highlight: true,
|
||||
createdAt: this.game.ticks(),
|
||||
});
|
||||
}
|
||||
// this.addEvent({
|
||||
// description: `Your alliance with ${other.name()} expired`,
|
||||
// type: MessageType.WARN,
|
||||
// highlight: true,
|
||||
// createdAt: this.game.ticks(),
|
||||
// });
|
||||
// }
|
||||
|
||||
onTargetPlayerEvent(event: TargetPlayerEvent) {
|
||||
const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
if (!myPlayer || !myPlayer.isAlliedWith(event.player)) return;
|
||||
// onTargetPlayerEvent(event: TargetPlayerUpdate) {
|
||||
// const other = this.game.playerBySmallID(event.playerID)
|
||||
// const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
// if (!myPlayer || !myPlayer.isAlliedWith(other)) return;
|
||||
|
||||
this.addEvent({
|
||||
description: `${event.player.name()} requests you attack ${event.target.name()}`,
|
||||
type: MessageType.INFO,
|
||||
highlight: true,
|
||||
createdAt: this.game.ticks(),
|
||||
});
|
||||
}
|
||||
// const target = this.game.playerBySmallID(event.targetID)
|
||||
|
||||
onEmojiMessageEvent(event: EmojiMessageEvent) {
|
||||
const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
if (!myPlayer) return;
|
||||
// this.addEvent({
|
||||
// description: `${other.name()} requests you attack ${target.name()}`,
|
||||
// type: MessageType.INFO,
|
||||
// highlight: true,
|
||||
// createdAt: this.game.ticks(),
|
||||
// });
|
||||
// }
|
||||
|
||||
if (event.message.recipient === myPlayer) {
|
||||
this.addEvent({
|
||||
description: `${event.message.sender.displayName()}:${event.message.emoji}`,
|
||||
unsafeDescription: true,
|
||||
type: MessageType.INFO,
|
||||
highlight: true,
|
||||
createdAt: this.game.ticks(),
|
||||
});
|
||||
} else if (event.message.sender === myPlayer && event.message.recipient !== AllPlayers) {
|
||||
this.addEvent({
|
||||
description: `Sent ${event.message.recipient.displayName()}: ${event.message.emoji}`,
|
||||
unsafeDescription: true,
|
||||
type: MessageType.INFO,
|
||||
highlight: true,
|
||||
createdAt: this.game.ticks(),
|
||||
});
|
||||
}
|
||||
}
|
||||
// onEmojiMessageEvent(update: EmojiUpdate) {
|
||||
// const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
// if (!myPlayer) return;
|
||||
|
||||
// const recipient = update.recipientID == AllPlayers ? AllPlayers : this.game.playerBySmallID(update.recipientID)
|
||||
// const sender = this.game.playerBySmallID(update.senderID)
|
||||
|
||||
// if (recipient == myPlayer) {
|
||||
// this.addEvent({
|
||||
// description: `${sender.displayName()}:${update.message}`,
|
||||
// unsafeDescription: true,
|
||||
// type: MessageType.INFO,
|
||||
// highlight: true,
|
||||
// createdAt: this.game.ticks(),
|
||||
// });
|
||||
// } else if (sender === myPlayer && recipient !== AllPlayers) {
|
||||
// this.addEvent({
|
||||
// description: `Sent ${recipient.displayName()}: ${update.message}`,
|
||||
// unsafeDescription: true,
|
||||
// type: MessageType.INFO,
|
||||
// highlight: true,
|
||||
// createdAt: this.game.ticks(),
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
render() {
|
||||
if (this.events.length === 0) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { colord, Colord } from "colord";
|
||||
import { Theme } from "../../../core/configuration/Config";
|
||||
import { Unit, UnitEvent, Cell, Game, Tile, UnitType } from "../../../core/game/Game";
|
||||
import { Unit, Cell, Game, Tile, UnitType } from "../../../core/game/Game";
|
||||
import { bfs, dist, euclDist } from "../../../core/Util";
|
||||
import { Layer } from "./Layer";
|
||||
import { EventBus } from "../../../core/EventBus";
|
||||
@@ -70,7 +70,7 @@ export class StructureLayer implements Layer {
|
||||
}
|
||||
|
||||
tick() {
|
||||
this.game.units().forEach(u => this.handleUnitRendering(new UnitEvent(u, u.tile())))
|
||||
this.game.units().forEach(u => this.handleUnitRendering(u))
|
||||
}
|
||||
|
||||
init() {
|
||||
@@ -83,7 +83,7 @@ export class StructureLayer implements Layer {
|
||||
this.context = this.canvas.getContext("2d", { alpha: true });
|
||||
this.canvas.width = this.game.width();
|
||||
this.canvas.height = this.game.height();
|
||||
this.game.units().forEach(u => this.handleUnitRendering(new UnitEvent(u, u.tile())))
|
||||
this.game.units().forEach(u => this.handleUnitRendering(u))
|
||||
}
|
||||
|
||||
renderLayer(context: CanvasRenderingContext2D) {
|
||||
@@ -100,15 +100,15 @@ export class StructureLayer implements Layer {
|
||||
return unitType in this.unitConfigs;
|
||||
}
|
||||
|
||||
private handleUnitRendering(event: UnitEvent) {
|
||||
const unitType = event.unit.type();
|
||||
private handleUnitRendering(unit: Unit) {
|
||||
const unitType = unit.type();
|
||||
if (!this.isUnitTypeSupported(unitType)) return;
|
||||
|
||||
if (event.unit.isActive() && this.seenUnits.has(event.unit)) {
|
||||
if (unit.isActive() && this.seenUnits.has(unit)) {
|
||||
// Already rendered, so don't do anything.
|
||||
return
|
||||
}
|
||||
if (!event.unit.isActive() && !this.seenUnits.has(event.unit)) {
|
||||
if (!unit.isActive() && !this.seenUnits.has(unit)) {
|
||||
// Has been deleted and render is cleared so don't do anything.
|
||||
return
|
||||
}
|
||||
@@ -119,14 +119,14 @@ export class StructureLayer implements Layer {
|
||||
if (!config || !unitImage) return;
|
||||
|
||||
// Clear previous rendering
|
||||
bfs(event.unit.tile(), euclDist(event.unit.tile(), config.borderRadius))
|
||||
bfs(unit.tile(), euclDist(unit.tile(), config.borderRadius))
|
||||
.forEach(t => this.clearCell(t.cell()));
|
||||
|
||||
if (!event.unit.isActive()) {
|
||||
this.seenUnits.delete(event.unit)
|
||||
if (!unit.isActive()) {
|
||||
this.seenUnits.delete(unit)
|
||||
return;
|
||||
}
|
||||
this.seenUnits.add(event.unit)
|
||||
this.seenUnits.add(unit)
|
||||
|
||||
// Create temporary canvas for icon processing
|
||||
const tempCanvas = document.createElement('canvas');
|
||||
@@ -138,19 +138,19 @@ export class StructureLayer implements Layer {
|
||||
tempContext.drawImage(unitImage, 0, 0);
|
||||
const iconData = tempContext.getImageData(0, 0, tempCanvas.width, tempCanvas.height);
|
||||
|
||||
const cell = event.unit.tile().cell();
|
||||
const cell = unit.tile().cell();
|
||||
const startX = cell.x - Math.floor(tempCanvas.width / 2);
|
||||
const startY = cell.y - Math.floor(tempCanvas.height / 2);
|
||||
|
||||
// Draw border and territory
|
||||
bfs(event.unit.tile(), euclDist(event.unit.tile(), config.borderRadius))
|
||||
.forEach(t => this.paintCell(t.cell(), this.theme.borderColor(event.unit.owner().info()), 255));
|
||||
bfs(unit.tile(), euclDist(unit.tile(), config.borderRadius))
|
||||
.forEach(t => this.paintCell(t.cell(), this.theme.borderColor(unit.owner().info()), 255));
|
||||
|
||||
bfs(event.unit.tile(), euclDist(event.unit.tile(), config.territoryRadius))
|
||||
.forEach(t => this.paintCell(t.cell(), this.theme.territoryColor(event.unit.owner().info()), 130));
|
||||
bfs(unit.tile(), euclDist(unit.tile(), config.territoryRadius))
|
||||
.forEach(t => this.paintCell(t.cell(), this.theme.territoryColor(unit.owner().info()), 130));
|
||||
|
||||
// Draw the icon
|
||||
this.renderIcon(iconData, startX, startY, tempCanvas.width, tempCanvas.height, event.unit);
|
||||
this.renderIcon(iconData, startX, startY, tempCanvas.width, tempCanvas.height, unit);
|
||||
}
|
||||
|
||||
private renderIcon(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { PriorityQueue } from "@datastructures-js/priority-queue";
|
||||
import { Cell, Game, Player, PlayerType, Tile, TileEvent, UnitEvent, UnitType } from "../../../core/game/Game";
|
||||
import { Cell, Game, Player, PlayerType, Tile, Unit, UnitType, UnitUpdate } from "../../../core/game/Game";
|
||||
import { PseudoRandom } from "../../../core/PseudoRandom";
|
||||
import { colord, Colord } from "colord";
|
||||
import { bfs, dist, euclDist, euclideanDist } from "../../../core/Util";
|
||||
@@ -197,19 +197,6 @@ export class TerritoryLayer implements Layer {
|
||||
this.imageData.data[offset + 3] = 0; // Set alpha to 0 (fully transparent)
|
||||
}
|
||||
|
||||
unitEvent(event: UnitEvent) {
|
||||
if (event.unit.type() == UnitType.DefensePost) {
|
||||
bfs(
|
||||
event.unit.tile(),
|
||||
dist(event.unit.tile(), this.game.config().defensePostRange())
|
||||
).forEach(t => {
|
||||
if (t.isBorder()) {
|
||||
this.enqueueTile(t)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
enqueueTile(tile: Tile) {
|
||||
this.tileToRenderQueue.push({ tile: tile, lastUpdate: this.game.ticks() + this.random.nextFloat(0, .5) })
|
||||
}
|
||||
|
||||
@@ -14,6 +14,10 @@ enum Relationship {
|
||||
Enemy
|
||||
}
|
||||
|
||||
class UnitEvent {
|
||||
constructor(public unit: Unit, public oldTile: Tile) { }
|
||||
}
|
||||
|
||||
export class UnitLayer implements Layer {
|
||||
private canvas: HTMLCanvasElement;
|
||||
private context: CanvasRenderingContext2D;
|
||||
@@ -176,22 +180,22 @@ export class UnitLayer implements Layer {
|
||||
|
||||
}
|
||||
|
||||
private handleTradeShipEvent(unit: Unit) {
|
||||
const rel = this.relationship(unit)
|
||||
bfs(unit.oldTile, euclDist(unit.oldTile, 3)).forEach(t => {
|
||||
private handleTradeShipEvent(event: UnitEvent) {
|
||||
const rel = this.relationship(event.unit)
|
||||
bfs(event.oldTile, euclDist(event.oldTile, 3)).forEach(t => {
|
||||
this.clearCell(t.cell());
|
||||
});
|
||||
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(), 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(), 1))
|
||||
.forEach(t => this.paintCell(t.cell(), rel, this.theme.borderColor(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));
|
||||
}
|
||||
}
|
||||
|
||||
private handleBoatEvent(event: Unit) {
|
||||
private handleBoatEvent(event: UnitEvent) {
|
||||
const rel = this.relationship(event.unit)
|
||||
if (!this.boatToTrail.has(event.unit)) {
|
||||
this.boatToTrail.set(event.unit, new Set<Tile>());
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { utcDay } from "d3";
|
||||
import { placeName } from "../client/graphics/NameBoxCalculator";
|
||||
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, UnitType } from "./game/Game";
|
||||
import { Cell, DisplayMessageUpdate, Game, GameUpdateType, 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";
|
||||
@@ -20,7 +21,6 @@ export async function createGameRunner(gameID: string, gameConfig: GameConfig, c
|
||||
}
|
||||
|
||||
export class GameRunner {
|
||||
private updatedTiles: Set<MutableTile> = new Set()
|
||||
private tickInterval = null
|
||||
private turns: Turn[] = []
|
||||
private currTurn = 0
|
||||
@@ -56,12 +56,11 @@ export class GameRunner {
|
||||
return
|
||||
}
|
||||
this.isExecuting = true
|
||||
this.updatedTiles.clear()
|
||||
|
||||
|
||||
this.game.addExecution(...this.execManager.createExecs(this.turns[this.currTurn]))
|
||||
this.currTurn++
|
||||
this.game.executeNextTick()
|
||||
const updates = this.game.executeNextTick()
|
||||
|
||||
if (this.game.inSpawnPhase() || this.game.ticks() % 10 == 0) {
|
||||
this.game.players()
|
||||
@@ -78,7 +77,7 @@ export class GameRunner {
|
||||
this.callBack({
|
||||
tick: this.game.ticks(),
|
||||
units: this.game.units().map(u => u.toViewData()),
|
||||
packedTileUpdates: Array.from(this.updatedTiles).map(t => packTileData(t.toViewData())),
|
||||
packedTileUpdates: updates.filter(u => u.type == GameUpdateType.Tile).map(u => packTileData(u)),
|
||||
players: playerViewData
|
||||
})
|
||||
this.isExecuting = false
|
||||
|
||||
+18
-15
@@ -1,4 +1,4 @@
|
||||
import { MessageType, Player, Tile, Unit } from './game/Game';
|
||||
import { GameUpdateType, MessageType, Player, Tile, TileUpdate, Unit } from './game/Game';
|
||||
import { Config } from "./configuration/Config";
|
||||
import { Alliance, AllianceRequest, AllPlayers, Cell, DefenseBonus, EmojiMessage, Execution, ExecutionView, Game, Gold, MutableTile, Nation, PlayerID, PlayerInfo, PlayerType, Relation, TerrainMap, TerrainTile, TerrainType, TerraNullius, Tick, UnitInfo, UnitType } from "./game/Game";
|
||||
import { ClientID } from "./Schemas";
|
||||
@@ -24,7 +24,7 @@ export interface TileViewData extends ViewData<TileViewData> {
|
||||
|
||||
export class TileView {
|
||||
|
||||
constructor(private game: GameView, public data: TileViewData, private _terrain: TerrainTile) { }
|
||||
constructor(private game: GameView, public data: TileUpdate, private _terrain: TerrainTile) { }
|
||||
|
||||
type(): TerrainType {
|
||||
return this._terrain.type()
|
||||
@@ -33,10 +33,10 @@ export class TileView {
|
||||
if (!this.hasOwner()) {
|
||||
return new TerraNulliusImpl()
|
||||
}
|
||||
return this.game.playerBySmallID(this.data?.smallID)
|
||||
return this.game.playerBySmallID(this.data?.ownerID)
|
||||
}
|
||||
hasOwner(): boolean {
|
||||
return this.data?.smallID !== undefined && this.data.smallID !== 0;
|
||||
return this.data?.ownerID !== undefined && this.data.ownerID !== 0;
|
||||
}
|
||||
isBorder(): boolean {
|
||||
return this.data?.isBorder
|
||||
@@ -276,7 +276,7 @@ export interface GameUpdateViewData extends ViewData<GameUpdateViewData> {
|
||||
tick: number
|
||||
units: UnitViewData[]
|
||||
players: Record<PlayerID, PlayerViewData>
|
||||
tileUpdates?: TileViewData[]
|
||||
tileUpdates?: TileUpdate[]
|
||||
packedTileUpdates: Uint16Array[]
|
||||
}
|
||||
|
||||
@@ -310,7 +310,7 @@ export class GameView {
|
||||
this.lastUpdate = gu
|
||||
this.lastUpdate.tileUpdates = this.lastUpdate.packedTileUpdates.map(tu => unpackTileData(tu))
|
||||
this.lastUpdate.tileUpdates.forEach(tu => {
|
||||
this.tiles[tu.x][tu.y].data = tu
|
||||
this.tiles[tu.pos.x][tu.pos.y].data = tu
|
||||
})
|
||||
Object.entries(gu.players).forEach(([key, value]) => {
|
||||
this.smallIDToID.set(value.smallID, key);
|
||||
@@ -330,7 +330,7 @@ export class GameView {
|
||||
}
|
||||
|
||||
recentlyUpdatedTiles(): TileView[] {
|
||||
return this.lastUpdate.tileUpdates.filter(d => true).map(tu => new TileView(this, tu, this._terrainMap.terrain(new Cell(tu.x, tu.y))))
|
||||
return this.lastUpdate.tileUpdates.map(tu => new TileView(this, tu, this._terrainMap.terrain(new Cell(tu.pos.x, tu.pos.y))))
|
||||
}
|
||||
|
||||
player(id: PlayerID): PlayerView {
|
||||
@@ -404,11 +404,11 @@ export class GameView {
|
||||
}
|
||||
}
|
||||
|
||||
export function packTileData(tile: TileViewData): Uint16Array {
|
||||
export function packTileData(tile: TileUpdate): Uint16Array {
|
||||
const packed = new Uint16Array(4);
|
||||
packed[0] = tile.x;
|
||||
packed[1] = tile.y;
|
||||
packed[2] = tile.smallID;
|
||||
packed[0] = tile.pos.x;
|
||||
packed[1] = tile.pos.y;
|
||||
packed[2] = tile.ownerID;
|
||||
|
||||
// Pack booleans into bits
|
||||
packed[3] = (tile.hasFallout ? 1 : 0) |
|
||||
@@ -418,11 +418,14 @@ export function packTileData(tile: TileViewData): Uint16Array {
|
||||
return packed;
|
||||
}
|
||||
|
||||
export function unpackTileData(packed: Uint16Array): TileViewData {
|
||||
export function unpackTileData(packed: Uint16Array): TileUpdate {
|
||||
return {
|
||||
x: packed[0],
|
||||
y: packed[1],
|
||||
smallID: packed[2],
|
||||
type: GameUpdateType.Tile,
|
||||
pos: {
|
||||
x: packed[0],
|
||||
y: packed[1],
|
||||
},
|
||||
ownerID: packed[2],
|
||||
hasFallout: !!(packed[3] & 1),
|
||||
hasDefenseBonus: !!(packed[3] & 2),
|
||||
isBorder: !!(packed[3] & 4),
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Unit, Cell, Execution, MutableUnit, MutableGame, MutablePlayer, Player, PlayerID, TerraNullius, Tile, 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';
|
||||
import { DisplayMessageEvent } from '../game/Game';
|
||||
import { DisplayMessageUpdate } from '../game/Game';
|
||||
import { PathFinder } from "../pathfinding/PathFinding";
|
||||
import { PathFindResultType } from "../pathfinding/AStar";
|
||||
import { SerialAStar } from "../pathfinding/SerialAStar";
|
||||
|
||||
@@ -344,7 +344,7 @@ export interface Game {
|
||||
forEachTile(fn: (tile: Tile) => void): void
|
||||
executions(): ExecutionView[]
|
||||
terraNullius(): TerraNullius
|
||||
executeNextTick(): void
|
||||
executeNextTick(): GameUpdate[]
|
||||
ticks(): Tick
|
||||
inSpawnPhase(): boolean
|
||||
addExecution(...exec: Execution[]): void
|
||||
@@ -391,17 +391,16 @@ export type GameUpdate = TileUpdate
|
||||
| AllianceRequestReplyUpdate
|
||||
| BrokeAllianceUpdate
|
||||
| AllianceExpiredUpdate
|
||||
| DisplayMessageEvent
|
||||
| DisplayMessageUpdate
|
||||
| TargetPlayerUpdate
|
||||
| EmojiUpdate
|
||||
| WinUpdate
|
||||
|
||||
export interface TileUpdate {
|
||||
type: GameUpdateType.Tile
|
||||
owner: number
|
||||
ownerID: number
|
||||
pos: MapPos
|
||||
isBorder: boolean
|
||||
borderOnlyChange: boolean
|
||||
hasFallout: boolean
|
||||
hasDefenseBonus: boolean
|
||||
}
|
||||
@@ -457,7 +456,7 @@ export interface EmojiUpdate {
|
||||
createdAt: Tick
|
||||
}
|
||||
|
||||
export interface DisplayMessageEvent {
|
||||
export interface DisplayMessageUpdate {
|
||||
type: GameUpdateType.DisplayEvent
|
||||
message: string
|
||||
messageType: MessageType
|
||||
|
||||
@@ -79,7 +79,7 @@ export class GameImpl implements MutableGame {
|
||||
throw Error(`cannot set fallout, tile ${tile} has owner`)
|
||||
}
|
||||
ti._hasFallout = true
|
||||
this.updates.push(ti.toUpdate(false))
|
||||
this.updates.push(ti.toUpdate())
|
||||
}
|
||||
|
||||
addTileDefenseBonus(tile: Tile, unit: Unit, amount: number): DefenseBonus {
|
||||
@@ -164,7 +164,8 @@ export class GameImpl implements MutableGame {
|
||||
return this._ticks
|
||||
}
|
||||
|
||||
executeNextTick() {
|
||||
executeNextTick(): GameUpdate[] {
|
||||
this.updates = []
|
||||
this.execs.forEach(e => {
|
||||
if (e.isActive() && (!this.inSpawnPhase() || e.activeDuringSpawnPhase())) {
|
||||
e.tick(this._ticks)
|
||||
@@ -193,6 +194,7 @@ export class GameImpl implements MutableGame {
|
||||
})
|
||||
consolex.log(`tick ${this._ticks}: hash ${hash}`)
|
||||
}
|
||||
return this.updates
|
||||
}
|
||||
|
||||
terraNullius(): TerraNullius {
|
||||
@@ -386,7 +388,6 @@ export class GameImpl implements MutableGame {
|
||||
tile.neighbors().forEach(t => tiles.push(t as TileImpl))
|
||||
|
||||
for (const t of tiles) {
|
||||
this.updates.push(t.toUpdate(true))
|
||||
if (!t.hasOwner()) {
|
||||
t._isBorder = false
|
||||
continue
|
||||
@@ -398,6 +399,7 @@ export class GameImpl implements MutableGame {
|
||||
(t.owner() as PlayerImpl)._borderTiles.delete(t);
|
||||
t._isBorder = false
|
||||
}
|
||||
this.updates.push(t.toUpdate())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,18 +27,17 @@ export class TileImpl implements MutableTile {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
toUpdate(borderOnlyChange: boolean = false): TileUpdate {
|
||||
toUpdate(): TileUpdate {
|
||||
return {
|
||||
type: GameUpdateType.Tile,
|
||||
pos: {
|
||||
x: this._cell.x,
|
||||
y: this._cell.y
|
||||
},
|
||||
owner: this._owner.isPlayer() ? this._owner.smallID() : 0,
|
||||
ownerID: this._owner.isPlayer() ? this._owner.smallID() : 0,
|
||||
hasFallout: this._hasFallout,
|
||||
hasDefenseBonus: this.hasDefenseBonus(),
|
||||
isBorder: this.isBorder(),
|
||||
borderOnlyChange: borderOnlyChange
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user