diff --git a/src/client/Transport.ts b/src/client/Transport.ts index 3bf4cca43..9c40e714e 100644 --- a/src/client/Transport.ts +++ b/src/client/Transport.ts @@ -9,6 +9,7 @@ import { UsernameInput } from "./UsernameInput"; import { HostLobbyModal as HostPrivateLobbyModal } from "./HostLobbyModal"; import { JoinPrivateLobbyModal } from "./JoinPrivateLobbyModal"; import { SinglePlayerModal } from "./SinglePlayerModal"; +import { PlayerView } from "../core/GameView" export class PauseGameEvent implements GameEvent { constructor(public readonly paused: boolean) { } @@ -16,23 +17,23 @@ export class PauseGameEvent implements GameEvent { export class SendAllianceRequestIntentEvent implements GameEvent { constructor( - public readonly requestor: Player, - public readonly recipient: Player + public readonly requestor: PlayerView, + public readonly recipient: PlayerView ) { } } export class SendBreakAllianceIntentEvent implements GameEvent { constructor( - public readonly requestor: Player, - public readonly recipient: Player + public readonly requestor: PlayerView, + public readonly recipient: PlayerView ) { } } export class SendAllianceReplyIntentEvent implements GameEvent { constructor( // The original alliance requestor - public readonly requestor: Player, - public readonly recipient: Player, + public readonly requestor: PlayerView, + public readonly recipient: PlayerView, public readonly accepted: boolean ) { } } @@ -73,15 +74,15 @@ export class SendTargetPlayerIntentEvent implements GameEvent { export class SendEmojiIntentEvent implements GameEvent { constructor( - public readonly recipient: Player | typeof AllPlayers, + public readonly recipient: PlayerView | typeof AllPlayers, public readonly emoji: string ) { } } export class SendDonateIntentEvent implements GameEvent { constructor( - public readonly sender: Player, - public readonly recipient: Player, + public readonly sender: PlayerView, + public readonly recipient: PlayerView, public readonly troops: number | null, ) { } } diff --git a/src/client/graphics/layers/NameLayer.ts b/src/client/graphics/layers/NameLayer.ts index 8925f9a52..ebcca6449 100644 --- a/src/client/graphics/layers/NameLayer.ts +++ b/src/client/graphics/layers/NameLayer.ts @@ -31,14 +31,14 @@ export class NameLayer implements Layer { private renderRefreshRate = 500 private rand = new PseudoRandom(10) private renders: RenderInfo[] = [] - private seenPlayers: Set = new Set() + private seenPlayers: Set = new Set() private traitorIconImage: HTMLImageElement; private allianceIconImage: HTMLImageElement; private targetIconImage: HTMLImageElement; private crownIconImage: HTMLImageElement; private container: HTMLDivElement - private myPlayer: Player | null = null - private firstPlace: Player | null = null + private myPlayer: PlayerView | null = null + private firstPlace: PlayerView | null = null constructor(private game: GameView, private theme: Theme, private transformHandler: TransformHandler, private clientID: ClientID) { this.traitorIconImage = new Image(); @@ -115,7 +115,7 @@ export class NameLayer implements Layer { ) } - private createPlayerElement(player: Player): HTMLDivElement { + private createPlayerElement(player: PlayerView): HTMLDivElement { const element = document.createElement('div') element.style.position = 'absolute' element.style.display = 'flex' @@ -281,7 +281,7 @@ export class NameLayer implements Layer { return icon } - private getPlayer(): Player | null { + private getPlayer(): PlayerView | null { if (this.myPlayer != null) { return this.myPlayer } diff --git a/src/client/graphics/layers/PlayerInfoOverlay.ts b/src/client/graphics/layers/PlayerInfoOverlay.ts index f1b9608e5..626ebadf1 100644 --- a/src/client/graphics/layers/PlayerInfoOverlay.ts +++ b/src/client/graphics/layers/PlayerInfoOverlay.ts @@ -6,7 +6,7 @@ import { ClientID } from '../../../core/Schemas'; import { EventBus } from '../../../core/EventBus'; import { TransformHandler } from '../TransformHandler'; import { MouseMoveEvent } from '../../InputHandler'; -import { GameView, PlayerView } from '../../../core/GameView'; +import { GameView, PlayerView, UnitView } from '../../../core/GameView'; import { TileRef } from '../../../core/game/GameMap'; import { PauseGameEvent } from '../../Transport'; import { renderNumber, renderTroops } from '../../Utils'; @@ -20,7 +20,7 @@ function euclideanDistWorld(coord: { x: number, y: number }, tileRef: TileRef, g } function distSortUnitWorld(coord: { x: number, y: number }, game: GameView) { - return (a: Unit, b: Unit) => { + return (a: Unit | UnitView, b: Unit | UnitView) => { const distA = euclideanDistWorld(coord, a.tile(), game); const distB = euclideanDistWorld(coord, b.tile(), game); return distA - distB; @@ -42,13 +42,13 @@ export class PlayerInfoOverlay extends LitElement implements Layer { public transform!: TransformHandler; @state() - private player: Player | null = null; + private player: PlayerView | null = null; @state() private playerProfile: PlayerProfile | null = null; @state() - private unit: Unit | null = null; + private unit: UnitView | null = null; @state() private showPauseButton: boolean = true; @@ -92,8 +92,8 @@ export class PlayerInfoOverlay extends LitElement implements Layer { const owner = this.game.owner(tile); if (owner && owner.isPlayer()) { - this.player = owner; - (this.player as PlayerView).profile().then(p => { + this.player = owner as PlayerView; + this.player.profile().then(p => { this.playerProfile = p; }); this.setVisible(true); @@ -135,14 +135,14 @@ export class PlayerInfoOverlay extends LitElement implements Layer { this.requestUpdate(); } - private myPlayer(): Player | null { + private myPlayer(): PlayerView | null { if (!this.game) { return null; } return this.game.playerByClientID(this.clientID); } - private renderPlayerInfo(player: Player) { + private renderPlayerInfo(player: PlayerView) { const myPlayer = this.myPlayer(); const isAlly = myPlayer?.isAlliedWith(player) let relationHtml = null; @@ -181,7 +181,7 @@ export class PlayerInfoOverlay extends LitElement implements Layer { `; } - private renderUnitInfo(unit: Unit) { + private renderUnitInfo(unit: UnitView) { const isAlly = (unit.owner() == this.myPlayer() || this.myPlayer()?.isAlliedWith(unit.owner())) ?? false; return html`
diff --git a/src/client/graphics/layers/StructureLayer.ts b/src/client/graphics/layers/StructureLayer.ts index e836d1f61..181dbc458 100644 --- a/src/client/graphics/layers/StructureLayer.ts +++ b/src/client/graphics/layers/StructureLayer.ts @@ -7,7 +7,7 @@ import anchorIcon from '../../../../resources/images/AnchorIcon.png'; import missileSiloIcon from '../../../../resources/images/MissileSiloUnit.png'; import shieldIcon from '../../../../resources/images/ShieldIcon.png'; import cityIcon from '../../../../resources/images/CityIcon.png'; -import { GameView } from "../../../core/GameView"; +import { GameView, UnitView } from "../../../core/GameView"; import { Cell, GameUpdateType, Unit, UnitType } from "../../../core/game/Game"; import { euclDistFN } from "../../../core/game/GameMap"; @@ -109,7 +109,7 @@ export class StructureLayer implements Layer { return unitType in this.unitConfigs; } - private handleUnitRendering(unit: Unit) { + private handleUnitRendering(unit: UnitView) { const unitType = unit.type(); if (!this.isUnitTypeSupported(unitType)) return; @@ -157,7 +157,7 @@ export class StructureLayer implements Layer { startY: number, width: number, height: number, - unit: Unit + unit: UnitView ) { for (let y = 0; y < height; y++) { for (let x = 0; x < width; x++) { diff --git a/src/client/graphics/layers/UnitLayer.ts b/src/client/graphics/layers/UnitLayer.ts index ac4285f23..e142658fc 100644 --- a/src/client/graphics/layers/UnitLayer.ts +++ b/src/client/graphics/layers/UnitLayer.ts @@ -5,7 +5,7 @@ import { Layer } from "./Layer"; import { EventBus } from "../../../core/EventBus"; import { AlternateViewEvent } from "../../InputHandler"; import { ClientID } from "../../../core/Schemas"; -import { GameView } from "../../../core/GameView"; +import { GameView, PlayerView, UnitView } from "../../../core/GameView"; import { euclDistFN, manhattanDistFN, TileRef } from "../../../core/game/GameMap"; enum Relationship { @@ -18,15 +18,15 @@ export class UnitLayer implements Layer { private canvas: HTMLCanvasElement; private context: CanvasRenderingContext2D; - private boatToTrail = new Map>(); + private boatToTrail = new Map>(); private theme: Theme = null; private alternateView = false; - private myPlayer: Player | null = null; + private myPlayer: PlayerView | null = null; - private oldShellTile = new Map(); + private oldShellTile = new Map(); constructor(private game: GameView, private eventBus: EventBus, private clientID: ClientID) { this.theme = game.config().theme(); @@ -77,7 +77,7 @@ export class UnitLayer implements Layer { } } - private relationship(unit: Unit): Relationship { + private relationship(unit: UnitView): Relationship { if (this.myPlayer == null) { return Relationship.Enemy; } @@ -90,7 +90,7 @@ export class UnitLayer implements Layer { return Relationship.Enemy; } - onUnitEvent(unit: Unit) { + onUnitEvent(unit: UnitView) { switch (unit.type()) { case UnitType.TransportShip: this.handleBoatEvent(unit); @@ -114,7 +114,7 @@ export class UnitLayer implements Layer { } } - private handleDestroyerEvent(unit: Unit) { + private handleDestroyerEvent(unit: UnitView) { const rel = this.relationship(unit); // Clear previous area @@ -149,7 +149,7 @@ export class UnitLayer implements Layer { } } - private handleBattleshipEvent(unit: Unit) { + private handleBattleshipEvent(unit: UnitView) { const rel = this.relationship(unit); // Clear previous area @@ -195,7 +195,7 @@ export class UnitLayer implements Layer { } } - private handleShellEvent(unit: Unit) { + private handleShellEvent(unit: UnitView) { const rel = this.relationship(unit); // Clear current and previous positions @@ -227,7 +227,7 @@ export class UnitLayer implements Layer { ); } - private handleNuke(unit: Unit) { + private handleNuke(unit: UnitView) { const rel = this.relationship(unit); // Clear previous area @@ -249,7 +249,7 @@ export class UnitLayer implements Layer { } } - private handleTradeShipEvent(unit: Unit) { + private handleTradeShipEvent(unit: UnitView) { const rel = this.relationship(unit); // Clear previous area @@ -282,7 +282,7 @@ export class UnitLayer implements Layer { } } - private handleBoatEvent(unit: Unit) { + private handleBoatEvent(unit: UnitView) { const rel = this.relationship(unit); if (!this.boatToTrail.has(unit)) { diff --git a/src/client/graphics/layers/radial/BuildMenu.ts b/src/client/graphics/layers/radial/BuildMenu.ts index b2c3ddac7..e13571ad6 100644 --- a/src/client/graphics/layers/radial/BuildMenu.ts +++ b/src/client/graphics/layers/radial/BuildMenu.ts @@ -38,7 +38,7 @@ const buildTable: BuildItemDisplay[][] = [ export class BuildMenu extends LitElement { public game: GameView; public eventBus: EventBus; - private myPlayer: Player; + private myPlayer: PlayerView; private clickedCell: Cell; private playerActions: PlayerActions | null diff --git a/src/client/graphics/layers/radial/RadialMenu.ts b/src/client/graphics/layers/radial/RadialMenu.ts index cfe05ab05..0d3f24bdb 100644 --- a/src/client/graphics/layers/radial/RadialMenu.ts +++ b/src/client/graphics/layers/radial/RadialMenu.ts @@ -263,7 +263,7 @@ export class RadialMenu implements Layer { const canSendEmojiToAllPlayers = this.g.ownerID(tile) == myPlayer.smallID() && actions.canSendEmojiAllPlayers if (canSendEmojiToPlayer || canSendEmojiToAllPlayers) { this.activateMenuElement(Slot.Emoji, "#00a6a4", emojiIcon, () => { - const target = this.g.owner(tile) == myPlayer ? AllPlayers : (this.g.owner(tile) as Player) + const target = this.g.owner(tile) == myPlayer ? AllPlayers : (this.g.owner(tile) as PlayerView) this.emojiTable.onEmojiClicked = (emoji: string) => { this.emojiTable.hideTable() this.eventBus.emit(new SendEmojiIntentEvent(target, emoji)) @@ -290,7 +290,7 @@ export class RadialMenu implements Layer { if (!this.g.hasOwner(tile)) { return } - const other = this.g.owner(tile) as Player + const other = this.g.owner(tile) as PlayerView if (actions?.interaction.canDonate) { diff --git a/src/core/GameView.ts b/src/core/GameView.ts index 1e1d90bba..0943582a0 100644 --- a/src/core/GameView.ts +++ b/src/core/GameView.ts @@ -6,7 +6,7 @@ import { TerraNulliusImpl } from './game/TerraNulliusImpl'; import { WorkerClient } from './worker/WorkerClient'; import { GameMap, GameMapImpl, TileRef, TileUpdate } from './game/GameMap'; -export class UnitView implements Unit { +export class UnitView { public _wasUpdated = true public lastPos: MapPos[] = [] @@ -62,12 +62,9 @@ export class UnitView implements Unit { } } -export class PlayerView implements Player { +export class PlayerView { constructor(private game: GameView, public data: PlayerUpdate, public nameData: NameViewData) { } - borderTiles(): ReadonlySet { - throw new Error('Method not implemented.'); - } async actions(tile: TileRef): Promise { return this.game.worker.playerInteraction(this.id(), this.game.x(tile), this.game.y(tile)) @@ -80,9 +77,6 @@ export class PlayerView implements Player { smallID(): number { return this.data.smallID } - lastTileChange(): Tick { - return 0 - } name(): string { return this.data.name } @@ -129,67 +123,24 @@ export class PlayerView implements Player { return this.data.troops } - isAlliedWith(other: Player): boolean { + isAlliedWith(other: PlayerView): boolean { return this.data.allies.some(n => other.smallID() == n) } - allianceWith(other: Player): Alliance | null { - return null - } - 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 - } profile(): Promise { return this.game.worker.playerProfile(this.smallID()) } - allRelationsSorted(): { player: Player; relation: Relation; }[] { - return [] - } - transitiveTargets(): Player[] { + transitiveTargets(): PlayerView[] { return [...this.targets(), ...this.allies().flatMap(p => p.targets())] } isTraitor(): boolean { return this.data.isTraitor } - canTarget(other: Player): boolean { - return false - } - toString(): string { - return '' - } - canSendEmoji(recipient: Player | typeof AllPlayers): boolean { - return false - } outgoingEmojis(): EmojiMessage[] { return this.data.outgoingEmojis } - canDonate(recipient: Player): boolean { - return false - } - canBuild(type: UnitType, targetTile: TileRef): TileRef | false { - return false - } info(): PlayerInfo { return new PlayerInfo(this.name(), this.type(), this.clientID(), this.id()) } diff --git a/src/core/configuration/Config.ts b/src/core/configuration/Config.ts index ac9ce08d4..b02628461 100644 --- a/src/core/configuration/Config.ts +++ b/src/core/configuration/Config.ts @@ -7,6 +7,7 @@ import { GameConfig } from "../Schemas"; import { DefaultConfig } from "./DefaultConfig"; import { DevConfig, DevServerConfig } from "./DevConfig"; import { GameMap, TileRef } from "../game/GameMap"; +import { PlayerView } from "../GameView"; export enum GameEnv { Dev, @@ -58,8 +59,8 @@ export interface Config { numSpawnPhaseTurns(): number startManpower(playerInfo: PlayerInfo): number - populationIncreaseRate(player: Player): number - goldAdditionRate(player: Player): number + populationIncreaseRate(player: Player | PlayerView): number + goldAdditionRate(player: Player | PlayerView): number troopAdjustmentRate(player: Player): number attackTilesPerTick(attckTroops: number, attacker: Player, defender: Player | TerraNullius, numAdjacentTilesWithEnemy: number): number attackLogic(gm: GameMap, attackTroops: number, attacker: Player, defender: Player | TerraNullius, tileToConquer: TileRef): { @@ -68,7 +69,7 @@ export interface Config { tilesPerTickUsed: number } attackAmount(attacker: Player, defender: Player | TerraNullius): number - maxPopulation(player: Player): number + maxPopulation(player: Player | PlayerView): number cityPopulationIncrease(): number boatAttackAmount(attacker: Player, defender: Player | TerraNullius): number boatMaxDistance(): number diff --git a/src/core/game/Game.ts b/src/core/game/Game.ts index 52cab714c..8a36e0035 100644 --- a/src/core/game/Game.ts +++ b/src/core/game/Game.ts @@ -1,5 +1,6 @@ import { Config } from "../configuration/Config" import { GameEvent } from "../EventBus" +import { PlayerView } from "../GameView" import { ClientID, GameConfig, GameID } from "../Schemas" import { GameMap, GameMapImpl, TileRef, TileUpdate } from "./GameMap" @@ -46,7 +47,7 @@ export enum GameType { } export interface UnitInfo { - cost: (player: Player) => Gold + cost: (player: Player | PlayerView) => Gold // Determines if its owner changes when its tile is conquered. territoryBound: boolean maxHealth?: number,