mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 08:11:54 +00:00
remove setnameexecution because unused, create DisplayName on Player
This commit is contained in:
@@ -1,5 +1,3 @@
|
|||||||
import twemoji from 'twemoji';
|
|
||||||
import DOMPurify from 'dompurify';
|
|
||||||
|
|
||||||
export function renderTroops(troops: number): string {
|
export function renderTroops(troops: number): string {
|
||||||
let troopsStr = ''
|
let troopsStr = ''
|
||||||
@@ -32,21 +30,3 @@ export function createCanvas(): HTMLCanvasElement {
|
|||||||
|
|
||||||
return canvas
|
return canvas
|
||||||
}
|
}
|
||||||
|
|
||||||
export function processName(name: string): string {
|
|
||||||
const sanitized = Array.from(name).slice(0, 10).join('').replace(/[^\p{L}\p{N}\s\p{Emoji}\p{Emoji_Component}]/gu, '');
|
|
||||||
|
|
||||||
// First sanitize the raw input - strip everything except text and emojis
|
|
||||||
const withEmojis = twemoji.parse(sanitized, {
|
|
||||||
base: 'https://cdn.jsdelivr.net/gh/twitter/twemoji@14.0.2/assets/', // Use jsDelivr CDN
|
|
||||||
folder: 'svg', // or 'png' if you prefer
|
|
||||||
ext: '.svg' // or '.png' if you prefer
|
|
||||||
});
|
|
||||||
return DOMPurify.sanitize(withEmojis, {
|
|
||||||
ALLOWED_TAGS: ['img'],
|
|
||||||
ALLOWED_ATTR: ['src', 'alt', 'class'],
|
|
||||||
// Only allow twemoji CDN URLs
|
|
||||||
ALLOWED_URI_REGEXP: /^https:\/\/cdn\.jsdelivr\.net\/gh\/twitter\/twemoji/
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import {nullable} from "zod";
|
import { nullable } from "zod";
|
||||||
import {EventBus, GameEvent} from "../../../core/EventBus";
|
import { EventBus, GameEvent } from "../../../core/EventBus";
|
||||||
import {AllianceExpiredEvent, AllianceRequestEvent, AllianceRequestReplyEvent, AllPlayers, BrokeAllianceEvent, EmojiMessageEvent, Game, Player, PlayerID, TargetPlayerEvent} from "../../../core/game/Game";
|
import { AllianceExpiredEvent, AllianceRequestEvent, AllianceRequestReplyEvent, AllPlayers, BrokeAllianceEvent, EmojiMessageEvent, Game, Player, PlayerID, TargetPlayerEvent } from "../../../core/game/Game";
|
||||||
import {ClientID} from "../../../core/Schemas";
|
import { ClientID } from "../../../core/Schemas";
|
||||||
import {Layer} from "./Layer";
|
import { Layer } from "./Layer";
|
||||||
import {SendAllianceReplyIntentEvent} from "../../Transport";
|
import { SendAllianceReplyIntentEvent } from "../../Transport";
|
||||||
|
|
||||||
export enum MessageType {
|
export enum MessageType {
|
||||||
SUCCESS,
|
SUCCESS,
|
||||||
@@ -234,7 +234,7 @@ export class EventsDisplay implements Layer {
|
|||||||
}
|
}
|
||||||
if (event.message.recipient == myPlayer) {
|
if (event.message.recipient == myPlayer) {
|
||||||
this.addEvent({
|
this.addEvent({
|
||||||
description: `${event.message.sender.name()}:${event.message.emoji}`,
|
description: `${event.message.sender.displayName()}:${event.message.emoji}`,
|
||||||
type: MessageType.INFO,
|
type: MessageType.INFO,
|
||||||
highlight: true,
|
highlight: true,
|
||||||
createdAt: this.game.ticks(),
|
createdAt: this.game.ticks(),
|
||||||
@@ -242,7 +242,7 @@ export class EventsDisplay implements Layer {
|
|||||||
}
|
}
|
||||||
if (event.message.sender == myPlayer && event.message.recipient != AllPlayers) {
|
if (event.message.sender == myPlayer && event.message.recipient != AllPlayers) {
|
||||||
this.addEvent({
|
this.addEvent({
|
||||||
description: `Sent ${event.message.recipient.name()} ${event.message.emoji}`,
|
description: `Sent ${event.message.recipient.displayName()} ${event.message.emoji}`,
|
||||||
type: MessageType.INFO,
|
type: MessageType.INFO,
|
||||||
highlight: true,
|
highlight: true,
|
||||||
createdAt: this.game.ticks(),
|
createdAt: this.game.ticks(),
|
||||||
|
|||||||
@@ -4,9 +4,6 @@ import { Layer } from './Layer';
|
|||||||
import { Game, Player } from '../../../core/game/Game';
|
import { Game, Player } from '../../../core/game/Game';
|
||||||
import { ClientID } from '../../../core/Schemas';
|
import { ClientID } from '../../../core/Schemas';
|
||||||
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
|
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
|
||||||
import { processName } from '../Utils';
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
interface Entry {
|
interface Entry {
|
||||||
name: string
|
name: string
|
||||||
@@ -68,7 +65,7 @@ export class Leaderboard extends LitElement implements Layer {
|
|||||||
|
|
||||||
this.players.pop()
|
this.players.pop()
|
||||||
this.players.push({
|
this.players.push({
|
||||||
name: myPlayer.name(),
|
name: myPlayer.displayName(),
|
||||||
position: place,
|
position: place,
|
||||||
score: formatPercentage(myPlayer.numTilesOwned() / this.game.numLandTiles()),
|
score: formatPercentage(myPlayer.numTilesOwned() / this.game.numLandTiles()),
|
||||||
isMyPlayer: true,
|
isMyPlayer: true,
|
||||||
@@ -166,7 +163,7 @@ export class Leaderboard extends LitElement implements Layer {
|
|||||||
.map((player, index) => html`
|
.map((player, index) => html`
|
||||||
<tr class="${player.isMyPlayer ? 'myPlayer' : 'otherPlayer'}">
|
<tr class="${player.isMyPlayer ? 'myPlayer' : 'otherPlayer'}">
|
||||||
<td>${player.position}</td>
|
<td>${player.position}</td>
|
||||||
<td>${unsafeHTML(processName(player.name))}</td>
|
<td>${unsafeHTML(player.name)}</td>
|
||||||
<td>${player.score}</td>
|
<td>${player.score}</td>
|
||||||
</tr>
|
</tr>
|
||||||
`)}
|
`)}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ export type ClientID = string
|
|||||||
export type Intent = SpawnIntent
|
export type Intent = SpawnIntent
|
||||||
| AttackIntent
|
| AttackIntent
|
||||||
| BoatAttackIntent
|
| BoatAttackIntent
|
||||||
| UpdateNameIntent
|
|
||||||
| AllianceRequestIntent
|
| AllianceRequestIntent
|
||||||
| AllianceRequestReplyIntent
|
| AllianceRequestReplyIntent
|
||||||
| BreakAllianceIntent
|
| BreakAllianceIntent
|
||||||
@@ -19,7 +18,6 @@ export type Intent = SpawnIntent
|
|||||||
export type AttackIntent = z.infer<typeof AttackIntentSchema>
|
export type AttackIntent = z.infer<typeof AttackIntentSchema>
|
||||||
export type SpawnIntent = z.infer<typeof SpawnIntentSchema>
|
export type SpawnIntent = z.infer<typeof SpawnIntentSchema>
|
||||||
export type BoatAttackIntent = z.infer<typeof BoatAttackIntentSchema>
|
export type BoatAttackIntent = z.infer<typeof BoatAttackIntentSchema>
|
||||||
export type UpdateNameIntent = z.infer<typeof UpdateNameIntentSchema>
|
|
||||||
export type AllianceRequestIntent = z.infer<typeof AllianceRequestIntentSchema>
|
export type AllianceRequestIntent = z.infer<typeof AllianceRequestIntentSchema>
|
||||||
export type AllianceRequestReplyIntent = z.infer<typeof AllianceRequestReplyIntentSchema>
|
export type AllianceRequestReplyIntent = z.infer<typeof AllianceRequestReplyIntentSchema>
|
||||||
export type BreakAllianceIntent = z.infer<typeof BreakAllianceIntentSchema>
|
export type BreakAllianceIntent = z.infer<typeof BreakAllianceIntentSchema>
|
||||||
@@ -101,11 +99,6 @@ export const BoatAttackIntentSchema = BaseIntentSchema.extend({
|
|||||||
y: z.number(),
|
y: z.number(),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const UpdateNameIntentSchema = BaseIntentSchema.extend({
|
|
||||||
type: z.literal('updateName'),
|
|
||||||
name: z.string(),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const AllianceRequestIntentSchema = BaseIntentSchema.extend({
|
export const AllianceRequestIntentSchema = BaseIntentSchema.extend({
|
||||||
type: z.literal('allianceRequest'),
|
type: z.literal('allianceRequest'),
|
||||||
requestor: z.string(),
|
requestor: z.string(),
|
||||||
@@ -157,7 +150,6 @@ const IntentSchema = z.union([
|
|||||||
AttackIntentSchema,
|
AttackIntentSchema,
|
||||||
SpawnIntentSchema,
|
SpawnIntentSchema,
|
||||||
BoatAttackIntentSchema,
|
BoatAttackIntentSchema,
|
||||||
UpdateNameIntentSchema,
|
|
||||||
AllianceRequestIntentSchema,
|
AllianceRequestIntentSchema,
|
||||||
AllianceRequestReplyIntentSchema,
|
AllianceRequestReplyIntentSchema,
|
||||||
BreakAllianceIntentSchema,
|
BreakAllianceIntentSchema,
|
||||||
|
|||||||
+28
-6
@@ -1,7 +1,9 @@
|
|||||||
import {v4 as uuidv4} from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
import twemoji from 'twemoji';
|
||||||
|
import DOMPurify from 'dompurify';
|
||||||
|
|
||||||
|
|
||||||
import {Cell, Game, Player, TerraNullius, Tile} from "./game/Game";
|
import { Cell, Game, Player, TerraNullius, Tile } from "./game/Game";
|
||||||
|
|
||||||
export function manhattanDist(c1: Cell, c2: Cell): number {
|
export function manhattanDist(c1: Cell, c2: Cell): number {
|
||||||
return Math.abs(c1.x - c2.x) + Math.abs(c1.y - c2.y);
|
return Math.abs(c1.x - c2.x) + Math.abs(c1.y - c2.y);
|
||||||
@@ -97,7 +99,7 @@ export function simpleHash(str: string): number {
|
|||||||
return Math.abs(hash);
|
return Math.abs(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function calculateBoundingBox(borderTiles: ReadonlySet<Tile>): {min: Cell; max: Cell} {
|
export function calculateBoundingBox(borderTiles: ReadonlySet<Tile>): { min: Cell; max: Cell } {
|
||||||
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
||||||
|
|
||||||
borderTiles.forEach((tile: Tile) => {
|
borderTiles.forEach((tile: Tile) => {
|
||||||
@@ -108,10 +110,10 @@ export function calculateBoundingBox(borderTiles: ReadonlySet<Tile>): {min: Cell
|
|||||||
maxY = Math.max(maxY, cell.y);
|
maxY = Math.max(maxY, cell.y);
|
||||||
});
|
});
|
||||||
|
|
||||||
return {min: new Cell(minX, minY), max: new Cell(maxX, maxY)}
|
return { min: new Cell(minX, minY), max: new Cell(maxX, maxY) }
|
||||||
}
|
}
|
||||||
|
|
||||||
export function inscribed(outer: {min: Cell; max: Cell}, inner: {min: Cell; max: Cell}): boolean {
|
export function inscribed(outer: { min: Cell; max: Cell }, inner: { min: Cell; max: Cell }): boolean {
|
||||||
return (
|
return (
|
||||||
outer.min.x <= inner.min.x &&
|
outer.min.x <= inner.min.x &&
|
||||||
outer.min.y <= inner.min.y &&
|
outer.min.y <= inner.min.y &&
|
||||||
@@ -122,7 +124,7 @@ export function inscribed(outer: {min: Cell; max: Cell}, inner: {min: Cell; max:
|
|||||||
|
|
||||||
export function getMode(list: string[]): string {
|
export function getMode(list: string[]): string {
|
||||||
// Count occurrences
|
// Count occurrences
|
||||||
const counts: {[key: string]: number} = {};
|
const counts: { [key: string]: number } = {};
|
||||||
for (const item of list) {
|
for (const item of list) {
|
||||||
counts[item] = (counts[item] || 0) + 1;
|
counts[item] = (counts[item] || 0) + 1;
|
||||||
}
|
}
|
||||||
@@ -139,4 +141,24 @@ export function getMode(list: string[]): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return mode;
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sanitize(name: string): string {
|
||||||
|
return Array.from(name).slice(0, 10).join('').replace(/[^\p{L}\p{N}\s\p{Emoji}\p{Emoji_Component}]/gu, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function processName(name: string): string {
|
||||||
|
// First sanitize the raw input - strip everything except text and emojis
|
||||||
|
const withEmojis = twemoji.parse(sanitize(name), {
|
||||||
|
base: 'https://cdn.jsdelivr.net/gh/twitter/twemoji@14.0.2/assets/', // Use jsDelivr CDN
|
||||||
|
folder: 'svg', // or 'png' if you prefer
|
||||||
|
ext: '.svg' // or '.png' if you prefer
|
||||||
|
});
|
||||||
|
return DOMPurify.sanitize(withEmojis, {
|
||||||
|
ALLOWED_TAGS: ['img'],
|
||||||
|
ALLOWED_ATTR: ['src', 'alt', 'class'],
|
||||||
|
// Only allow twemoji CDN URLs
|
||||||
|
ALLOWED_URI_REGEXP: /^https:\/\/cdn\.jsdelivr\.net\/gh\/twitter\/twemoji/
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,21 +1,20 @@
|
|||||||
import {Cell, Execution, MutableGame, Game, MutablePlayer, PlayerInfo, TerraNullius, Tile, PlayerType, Alliance, AllianceRequestReplyEvent, Difficulty} from "../game/Game";
|
import { Cell, Execution, MutableGame, Game, MutablePlayer, PlayerInfo, TerraNullius, Tile, PlayerType, Alliance, AllianceRequestReplyEvent, Difficulty } from "../game/Game";
|
||||||
import {AttackIntent, BoatAttackIntentSchema, GameID, Intent, Turn} from "../Schemas";
|
import { AttackIntent, BoatAttackIntentSchema, GameID, Intent, Turn } from "../Schemas";
|
||||||
import {AttackExecution} from "./AttackExecution";
|
import { AttackExecution } from "./AttackExecution";
|
||||||
import {SpawnExecution} from "./SpawnExecution";
|
import { SpawnExecution } from "./SpawnExecution";
|
||||||
import {BotSpawner} from "./BotSpawner";
|
import { BotSpawner } from "./BotSpawner";
|
||||||
import {BoatAttackExecution} from "./BoatAttackExecution";
|
import { BoatAttackExecution } from "./BoatAttackExecution";
|
||||||
import {PseudoRandom} from "../PseudoRandom";
|
import { PseudoRandom } from "../PseudoRandom";
|
||||||
import {UpdateNameExecution} from "./UpdateNameExecution";
|
import { FakeHumanExecution } from "./FakeHumanExecution";
|
||||||
import {FakeHumanExecution} from "./FakeHumanExecution";
|
|
||||||
import Usernames from '../../../resources/Usernames.txt'
|
import Usernames from '../../../resources/Usernames.txt'
|
||||||
import {simpleHash} from "../Util";
|
import { processName, sanitize, simpleHash } from "../Util";
|
||||||
import {AllianceRequestExecution} from "./alliance/AllianceRequestExecution";
|
import { AllianceRequestExecution } from "./alliance/AllianceRequestExecution";
|
||||||
import {AllianceRequestReplyExecution} from "./alliance/AllianceRequestReplyExecution";
|
import { AllianceRequestReplyExecution } from "./alliance/AllianceRequestReplyExecution";
|
||||||
import {BreakAllianceExecution} from "./alliance/BreakAllianceExecution";
|
import { BreakAllianceExecution } from "./alliance/BreakAllianceExecution";
|
||||||
import {TargetPlayerExecution} from "./TargetPlayerExecution";
|
import { TargetPlayerExecution } from "./TargetPlayerExecution";
|
||||||
import {EmojiExecution} from "./EmojiExecution";
|
import { EmojiExecution } from "./EmojiExecution";
|
||||||
import {DonateExecution} from "./DonateExecution";
|
import { DonateExecution } from "./DonateExecution";
|
||||||
import {NukeExecution} from "./NukeExecution";
|
import { NukeExecution } from "./NukeExecution";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -48,7 +47,7 @@ export class Executor {
|
|||||||
)
|
)
|
||||||
} else if (intent.type == "spawn") {
|
} else if (intent.type == "spawn") {
|
||||||
return new SpawnExecution(
|
return new SpawnExecution(
|
||||||
new PlayerInfo(intent.name.slice(0, 18), intent.playerType, intent.clientID, intent.playerID),
|
new PlayerInfo(sanitize(intent.name), intent.playerType, intent.clientID, intent.playerID),
|
||||||
new Cell(intent.x, intent.y)
|
new Cell(intent.x, intent.y)
|
||||||
)
|
)
|
||||||
} else if (intent.type == "boat") {
|
} else if (intent.type == "boat") {
|
||||||
@@ -58,11 +57,6 @@ export class Executor {
|
|||||||
new Cell(intent.x, intent.y),
|
new Cell(intent.x, intent.y),
|
||||||
intent.troops
|
intent.troops
|
||||||
)
|
)
|
||||||
} else if (intent.type == "updateName") {
|
|
||||||
return new UpdateNameExecution(
|
|
||||||
intent.name,
|
|
||||||
intent.clientID
|
|
||||||
)
|
|
||||||
} else if (intent.type == "allianceRequest") {
|
} else if (intent.type == "allianceRequest") {
|
||||||
return new AllianceRequestExecution(intent.requestor, intent.recipient)
|
return new AllianceRequestExecution(intent.requestor, intent.recipient)
|
||||||
} else if (intent.type == "allianceRequestReply") {
|
} else if (intent.type == "allianceRequestReply") {
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
import {Execution, MutableGame, MutablePlayer, PlayerID} from "../game/Game"
|
|
||||||
import {ClientID} from "../Schemas"
|
|
||||||
|
|
||||||
export class UpdateNameExecution implements Execution {
|
|
||||||
|
|
||||||
private active = true
|
|
||||||
private mg: MutableGame
|
|
||||||
|
|
||||||
constructor(private newName: string, private clientID: ClientID) {
|
|
||||||
}
|
|
||||||
|
|
||||||
init(mg: MutableGame, ticks: number) {
|
|
||||||
this.mg = mg
|
|
||||||
}
|
|
||||||
|
|
||||||
tick(ticks: number) {
|
|
||||||
const player = this.mg.players().find(p => p.clientID() == this.clientID)
|
|
||||||
if (player == null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
player.setName(this.newName)
|
|
||||||
this.active = false
|
|
||||||
}
|
|
||||||
|
|
||||||
owner(): MutablePlayer {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
isActive(): boolean {
|
|
||||||
return this.active
|
|
||||||
}
|
|
||||||
activeDuringSpawnPhase(): boolean {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -163,6 +163,7 @@ export interface TerraNullius {
|
|||||||
export interface Player {
|
export interface Player {
|
||||||
info(): PlayerInfo
|
info(): PlayerInfo
|
||||||
name(): string
|
name(): string
|
||||||
|
displayName(): string
|
||||||
clientID(): ClientID
|
clientID(): ClientID
|
||||||
id(): PlayerID
|
id(): PlayerID
|
||||||
type(): PlayerType
|
type(): PlayerType
|
||||||
|
|||||||
+22
-17
@@ -1,12 +1,12 @@
|
|||||||
import {MutablePlayer, Tile, PlayerInfo, PlayerID, PlayerType, Player, TerraNullius, Cell, Execution, AllianceRequest, MutableAllianceRequest, MutableAlliance, Alliance, Tick, TargetPlayerEvent, EmojiMessage, EmojiMessageEvent, AllPlayers, Currency} from "./Game";
|
import { MutablePlayer, Tile, PlayerInfo, PlayerID, PlayerType, Player, TerraNullius, Cell, Execution, AllianceRequest, MutableAllianceRequest, MutableAlliance, Alliance, Tick, TargetPlayerEvent, EmojiMessage, EmojiMessageEvent, AllPlayers, Currency } from "./Game";
|
||||||
import {ClientID} from "../Schemas";
|
import { ClientID } from "../Schemas";
|
||||||
import {simpleHash} from "../Util";
|
import { processName, simpleHash } from "../Util";
|
||||||
import {CellString, GameImpl} from "./GameImpl";
|
import { CellString, GameImpl } from "./GameImpl";
|
||||||
import {BoatImpl} from "./BoatImpl";
|
import { BoatImpl } from "./BoatImpl";
|
||||||
import {TileImpl} from "./TileImpl";
|
import { TileImpl } from "./TileImpl";
|
||||||
import {TerraNulliusImpl} from "./TerraNulliusImpl";
|
import { TerraNulliusImpl } from "./TerraNulliusImpl";
|
||||||
import {MessageType} from "../../client/graphics/layers/EventsDisplay";
|
import { MessageType } from "../../client/graphics/layers/EventsDisplay";
|
||||||
import {renderTroops} from "../../client/graphics/Utils";
|
import { renderTroops } from "../../client/graphics/Utils";
|
||||||
|
|
||||||
interface Target {
|
interface Target {
|
||||||
tick: Tick
|
tick: Tick
|
||||||
@@ -29,6 +29,7 @@ export class PlayerImpl implements MutablePlayer {
|
|||||||
public _tiles: Map<CellString, Tile> = new Map<CellString, Tile>();
|
public _tiles: Map<CellString, Tile> = new Map<CellString, Tile>();
|
||||||
|
|
||||||
private _name: string;
|
private _name: string;
|
||||||
|
private _displayerName: string;
|
||||||
|
|
||||||
public pastOutgoingAllianceRequests: AllianceRequest[] = []
|
public pastOutgoingAllianceRequests: AllianceRequest[] = []
|
||||||
|
|
||||||
@@ -40,11 +41,15 @@ export class PlayerImpl implements MutablePlayer {
|
|||||||
|
|
||||||
constructor(private gs: GameImpl, private readonly playerInfo: PlayerInfo, private _troops) {
|
constructor(private gs: GameImpl, private readonly playerInfo: PlayerInfo, private _troops) {
|
||||||
this._name = playerInfo.name;
|
this._name = playerInfo.name;
|
||||||
|
this._displayerName = processName(this._name)
|
||||||
}
|
}
|
||||||
|
|
||||||
name(): string {
|
name(): string {
|
||||||
return this._name;
|
return this._name;
|
||||||
}
|
}
|
||||||
|
displayName(): string {
|
||||||
|
return this._displayerName
|
||||||
|
}
|
||||||
|
|
||||||
clientID(): ClientID {
|
clientID(): ClientID {
|
||||||
return this.playerInfo.clientID;
|
return this.playerInfo.clientID;
|
||||||
@@ -115,19 +120,19 @@ export class PlayerImpl implements MutablePlayer {
|
|||||||
return toRemove
|
return toRemove
|
||||||
}
|
}
|
||||||
|
|
||||||
isPlayer(): this is MutablePlayer {return true as const;}
|
isPlayer(): this is MutablePlayer { return true as const; }
|
||||||
ownsTile(cell: Cell): boolean {return this._tiles.has(cell.toString());}
|
ownsTile(cell: Cell): boolean { return this._tiles.has(cell.toString()); }
|
||||||
setTroops(troops: number) {this._troops = Math.floor(troops);}
|
setTroops(troops: number) { this._troops = Math.floor(troops); }
|
||||||
conquer(tile: Tile) {this.gs.conquer(this, tile);}
|
conquer(tile: Tile) { this.gs.conquer(this, tile); }
|
||||||
relinquish(tile: Tile) {
|
relinquish(tile: Tile) {
|
||||||
if (tile.owner() != this) {
|
if (tile.owner() != this) {
|
||||||
throw new Error(`Cannot relinquish tile not owned by this player`);
|
throw new Error(`Cannot relinquish tile not owned by this player`);
|
||||||
}
|
}
|
||||||
this.gs.relinquish(tile);
|
this.gs.relinquish(tile);
|
||||||
}
|
}
|
||||||
info(): PlayerInfo {return this.playerInfo;}
|
info(): PlayerInfo { return this.playerInfo; }
|
||||||
troops(): number {return this._troops;}
|
troops(): number { return this._troops; }
|
||||||
isAlive(): boolean {return this._tiles.size > 0;}
|
isAlive(): boolean { return this._tiles.size > 0; }
|
||||||
executions(): Execution[] {
|
executions(): Execution[] {
|
||||||
return this.gs.executions().filter(exec => exec.owner().id() == this.id());
|
return this.gs.executions().filter(exec => exec.owner().id() == this.id());
|
||||||
}
|
}
|
||||||
@@ -204,7 +209,7 @@ export class PlayerImpl implements MutablePlayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
target(other: Player): void {
|
target(other: Player): void {
|
||||||
this.targets_.push({tick: this.gs.ticks(), target: other})
|
this.targets_.push({ tick: this.gs.ticks(), target: other })
|
||||||
this.gs.eventBus.emit(new TargetPlayerEvent(this, other))
|
this.gs.eventBus.emit(new TargetPlayerEvent(this, other))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user