mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-02 12:48:11 +00:00
fix bugs from using tilerefs
This commit is contained in:
@@ -67,7 +67,7 @@ export function createGrid(game: Game, player: Player, boundingBox: { min: Point
|
||||
const cell = new Cell(x * scalingFactor, y * scalingFactor);
|
||||
if (game.isOnMap(cell)) {
|
||||
const tile = game.ref(cell.x, cell.y);
|
||||
grid[x - scaledBoundingBox.min.x][y - scaledBoundingBox.min.y] = this.game.isLake(tile) || this.game.owner(tile) === player; // TODO: okay if lake
|
||||
grid[x - scaledBoundingBox.min.x][y - scaledBoundingBox.min.y] = game.isLake(tile) || game.owner(tile) === player; // TODO: okay if lake
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import { Layer } from "./Layer";
|
||||
import { SendAllianceReplyIntentEvent } from "../../Transport";
|
||||
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
|
||||
import { onlyImages, sanitize } from '../../../core/Util';
|
||||
import { GameView } from '../../../core/GameView';
|
||||
import { GameView, PlayerView } from '../../../core/GameView';
|
||||
|
||||
interface Event {
|
||||
description: string;
|
||||
@@ -222,8 +222,8 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
return;
|
||||
}
|
||||
|
||||
const requestor = this.game.playerBySmallID(update.requestorID)
|
||||
const recipient = this.game.playerBySmallID(update.recipientID)
|
||||
const requestor = this.game.playerBySmallID(update.requestorID) as PlayerView
|
||||
const recipient = this.game.playerBySmallID(update.recipientID) as PlayerView
|
||||
|
||||
this.addEvent({
|
||||
description: `${requestor.name()} requests an alliance!`,
|
||||
@@ -258,7 +258,7 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
return;
|
||||
}
|
||||
|
||||
const recipient = this.game.playerBySmallID(update.request.recipientID)
|
||||
const recipient = this.game.playerBySmallID(update.request.recipientID) as PlayerView
|
||||
|
||||
this.addEvent({
|
||||
description: `${recipient.name()} ${update.accepted ? "accepted" : "rejected"} your alliance request`,
|
||||
@@ -272,8 +272,8 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
if (!myPlayer) return;
|
||||
|
||||
const betrayed = this.game.playerBySmallID(update.betrayedID)
|
||||
const traitor = this.game.playerBySmallID(update.traitorID)
|
||||
const betrayed = this.game.playerBySmallID(update.betrayedID) as PlayerView
|
||||
const traitor = this.game.playerBySmallID(update.traitorID) as PlayerView
|
||||
|
||||
if (!betrayed.isTraitor() && traitor === myPlayer) {
|
||||
this.addEvent({
|
||||
@@ -297,7 +297,7 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
if (!myPlayer) return;
|
||||
|
||||
const otherID = update.player1ID === myPlayer.smallID() ? update.player2ID : update.player2ID === myPlayer.smallID() ? update.player1ID : null;
|
||||
const other = this.game.playerBySmallID(otherID)
|
||||
const other = this.game.playerBySmallID(otherID) as PlayerView
|
||||
if (!other || !myPlayer.isAlive() || !other.isAlive()) return;
|
||||
|
||||
this.addEvent({
|
||||
@@ -309,11 +309,11 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
}
|
||||
|
||||
onTargetPlayerEvent(event: TargetPlayerUpdate) {
|
||||
const other = this.game.playerBySmallID(event.playerID)
|
||||
const myPlayer = this.game.playerByClientID(this.clientID);
|
||||
const other = this.game.playerBySmallID(event.playerID) as PlayerView
|
||||
const myPlayer = this.game.playerByClientID(this.clientID) as PlayerView
|
||||
if (!myPlayer || !myPlayer.isAlliedWith(other)) return;
|
||||
|
||||
const target = this.game.playerBySmallID(event.targetID)
|
||||
const target = this.game.playerBySmallID(event.targetID) as PlayerView
|
||||
|
||||
this.addEvent({
|
||||
description: `${other.name()} requests you attack ${target.name()}`,
|
||||
@@ -328,7 +328,7 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
if (!myPlayer) return;
|
||||
|
||||
const recipient = update.recipientID == AllPlayers ? AllPlayers : this.game.playerBySmallID(update.recipientID)
|
||||
const sender = this.game.playerBySmallID(update.senderID)
|
||||
const sender = this.game.playerBySmallID(update.senderID) as PlayerView
|
||||
|
||||
if (recipient == myPlayer) {
|
||||
this.addEvent({
|
||||
@@ -340,7 +340,7 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
});
|
||||
} else if (sender === myPlayer && recipient !== AllPlayers) {
|
||||
this.addEvent({
|
||||
description: `Sent ${recipient.displayName()}: ${update.message}`,
|
||||
description: `Sent ${(recipient as PlayerView).displayName()}: ${update.message}`,
|
||||
unsafeDescription: true,
|
||||
type: MessageType.INFO,
|
||||
highlight: true,
|
||||
|
||||
@@ -161,7 +161,8 @@ export class TerritoryLayer implements Layer {
|
||||
if (!this.game.hasOwner(tile)) {
|
||||
if (this.game.hasFallout(tile)) {
|
||||
this.paintCell(
|
||||
new Cell(this.game.x(tile), this.game.y(tile)),
|
||||
this.game.x(tile),
|
||||
this.game.y(tile),
|
||||
this.theme.falloutColor(),
|
||||
150
|
||||
);
|
||||
@@ -173,21 +174,21 @@ export class TerritoryLayer implements Layer {
|
||||
const owner = this.game.owner(tile) as Player;
|
||||
if (this.game.isBorder(tile)) {
|
||||
this.paintCell(
|
||||
new Cell(this.game.x(tile), this.game.y(tile)),
|
||||
this.game.x(tile), this.game.y(tile),
|
||||
this.theme.borderColor(owner.info()),
|
||||
255
|
||||
);
|
||||
} else {
|
||||
this.paintCell(
|
||||
new Cell(this.game.x(tile), this.game.y(tile)),
|
||||
this.game.x(tile), this.game.y(tile),
|
||||
this.theme.territoryColor(owner.info()),
|
||||
150
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
paintCell(cell: Cell, color: Colord, alpha: number) {
|
||||
const index = (cell.y * this.game.width()) + cell.x;
|
||||
paintCell(x: number, y: number, color: Colord, alpha: number) {
|
||||
const index = (y * this.game.width()) + x;
|
||||
const offset = index * 4;
|
||||
this.imageData.data[offset] = color.rgba.r;
|
||||
this.imageData.data[offset + 1] = color.rgba.g;
|
||||
|
||||
@@ -49,7 +49,7 @@ export class UnitView implements Unit {
|
||||
return this.gameView.ref(this.data.pos.x, this.data.pos.y)
|
||||
}
|
||||
owner(): PlayerView {
|
||||
return this.gameView.playerBySmallID(this.data.ownerID)
|
||||
return this.gameView.playerBySmallID(this.data.ownerID) as PlayerView
|
||||
}
|
||||
isActive(): boolean {
|
||||
return this.data.isActive
|
||||
@@ -222,6 +222,7 @@ export class GameView implements GameMap {
|
||||
public update(gu: GameUpdateViewData) {
|
||||
this.lastUpdate = gu
|
||||
|
||||
this.updatedTiles = []
|
||||
this.lastUpdate.packedTileUpdates.forEach(tu => {
|
||||
this.updatedTiles.push(this.updateTile(tu))
|
||||
})
|
||||
@@ -259,7 +260,10 @@ export class GameView implements GameMap {
|
||||
throw Error(`player id ${id} not found`)
|
||||
}
|
||||
|
||||
playerBySmallID(id: number): PlayerView {
|
||||
playerBySmallID(id: number): PlayerView | TerraNullius {
|
||||
if (id == 0) {
|
||||
return new TerraNulliusImpl()
|
||||
}
|
||||
if (!this.smallIDToID.has(id)) {
|
||||
throw new Error(`small id ${id} not found`)
|
||||
}
|
||||
@@ -284,7 +288,7 @@ export class GameView implements GameMap {
|
||||
return []
|
||||
}
|
||||
|
||||
owner(tile: TileRef): PlayerView {
|
||||
owner(tile: TileRef): PlayerView | TerraNullius {
|
||||
return this.playerBySmallID(this.ownerID(tile))
|
||||
}
|
||||
|
||||
@@ -312,7 +316,7 @@ export class GameView implements GameMap {
|
||||
height(): number { return this._map.height() }
|
||||
numLandTiles(): number { return this._map.numLandTiles() }
|
||||
isValidCoord(x: number, y: number): boolean { return this._map.isValidCoord(x, y) }
|
||||
isLand(ref: TileRef): boolean { return this._map.isLake(ref) }
|
||||
isLand(ref: TileRef): boolean { return this._map.isLand(ref) }
|
||||
isOceanShore(ref: TileRef): boolean { return this._map.isOceanShore(ref) }
|
||||
isOcean(ref: TileRef): boolean { return this._map.isOcean(ref) }
|
||||
isShoreline(ref: TileRef): boolean { return this._map.isShoreline(ref) }
|
||||
@@ -323,7 +327,6 @@ export class GameView implements GameMap {
|
||||
hasFallout(ref: TileRef): boolean { return this._map.hasFallout(ref) }
|
||||
setFallout(ref: TileRef, value: boolean): void { return this._map.setFallout(ref, value) }
|
||||
isBorder(ref: TileRef): boolean { return this._map.isBorder(ref) }
|
||||
setBorder(ref: TileRef, value: boolean): void { return this._map.setBorder(ref, value) }
|
||||
neighbors(ref: TileRef): TileRef[] { return this._map.neighbors(ref) }
|
||||
isWater(ref: TileRef): boolean { return this._map.isWater(ref) }
|
||||
isLake(ref: TileRef): boolean { return this._map.isLake(ref) }
|
||||
|
||||
@@ -175,7 +175,6 @@ export class AttackExecution implements Execution {
|
||||
}
|
||||
this.border.add(neighbor)
|
||||
let numOwnedByMe = this.mg.neighbors(neighbor)
|
||||
.filter(t => this.mg.isLake(t))
|
||||
.filter(t => this.mg.owner(t) == this._owner)
|
||||
.length
|
||||
let dist = 0
|
||||
|
||||
@@ -56,7 +56,7 @@ export class BotExecution implements Execution {
|
||||
if (this.neighborsTerraNullius) {
|
||||
for (const b of this.bot.borderTiles()) {
|
||||
for (const n of this.mg.neighbors(b)) {
|
||||
if (!this.mg.hasOwner(n) && this.mg.isLake(n)) {
|
||||
if (!this.mg.hasOwner(n) && this.mg.isLand(n)) {
|
||||
this.sendAttack(this.mg.terraNullius())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ export class CityExecution implements Execution {
|
||||
if (this.city == null) {
|
||||
const spawnTile = this.player.canBuild(UnitType.City, this.tile)
|
||||
if (spawnTile == false) {
|
||||
consolex.warn('cannot build Defense Post')
|
||||
consolex.warn('cannot build city')
|
||||
this.active = false
|
||||
return
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ export class FakeHumanExecution implements Execution {
|
||||
|
||||
const enemyborder = Array.from(this.player.borderTiles())
|
||||
.flatMap(t => this.mg.neighbors(t))
|
||||
.filter(t => this.mg.isLake(t) && this.mg.ownerID(t) != this.player.smallID())
|
||||
.filter(t => this.mg.isLand(t) && this.mg.ownerID(t) != this.player.smallID())
|
||||
|
||||
if (enemyborder.length == 0) {
|
||||
if (this.random.chance(5)) {
|
||||
|
||||
@@ -150,9 +150,9 @@ export class PlayerExecution implements Execution {
|
||||
private removeCluster(cluster: Set<TileRef>) {
|
||||
const arr = Array.from(cluster)
|
||||
const mode = getMode(
|
||||
arr.
|
||||
flatMap(t => this.mg.neighbors(t))
|
||||
.filter(t => this.mg.ownerID(t) != this.player.smallID())
|
||||
arr
|
||||
.flatMap(t => this.mg.neighbors(t))
|
||||
.filter(t => this.mg.hasOwner(t) && this.mg.ownerID(t) != this.player.smallID())
|
||||
.map(t => this.mg.ownerID(t))
|
||||
)
|
||||
if (!this.mg.playerBySmallID(mode).isPlayer()) {
|
||||
|
||||
@@ -337,7 +337,6 @@ export interface MutableGame extends Game {
|
||||
units(...types: UnitType[]): MutableUnit[]
|
||||
addTileDefenseBonus(tile: TileRef, unit: Unit, amount: number): DefenseBonus
|
||||
removeTileDefenseBonus(bonus: DefenseBonus): void
|
||||
addFallout(tile: TileRef): void
|
||||
setWinner(winner: Player): void
|
||||
}
|
||||
|
||||
|
||||
@@ -84,11 +84,11 @@ export class GameImpl implements MutableGame {
|
||||
return old
|
||||
}
|
||||
|
||||
addFallout(tile: TileRef) {
|
||||
if (this.hasOwner(tile)) {
|
||||
setFallout(tile: TileRef, value: boolean) {
|
||||
if (value && this.hasOwner(tile)) {
|
||||
throw Error(`cannot set fallout, tile ${tile} has owner`)
|
||||
}
|
||||
this._map.setFallout(tile, true)
|
||||
this._map.setFallout(tile, value)
|
||||
this.addUpdate({
|
||||
type: GameUpdateType.Tile,
|
||||
update: this.toTileUpdate(tile)
|
||||
@@ -315,12 +315,6 @@ export class GameImpl implements MutableGame {
|
||||
return ns
|
||||
}
|
||||
|
||||
private assertIsOnMap(cell: Cell) {
|
||||
if (!this.isOnMap(cell)) {
|
||||
throw new Error(`cell ${cell.toString()} is not on map`)
|
||||
}
|
||||
}
|
||||
|
||||
conquer(owner: PlayerImpl, tile: TileRef): void {
|
||||
if (!this.isLand(tile)) {
|
||||
throw Error(`cannot conquer water`)
|
||||
@@ -330,7 +324,6 @@ export class GameImpl implements MutableGame {
|
||||
previousOwner._lastTileChange = this._ticks
|
||||
previousOwner._tiles.delete(tile)
|
||||
previousOwner._borderTiles.delete(tile)
|
||||
this._map.setBorder(tile, false)
|
||||
}
|
||||
this._map.setOwnerID(tile, owner.smallID())
|
||||
owner._tiles.add(tile)
|
||||
@@ -355,7 +348,6 @@ export class GameImpl implements MutableGame {
|
||||
previousOwner._lastTileChange = this._ticks
|
||||
previousOwner._tiles.delete(tile)
|
||||
previousOwner._borderTiles.delete(tile)
|
||||
this._map.setBorder(tile, false)
|
||||
|
||||
this._map.setOwnerID(tile, 0)
|
||||
this.updateBorders(tile)
|
||||
@@ -373,15 +365,12 @@ export class GameImpl implements MutableGame {
|
||||
|
||||
for (const t of tiles) {
|
||||
if (!this.hasOwner(t)) {
|
||||
this._map.setBorder(t, false)
|
||||
continue
|
||||
}
|
||||
if (this.calcIsBorder(t)) {
|
||||
(this.owner(t) as PlayerImpl)._borderTiles.add(t);
|
||||
this._map.setBorder(t, true)
|
||||
} else {
|
||||
(this.owner(t) as PlayerImpl)._borderTiles.delete(t);
|
||||
this._map.setBorder(t, false)
|
||||
}
|
||||
// this.updates.push(t.toUpdate())
|
||||
}
|
||||
@@ -494,7 +483,7 @@ export class GameImpl implements MutableGame {
|
||||
height(): number { return this._map.height() }
|
||||
numLandTiles(): number { return this._map.numLandTiles() }
|
||||
isValidCoord(x: number, y: number): boolean { return this._map.isValidCoord(x, y) }
|
||||
isLand(ref: TileRef): boolean { return this._map.isLake(ref) }
|
||||
isLand(ref: TileRef): boolean { return this._map.isLand(ref) }
|
||||
isOceanShore(ref: TileRef): boolean { return this._map.isOceanShore(ref) }
|
||||
isOcean(ref: TileRef): boolean { return this._map.isOcean(ref) }
|
||||
isShoreline(ref: TileRef): boolean { return this._map.isShoreline(ref) }
|
||||
@@ -503,9 +492,7 @@ export class GameImpl implements MutableGame {
|
||||
hasOwner(ref: TileRef): boolean { return this._map.hasOwner(ref) }
|
||||
setOwnerID(ref: TileRef, playerId: number): void { return this._map.setOwnerID(ref, playerId) }
|
||||
hasFallout(ref: TileRef): boolean { return this._map.hasFallout(ref) }
|
||||
setFallout(ref: TileRef, value: boolean): void { return this._map.setFallout(ref, value) }
|
||||
isBorder(ref: TileRef): boolean { return this._map.isBorder(ref) }
|
||||
setBorder(ref: TileRef, value: boolean): void { return this._map.setBorder(ref, value) }
|
||||
neighbors(ref: TileRef): TileRef[] { return this._map.neighbors(ref) }
|
||||
isWater(ref: TileRef): boolean { return this._map.isWater(ref) }
|
||||
isLake(ref: TileRef): boolean { return this._map.isLake(ref) }
|
||||
|
||||
@@ -28,7 +28,6 @@ export interface GameMap {
|
||||
hasFallout(ref: TileRef): boolean
|
||||
setFallout(ref: TileRef, value: boolean): void
|
||||
isBorder(ref: TileRef): boolean
|
||||
setBorder(ref: TileRef, value: boolean): void
|
||||
neighbors(ref: TileRef): TileRef[]
|
||||
isWater(ref: TileRef): boolean
|
||||
isLake(ref: TileRef): boolean
|
||||
@@ -62,8 +61,7 @@ export class GameMapImpl implements GameMap {
|
||||
// State bits (Uint16Array)
|
||||
private static readonly PLAYER_ID_OFFSET = 0; // Uses bits 0-11 (12 bits)
|
||||
private static readonly PLAYER_ID_MASK = 0xFFF;
|
||||
private static readonly FALLOUT_BIT = 12;
|
||||
private static readonly BORDER_BIT = 13;
|
||||
private static readonly FALLOUT_BIT = 13;
|
||||
private static readonly DEFENSE_BONUS_BIT = 14;
|
||||
// Bit 15 still reserved
|
||||
|
||||
@@ -155,15 +153,7 @@ export class GameMapImpl implements GameMap {
|
||||
}
|
||||
|
||||
isBorder(ref: TileRef): boolean {
|
||||
return Boolean(this.state[ref] & (1 << GameMapImpl.BORDER_BIT));
|
||||
}
|
||||
|
||||
setBorder(ref: TileRef, value: boolean): void {
|
||||
if (value) {
|
||||
this.state[ref] |= 1 << GameMapImpl.BORDER_BIT;
|
||||
} else {
|
||||
this.state[ref] &= ~(1 << GameMapImpl.BORDER_BIT);
|
||||
}
|
||||
return this.neighbors(ref).some(tr => this.ownerID(tr) != this.ownerID(ref))
|
||||
}
|
||||
|
||||
hasDefenseBonus(ref: TileRef): boolean {
|
||||
|
||||
@@ -31,7 +31,7 @@ export class PlayerImpl implements MutablePlayer {
|
||||
public _borderTiles: Set<TileRef> = new Set();
|
||||
|
||||
public _units: UnitImpl[] = [];
|
||||
public _tiles: Set<TileRef>
|
||||
public _tiles: Set<TileRef> = new Set()
|
||||
|
||||
private _name: string;
|
||||
private _displayName: string;
|
||||
|
||||
@@ -40,7 +40,7 @@ export class MiniAStar implements AStar {
|
||||
}
|
||||
|
||||
reconstructPath(): TileRef[] {
|
||||
const upscaled = upscalePath(this.aStar.reconstructPath().map(tr => new Cell(this.gameMap.x(tr), this.gameMap.y(tr))))
|
||||
const upscaled = upscalePath(this.aStar.reconstructPath().map(tr => new Cell(this.miniMap.x(tr), this.miniMap.y(tr))))
|
||||
upscaled.push(new Cell(this.gameMap.x(this.dst), this.gameMap.y(this.dst)))
|
||||
return upscaled.map(c => this.gameMap.ref(c.x, c.y))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user