mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 16:46:35 +00:00
update views
This commit is contained in:
@@ -146,7 +146,7 @@ export class TerritoryLayer implements Layer {
|
||||
}
|
||||
const owner = tile.owner() as Player
|
||||
if (tile.isBorder()) {
|
||||
if (tile.defenseBonuses().filter(db => db.unit.owner() == owner).length > 0) {
|
||||
if (tile.hasDefenseBonus()) {
|
||||
this.paintCell(
|
||||
tile.cell(),
|
||||
this.theme.defendedBorderColor(owner.info()),
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Executor } from "./execution/ExecutionManager";
|
||||
import { Game, Tile, TileEvent } from "./game/Game";
|
||||
import { createGame } from "./game/GameImpl";
|
||||
import { loadTerrainMap } from "./game/TerrainMapLoader";
|
||||
import { GameUpdateViewData } from "./GameViewData";
|
||||
import { GameUpdateViewData } from "./GameView";
|
||||
import { GameConfig, Turn } from "./Schemas";
|
||||
|
||||
export async function createGameRunner(gameID: string, gameConfig: GameConfig): Promise<GameRunner> {
|
||||
|
||||
+145
-147
@@ -1,80 +1,70 @@
|
||||
import { MessageType } from "../client/graphics/layers/EventsDisplay";
|
||||
import { Config } from "./configuration/Config";
|
||||
import { Alliance, AllianceRequest, AllPlayers, Cell, DefenseBonus, EmojiMessage, Execution, ExecutionView, Game, Gold, Nation, Player, PlayerID, PlayerInfo, PlayerType, Relation, TerrainMap, TerrainTile, TerrainType, TerraNullius, Tick, Tile, Unit, UnitInfo, UnitType } from "./game/Game";
|
||||
import { GameUpdateViewData, PlayerViewData, TileViewData, UnitViewData } from "./GameViewData";
|
||||
import { Alliance, AllianceRequest, AllPlayers, Cell, DefenseBonus, EmojiMessage, Execution, ExecutionView, Game, Gold, MutableTile, Nation, Player, PlayerID, PlayerInfo, PlayerType, Relation, TerrainMap, TerrainTile, TerrainType, TerraNullius, Tick, Tile, Unit, UnitInfo, UnitType } from "./game/Game";
|
||||
import { ClientID } from "./Schemas";
|
||||
|
||||
export interface ViewSerializable<T> {
|
||||
toViewData(): ViewData<T>;
|
||||
}
|
||||
|
||||
export interface ViewData<T> {
|
||||
// Base view data properties if any
|
||||
}
|
||||
|
||||
export interface TileViewData extends ViewData<TileViewData> {
|
||||
x: number
|
||||
y: number
|
||||
owner: PlayerID,
|
||||
hasFallout: boolean
|
||||
hasDefenseBonus: boolean
|
||||
isBorder: boolean
|
||||
}
|
||||
|
||||
export class TileView implements Tile {
|
||||
constructor(private data: TileViewData, terrain: TerrainTile) { }
|
||||
isLand(): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
isShore(): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
isOceanShore(): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
isWater(): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
isShorelineWater(): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
isOcean(): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
isLake(): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
terrain(): TerrainTile {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
magnitude(): number {
|
||||
throw new Error("Method not implemented.");
|
||||
constructor(private game: Game, private data: TileViewData, private _terrain: TerrainTile) { }
|
||||
type(): TerrainType {
|
||||
return this._terrain.type()
|
||||
}
|
||||
owner(): Player | TerraNullius {
|
||||
throw new Error("Method not implemented.");
|
||||
return this.game.player(this.data.owner)
|
||||
}
|
||||
hasOwner(): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
return this.data.owner != null
|
||||
}
|
||||
isBorder(): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
borders(other: Player | TerraNullius): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
isInterior(): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
return this.data.isBorder
|
||||
}
|
||||
cell(): Cell {
|
||||
throw new Error("Method not implemented.");
|
||||
return new Cell(this.data.x, this.data.y)
|
||||
}
|
||||
hasFallout(): boolean {
|
||||
return this.data.hasFallout
|
||||
}
|
||||
terrain(): TerrainTile {
|
||||
return this._terrain
|
||||
}
|
||||
|
||||
neighbors(): Tile[] {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
neighborsWrapped(): Tile[] {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
onShore(): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
defenseBonuses(): DefenseBonus[] {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
defenseBonus(player: Player): number {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
hasFallout(): boolean {
|
||||
|
||||
|
||||
hasDefenseBonus(): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
cost(): number {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
type(): TerrainType {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
}
|
||||
|
||||
export interface UnitViewData extends ViewData<UnitView> {
|
||||
type: UnitType,
|
||||
troops: number,
|
||||
x: number,
|
||||
y: number,
|
||||
owner: string,
|
||||
isActive: boolean,
|
||||
health?: number
|
||||
}
|
||||
|
||||
export class UnitView implements Unit {
|
||||
@@ -95,136 +85,144 @@ export class UnitView implements Unit {
|
||||
isActive(): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
info(): UnitInfo {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
hasHealth(): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
return this.data.health != undefined
|
||||
}
|
||||
health(): number {
|
||||
throw new Error("Method not implemented.");
|
||||
return this.data.health ?? 0
|
||||
}
|
||||
}
|
||||
|
||||
export interface PlayerViewData extends ViewData<PlayerViewData> {
|
||||
clientID: ClientID,
|
||||
name: string,
|
||||
displayName: string,
|
||||
id: PlayerID,
|
||||
type: PlayerType,
|
||||
isAlive: boolean,
|
||||
tilesOwned: number,
|
||||
allies: PlayerID[],
|
||||
gold: number,
|
||||
population: number,
|
||||
workers: number,
|
||||
troops: number,
|
||||
targetTroopRatio: number
|
||||
}
|
||||
|
||||
export class PlayerView implements Player {
|
||||
constructor(private data: PlayerViewData) { }
|
||||
info(): PlayerInfo {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
constructor(private game: Game, private data: PlayerViewData) { }
|
||||
name(): string {
|
||||
throw new Error("Method not implemented.");
|
||||
return this.data.name
|
||||
}
|
||||
displayName(): string {
|
||||
throw new Error("Method not implemented.");
|
||||
return this.data.displayName
|
||||
}
|
||||
clientID(): ClientID {
|
||||
throw new Error("Method not implemented.");
|
||||
return this.data.clientID
|
||||
}
|
||||
id(): PlayerID {
|
||||
throw new Error("Method not implemented.");
|
||||
return this.data.id
|
||||
}
|
||||
type(): PlayerType {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
units(...types: UnitType[]): Unit[] {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
ownsTile(cell: Cell): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
return this.data.type
|
||||
}
|
||||
isAlive(): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
borderTiles(): ReadonlySet<Tile> {
|
||||
throw new Error("Method not implemented.");
|
||||
return this.data.isAlive
|
||||
}
|
||||
isPlayer(): this is Player {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
neighbors(): (Player | TerraNullius)[] {
|
||||
throw new Error("Method not implemented.");
|
||||
return true
|
||||
}
|
||||
numTilesOwned(): number {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
tiles(): ReadonlySet<Tile> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
sharesBorderWith(other: Player | TerraNullius): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
incomingAllianceRequests(): AllianceRequest[] {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
outgoingAllianceRequests(): AllianceRequest[] {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
alliances(): Alliance[] {
|
||||
throw new Error("Method not implemented.");
|
||||
return this.data.tilesOwned
|
||||
}
|
||||
allies(): Player[] {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
isAlliedWith(other: Player): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
allianceWith(other: Player): Alliance | null {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
recentOrPendingAllianceRequestWith(other: Player): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
relation(other: Player): Relation {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
allRelationsSorted(): { player: Player; relation: Relation; }[] {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
isTraitor(): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
canTarget(other: Player): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
targets(): Player[] {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
transitiveTargets(): Player[] {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
toString(): string {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
canSendEmoji(recipient: Player | typeof AllPlayers): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
outgoingEmojis(): EmojiMessage[] {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
canDonate(recipient: Player): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
return this.data.allies.map(a => this.game.player(a))
|
||||
}
|
||||
gold(): Gold {
|
||||
throw new Error("Method not implemented.");
|
||||
return this.data.gold
|
||||
}
|
||||
population(): number {
|
||||
throw new Error("Method not implemented.");
|
||||
return this.data.workers
|
||||
}
|
||||
workers(): number {
|
||||
throw new Error("Method not implemented.");
|
||||
return this.data.workers
|
||||
}
|
||||
targetTroopRatio(): number {
|
||||
throw new Error("Method not implemented.");
|
||||
return this.data.targetTroopRatio
|
||||
}
|
||||
troops(): number {
|
||||
throw new Error("Method not implemented.");
|
||||
return
|
||||
}
|
||||
|
||||
isAlliedWith(other: Player): boolean {
|
||||
return false
|
||||
}
|
||||
allianceWith(other: Player): Alliance | null {
|
||||
return null
|
||||
}
|
||||
borderTiles(): ReadonlySet<Tile> {
|
||||
return new Set()
|
||||
}
|
||||
units(...types: UnitType[]): Unit[] {
|
||||
return []
|
||||
}
|
||||
sharesBorderWith(other: Player | TerraNullius): boolean {
|
||||
return false
|
||||
}
|
||||
incomingAllianceRequests(): AllianceRequest[] {
|
||||
return []
|
||||
}
|
||||
outgoingAllianceRequests(): AllianceRequest[] {
|
||||
return []
|
||||
}
|
||||
alliances(): Alliance[] {
|
||||
return []
|
||||
}
|
||||
recentOrPendingAllianceRequestWith(other: Player): boolean {
|
||||
return false
|
||||
}
|
||||
relation(other: Player): Relation {
|
||||
return Relation.Neutral
|
||||
}
|
||||
allRelationsSorted(): { player: Player; relation: Relation; }[] {
|
||||
return []
|
||||
}
|
||||
transitiveTargets(): Player[] {
|
||||
return []
|
||||
}
|
||||
isTraitor(): boolean {
|
||||
return false
|
||||
}
|
||||
canTarget(other: Player): boolean {
|
||||
return false
|
||||
}
|
||||
toString(): string {
|
||||
return ''
|
||||
}
|
||||
canSendEmoji(recipient: Player | typeof AllPlayers): boolean {
|
||||
return false
|
||||
}
|
||||
outgoingEmojis(): EmojiMessage[] {
|
||||
return []
|
||||
}
|
||||
canDonate(recipient: Player): boolean {
|
||||
return false
|
||||
}
|
||||
canBuild(type: UnitType, targetTile: Tile): Tile | false {
|
||||
throw new Error("Method not implemented.");
|
||||
return false
|
||||
}
|
||||
lastTileChange(): Tick {
|
||||
throw new Error("Method not implemented.");
|
||||
return 0
|
||||
}
|
||||
info(): PlayerInfo {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export interface GameUpdateViewData extends ViewData<GameUpdateViewData> {
|
||||
units: UnitViewData[]
|
||||
players: PlayerViewData[]
|
||||
tileUpdates: TileViewData[]
|
||||
}
|
||||
|
||||
export class GameView implements Game {
|
||||
@@ -247,7 +245,7 @@ export class GameView implements Game {
|
||||
}
|
||||
|
||||
recentlyUpdatedTiles(): TileView[] {
|
||||
return this.lastGameUpdate.tileUpdates.map(tu => new TileView(tu, this._terrainMap.terrain(new Cell(tu.x, tu.y))))
|
||||
return this.lastGameUpdate.tileUpdates.map(tu => new TileView(this, tu, this._terrainMap.terrain(new Cell(tu.x, tu.y))))
|
||||
}
|
||||
|
||||
player(id: PlayerID): Player {
|
||||
|
||||
@@ -1,26 +1,4 @@
|
||||
export interface ViewSerialiable {
|
||||
toViewData(): ViewData
|
||||
}
|
||||
|
||||
export interface ViewData {
|
||||
|
||||
}
|
||||
|
||||
export interface TileViewData extends ViewData {
|
||||
x: number
|
||||
y: number
|
||||
}
|
||||
|
||||
export interface UnitViewData extends ViewData {
|
||||
|
||||
}
|
||||
|
||||
export interface PlayerViewData extends ViewData {
|
||||
|
||||
}
|
||||
|
||||
export interface GameUpdateViewData extends ViewData {
|
||||
units: UnitViewData[]
|
||||
players: PlayerViewData[]
|
||||
tileUpdates: TileViewData[]
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Difficulty, GameType, Gold, Player, PlayerInfo, PlayerType, TerrainType, TerraNullius, Tick, Tile, Unit, UnitInfo, UnitType } from "../game/Game";
|
||||
import { Difficulty, GameType, Gold, MutableTile, Player, PlayerInfo, PlayerType, TerrainType, TerraNullius, Tick, Tile, Unit, UnitInfo, UnitType } from "../game/Game";
|
||||
import { GameConfig } from "../Schemas";
|
||||
import { assertNever, distSort, manhattanDist, simpleHash, within } from "../Util";
|
||||
import { Config, ServerConfig, Theme } from "./Config";
|
||||
@@ -186,7 +186,7 @@ export class DefaultConfig implements Config {
|
||||
}
|
||||
theme(): Theme { return pastelTheme; }
|
||||
|
||||
attackLogic(attackTroops: number, attacker: Player, defender: Player | TerraNullius, tileToConquer: Tile): { attackerTroopLoss: number; defenderTroopLoss: number; tilesPerTickUsed: number } {
|
||||
attackLogic(attackTroops: number, attacker: Player, defender: Player | TerraNullius, tileToConquer: MutableTile): { attackerTroopLoss: number; defenderTroopLoss: number; tilesPerTickUsed: number } {
|
||||
let mag = 0
|
||||
let speed = 0
|
||||
switch (tileToConquer.terrain().type()) {
|
||||
|
||||
+20
-15
@@ -184,16 +184,19 @@ export interface Tile extends SearchNode {
|
||||
owner(): Player | TerraNullius
|
||||
hasOwner(): boolean
|
||||
isBorder(): boolean
|
||||
borders(other: Player | TerraNullius): boolean
|
||||
isInterior(): boolean
|
||||
cell(): Cell
|
||||
neighbors(): Tile[]
|
||||
neighborsWrapped(): Tile[]
|
||||
defenseBonuses(): DefenseBonus[]
|
||||
// defense bonus against this player
|
||||
defenseBonus(player: Player): number
|
||||
hasFallout(): boolean
|
||||
terrain(): TerrainTile
|
||||
neighbors(): Tile[]
|
||||
hasDefenseBonus(): boolean
|
||||
}
|
||||
|
||||
export interface MutableTile extends Tile {
|
||||
// defense bonus against this player
|
||||
defenseBonus(player: Player): number
|
||||
borders(other: Player | TerraNullius): boolean
|
||||
neighborsWrapped(): Tile[]
|
||||
defenseBonuses(): DefenseBonus[]
|
||||
}
|
||||
|
||||
export interface Unit {
|
||||
@@ -202,7 +205,6 @@ export interface Unit {
|
||||
tile(): Tile
|
||||
owner(): Player
|
||||
isActive(): boolean
|
||||
info(): UnitInfo
|
||||
hasHealth(): boolean
|
||||
health(): number
|
||||
}
|
||||
@@ -211,6 +213,7 @@ export interface MutableUnit extends Unit {
|
||||
move(tile: Tile): void
|
||||
owner(): MutablePlayer
|
||||
setTroops(troops: number): void
|
||||
info(): UnitInfo
|
||||
delete(displayerMessage?: boolean): void
|
||||
modifyHealth(delta: number): void
|
||||
}
|
||||
@@ -230,13 +233,10 @@ export interface Player {
|
||||
id(): PlayerID
|
||||
type(): PlayerType
|
||||
units(...types: UnitType[]): Unit[]
|
||||
ownsTile(cell: Cell): boolean
|
||||
isAlive(): boolean
|
||||
borderTiles(): ReadonlySet<Tile>
|
||||
isPlayer(): this is Player
|
||||
neighbors(): (Player | TerraNullius)[]
|
||||
numTilesOwned(): number
|
||||
tiles(): ReadonlySet<Tile>
|
||||
sharesBorderWith(other: Player | TerraNullius): boolean
|
||||
incomingAllianceRequests(): AllianceRequest[]
|
||||
outgoingAllianceRequests(): AllianceRequest[]
|
||||
@@ -251,12 +251,9 @@ export interface Player {
|
||||
relation(other: Player): Relation
|
||||
// Sorted from most hated to most liked
|
||||
allRelationsSorted(): { player: Player, relation: Relation }[]
|
||||
transitiveTargets(): Player[]
|
||||
isTraitor(): boolean
|
||||
canTarget(other: Player): boolean
|
||||
// Targets for this player
|
||||
targets(): Player[]
|
||||
// Targets of player and all allies.
|
||||
transitiveTargets(): Player[]
|
||||
toString(): string
|
||||
canSendEmoji(recipient: Player | typeof AllPlayers): boolean
|
||||
outgoingEmojis(): EmojiMessage[]
|
||||
@@ -275,6 +272,13 @@ export interface Player {
|
||||
}
|
||||
|
||||
export interface MutablePlayer extends Player {
|
||||
// Targets for this player
|
||||
targets(): Player[]
|
||||
// Targets of player and all allies.
|
||||
neighbors(): (Player | TerraNullius)[]
|
||||
tiles(): ReadonlySet<MutableTile>
|
||||
ownsTile(cell: Cell): boolean
|
||||
tiles(): ReadonlySet<MutableTile>
|
||||
conquer(tile: Tile): void
|
||||
relinquish(tile: Tile): void
|
||||
executions(): Execution[]
|
||||
@@ -338,6 +342,7 @@ export interface Game {
|
||||
}
|
||||
|
||||
export interface MutableGame extends Game {
|
||||
tile(cell: Cell): MutableTile
|
||||
player(id: PlayerID): MutablePlayer
|
||||
playerByClientID(id: ClientID): MutablePlayer | null
|
||||
players(): MutablePlayer[]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { info } from "console";
|
||||
import { Config } from "../configuration/Config";
|
||||
import { EventBus } from "../EventBus";
|
||||
import { Cell, Execution, MutableGame, Game, MutablePlayer, PlayerEvent, PlayerID, PlayerInfo, Player, TerraNullius, Tile, TileEvent, Unit, UnitEvent as UnitEvent, PlayerType, MutableAllianceRequest, AllianceRequestReplyEvent, AllianceRequestEvent, BrokeAllianceEvent, MutableAlliance, Alliance, AllianceExpiredEvent, Nation, UnitType, UnitInfo, TerrainMap, DefenseBonus } from "./Game";
|
||||
import { Cell, Execution, MutableGame, Game, MutablePlayer, PlayerEvent, PlayerID, PlayerInfo, Player, TerraNullius, Tile, TileEvent, Unit, UnitEvent as UnitEvent, PlayerType, MutableAllianceRequest, AllianceRequestReplyEvent, AllianceRequestEvent, BrokeAllianceEvent, MutableAlliance, Alliance, AllianceExpiredEvent, Nation, UnitType, UnitInfo, TerrainMap, DefenseBonus, MutableTile } from "./Game";
|
||||
import { TerrainMapImpl } from "./TerrainMapLoader";
|
||||
import { PlayerImpl } from "./PlayerImpl";
|
||||
import { TerraNulliusImpl } from "./TerraNulliusImpl";
|
||||
@@ -267,9 +267,9 @@ export class GameImpl implements MutableGame {
|
||||
}
|
||||
|
||||
|
||||
tile(cell: Cell): Tile {
|
||||
tile(cell: Cell): MutableTile {
|
||||
this.assertIsOnMap(cell)
|
||||
return this.map[cell.x][cell.y]
|
||||
return this.map[cell.x][cell.y] as MutableTile
|
||||
}
|
||||
|
||||
isOnMap(cell: Cell): boolean {
|
||||
@@ -327,7 +327,7 @@ export class GameImpl implements MutableGame {
|
||||
if (previousOwner.isPlayer()) {
|
||||
previousOwner._lastTileChange = this._ticks
|
||||
previousOwner._tiles.delete(tile.cell().toString())
|
||||
previousOwner._borderTiles.delete(tile)
|
||||
previousOwner._borderTiles.delete(tileImpl)
|
||||
tileImpl._isBorder = false
|
||||
}
|
||||
tileImpl._owner = owner
|
||||
@@ -350,7 +350,7 @@ export class GameImpl implements MutableGame {
|
||||
let previousOwner = tileImpl._owner as PlayerImpl
|
||||
previousOwner._lastTileChange = this._ticks
|
||||
previousOwner._tiles.delete(tile.cell().toString())
|
||||
previousOwner._borderTiles.delete(tile)
|
||||
previousOwner._borderTiles.delete(tileImpl)
|
||||
tileImpl._isBorder = false
|
||||
|
||||
tileImpl._owner = this._terraNullius
|
||||
@@ -382,7 +382,7 @@ export class GameImpl implements MutableGame {
|
||||
if (!tile.hasOwner()) {
|
||||
return false
|
||||
}
|
||||
for (const neighbor of tile.neighbors()) {
|
||||
for (const neighbor of (tile as MutableTile).neighbors()) {
|
||||
let bordersEnemy = tile.owner() != neighbor.owner()
|
||||
if (bordersEnemy) {
|
||||
return true
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MutablePlayer, Tile, PlayerInfo, PlayerID, PlayerType, Player, TerraNullius, Cell, Execution, AllianceRequest, MutableAllianceRequest, MutableAlliance, Alliance, Tick, TargetPlayerEvent, EmojiMessage, EmojiMessageEvent, AllPlayers, Gold, UnitType, Unit, MutableUnit, Relation } from "./Game";
|
||||
import { MutablePlayer, Tile, PlayerInfo, PlayerID, PlayerType, Player, TerraNullius, Cell, Execution, AllianceRequest, MutableAllianceRequest, MutableAlliance, Alliance, Tick, TargetPlayerEvent, EmojiMessage, EmojiMessageEvent, AllPlayers, Gold, UnitType, Unit, MutableUnit, Relation, MutableTile } from "./Game";
|
||||
import { ClientID } from "../Schemas";
|
||||
import { assertNever, bfs, closestOceanShoreFromPlayer, dist, distSortUnit, manhattanDist, manhattanDistWrapped, processName, simpleHash, sourceDstOceanShore, within } from "../Util";
|
||||
import { CellString, GameImpl } from "./GameImpl";
|
||||
@@ -6,6 +6,7 @@ import { UnitImpl } from "./UnitImpl";
|
||||
import { TileImpl } from "./TileImpl";
|
||||
import { MessageType } from "../../client/graphics/layers/EventsDisplay";
|
||||
import { renderTroops } from "../../client/Utils";
|
||||
import { PlayerViewData, ViewData, ViewSerializable } from "../GameView";
|
||||
|
||||
interface Target {
|
||||
tick: Tick
|
||||
@@ -16,7 +17,7 @@ class Donation {
|
||||
constructor(public readonly recipient: Player, public readonly tick: Tick) { }
|
||||
}
|
||||
|
||||
export class PlayerImpl implements MutablePlayer {
|
||||
export class PlayerImpl implements MutablePlayer, ViewSerializable<PlayerViewData> {
|
||||
|
||||
public _lastTileChange: number = 0
|
||||
|
||||
@@ -27,10 +28,10 @@ export class PlayerImpl implements MutablePlayer {
|
||||
|
||||
isTraitor_ = false
|
||||
|
||||
public _borderTiles: Set<Tile> = new Set();
|
||||
public _borderTiles: Set<TileImpl> = new Set();
|
||||
|
||||
public _units: UnitImpl[] = [];
|
||||
public _tiles: Map<CellString, Tile> = new Map<CellString, Tile>();
|
||||
public _tiles: Map<CellString, Tile> = new Map<CellString, TileImpl>();
|
||||
|
||||
private _name: string;
|
||||
private _displayName: string;
|
||||
@@ -54,6 +55,23 @@ export class PlayerImpl implements MutablePlayer {
|
||||
this._displayName = processName(this._name)
|
||||
|
||||
}
|
||||
toViewData(): ViewData<PlayerViewData> {
|
||||
return {
|
||||
clientID: this.clientID(),
|
||||
name: this.name(),
|
||||
displayName: this.displayName(),
|
||||
id: this.id(),
|
||||
type: this.type(),
|
||||
isAlive: this.isAlive(),
|
||||
tilesOwned: this.numTilesOwned(),
|
||||
allies: this.allies().map(p => p.id()),
|
||||
gold: this._gold,
|
||||
population: this.population(),
|
||||
workers: this.workers(),
|
||||
troops: this.troops(),
|
||||
targetTroopRatio: this.targetTroopRatio()
|
||||
}
|
||||
}
|
||||
|
||||
name(): string {
|
||||
return this._name;
|
||||
@@ -98,11 +116,11 @@ export class PlayerImpl implements MutablePlayer {
|
||||
return this._tiles.size;
|
||||
}
|
||||
|
||||
tiles(): ReadonlySet<Tile> {
|
||||
return new Set(this._tiles.values());
|
||||
tiles(): ReadonlySet<MutableTile> {
|
||||
return new Set(this._tiles.values()) as Set<MutableTile>;
|
||||
}
|
||||
|
||||
borderTiles(): ReadonlySet<Tile> {
|
||||
borderTiles(): ReadonlySet<MutableTile> {
|
||||
return this._borderTiles;
|
||||
}
|
||||
|
||||
@@ -279,7 +297,7 @@ export class PlayerImpl implements MutablePlayer {
|
||||
transitiveTargets(): MutablePlayer[] {
|
||||
const ts = this.alliances().map(a => a.other(this)).flatMap(ally => ally.targets())
|
||||
ts.push(...this.targets())
|
||||
return [...new Set(ts)]
|
||||
return [...new Set(ts)] as MutablePlayer[]
|
||||
}
|
||||
|
||||
sendEmoji(recipient: Player | typeof AllPlayers, emoji: string): void {
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { Tile, Cell, TerrainType, Player, TerraNullius, MutablePlayer, TerrainTile, DefenseBonus } from "./Game";
|
||||
import { Tile, Cell, TerrainType, Player, TerraNullius, MutablePlayer, TerrainTile, DefenseBonus, MutableTile } from "./Game";
|
||||
import { SearchNode } from "../pathfinding/AStar";
|
||||
import { TerrainTileImpl } from "./TerrainMapLoader";
|
||||
import { GameImpl } from "./GameImpl";
|
||||
import { PlayerImpl } from "./PlayerImpl";
|
||||
import { TerraNulliusImpl } from "./TerraNulliusImpl";
|
||||
import { TileView, TileViewData, ViewData, ViewSerializable } from "../GameView";
|
||||
|
||||
|
||||
export class TileImpl implements Tile {
|
||||
export class TileImpl implements MutableTile, ViewSerializable<TileViewData> {
|
||||
|
||||
public _isBorder = false;
|
||||
private _neighbors: Tile[] = null;
|
||||
@@ -22,6 +23,17 @@ export class TileImpl implements Tile {
|
||||
private readonly _terrain: TerrainTileImpl
|
||||
) { }
|
||||
|
||||
toViewData(): ViewData<TileViewData> {
|
||||
return {
|
||||
x: this._cell.x,
|
||||
y: this._cell.y,
|
||||
owner: this._owner?.id(),
|
||||
hasFallout: this._hasFallout,
|
||||
hasDefenseBonus: this.hasDefenseBonus(),
|
||||
isBorder: this.isBorder()
|
||||
}
|
||||
}
|
||||
|
||||
hasFallout(): boolean {
|
||||
return this._hasFallout
|
||||
}
|
||||
@@ -30,6 +42,10 @@ export class TileImpl implements Tile {
|
||||
return this._terrain._type
|
||||
}
|
||||
|
||||
hasDefenseBonus(): boolean {
|
||||
return this.defenseBonuses.length > 0
|
||||
}
|
||||
|
||||
defenseBonus(player: Player): number {
|
||||
if (this.owner() == player) {
|
||||
throw Error(`cannot get defense bonus of tile already owned by player, ${player}`)
|
||||
@@ -93,7 +109,6 @@ export class TileImpl implements Tile {
|
||||
hasOwner(): boolean { return this._owner != this.gs._terraNullius; }
|
||||
owner(): MutablePlayer | TerraNullius { return this._owner; }
|
||||
isBorder(): boolean { return this._isBorder; }
|
||||
isInterior(): boolean { return this.hasOwner() && !this.isBorder(); }
|
||||
cell(): Cell { return this._cell; }
|
||||
x(): number {
|
||||
return this._cell.x
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { MessageType } from "../../client/graphics/layers/EventsDisplay";
|
||||
import { UnitViewData, ViewData, ViewSerializable } from "../GameView";
|
||||
import { simpleHash, within } from "../Util";
|
||||
import { MutableUnit, Tile, TerraNullius, UnitType, Player, UnitInfo } from "./Game";
|
||||
import { GameImpl } from "./GameImpl";
|
||||
@@ -6,7 +7,7 @@ import { PlayerImpl } from "./PlayerImpl";
|
||||
import { TerraNulliusImpl } from "./TerraNulliusImpl";
|
||||
|
||||
|
||||
export class UnitImpl implements MutableUnit {
|
||||
export class UnitImpl implements MutableUnit, ViewSerializable<UnitViewData> {
|
||||
private _active = true;
|
||||
private _health: number
|
||||
|
||||
@@ -21,6 +22,18 @@ export class UnitImpl implements MutableUnit {
|
||||
this._health = (this.g.unitInfo(_type).maxHealth ?? 2) / 2
|
||||
}
|
||||
|
||||
toViewData(): ViewData<UnitViewData> {
|
||||
return {
|
||||
type: this._type,
|
||||
troops: this._troops,
|
||||
x: this.tile().cell().x,
|
||||
y: this.tile().cell().y,
|
||||
owner: this.owner().id(),
|
||||
isActive: this.isActive(),
|
||||
health: this._health,
|
||||
}
|
||||
}
|
||||
|
||||
type(): UnitType {
|
||||
return this._type
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user