${this.renderSpeedButton(ReplaySpeedMultiplier.slow, "×0.5")}
@@ -92,9 +94,9 @@ export class ReplayPanel extends LitElement implements Layer {
const isActive = this._replaySpeedMultiplier === value;
return html`
- ${this.alternateView
- ? translateText("user_setting.terrain_enabled")
- : translateText("user_setting.terrain_disabled")}
+ ${
+ this.alternateView
+ ? translateText("user_setting.terrain_enabled")
+ : translateText("user_setting.terrain_disabled")
+ }
- ${this.alternateView
- ? translateText("user_setting.on")
- : translateText("user_setting.off")}
+ ${
+ this.alternateView
+ ? translateText("user_setting.on")
+ : translateText("user_setting.off")
+ }
@@ -222,15 +226,19 @@ export class SettingsModal extends LitElement implements Layer {
${translateText("user_setting.emojis_label")}
- ${this.userSettings?.emojis()
- ? translateText("user_setting.emojis_visible")
- : translateText("user_setting.emojis_hidden")}
+ ${
+ this.userSettings?.emojis()
+ ? translateText("user_setting.emojis_visible")
+ : translateText("user_setting.emojis_hidden")
+ }
- ${this.userSettings?.emojis()
- ? translateText("user_setting.on")
- : translateText("user_setting.off")}
+ ${
+ this.userSettings?.emojis()
+ ? translateText("user_setting.on")
+ : translateText("user_setting.off")
+ }
@@ -250,15 +258,19 @@ export class SettingsModal extends LitElement implements Layer {
${translateText("user_setting.dark_mode_label")}
- ${this.userSettings?.darkMode()
- ? translateText("user_setting.dark_mode_enabled")
- : translateText("user_setting.light_mode_enabled")}
+ ${
+ this.userSettings?.darkMode()
+ ? translateText("user_setting.dark_mode_enabled")
+ : translateText("user_setting.light_mode_enabled")
+ }
- ${this.userSettings?.darkMode()
- ? translateText("user_setting.on")
- : translateText("user_setting.off")}
+ ${
+ this.userSettings?.darkMode()
+ ? translateText("user_setting.on")
+ : translateText("user_setting.off")
+ }
@@ -278,15 +290,19 @@ export class SettingsModal extends LitElement implements Layer {
${translateText("user_setting.special_effects_label")}
- ${this.userSettings?.fxLayer()
- ? translateText("user_setting.special_effects_enabled")
- : translateText("user_setting.special_effects_disabled")}
+ ${
+ this.userSettings?.fxLayer()
+ ? translateText("user_setting.special_effects_enabled")
+ : translateText("user_setting.special_effects_disabled")
+ }
- ${this.userSettings?.fxLayer()
- ? translateText("user_setting.on")
- : translateText("user_setting.off")}
+ ${
+ this.userSettings?.fxLayer()
+ ? translateText("user_setting.on")
+ : translateText("user_setting.off")
+ }
@@ -306,15 +322,19 @@ export class SettingsModal extends LitElement implements Layer {
${translateText("user_setting.structure_sprites_label")}
- ${this.userSettings?.structureSprites()
- ? translateText("user_setting.structure_sprites_enabled")
- : translateText("user_setting.structure_sprites_disabled")}
+ ${
+ this.userSettings?.structureSprites()
+ ? translateText("user_setting.structure_sprites_enabled")
+ : translateText("user_setting.structure_sprites_disabled")
+ }
- ${this.userSettings?.structureSprites()
- ? translateText("user_setting.on")
- : translateText("user_setting.off")}
+ ${
+ this.userSettings?.structureSprites()
+ ? translateText("user_setting.on")
+ : translateText("user_setting.off")
+ }
@@ -329,15 +349,19 @@ export class SettingsModal extends LitElement implements Layer {
${translateText("user_setting.anonymous_names_label")}
- ${this.userSettings?.anonymousNames()
- ? translateText("user_setting.anonymous_names_enabled")
- : translateText("user_setting.real_names_shown")}
+ ${
+ this.userSettings?.anonymousNames()
+ ? translateText("user_setting.anonymous_names_enabled")
+ : translateText("user_setting.real_names_shown")
+ }
- ${this.userSettings?.anonymousNames()
- ? translateText("user_setting.on")
- : translateText("user_setting.off")}
+ ${
+ this.userSettings?.anonymousNames()
+ ? translateText("user_setting.on")
+ : translateText("user_setting.off")
+ }
@@ -352,15 +376,19 @@ export class SettingsModal extends LitElement implements Layer {
${translateText("user_setting.left_click_menu")}
- ${this.userSettings?.leftClickOpensMenu()
- ? translateText("user_setting.left_click_opens_menu")
- : translateText("user_setting.right_click_opens_menu")}
+ ${
+ this.userSettings?.leftClickOpensMenu()
+ ? translateText("user_setting.left_click_opens_menu")
+ : translateText("user_setting.right_click_opens_menu")
+ }
- ${this.userSettings?.leftClickOpensMenu()
- ? translateText("user_setting.on")
- : translateText("user_setting.off")}
+ ${
+ this.userSettings?.leftClickOpensMenu()
+ ? translateText("user_setting.on")
+ : translateText("user_setting.off")
+ }
@@ -380,17 +408,23 @@ export class SettingsModal extends LitElement implements Layer {
${translateText("user_setting.performance_overlay_label")}
- ${this.userSettings?.performanceOverlay()
- ? translateText("user_setting.performance_overlay_enabled")
- : translateText(
- "user_setting.performance_overlay_disabled",
- )}
+ ${
+ this.userSettings?.performanceOverlay()
+ ? translateText(
+ "user_setting.performance_overlay_enabled",
+ )
+ : translateText(
+ "user_setting.performance_overlay_disabled",
+ )
+ }
- ${this.userSettings?.performanceOverlay()
- ? translateText("user_setting.on")
- : translateText("user_setting.off")}
+ ${
+ this.userSettings?.performanceOverlay()
+ ? translateText("user_setting.on")
+ : translateText("user_setting.off")
+ }
diff --git a/src/client/graphics/layers/SpawnAd.ts b/src/client/graphics/layers/SpawnAd.ts
index 960260af5c..9dd4f32f12 100644
--- a/src/client/graphics/layers/SpawnAd.ts
+++ b/src/client/graphics/layers/SpawnAd.ts
@@ -1,9 +1,9 @@
-import { LitElement, css, html } from "lit";
+import { css, html, LitElement } from "lit";
import { customElement, state } from "lit/decorators.js";
+import { translateText } from "../../../client/Utils";
import { GameView } from "../../../core/game/GameView";
-import { Layer } from "./Layer";
import { getGamesPlayed } from "../../Utils";
-import { translateText } from "../../../client/Utils";
+import { Layer } from "./Layer";
const AD_TYPE = "bottom_rail";
const AD_CONTAINER_ID = "bottom-rail-ad-container";
@@ -79,8 +79,8 @@ export class SpawnAd extends LitElement implements Layer {
window.ramp.que.push(() => {
window.ramp.spaAddAds([
{
- type: AD_TYPE,
selectorId: AD_CONTAINER_ID,
+ type: AD_TYPE,
},
]);
this.adLoaded = true;
@@ -125,11 +125,13 @@ export class SpawnAd extends LitElement implements Layer {
id="${AD_CONTAINER_ID}"
class="w-full h-full flex items-center justify-center"
>
- ${!this.adLoaded
- ? html`> = {
[UnitType.Port]: {
- icon: anchorIcon,
borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR,
+ icon: anchorIcon,
territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR,
},
[UnitType.City]: {
- icon: cityIcon,
borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR,
+ icon: cityIcon,
territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR,
},
[UnitType.Factory]: {
- icon: factoryIcon,
borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR,
+ icon: factoryIcon,
territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR,
},
[UnitType.MissileSilo]: {
- icon: missileSiloIcon,
borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR,
+ icon: missileSiloIcon,
territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR,
},
[UnitType.DefensePost]: {
- icon: shieldIcon,
borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR,
+ icon: shieldIcon,
territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR,
},
[UnitType.SAMLauncher]: {
- icon: SAMMissileIcon,
borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR,
+ icon: SAMMissileIcon,
territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR,
},
};
diff --git a/src/client/graphics/layers/TeamStats.ts b/src/client/graphics/layers/TeamStats.ts
index 8d3830633b..7f2f223f56 100644
--- a/src/client/graphics/layers/TeamStats.ts
+++ b/src/client/graphics/layers/TeamStats.ts
@@ -1,9 +1,9 @@
+import { html, LitElement } from "lit";
+import { customElement, property } from "lit/decorators.js";
+import { EventBus } from "../../../core/EventBus";
import { GameMode, Team, UnitType } from "../../../core/game/Game";
import { GameView, PlayerView } from "../../../core/game/GameView";
-import { LitElement, html } from "lit";
-import { customElement, property } from "lit/decorators.js";
import { renderNumber, translateText } from "../../Utils";
-import { EventBus } from "../../../core/EventBus";
import { Layer } from "./Layer";
type TeamEntry = {
@@ -89,17 +89,17 @@ export class TeamStats extends LitElement implements Layer {
const totalScorePercent = totalScoreSort / this.game.numLandTiles();
return {
+ players: teamPlayers,
teamName: teamStr,
- totalScoreStr: formatPercentage(totalScorePercent),
- totalScoreSort,
+ totalCities: renderNumber(totalCities),
totalGold: renderNumber(totalGold),
- totalTroops: renderNumber(totalTroops / 10),
- players: teamPlayers,
totalLaunchers: renderNumber(totalLaunchers),
totalSAMs: renderNumber(totalSAMs),
+ totalScoreSort,
+ totalScoreStr: formatPercentage(totalScorePercent),
+ totalTroops: renderNumber(totalTroops / 10),
totalWarShips: renderNumber(totalWarShips),
- totalCities: renderNumber(totalCities),
};
})
.sort((a, b) => b.totalScoreSort - a.totalScoreSort);
@@ -130,8 +130,9 @@ export class TeamStats extends LitElement implements Layer {
${translateText("leaderboard.team")}
- ${this.showUnits
- ? html`
+ ${
+ this.showUnits
+ ? html`
${translateText("leaderboard.launchers")}
@@ -145,7 +146,7 @@ export class TeamStats extends LitElement implements Layer {
${translateText("leaderboard.cities")}
`
- : html`
+ : html`
${translateText("leaderboard.owned")}
@@ -155,7 +156,8 @@ export class TeamStats extends LitElement implements Layer {
${translateText("leaderboard.troops")}
- `}
+ `
+ }
diff --git a/src/client/graphics/layers/TerrainLayer.ts b/src/client/graphics/layers/TerrainLayer.ts
index e5d4d6b99c..a88fe8904a 100644
--- a/src/client/graphics/layers/TerrainLayer.ts
+++ b/src/client/graphics/layers/TerrainLayer.ts
@@ -1,7 +1,7 @@
-import { GameView } from "../../../core/game/GameView";
-import { Layer } from "./Layer";
import { Theme } from "../../../core/configuration/Config";
+import { GameView } from "../../../core/game/GameView";
import { TransformHandler } from "../TransformHandler";
+import { Layer } from "./Layer";
export class TerrainLayer implements Layer {
private canvas: HTMLCanvasElement | undefined;
diff --git a/src/client/graphics/layers/TerritoryLayer.ts b/src/client/graphics/layers/TerritoryLayer.ts
index 58d77526ba..508fc8c612 100644
--- a/src/client/graphics/layers/TerritoryLayer.ts
+++ b/src/client/graphics/layers/TerritoryLayer.ts
@@ -1,21 +1,21 @@
+import { PriorityQueue } from "@datastructures-js/priority-queue";
+import { Colord } from "colord";
+import { Theme } from "../../../core/configuration/Config";
+import { EventBus } from "../../../core/EventBus";
+import { Cell, PlayerType, UnitType } from "../../../core/game/Game";
+import { euclDistFN, TileRef } from "../../../core/game/GameMap";
+import { GameUpdateType } from "../../../core/game/GameUpdates";
+import { GameView, PlayerView } from "../../../core/game/GameView";
+import { UserSettings } from "../../../core/game/UserSettings";
+import { PseudoRandom } from "../../../core/PseudoRandom";
import {
AlternateViewEvent,
DragEvent,
MouseOverEvent,
RedrawGraphicsEvent,
} from "../../InputHandler";
-import { Cell, PlayerType, UnitType } from "../../../core/game/Game";
-import { GameView, PlayerView } from "../../../core/game/GameView";
-import { TileRef, euclDistFN } from "../../../core/game/GameMap";
-import { Colord } from "colord";
-import { EventBus } from "../../../core/EventBus";
-import { GameUpdateType } from "../../../core/game/GameUpdates";
-import { Layer } from "./Layer";
-import { PriorityQueue } from "@datastructures-js/priority-queue";
-import { PseudoRandom } from "../../../core/PseudoRandom";
-import { Theme } from "../../../core/configuration/Config";
import { TransformHandler } from "../TransformHandler";
-import { UserSettings } from "../../../core/game/UserSettings";
+import { Layer } from "./Layer";
export class TerritoryLayer implements Layer {
private readonly userSettings: UserSettings;
@@ -323,7 +323,8 @@ export class TerritoryLayer implements Layer {
initImageData() {
this.game.forEachTile((tile) => {
if (this.imageData === undefined) throw new Error("Not initialized");
- if (this.alternativeImageData === undefined) throw new Error("Not initialized");
+ if (this.alternativeImageData === undefined)
+ throw new Error("Not initialized");
const cell = new Cell(this.game.x(tile), this.game.y(tile));
const index = cell.y * this.game.width() + cell.x;
const offset = index * 4;
@@ -337,7 +338,8 @@ export class TerritoryLayer implements Layer {
if (this.highlightCanvas === undefined) throw new Error("Not initialized");
if (this.context === undefined) throw new Error("Not initialized");
if (this.imageData === undefined) throw new Error("Not initialized");
- if (this.alternativeImageData === undefined) throw new Error("Not initialized");
+ if (this.alternativeImageData === undefined)
+ throw new Error("Not initialized");
const now = Date.now();
if (
now > this.lastDragTime + this.nodrawDragDuration &&
@@ -413,7 +415,8 @@ export class TerritoryLayer implements Layer {
return;
}
if (this.imageData === undefined) throw new Error("Not initialized");
- if (this.alternativeImageData === undefined) throw new Error("Not initialized");
+ if (this.alternativeImageData === undefined)
+ throw new Error("Not initialized");
if (!this.game.hasOwner(tile)) {
if (this.game.hasFallout(tile)) {
@@ -509,7 +512,8 @@ export class TerritoryLayer implements Layer {
}
paintAlternateViewTile(tile: TileRef, other: PlayerView) {
- if (this.alternativeImageData === undefined) throw new Error("Not initialized");
+ if (this.alternativeImageData === undefined)
+ throw new Error("Not initialized");
const color = this.alternateViewColor(other);
this.paintTile(this.alternativeImageData, tile, color, 255);
}
@@ -525,21 +529,23 @@ export class TerritoryLayer implements Layer {
clearTile(tile: TileRef) {
const offset = tile * 4;
if (this.imageData === undefined) throw new Error("Not initialized");
- if (this.alternativeImageData === undefined) throw new Error("Not initialized");
+ if (this.alternativeImageData === undefined)
+ throw new Error("Not initialized");
this.imageData.data[offset + 3] = 0; // Set alpha to 0 (fully transparent)
this.alternativeImageData.data[offset + 3] = 0; // Set alpha to 0 (fully transparent)
}
clearAlternativeTile(tile: TileRef) {
const offset = tile * 4;
- if (this.alternativeImageData === undefined) throw new Error("Not initialized");
+ if (this.alternativeImageData === undefined)
+ throw new Error("Not initialized");
this.alternativeImageData.data[offset + 3] = 0; // Set alpha to 0 (fully transparent)
}
enqueueTile(tile: TileRef) {
this.tileToRenderQueue.push({
- tile,
lastUpdate: this.game.ticks() + this.random.nextFloat(0, 0.5),
+ tile,
});
}
diff --git a/src/client/graphics/layers/UILayer.ts b/src/client/graphics/layers/UILayer.ts
index bfaa63b168..9215302dad 100644
--- a/src/client/graphics/layers/UILayer.ts
+++ b/src/client/graphics/layers/UILayer.ts
@@ -1,14 +1,14 @@
-import { GameView, UnitView } from "../../../core/game/GameView";
import { Colord } from "colord";
+import { Theme } from "../../../core/configuration/Config";
import { EventBus } from "../../../core/EventBus";
+import { UnitType } from "../../../core/game/Game";
import { GameUpdateType } from "../../../core/game/GameUpdates";
-import { Layer } from "./Layer";
+import { GameView, UnitView } from "../../../core/game/GameView";
+import { UserSettings } from "../../../core/game/UserSettings";
+import { UnitSelectionEvent } from "../../InputHandler";
import { ProgressBar } from "../ProgressBar";
-import { Theme } from "../../../core/configuration/Config";
import { TransformHandler } from "../TransformHandler";
-import { UnitSelectionEvent } from "../../InputHandler";
-import { UnitType } from "../../../core/game/Game";
-import { UserSettings } from "../../../core/game/UserSettings";
+import { Layer } from "./Layer";
const COLOR_PROGRESSION = [
"rgb(232, 25, 25)",
@@ -69,8 +69,7 @@ export class UILayer implements Layer {
this.game
.updatesSinceLastTick()
- ?.[GameUpdateType.Unit]
- ?.map((unit) => this.game.unit(unit.id))
+ ?.[GameUpdateType.Unit]?.map((unit) => this.game.unit(unit.id))
?.forEach((unitView) => {
if (unitView === undefined) return;
this.onUnitEvent(unitView);
@@ -253,9 +252,9 @@ export class UILayer implements Layer {
// Store current selection box position for next cleanup
this.lastSelectionBoxCenter = {
+ size: selectionSize,
x: centerX,
y: centerY,
- size: selectionSize,
};
}
@@ -350,8 +349,8 @@ export class UILayer implements Layer {
0,
);
this.allProgressBars.set(unit.id(), {
- unit,
progressBar,
+ unit,
});
}
}
diff --git a/src/client/graphics/layers/UnitDisplay.ts b/src/client/graphics/layers/UnitDisplay.ts
index 2876d1e9a4..a4df6fd316 100644
--- a/src/client/graphics/layers/UnitDisplay.ts
+++ b/src/client/graphics/layers/UnitDisplay.ts
@@ -1,17 +1,17 @@
-import { LitElement, html } from "lit";
-import { EventBus } from "../../../core/EventBus";
-import { GameView } from "../../../core/game/GameView";
-import { Layer } from "./Layer";
-import { ToggleStructureEvent } from "../../InputHandler";
-import { UnitType } from "../../../core/game/Game";
-import cityIcon from "../../../../resources/images/CityIconWhite.svg";
+import { html, LitElement } from "lit";
import { customElement } from "lit/decorators.js";
-import defensePostIcon from "../../../../resources/images/ShieldIconWhite.svg";
+import portIcon from "../../../../resources/images/AnchorIcon.png";
+import cityIcon from "../../../../resources/images/CityIconWhite.svg";
import factoryIcon from "../../../../resources/images/FactoryIconWhite.svg";
import missileSiloIcon from "../../../../resources/images/MissileSiloUnit.png";
-import portIcon from "../../../../resources/images/AnchorIcon.png";
-import { renderNumber } from "../../Utils";
+import defensePostIcon from "../../../../resources/images/ShieldIconWhite.svg";
import samLauncherIcon from "../../../../resources/non-commercial/svg/SamLauncherIconWhite.svg";
+import { EventBus } from "../../../core/EventBus";
+import { UnitType } from "../../../core/game/Game";
+import { GameView } from "../../../core/game/GameView";
+import { ToggleStructureEvent } from "../../InputHandler";
+import { renderNumber } from "../../Utils";
+import { Layer } from "./Layer";
@customElement("unit-display")
export class UnitDisplay extends LitElement implements Layer {
@@ -69,9 +69,9 @@ export class UnitDisplay extends LitElement implements Layer {
return html`
this.eventBus?.emit(new ToggleStructureEvent(unitType))}"
@mouseleave="${() =>
diff --git a/src/client/graphics/layers/UnitLayer.ts b/src/client/graphics/layers/UnitLayer.ts
index cfa0b69beb..0b1a6f2530 100644
--- a/src/client/graphics/layers/UnitLayer.ts
+++ b/src/client/graphics/layers/UnitLayer.ts
@@ -1,24 +1,24 @@
+import { Colord, colord } from "colord";
+import { Theme } from "../../../core/configuration/Config";
+import { EventBus } from "../../../core/EventBus";
+import { UnitType } from "../../../core/game/Game";
+import { TileRef } from "../../../core/game/GameMap";
+import { GameUpdateType } from "../../../core/game/GameUpdates";
+import { GameView, UnitView } from "../../../core/game/GameView";
+import { BezenhamLine } from "../../../core/utilities/Line";
import {
AlternateViewEvent,
MouseUpEvent,
UnitSelectionEvent,
} from "../../InputHandler";
-import { Colord, colord } from "colord";
-import { GameView, UnitView } from "../../../core/game/GameView";
+import { MoveWarshipIntentEvent } from "../../Transport";
import {
getColoredSprite,
isSpriteReady,
loadAllSprites,
} from "../SpriteLoader";
-import { BezenhamLine } from "../../../core/utilities/Line";
-import { EventBus } from "../../../core/EventBus";
-import { GameUpdateType } from "../../../core/game/GameUpdates";
-import { Layer } from "./Layer";
-import { MoveWarshipIntentEvent } from "../../Transport";
-import { Theme } from "../../../core/configuration/Config";
-import { TileRef } from "../../../core/game/GameMap";
import { TransformHandler } from "../TransformHandler";
-import { UnitType } from "../../../core/game/Game";
+import { Layer } from "./Layer";
enum Relationship {
Self,
@@ -156,7 +156,8 @@ export class UnitLayer implements Layer {
}
renderLayer(context: CanvasRenderingContext2D) {
- if (this.transportShipTrailCanvas === undefined) throw new Error("Not initialized");
+ if (this.transportShipTrailCanvas === undefined)
+ throw new Error("Not initialized");
if (this.canvas === undefined) throw new Error("Not initialized");
context.drawImage(
this.transportShipTrailCanvas,
@@ -197,7 +198,8 @@ export class UnitLayer implements Layer {
this.updateUnitsSprites(this.game.units().map((unit) => unit.id()));
this.unitToTrail.forEach((trail, unit) => {
- if (this.unitTrailContext === undefined) throw new Error("Not initialized");
+ if (this.unitTrailContext === undefined)
+ throw new Error("Not initialized");
for (const t of trail) {
this.paintCell(
this.game.x(t),
@@ -298,7 +300,7 @@ export class UnitLayer implements Layer {
private handleWarShipEvent(unit: UnitView) {
if (unit.targetUnitId()) {
- this.drawSprite(unit, colord({ r: 200, b: 0, g: 0 }));
+ this.drawSprite(unit, colord({ b: 0, g: 0, r: 200 }));
} else {
this.drawSprite(unit);
}
@@ -309,7 +311,11 @@ export class UnitLayer implements Layer {
const rel = this.relationship(unit);
// Clear current and previous positions
- this.clearCell(this.game.x(unit.lastTile()), this.game.y(unit.lastTile()), this.context);
+ this.clearCell(
+ this.game.x(unit.lastTile()),
+ this.game.y(unit.lastTile()),
+ this.context,
+ );
const oldTile = this.oldShellTile.get(unit);
if (oldTile !== undefined) {
this.clearCell(this.game.x(oldTile), this.game.y(oldTile), this.context);
@@ -432,7 +438,11 @@ export class UnitLayer implements Layer {
const rel = this.relationship(unit);
if (this.context === undefined) throw new Error("Not initialized");
- this.clearCell(this.game.x(unit.lastTile()), this.game.y(unit.lastTile()), this.context);
+ this.clearCell(
+ this.game.x(unit.lastTile()),
+ this.game.y(unit.lastTile()),
+ this.context,
+ );
if (unit.isActive()) {
// Paint area
@@ -504,11 +514,7 @@ export class UnitLayer implements Layer {
context.fillRect(x, y, 1, 1);
}
- clearCell(
- x: number,
- y: number,
- context: CanvasRenderingContext2D,
- ) {
+ clearCell(x: number, y: number, context: CanvasRenderingContext2D) {
context.clearRect(x, y, 1, 1);
}
diff --git a/src/client/graphics/layers/WinModal.ts b/src/client/graphics/layers/WinModal.ts
index 1f86056414..e8ce74b977 100644
--- a/src/client/graphics/layers/WinModal.ts
+++ b/src/client/graphics/layers/WinModal.ts
@@ -1,12 +1,12 @@
-import { LitElement, css, html } from "lit";
+import { css, html, LitElement } from "lit";
import { customElement, state } from "lit/decorators.js";
+import { translateText } from "../../../client/Utils";
import { EventBus } from "../../../core/EventBus";
import { GameUpdateType } from "../../../core/game/GameUpdates";
import { GameView } from "../../../core/game/GameView";
+import { SendWinnerEvent } from "../../Transport";
import { GutterAdModalEvent } from "./GutterAdModal";
import { Layer } from "./Layer";
-import { SendWinnerEvent } from "../../Transport";
-import { translateText } from "../../../client/Utils";
@customElement("win-modal")
export class WinModal extends LitElement implements Layer {
diff --git a/src/client/jwt.ts b/src/client/jwt.ts
index 68a230bcae..019aa47916 100644
--- a/src/client/jwt.ts
+++ b/src/client/jwt.ts
@@ -1,3 +1,5 @@
+import { decodeJwt } from "jose";
+import { z } from "zod";
import {
RefreshResponseSchema,
TokenPayload,
@@ -5,9 +7,7 @@ import {
UserMeResponse,
UserMeResponseSchema,
} from "../core/ApiSchemas";
-import { decodeJwt } from "jose";
import { getServerConfigFromClient } from "../core/configuration/ConfigLoader";
-import { z } from "zod";
function getAudience() {
const { hostname } = new URL(window.location.href);
@@ -85,10 +85,10 @@ export async function logOut(allSessions = false) {
const response = await fetch(
getApiBase() + (allSessions ? "/revoke" : "/logout"),
{
- method: "POST",
headers: {
authorization: `Bearer ${token}`,
},
+ method: "POST",
},
);
@@ -179,7 +179,7 @@ function _isLoggedIn(): IsLoggedInResponse {
}
const claims = result.data;
- return { token, claims };
+ return { claims, token };
} catch (e) {
console.log(e);
return false;
@@ -193,10 +193,10 @@ export async function postRefresh(): Promise {
// Refresh the JWT
const response = await fetch(getApiBase() + "/refresh", {
- method: "POST",
headers: {
authorization: `Bearer ${token}`,
},
+ method: "POST",
});
if (response.status === 401) {
clearToken();
diff --git a/src/client/styles.css b/src/client/styles.css
index 6afaafe464..fe34dc08d8 100644
--- a/src/client/styles.css
+++ b/src/client/styles.css
@@ -134,7 +134,7 @@
.option-image {
width: 100%;
- aspect-ratio: 4/2;
+ aspect-ratio: 4 / 2;
color: #aaa;
transition: transform 0.2s ease-in-out;
border-radius: 8px;
@@ -373,17 +373,18 @@ label.option-card:hover {
}
#helpModal .city-icon {
- mask: url("../../resources/images/CityIconWhite.svg") no-repeat center / cover;
+ mask:
+ url("../../resources/images/CityIconWhite.svg") no-repeat center / cover;
}
#helpModal .factory-icon {
- mask: url("../../resources/images/FactoryIconWhite.svg") no-repeat center /
- cover;
+ mask:
+ url("../../resources/images/FactoryIconWhite.svg") no-repeat center / cover;
}
#helpModal .defense-post-icon {
- mask: url("../../resources/images/ShieldIconWhite.svg") no-repeat center /
- cover;
+ mask:
+ url("../../resources/images/ShieldIconWhite.svg") no-repeat center / cover;
}
#helpModal .port-icon {
@@ -391,27 +392,32 @@ label.option-card:hover {
}
#helpModal .warship-icon {
- mask: url("../../resources/images/BattleshipIconWhite.svg") no-repeat center /
+ mask:
+ url("../../resources/images/BattleshipIconWhite.svg") no-repeat center /
cover;
}
#helpModal .missile-silo-icon {
- mask: url("../../resources/non-commercial/svg/MissileSiloIconWhite.svg")
- no-repeat center / cover;
+ mask:
+ url("../../resources/non-commercial/svg/MissileSiloIconWhite.svg") no-repeat
+ center / cover;
}
#helpModal .sam-launcher-icon {
- mask: url("../../resources/non-commercial/svg/SamLauncherIconWhite.svg")
- no-repeat center / cover;
+ mask:
+ url("../../resources/non-commercial/svg/SamLauncherIconWhite.svg") no-repeat
+ center / cover;
}
#helpModal .atom-bomb-icon {
- mask: url("../../resources/images/NukeIconWhite.svg") no-repeat center / cover;
+ mask:
+ url("../../resources/images/NukeIconWhite.svg") no-repeat center / cover;
}
#helpModal .hydrogen-bomb-icon {
- mask: url("../../resources/images/MushroomCloudIconWhite.svg") no-repeat
- center / cover;
+ mask:
+ url("../../resources/images/MushroomCloudIconWhite.svg") no-repeat center /
+ cover;
}
#helpModal .mirv-icon {
@@ -419,7 +425,8 @@ label.option-card:hover {
}
#helpModal .chat-icon {
- mask: url("../../resources/images/ChatIconWhite.svg") no-repeat center / cover;
+ mask:
+ url("../../resources/images/ChatIconWhite.svg") no-repeat center / cover;
}
#helpModal .target-icon {
@@ -427,33 +434,35 @@ label.option-card:hover {
}
#helpModal .alliance-icon {
- mask: url("../../resources/images/AllianceIconWhite.svg") no-repeat center /
- cover;
+ mask:
+ url("../../resources/images/AllianceIconWhite.svg") no-repeat center / cover;
}
#helpModal .emoji-icon {
- mask: url("../../resources/images/EmojiIconWhite.svg") no-repeat center /
- cover;
+ mask:
+ url("../../resources/images/EmojiIconWhite.svg") no-repeat center / cover;
}
#helpModal .betray-icon {
- mask: url("../../resources/images/TraitorIconWhite.svg") no-repeat center /
- cover;
+ mask:
+ url("../../resources/images/TraitorIconWhite.svg") no-repeat center / cover;
}
#helpModal .donate-icon {
- mask: url("../../resources/images/DonateTroopIconWhite.svg") no-repeat
- center / cover;
+ mask:
+ url("../../resources/images/DonateTroopIconWhite.svg") no-repeat center /
+ cover;
}
#helpModal .donate-gold-icon {
- mask: url("../../resources/images/DonateGoldIconWhite.svg") no-repeat center /
+ mask:
+ url("../../resources/images/DonateGoldIconWhite.svg") no-repeat center /
cover;
}
#helpModal .build-icon {
- mask: url("../../resources/images/BuildIconWhite.svg") no-repeat center /
- cover;
+ mask:
+ url("../../resources/images/BuildIconWhite.svg") no-repeat center / cover;
}
#helpModal .info-icon {
diff --git a/src/client/utilities/RenderUnitTypeOptions.ts b/src/client/utilities/RenderUnitTypeOptions.ts
index 02569e654c..d777b4f0cf 100644
--- a/src/client/utilities/RenderUnitTypeOptions.ts
+++ b/src/client/utilities/RenderUnitTypeOptions.ts
@@ -1,5 +1,5 @@
// renderUnitTypeOptions.ts
-import { TemplateResult, html } from "lit";
+import { html, TemplateResult } from "lit";
import { UnitType } from "../../core/game/Game";
import { translateText } from "../Utils";
@@ -9,16 +9,16 @@ export type UnitTypeRenderContext = {
};
const unitOptions: { type: UnitType; translationKey: string }[] = [
- { type: UnitType.City, translationKey: "unit_type.city" },
- { type: UnitType.DefensePost, translationKey: "unit_type.defense_post" },
- { type: UnitType.Port, translationKey: "unit_type.port" },
- { type: UnitType.Warship, translationKey: "unit_type.warship" },
- { type: UnitType.MissileSilo, translationKey: "unit_type.missile_silo" },
- { type: UnitType.SAMLauncher, translationKey: "unit_type.sam_launcher" },
- { type: UnitType.AtomBomb, translationKey: "unit_type.atom_bomb" },
- { type: UnitType.HydrogenBomb, translationKey: "unit_type.hydrogen_bomb" },
- { type: UnitType.MIRV, translationKey: "unit_type.mirv" },
- { type: UnitType.Factory, translationKey: "unit_type.factory" },
+ { translationKey: "unit_type.city", type: UnitType.City },
+ { translationKey: "unit_type.defense_post", type: UnitType.DefensePost },
+ { translationKey: "unit_type.port", type: UnitType.Port },
+ { translationKey: "unit_type.warship", type: UnitType.Warship },
+ { translationKey: "unit_type.missile_silo", type: UnitType.MissileSilo },
+ { translationKey: "unit_type.sam_launcher", type: UnitType.SAMLauncher },
+ { translationKey: "unit_type.atom_bomb", type: UnitType.AtomBomb },
+ { translationKey: "unit_type.hydrogen_bomb", type: UnitType.HydrogenBomb },
+ { translationKey: "unit_type.mirv", type: UnitType.MIRV },
+ { translationKey: "unit_type.factory", type: UnitType.Factory },
];
export function renderUnitTypeOptions({
@@ -36,7 +36,7 @@ export function renderUnitTypeOptions({
type="checkbox"
.checked=${disabledUnits.includes(type)}
@change=${(e: Event) => {
- const { checked } = (e.target as HTMLInputElement);
+ const { checked } = e.target as HTMLInputElement;
toggleUnit(type, checked);
}}
/>
diff --git a/src/core/ApiSchemas.ts b/src/core/ApiSchemas.ts
index a46f2976a6..4ab8089fe4 100644
--- a/src/core/ApiSchemas.ts
+++ b/src/core/ApiSchemas.ts
@@ -1,14 +1,18 @@
// This file contains schemas for api.openfront.io
-import { base64urlToUuid } from "./Base64";
+
import { z } from "zod";
+import { base64urlToUuid } from "./Base64";
export const RefreshResponseSchema = z.object({
token: z.string(),
});
export type RefreshResponse = z.infer;
-/* eslint-disable sort-keys */
export const TokenPayloadSchema = z.object({
+ aud: z.string(),
+ exp: z.number(),
+ iat: z.number(),
+ iss: z.string(),
jti: z.string(),
sub: z
.string()
@@ -26,41 +30,37 @@ export const TokenPayloadSchema = z.object({
if (!uuid) throw new Error("Invalid base64 UUID");
return uuid;
}),
- iat: z.number(),
- iss: z.string(),
- aud: z.string(),
- exp: z.number(),
});
export type TokenPayload = z.infer;
export const UserMeResponseSchema = z.object({
+ player: z.object({
+ flares: z.string().array().optional(),
+ publicId: z.string(),
+ roles: z.string().array().optional(),
+ }),
user: z.object({
- id: z.string(),
avatar: z.string().nullable(),
- username: z.string(),
- global_name: z.string().nullable(),
discriminator: z.string(),
+ global_name: z.string().nullable(),
+ id: z.string(),
locale: z.string().optional(),
- }),
- player: z.object({
- publicId: z.string(),
- roles: z.string().array().optional(),
- flares: z.string().array().optional(),
+ username: z.string(),
}),
});
export type UserMeResponse = z.infer;
export const StripeCreateCheckoutSessionResponseSchema = z.object({
+ client_reference_id: z.string().optional(),
+ customer: z.string().optional(),
id: z.string(),
+ metadata: z.partialRecord(z.string(), z.string()),
object: z.literal("checkout.session"),
- url: z.string(),
+ payment_intent: z.string().optional(),
payment_status: z.enum(["paid", "unpaid", "no_payment_required"]),
status: z.enum(["open", "complete", "expired"]),
- client_reference_id: z.string().optional(),
- customer: z.string().optional(),
- payment_intent: z.string().optional(),
subscription: z.string().optional(),
- metadata: z.partialRecord(z.string(), z.string()),
+ url: z.string(),
});
export type StripeCreateCheckoutSessionResponse = z.infer<
typeof StripeCreateCheckoutSessionResponseSchema
diff --git a/src/core/CosmeticSchemas.ts b/src/core/CosmeticSchemas.ts
index c8950fcc1c..35ef1ce13f 100644
--- a/src/core/CosmeticSchemas.ts
+++ b/src/core/CosmeticSchemas.ts
@@ -1,12 +1,11 @@
-import { RequiredPatternSchema } from "./Schemas";
import { z } from "zod";
+import { RequiredPatternSchema } from "./Schemas";
export const ProductSchema = z.object({
- productId: z.string(),
- /* eslint-disable sort-keys */
- priceId: z.string(),
price: z.string(),
- /* eslint-enable sort-keys */
+
+ priceId: z.string(),
+ productId: z.string(),
});
const PatternSchema = z.object({
@@ -17,28 +16,26 @@ const PatternSchema = z.object({
// Schema for resources/cosmetics/cosmetics.json
export const CosmeticsSchema = z.object({
- patterns: z.record(z.string(), PatternSchema),
- /* eslint-disable sort-keys */
flag: z
.object({
- layers: z.record(
+ color: z.record(
z.string(),
z.object({
- name: z.string(),
+ color: z.string(),
flares: z.string().array().optional(),
+ name: z.string(),
}),
),
- color: z.record(
+ layers: z.record(
z.string(),
z.object({
- color: z.string(),
- name: z.string(),
flares: z.string().array().optional(),
+ name: z.string(),
}),
),
})
.optional(),
- /* eslint-enable sort-keys */
+ patterns: z.record(z.string(), PatternSchema),
});
export type Cosmetics = z.infer;
export type Pattern = z.infer;
diff --git a/src/core/CustomFlag.ts b/src/core/CustomFlag.ts
index 16f44a6c2b..4df27b1fea 100644
--- a/src/core/CustomFlag.ts
+++ b/src/core/CustomFlag.ts
@@ -4,11 +4,11 @@ const ANIMATION_DURATIONS: Record = {
"bright-rainbow": 4000,
"copper-glow": 3000,
"gold-glow": 3000,
- "lava": 6000,
- "neon": 3000,
- "rainbow": 4000,
+ lava: 6000,
+ neon: 3000,
+ rainbow: 4000,
"silver-glow": 3000,
- "water": 6200,
+ water: 6200,
};
// TODO: Pass in cosmetics as a parameter when
@@ -28,8 +28,8 @@ export function renderPlayerFlag(
const code = flag.slice("!".length);
const layers = code.split("_").map((segment) => {
const [layerKey, colorKey] = segment.split("-");
- // eslint-disable-next-line sort-keys
- return { layerKey, colorKey };
+
+ return { colorKey, layerKey };
});
target.innerHTML = "";
diff --git a/src/core/EventBus.ts b/src/core/EventBus.ts
index 60e351d8fc..4f42480463 100644
--- a/src/core/EventBus.ts
+++ b/src/core/EventBus.ts
@@ -6,8 +6,10 @@ export type EventConstructor = new (
) => T;
export class EventBus {
- private readonly listeners: Map void>> =
- new Map();
+ private readonly listeners: Map<
+ EventConstructor,
+ Array<(event: GameEvent) => void>
+ > = new Map();
emit(event: T): void {
const eventConstructor = event.constructor as EventConstructor;
diff --git a/src/core/ExpressSchemas.ts b/src/core/ExpressSchemas.ts
index 23491e4707..36aa87b9a6 100644
--- a/src/core/ExpressSchemas.ts
+++ b/src/core/ExpressSchemas.ts
@@ -1,6 +1,7 @@
// This file contians schemas for the primary openfront express server
-import { GameInfoSchema } from "./Schemas";
+
import { z } from "zod";
+import { GameInfoSchema } from "./Schemas";
export const ApiEnvResponseSchema = z.object({
game_env: z.string(),
diff --git a/src/core/GameRunner.ts b/src/core/GameRunner.ts
index b9c23465f3..da26c867d8 100644
--- a/src/core/GameRunner.ts
+++ b/src/core/GameRunner.ts
@@ -1,3 +1,7 @@
+import { placeName } from "../client/graphics/NameBoxCalculator";
+import { getConfig } from "./configuration/ConfigLoader";
+import { Executor } from "./execution/ExecutionManager";
+import { WinCheckExecution } from "./execution/WinCheckExecution";
import {
AllPlayers,
Attack,
@@ -14,23 +18,19 @@ import {
PlayerProfile,
PlayerType,
} from "./game/Game";
-import { ClientID, GameStartInfo, Turn } from "./Schemas";
+import { createGame } from "./game/GameImpl";
+import { TileRef } from "./game/GameMap";
+import { GameMapLoader } from "./game/GameMapLoader";
import {
ErrorUpdate,
GameUpdateType,
GameUpdateViewData,
} from "./game/GameUpdates";
-import { sanitize, simpleHash } from "./Util";
-import { Executor } from "./execution/ExecutionManager";
-import { GameMapLoader } from "./game/GameMapLoader";
+import { loadTerrainMap } from "./game/TerrainMapLoader";
import { PseudoRandom } from "./PseudoRandom";
-import { TileRef } from "./game/GameMap";
-import { WinCheckExecution } from "./execution/WinCheckExecution";
-import { createGame } from "./game/GameImpl";
+import { ClientID, GameStartInfo, Turn } from "./Schemas";
+import { sanitize, simpleHash } from "./Util";
import { fixProfaneUsername } from "./validations/username";
-import { getConfig } from "./configuration/ConfigLoader";
-import { loadTerrainMap } from "./game/TerrainMapLoader";
-import { placeName } from "../client/graphics/NameBoxCalculator";
export async function createGameRunner(
gameStart: GameStartInfo,
@@ -57,13 +57,13 @@ export async function createGameRunner(
const nations = gameStart.config.disableNPCs
? []
: gameMap.manifest.nations.map(
- (n) =>
- new Nation(
- new Cell(n.coordinates[0], n.coordinates[1]),
- n.strength,
- new PlayerInfo(n.name, PlayerType.FakeHuman, null, random.nextID()),
- ),
- );
+ (n) =>
+ new Nation(
+ new Cell(n.coordinates[0], n.coordinates[1]),
+ n.strength,
+ new PlayerInfo(n.name, PlayerType.FakeHuman, null, random.nextID()),
+ ),
+ );
const game: Game = createGame(
humans,
diff --git a/src/core/Schemas.ts b/src/core/Schemas.ts
index e70b9c9601..46bf7c4ebb 100644
--- a/src/core/Schemas.ts
+++ b/src/core/Schemas.ts
@@ -1,3 +1,10 @@
+import { base64url } from "jose";
+import { z } from "zod";
+import quickChatData from "../../resources/QuickChat.json" with {
+ type: "json",
+};
+import countries from "../client/data/countries.json" with { type: "json" };
+import { ID } from "./BaseSchemas";
import {
AllPlayers,
Difficulty,
@@ -10,14 +17,9 @@ import {
Trios,
UnitType,
} from "./game/Game";
-import { ID } from "./BaseSchemas";
import { PatternDecoder } from "./PatternDecoder";
import { PlayerStatsSchema } from "./StatsSchemas";
-import { base64url } from "jose";
-import countries from "../client/data/countries.json" with { type: "json" };
import { flattenedEmojiTable } from "./Util";
-import quickChatData from "../../resources/QuickChat.json" with { type: "json" };
-import { z } from "zod";
export type GameID = string;
export type ClientID = string;
@@ -136,8 +138,8 @@ export type TeamCountConfig = z.infer;
export const GameConfigSchema = z.object({
bots: z.number().int().min(0).max(400),
difficulty: z.enum(Difficulty),
- disableNPCs: z.boolean(),
disabledUnits: z.enum(UnitType).array().optional(),
+ disableNPCs: z.boolean(),
donateGold: z.boolean(),
donateTroops: z.boolean(),
gameMap: z.enum(GameMapType),
diff --git a/src/core/StatsSchemas.ts b/src/core/StatsSchemas.ts
index 6f58d84f28..41cb3a47ed 100644
--- a/src/core/StatsSchemas.ts
+++ b/src/core/StatsSchemas.ts
@@ -1,5 +1,5 @@
-import { UnitType } from "./game/Game";
import { z } from "zod";
+import { UnitType } from "./game/Game";
export const BombUnitSchema = z.union([
z.literal("abomb"),
diff --git a/src/core/Util.ts b/src/core/Util.ts
index cb919dd720..3f3ab14c06 100644
--- a/src/core/Util.ts
+++ b/src/core/Util.ts
@@ -1,8 +1,13 @@
+import DOMPurify from "dompurify";
+import { customAlphabet } from "nanoid";
+import { ID } from "./BaseSchemas";
+import { ServerConfig } from "./configuration/Config";
import {
BOT_NAME_PREFIXES,
BOT_NAME_SUFFIXES,
} from "./execution/utils/BotNames";
import { Cell, Unit } from "./game/Game";
+import { GameMap, TileRef } from "./game/GameMap";
import {
ClientID,
GameConfig,
@@ -12,11 +17,6 @@ import {
Turn,
Winner,
} from "./Schemas";
-import { GameMap, TileRef } from "./game/GameMap";
-import DOMPurify from "dompurify";
-import { ID } from "./BaseSchemas";
-import { ServerConfig } from "./configuration/Config";
-import { customAlphabet } from "nanoid";
export function manhattanDistWrapped(
c1: Cell,
@@ -89,8 +89,7 @@ export function calculateBoundingBox(
maxY = Math.max(maxY, cell.y);
});
- // eslint-disable-next-line sort-keys
- return { min: new Cell(minX, minY), max: new Cell(maxX, maxY) };
+ return { max: new Cell(maxX, maxY), min: new Cell(minX, minY) };
}
export function calculateBoundingBoxCenter(
@@ -233,7 +232,12 @@ export function getClientID(gameID: GameID): ClientID {
const cachedGame = localStorage.getItem("game_id");
const cachedClient = localStorage.getItem("client_id");
- if (gameID === cachedGame && cachedClient && ID.safeParse(cachedClient).success) return cachedClient;
+ if (
+ gameID === cachedGame &&
+ cachedClient &&
+ ID.safeParse(cachedClient).success
+ )
+ return cachedClient;
const clientId = generateID();
localStorage.setItem("game_id", gameID);
diff --git a/src/core/WorkerSchemas.ts b/src/core/WorkerSchemas.ts
index f8ce257786..94b8ae08af 100644
--- a/src/core/WorkerSchemas.ts
+++ b/src/core/WorkerSchemas.ts
@@ -1,6 +1,7 @@
// This file contians schemas for the openfront worker express server
-import { GameConfigSchema, GameRecordSchema } from "./Schemas";
+
import { z } from "zod";
+import { GameConfigSchema, GameRecordSchema } from "./Schemas";
export const CreateGameInputSchema = GameConfigSchema.or(
z
diff --git a/src/core/configuration/ColorAllocator.ts b/src/core/configuration/ColorAllocator.ts
index e4bef8d361..a95e261591 100644
--- a/src/core/configuration/ColorAllocator.ts
+++ b/src/core/configuration/ColorAllocator.ts
@@ -1,5 +1,10 @@
import { Colord, extend } from "colord";
+import labPlugin from "colord/plugins/lab";
+import lchPlugin from "colord/plugins/lch";
+import Color from "colorjs.io";
import { ColoredTeams, Team } from "../game/Game";
+import { PseudoRandom } from "../PseudoRandom";
+import { simpleHash } from "../Util";
import {
blueTeamColors,
botTeamColors,
@@ -10,11 +15,7 @@ import {
tealTeamColors,
yellowTeamColors,
} from "./Colors";
-import Color from "colorjs.io";
-import { PseudoRandom } from "../PseudoRandom";
-import labPlugin from "colord/plugins/lab";
-import lchPlugin from "colord/plugins/lch";
-import { simpleHash } from "../Util";
+
extend([lchPlugin]);
extend([labPlugin]);
diff --git a/src/core/configuration/Colors.ts b/src/core/configuration/Colors.ts
index afee46dc47..2bfa66bac1 100644
--- a/src/core/configuration/Colors.ts
+++ b/src/core/configuration/Colors.ts
@@ -5,15 +5,14 @@ import lchPlugin from "colord/plugins/lch";
extend([lchPlugin]);
extend([labPlugin]);
-/* eslint-disable sort-keys */
-export const red = colord({ h: 0, s: 82, l: 56 });
-export const blue = colord({ h: 224, s: 100, l: 58 });
-export const teal = colord({ h: 172, s: 66, l: 50 });
-export const purple = colord({ h: 271, s: 81, l: 56 });
-export const yellow = colord({ h: 45, s: 93, l: 47 });
-export const orange = colord({ h: 25, s: 95, l: 53 });
-export const green = colord({ h: 128, s: 49, l: 50 });
-export const botColor = colord({ h: 36, s: 10, l: 80 });
+export const red = colord({ h: 0, l: 56, s: 82 });
+export const blue = colord({ h: 224, l: 58, s: 100 });
+export const teal = colord({ h: 172, l: 50, s: 66 });
+export const purple = colord({ h: 271, l: 56, s: 81 });
+export const yellow = colord({ h: 45, l: 47, s: 93 });
+export const orange = colord({ h: 25, l: 53, s: 95 });
+export const green = colord({ h: 128, l: 50, s: 49 });
+export const botColor = colord({ h: 36, l: 80, s: 10 });
export const redTeamColors: Colord[] = generateTeamColors(red);
export const blueTeamColors: Colord[] = generateTeamColors(blue);
@@ -36,331 +35,331 @@ function generateTeamColors(baseColor: Colord): Colord[] {
return colord({
h: baseHue,
- s: saturation,
l: lightness,
+ s: saturation,
});
});
}
export const nationColors: Colord[] = [
- colord({ r: 230, g: 100, b: 100 }), // Bright Red
- colord({ r: 100, g: 180, b: 230 }), // Sky Blue
- colord({ r: 230, g: 180, b: 80 }), // Golden Yellow
- colord({ r: 180, g: 100, b: 230 }), // Purple
- colord({ r: 80, g: 200, b: 120 }), // Emerald Green
- colord({ r: 230, g: 130, b: 180 }), // Pink
- colord({ r: 100, g: 160, b: 80 }), // Olive Green
- colord({ r: 230, g: 150, b: 100 }), // Peach
- colord({ r: 80, g: 130, b: 190 }), // Navy Blue
- colord({ r: 210, g: 210, b: 100 }), // Lime Yellow
- colord({ r: 190, g: 100, b: 130 }), // Maroon
- colord({ r: 100, g: 210, b: 210 }), // Turquoise
- colord({ r: 210, g: 140, b: 80 }), // Light Orange
- colord({ r: 150, g: 110, b: 190 }), // Lavender
- colord({ r: 180, g: 210, b: 120 }), // Light Green
- colord({ r: 210, g: 100, b: 160 }), // Hot Pink
- colord({ r: 100, g: 140, b: 110 }), // Sea Green
- colord({ r: 230, g: 180, b: 180 }), // Light Pink
- colord({ r: 120, g: 120, b: 190 }), // Periwinkle
- colord({ r: 190, g: 170, b: 100 }), // Sand
- colord({ r: 100, g: 180, b: 160 }), // Aquamarine
- colord({ r: 210, g: 160, b: 200 }), // Orchid
- colord({ r: 170, g: 190, b: 100 }), // Yellow Green
- colord({ r: 100, g: 130, b: 150 }), // Steel Blue
- colord({ r: 230, g: 140, b: 140 }), // Salmon
- colord({ r: 140, g: 180, b: 220 }), // Light Blue
- colord({ r: 200, g: 160, b: 110 }), // Tan
- colord({ r: 180, g: 130, b: 180 }), // Plum
- colord({ r: 130, g: 200, b: 130 }), // Light Sea Green
- colord({ r: 220, g: 120, b: 120 }), // Coral
- colord({ r: 120, g: 160, b: 200 }), // Cornflower Blue
- colord({ r: 200, g: 200, b: 140 }), // Khaki
- colord({ r: 160, g: 120, b: 160 }), // Purple Gray
- colord({ r: 140, g: 180, b: 140 }), // Dark Sea Green
- colord({ r: 200, g: 130, b: 110 }), // Dark Salmon
- colord({ r: 130, g: 170, b: 190 }), // Cadet Blue
- colord({ r: 190, g: 180, b: 160 }), // Tan Gray
- colord({ r: 170, g: 140, b: 190 }), // Medium Purple
- colord({ r: 160, g: 190, b: 160 }), // Pale Green
- colord({ r: 190, g: 150, b: 130 }), // Rosy Brown
- colord({ r: 140, g: 150, b: 180 }), // Light Slate Gray
- colord({ r: 180, g: 170, b: 140 }), // Dark Khaki
- colord({ r: 150, g: 130, b: 150 }), // Thistle
- colord({ r: 170, g: 190, b: 180 }), // Pale Blue Green
- colord({ r: 190, g: 140, b: 150 }), // Puce
- colord({ r: 130, g: 180, b: 170 }), // Medium Aquamarine
- colord({ r: 180, g: 160, b: 180 }), // Mauve
- colord({ r: 160, g: 180, b: 140 }), // Dark Olive Green
- colord({ r: 170, g: 150, b: 170 }), // Dusty Rose
- colord({ r: 100, g: 180, b: 230 }), // Sky Blue
- colord({ r: 230, g: 180, b: 80 }), // Golden Yellow
- colord({ r: 180, g: 100, b: 230 }), // Purple
- colord({ r: 80, g: 200, b: 120 }), // Emerald Green
- colord({ r: 230, g: 130, b: 180 }), // Pink
- colord({ r: 100, g: 160, b: 80 }), // Olive Green
- colord({ r: 230, g: 150, b: 100 }), // Peach
- colord({ r: 80, g: 130, b: 190 }), // Navy Blue
- colord({ r: 210, g: 210, b: 100 }), // Lime Yellow
- colord({ r: 190, g: 100, b: 130 }), // Maroon
- colord({ r: 100, g: 210, b: 210 }), // Turquoise
- colord({ r: 210, g: 140, b: 80 }), // Light Orange
- colord({ r: 150, g: 110, b: 190 }), // Lavender
- colord({ r: 180, g: 210, b: 120 }), // Light Green
- colord({ r: 210, g: 100, b: 160 }), // Hot Pink
- colord({ r: 100, g: 140, b: 110 }), // Sea Green
- colord({ r: 230, g: 180, b: 180 }), // Light Pink
- colord({ r: 120, g: 120, b: 190 }), // Periwinkle
- colord({ r: 190, g: 170, b: 100 }), // Sand
- colord({ r: 100, g: 180, b: 160 }), // Aquamarine
- colord({ r: 210, g: 160, b: 200 }), // Orchid
- colord({ r: 170, g: 190, b: 100 }), // Yellow Green
- colord({ r: 100, g: 130, b: 150 }), // Steel Blue
- colord({ r: 230, g: 140, b: 140 }), // Salmon
- colord({ r: 140, g: 180, b: 220 }), // Light Blue
- colord({ r: 200, g: 160, b: 110 }), // Tan
- colord({ r: 180, g: 130, b: 180 }), // Plum
- colord({ r: 130, g: 200, b: 130 }), // Light Sea Green
- colord({ r: 220, g: 120, b: 120 }), // Coral
- colord({ r: 120, g: 160, b: 200 }), // Cornflower Blue
- colord({ r: 200, g: 200, b: 140 }), // Khaki
- colord({ r: 160, g: 120, b: 160 }), // Purple Gray
- colord({ r: 140, g: 180, b: 140 }), // Dark Sea Green
- colord({ r: 200, g: 130, b: 110 }), // Dark Salmon
- colord({ r: 130, g: 170, b: 190 }), // Cadet Blue
- colord({ r: 190, g: 180, b: 160 }), // Tan Gray
- colord({ r: 170, g: 140, b: 190 }), // Medium Purple
- colord({ r: 160, g: 190, b: 160 }), // Pale Green
- colord({ r: 190, g: 150, b: 130 }), // Rosy Brown
- colord({ r: 140, g: 150, b: 180 }), // Light Slate Gray
- colord({ r: 180, g: 170, b: 140 }), // Dark Khaki
- colord({ r: 150, g: 130, b: 150 }), // Thistle
- colord({ r: 170, g: 190, b: 180 }), // Pale Blue Green
- colord({ r: 190, g: 140, b: 150 }), // Puce
- colord({ r: 130, g: 180, b: 170 }), // Medium Aquamarine
- colord({ r: 180, g: 160, b: 180 }), // Mauve
- colord({ r: 160, g: 180, b: 140 }), // Dark Olive Green
- colord({ r: 170, g: 150, b: 170 }), // Dusty Rose
+ colord({ b: 100, g: 100, r: 230 }), // Bright Red
+ colord({ b: 230, g: 180, r: 100 }), // Sky Blue
+ colord({ b: 80, g: 180, r: 230 }), // Golden Yellow
+ colord({ b: 230, g: 100, r: 180 }), // Purple
+ colord({ b: 120, g: 200, r: 80 }), // Emerald Green
+ colord({ b: 180, g: 130, r: 230 }), // Pink
+ colord({ b: 80, g: 160, r: 100 }), // Olive Green
+ colord({ b: 100, g: 150, r: 230 }), // Peach
+ colord({ b: 190, g: 130, r: 80 }), // Navy Blue
+ colord({ b: 100, g: 210, r: 210 }), // Lime Yellow
+ colord({ b: 130, g: 100, r: 190 }), // Maroon
+ colord({ b: 210, g: 210, r: 100 }), // Turquoise
+ colord({ b: 80, g: 140, r: 210 }), // Light Orange
+ colord({ b: 190, g: 110, r: 150 }), // Lavender
+ colord({ b: 120, g: 210, r: 180 }), // Light Green
+ colord({ b: 160, g: 100, r: 210 }), // Hot Pink
+ colord({ b: 110, g: 140, r: 100 }), // Sea Green
+ colord({ b: 180, g: 180, r: 230 }), // Light Pink
+ colord({ b: 190, g: 120, r: 120 }), // Periwinkle
+ colord({ b: 100, g: 170, r: 190 }), // Sand
+ colord({ b: 160, g: 180, r: 100 }), // Aquamarine
+ colord({ b: 200, g: 160, r: 210 }), // Orchid
+ colord({ b: 100, g: 190, r: 170 }), // Yellow Green
+ colord({ b: 150, g: 130, r: 100 }), // Steel Blue
+ colord({ b: 140, g: 140, r: 230 }), // Salmon
+ colord({ b: 220, g: 180, r: 140 }), // Light Blue
+ colord({ b: 110, g: 160, r: 200 }), // Tan
+ colord({ b: 180, g: 130, r: 180 }), // Plum
+ colord({ b: 130, g: 200, r: 130 }), // Light Sea Green
+ colord({ b: 120, g: 120, r: 220 }), // Coral
+ colord({ b: 200, g: 160, r: 120 }), // Cornflower Blue
+ colord({ b: 140, g: 200, r: 200 }), // Khaki
+ colord({ b: 160, g: 120, r: 160 }), // Purple Gray
+ colord({ b: 140, g: 180, r: 140 }), // Dark Sea Green
+ colord({ b: 110, g: 130, r: 200 }), // Dark Salmon
+ colord({ b: 190, g: 170, r: 130 }), // Cadet Blue
+ colord({ b: 160, g: 180, r: 190 }), // Tan Gray
+ colord({ b: 190, g: 140, r: 170 }), // Medium Purple
+ colord({ b: 160, g: 190, r: 160 }), // Pale Green
+ colord({ b: 130, g: 150, r: 190 }), // Rosy Brown
+ colord({ b: 180, g: 150, r: 140 }), // Light Slate Gray
+ colord({ b: 140, g: 170, r: 180 }), // Dark Khaki
+ colord({ b: 150, g: 130, r: 150 }), // Thistle
+ colord({ b: 180, g: 190, r: 170 }), // Pale Blue Green
+ colord({ b: 150, g: 140, r: 190 }), // Puce
+ colord({ b: 170, g: 180, r: 130 }), // Medium Aquamarine
+ colord({ b: 180, g: 160, r: 180 }), // Mauve
+ colord({ b: 140, g: 180, r: 160 }), // Dark Olive Green
+ colord({ b: 170, g: 150, r: 170 }), // Dusty Rose
+ colord({ b: 230, g: 180, r: 100 }), // Sky Blue
+ colord({ b: 80, g: 180, r: 230 }), // Golden Yellow
+ colord({ b: 230, g: 100, r: 180 }), // Purple
+ colord({ b: 120, g: 200, r: 80 }), // Emerald Green
+ colord({ b: 180, g: 130, r: 230 }), // Pink
+ colord({ b: 80, g: 160, r: 100 }), // Olive Green
+ colord({ b: 100, g: 150, r: 230 }), // Peach
+ colord({ b: 190, g: 130, r: 80 }), // Navy Blue
+ colord({ b: 100, g: 210, r: 210 }), // Lime Yellow
+ colord({ b: 130, g: 100, r: 190 }), // Maroon
+ colord({ b: 210, g: 210, r: 100 }), // Turquoise
+ colord({ b: 80, g: 140, r: 210 }), // Light Orange
+ colord({ b: 190, g: 110, r: 150 }), // Lavender
+ colord({ b: 120, g: 210, r: 180 }), // Light Green
+ colord({ b: 160, g: 100, r: 210 }), // Hot Pink
+ colord({ b: 110, g: 140, r: 100 }), // Sea Green
+ colord({ b: 180, g: 180, r: 230 }), // Light Pink
+ colord({ b: 190, g: 120, r: 120 }), // Periwinkle
+ colord({ b: 100, g: 170, r: 190 }), // Sand
+ colord({ b: 160, g: 180, r: 100 }), // Aquamarine
+ colord({ b: 200, g: 160, r: 210 }), // Orchid
+ colord({ b: 100, g: 190, r: 170 }), // Yellow Green
+ colord({ b: 150, g: 130, r: 100 }), // Steel Blue
+ colord({ b: 140, g: 140, r: 230 }), // Salmon
+ colord({ b: 220, g: 180, r: 140 }), // Light Blue
+ colord({ b: 110, g: 160, r: 200 }), // Tan
+ colord({ b: 180, g: 130, r: 180 }), // Plum
+ colord({ b: 130, g: 200, r: 130 }), // Light Sea Green
+ colord({ b: 120, g: 120, r: 220 }), // Coral
+ colord({ b: 200, g: 160, r: 120 }), // Cornflower Blue
+ colord({ b: 140, g: 200, r: 200 }), // Khaki
+ colord({ b: 160, g: 120, r: 160 }), // Purple Gray
+ colord({ b: 140, g: 180, r: 140 }), // Dark Sea Green
+ colord({ b: 110, g: 130, r: 200 }), // Dark Salmon
+ colord({ b: 190, g: 170, r: 130 }), // Cadet Blue
+ colord({ b: 160, g: 180, r: 190 }), // Tan Gray
+ colord({ b: 190, g: 140, r: 170 }), // Medium Purple
+ colord({ b: 160, g: 190, r: 160 }), // Pale Green
+ colord({ b: 130, g: 150, r: 190 }), // Rosy Brown
+ colord({ b: 180, g: 150, r: 140 }), // Light Slate Gray
+ colord({ b: 140, g: 170, r: 180 }), // Dark Khaki
+ colord({ b: 150, g: 130, r: 150 }), // Thistle
+ colord({ b: 180, g: 190, r: 170 }), // Pale Blue Green
+ colord({ b: 150, g: 140, r: 190 }), // Puce
+ colord({ b: 170, g: 180, r: 130 }), // Medium Aquamarine
+ colord({ b: 180, g: 160, r: 180 }), // Mauve
+ colord({ b: 140, g: 180, r: 160 }), // Dark Olive Green
+ colord({ b: 170, g: 150, r: 170 }), // Dusty Rose
];
// Bright pastel theme with 64 colors
export const humanColors: Colord[] = [
- colord({ r: 16, g: 185, b: 129 }), // Sea Green
- colord({ r: 34, g: 197, b: 94 }), // Emerald
- colord({ r: 45, g: 212, b: 191 }), // Turquoise
- colord({ r: 48, g: 178, b: 180 }), // Teal
- colord({ r: 52, g: 211, b: 153 }), // Spearmint
- colord({ r: 56, g: 189, b: 248 }), // Light Blue
- colord({ r: 59, g: 130, b: 246 }), // Royal Blue
- colord({ r: 67, g: 190, b: 84 }), // Fresh Green
- colord({ r: 74, g: 222, b: 128 }), // Mint
- colord({ r: 79, g: 70, b: 229 }), // Indigo
- colord({ r: 82, g: 183, b: 136 }), // Jade
- colord({ r: 96, g: 165, b: 250 }), // Sky Blue
- colord({ r: 99, g: 202, b: 253 }), // Azure
- colord({ r: 110, g: 231, b: 183 }), // Seafoam
- colord({ r: 124, g: 58, b: 237 }), // Royal Purple
- colord({ r: 125, g: 211, b: 252 }), // Crystal Blue
- colord({ r: 132, g: 204, b: 22 }), // Lime
- colord({ r: 133, g: 77, b: 14 }), // Chocolate
- colord({ r: 134, g: 239, b: 172 }), // Light Green
- colord({ r: 147, g: 51, b: 234 }), // Bright Purple
- colord({ r: 147, g: 197, b: 253 }), // Powder Blue
- colord({ r: 151, g: 255, b: 187 }), // Fresh Mint
- colord({ r: 163, g: 230, b: 53 }), // Yellow Green
- colord({ r: 167, g: 139, b: 250 }), // Periwinkle
- colord({ r: 168, g: 85, b: 247 }), // Vibrant Purple
- colord({ r: 179, g: 136, b: 255 }), // Light Purple
- colord({ r: 186, g: 255, b: 201 }), // Pale Emerald
- colord({ r: 190, g: 92, b: 251 }), // Amethyst
- colord({ r: 192, g: 132, b: 252 }), // Lavender
- colord({ r: 202, g: 138, b: 4 }), // Rich Gold
- colord({ r: 202, g: 225, b: 255 }), // Baby Blue
- colord({ r: 204, g: 204, b: 255 }), // Soft Lavender Blue
- colord({ r: 217, g: 70, b: 239 }), // Fuchsia
- colord({ r: 220, g: 38, b: 38 }), // Ruby
- colord({ r: 220, g: 220, b: 255 }), // Meringue Blue
- colord({ r: 220, g: 240, b: 250 }), // Ice Blue
- colord({ r: 230, g: 250, b: 210 }), // Pastel Lime
- colord({ r: 230, g: 255, b: 250 }), // Mint Whisper
- colord({ r: 233, g: 213, b: 255 }), // Light Lilac
- colord({ r: 234, g: 88, b: 12 }), // Burnt Orange
- colord({ r: 234, g: 179, b: 8 }), // Sunflower
- colord({ r: 235, g: 75, b: 75 }), // Bright Red
- colord({ r: 236, g: 72, b: 153 }), // Deep Pink
- colord({ r: 239, g: 68, b: 68 }), // Crimson
- colord({ r: 240, g: 171, b: 252 }), // Orchid
- colord({ r: 240, g: 240, b: 200 }), // Light Khaki
- colord({ r: 244, g: 114, b: 182 }), // Rose
- colord({ r: 245, g: 101, b: 101 }), // Coral
- colord({ r: 245, g: 158, b: 11 }), // Amber
- colord({ r: 248, g: 113, b: 113 }), // Warm Red
- colord({ r: 249, g: 115, b: 22 }), // Tangerine
- colord({ r: 250, g: 215, b: 225 }), // Cotton Candy
- colord({ r: 250, g: 250, b: 210 }), // Pastel Lemon
- colord({ r: 251, g: 113, b: 133 }), // Watermelon
- colord({ r: 251, g: 146, b: 60 }), // Light Orange
- colord({ r: 251, g: 191, b: 36 }), // Marigold
- colord({ r: 251, g: 235, b: 245 }), // Rose Powder
- colord({ r: 252, g: 165, b: 165 }), // Peach
- colord({ r: 252, g: 211, b: 77 }), // Golden
- colord({ r: 253, g: 164, b: 175 }), // Salmon Pink
- colord({ r: 255, g: 204, b: 229 }), // Blush Pink
- colord({ r: 255, g: 223, b: 186 }), // Apricot Cream
- colord({ r: 255, g: 240, b: 200 }), // Vanilla
+ colord({ b: 129, g: 185, r: 16 }), // Sea Green
+ colord({ b: 94, g: 197, r: 34 }), // Emerald
+ colord({ b: 191, g: 212, r: 45 }), // Turquoise
+ colord({ b: 180, g: 178, r: 48 }), // Teal
+ colord({ b: 153, g: 211, r: 52 }), // Spearmint
+ colord({ b: 248, g: 189, r: 56 }), // Light Blue
+ colord({ b: 246, g: 130, r: 59 }), // Royal Blue
+ colord({ b: 84, g: 190, r: 67 }), // Fresh Green
+ colord({ b: 128, g: 222, r: 74 }), // Mint
+ colord({ b: 229, g: 70, r: 79 }), // Indigo
+ colord({ b: 136, g: 183, r: 82 }), // Jade
+ colord({ b: 250, g: 165, r: 96 }), // Sky Blue
+ colord({ b: 253, g: 202, r: 99 }), // Azure
+ colord({ b: 183, g: 231, r: 110 }), // Seafoam
+ colord({ b: 237, g: 58, r: 124 }), // Royal Purple
+ colord({ b: 252, g: 211, r: 125 }), // Crystal Blue
+ colord({ b: 22, g: 204, r: 132 }), // Lime
+ colord({ b: 14, g: 77, r: 133 }), // Chocolate
+ colord({ b: 172, g: 239, r: 134 }), // Light Green
+ colord({ b: 234, g: 51, r: 147 }), // Bright Purple
+ colord({ b: 253, g: 197, r: 147 }), // Powder Blue
+ colord({ b: 187, g: 255, r: 151 }), // Fresh Mint
+ colord({ b: 53, g: 230, r: 163 }), // Yellow Green
+ colord({ b: 250, g: 139, r: 167 }), // Periwinkle
+ colord({ b: 247, g: 85, r: 168 }), // Vibrant Purple
+ colord({ b: 255, g: 136, r: 179 }), // Light Purple
+ colord({ b: 201, g: 255, r: 186 }), // Pale Emerald
+ colord({ b: 251, g: 92, r: 190 }), // Amethyst
+ colord({ b: 252, g: 132, r: 192 }), // Lavender
+ colord({ b: 4, g: 138, r: 202 }), // Rich Gold
+ colord({ b: 255, g: 225, r: 202 }), // Baby Blue
+ colord({ b: 255, g: 204, r: 204 }), // Soft Lavender Blue
+ colord({ b: 239, g: 70, r: 217 }), // Fuchsia
+ colord({ b: 38, g: 38, r: 220 }), // Ruby
+ colord({ b: 255, g: 220, r: 220 }), // Meringue Blue
+ colord({ b: 250, g: 240, r: 220 }), // Ice Blue
+ colord({ b: 210, g: 250, r: 230 }), // Pastel Lime
+ colord({ b: 250, g: 255, r: 230 }), // Mint Whisper
+ colord({ b: 255, g: 213, r: 233 }), // Light Lilac
+ colord({ b: 12, g: 88, r: 234 }), // Burnt Orange
+ colord({ b: 8, g: 179, r: 234 }), // Sunflower
+ colord({ b: 75, g: 75, r: 235 }), // Bright Red
+ colord({ b: 153, g: 72, r: 236 }), // Deep Pink
+ colord({ b: 68, g: 68, r: 239 }), // Crimson
+ colord({ b: 252, g: 171, r: 240 }), // Orchid
+ colord({ b: 200, g: 240, r: 240 }), // Light Khaki
+ colord({ b: 182, g: 114, r: 244 }), // Rose
+ colord({ b: 101, g: 101, r: 245 }), // Coral
+ colord({ b: 11, g: 158, r: 245 }), // Amber
+ colord({ b: 113, g: 113, r: 248 }), // Warm Red
+ colord({ b: 22, g: 115, r: 249 }), // Tangerine
+ colord({ b: 225, g: 215, r: 250 }), // Cotton Candy
+ colord({ b: 210, g: 250, r: 250 }), // Pastel Lemon
+ colord({ b: 133, g: 113, r: 251 }), // Watermelon
+ colord({ b: 60, g: 146, r: 251 }), // Light Orange
+ colord({ b: 36, g: 191, r: 251 }), // Marigold
+ colord({ b: 245, g: 235, r: 251 }), // Rose Powder
+ colord({ b: 165, g: 165, r: 252 }), // Peach
+ colord({ b: 77, g: 211, r: 252 }), // Golden
+ colord({ b: 175, g: 164, r: 253 }), // Salmon Pink
+ colord({ b: 229, g: 204, r: 255 }), // Blush Pink
+ colord({ b: 186, g: 223, r: 255 }), // Apricot Cream
+ colord({ b: 200, g: 240, r: 255 }), // Vanilla
];
export const botColors: Colord[] = [
- colord({ r: 190, g: 120, b: 120 }), // Muted Red
- colord({ r: 120, g: 160, b: 190 }), // Muted Sky Blue
- colord({ r: 190, g: 160, b: 100 }), // Muted Golden Yellow
- colord({ r: 160, g: 120, b: 190 }), // Muted Purple
- colord({ r: 100, g: 170, b: 130 }), // Muted Emerald Green
- colord({ r: 190, g: 130, b: 160 }), // Muted Pink
- colord({ r: 120, g: 150, b: 100 }), // Muted Olive Green
- colord({ r: 190, g: 140, b: 120 }), // Muted Peach
- colord({ r: 100, g: 120, b: 160 }), // Muted Navy Blue
- colord({ r: 170, g: 170, b: 120 }), // Muted Lime Yellow
- colord({ r: 160, g: 120, b: 130 }), // Muted Maroon
- colord({ r: 120, g: 170, b: 170 }), // Muted Turquoise
- colord({ r: 170, g: 140, b: 100 }), // Muted Light Orange
- colord({ r: 140, g: 120, b: 160 }), // Muted Lavender
- colord({ r: 150, g: 170, b: 130 }), // Muted Light Green
- colord({ r: 170, g: 120, b: 140 }), // Muted Hot Pink
- colord({ r: 120, g: 140, b: 120 }), // Muted Sea Green
- colord({ r: 180, g: 160, b: 160 }), // Muted Light Pink
- colord({ r: 130, g: 130, b: 160 }), // Muted Periwinkle
- colord({ r: 160, g: 150, b: 120 }), // Muted Sand
- colord({ r: 120, g: 160, b: 150 }), // Muted Aquamarine
- colord({ r: 170, g: 150, b: 170 }), // Muted Orchid
- colord({ r: 150, g: 160, b: 120 }), // Muted Yellow Green
- colord({ r: 120, g: 130, b: 140 }), // Muted Steel Blue
- colord({ r: 180, g: 140, b: 140 }), // Muted Salmon
- colord({ r: 140, g: 160, b: 170 }), // Muted Light Blue
- colord({ r: 170, g: 150, b: 130 }), // Muted Tan
- colord({ r: 160, g: 130, b: 160 }), // Muted Plum
- colord({ r: 130, g: 170, b: 130 }), // Muted Light Sea Green
- colord({ r: 170, g: 130, b: 130 }), // Muted Coral
- colord({ r: 130, g: 150, b: 170 }), // Muted Cornflower Blue
- colord({ r: 170, g: 170, b: 140 }), // Muted Khaki
- colord({ r: 150, g: 130, b: 150 }), // Muted Purple Gray
- colord({ r: 140, g: 160, b: 140 }), // Muted Dark Sea Green
- colord({ r: 170, g: 130, b: 120 }), // Muted Dark Salmon
- colord({ r: 130, g: 150, b: 160 }), // Muted Cadet Blue
- colord({ r: 160, g: 160, b: 150 }), // Muted Tan Gray
- colord({ r: 150, g: 140, b: 160 }), // Muted Medium Purple
- colord({ r: 150, g: 170, b: 150 }), // Muted Pale Green
- colord({ r: 160, g: 140, b: 130 }), // Muted Rosy Brown
- colord({ r: 140, g: 150, b: 160 }), // Muted Light Slate Gray
- colord({ r: 160, g: 150, b: 140 }), // Muted Dark Khaki
- colord({ r: 140, g: 130, b: 140 }), // Muted Thistle
- colord({ r: 150, g: 160, b: 160 }), // Muted Pale Blue Green
- colord({ r: 160, g: 140, b: 150 }), // Muted Puce
- colord({ r: 130, g: 160, b: 150 }), // Muted Medium Aquamarine
- colord({ r: 160, g: 150, b: 160 }), // Muted Mauve
- colord({ r: 150, g: 160, b: 140 }), // Muted Dark Olive Green
- colord({ r: 150, g: 140, b: 150 }), // Muted Dusty Rose
+ colord({ b: 120, g: 120, r: 190 }), // Muted Red
+ colord({ b: 190, g: 160, r: 120 }), // Muted Sky Blue
+ colord({ b: 100, g: 160, r: 190 }), // Muted Golden Yellow
+ colord({ b: 190, g: 120, r: 160 }), // Muted Purple
+ colord({ b: 130, g: 170, r: 100 }), // Muted Emerald Green
+ colord({ b: 160, g: 130, r: 190 }), // Muted Pink
+ colord({ b: 100, g: 150, r: 120 }), // Muted Olive Green
+ colord({ b: 120, g: 140, r: 190 }), // Muted Peach
+ colord({ b: 160, g: 120, r: 100 }), // Muted Navy Blue
+ colord({ b: 120, g: 170, r: 170 }), // Muted Lime Yellow
+ colord({ b: 130, g: 120, r: 160 }), // Muted Maroon
+ colord({ b: 170, g: 170, r: 120 }), // Muted Turquoise
+ colord({ b: 100, g: 140, r: 170 }), // Muted Light Orange
+ colord({ b: 160, g: 120, r: 140 }), // Muted Lavender
+ colord({ b: 130, g: 170, r: 150 }), // Muted Light Green
+ colord({ b: 140, g: 120, r: 170 }), // Muted Hot Pink
+ colord({ b: 120, g: 140, r: 120 }), // Muted Sea Green
+ colord({ b: 160, g: 160, r: 180 }), // Muted Light Pink
+ colord({ b: 160, g: 130, r: 130 }), // Muted Periwinkle
+ colord({ b: 120, g: 150, r: 160 }), // Muted Sand
+ colord({ b: 150, g: 160, r: 120 }), // Muted Aquamarine
+ colord({ b: 170, g: 150, r: 170 }), // Muted Orchid
+ colord({ b: 120, g: 160, r: 150 }), // Muted Yellow Green
+ colord({ b: 140, g: 130, r: 120 }), // Muted Steel Blue
+ colord({ b: 140, g: 140, r: 180 }), // Muted Salmon
+ colord({ b: 170, g: 160, r: 140 }), // Muted Light Blue
+ colord({ b: 130, g: 150, r: 170 }), // Muted Tan
+ colord({ b: 160, g: 130, r: 160 }), // Muted Plum
+ colord({ b: 130, g: 170, r: 130 }), // Muted Light Sea Green
+ colord({ b: 130, g: 130, r: 170 }), // Muted Coral
+ colord({ b: 170, g: 150, r: 130 }), // Muted Cornflower Blue
+ colord({ b: 140, g: 170, r: 170 }), // Muted Khaki
+ colord({ b: 150, g: 130, r: 150 }), // Muted Purple Gray
+ colord({ b: 140, g: 160, r: 140 }), // Muted Dark Sea Green
+ colord({ b: 120, g: 130, r: 170 }), // Muted Dark Salmon
+ colord({ b: 160, g: 150, r: 130 }), // Muted Cadet Blue
+ colord({ b: 150, g: 160, r: 160 }), // Muted Tan Gray
+ colord({ b: 160, g: 140, r: 150 }), // Muted Medium Purple
+ colord({ b: 150, g: 170, r: 150 }), // Muted Pale Green
+ colord({ b: 130, g: 140, r: 160 }), // Muted Rosy Brown
+ colord({ b: 160, g: 150, r: 140 }), // Muted Light Slate Gray
+ colord({ b: 140, g: 150, r: 160 }), // Muted Dark Khaki
+ colord({ b: 140, g: 130, r: 140 }), // Muted Thistle
+ colord({ b: 160, g: 160, r: 150 }), // Muted Pale Blue Green
+ colord({ b: 150, g: 140, r: 160 }), // Muted Puce
+ colord({ b: 150, g: 160, r: 130 }), // Muted Medium Aquamarine
+ colord({ b: 160, g: 150, r: 160 }), // Muted Mauve
+ colord({ b: 140, g: 160, r: 150 }), // Muted Dark Olive Green
+ colord({ b: 150, g: 140, r: 150 }), // Muted Dusty Rose
];
// Fallback colors for when the color palette is exhausted. Currently 100 colors.
export const fallbackColors: Colord[] = [
- colord({ r: 0, g: 5, b: 0 }), // Black Mint
- colord({ r: 0, g: 15, b: 0 }), // Deep Forest
- colord({ r: 0, g: 25, b: 0 }), // Jungle
- colord({ r: 0, g: 35, b: 0 }), // Dark Emerald
- colord({ r: 0, g: 45, b: 0 }), // Green Moss
- colord({ r: 0, g: 55, b: 0 }), // Moss Shadow
- colord({ r: 0, g: 65, b: 0 }), // Dark Meadow
- colord({ r: 0, g: 75, b: 0 }), // Forest Fern
- colord({ r: 0, g: 85, b: 0 }), // Pine Leaf
- colord({ r: 0, g: 95, b: 0 }), // Shadow Grass
- colord({ r: 0, g: 105, b: 0 }), // Classic Green
- colord({ r: 0, g: 115, b: 0 }), // Deep Lime
- colord({ r: 0, g: 125, b: 0 }), // Dense Leaf
- colord({ r: 0, g: 135, b: 0 }), // Basil Green
- colord({ r: 0, g: 145, b: 0 }), // Organic Green
- colord({ r: 0, g: 155, b: 0 }), // Bitter Herb
- colord({ r: 0, g: 165, b: 0 }), // Raw Spinach
- colord({ r: 0, g: 175, b: 0 }), // Woodland
- colord({ r: 0, g: 185, b: 0 }), // Spring Weed
- colord({ r: 0, g: 195, b: 5 }), // Apple Stem
- colord({ r: 0, g: 205, b: 10 }), // Crisp Lettuce
- colord({ r: 0, g: 215, b: 15 }), // Vibrant Green
- colord({ r: 0, g: 225, b: 20 }), // Bright Herb
- colord({ r: 0, g: 235, b: 25 }), // Green Splash
- colord({ r: 0, g: 245, b: 30 }), // Mint Leaf
- colord({ r: 0, g: 255, b: 35 }), // Fresh Mint
- colord({ r: 10, g: 255, b: 45 }), // Neon Grass
- colord({ r: 20, g: 255, b: 55 }), // Lemon Balm
- colord({ r: 30, g: 255, b: 65 }), // Juicy Green
- colord({ r: 40, g: 255, b: 75 }), // Pear Tint
- colord({ r: 50, g: 255, b: 85 }), // Avocado Pastel
- colord({ r: 60, g: 255, b: 95 }), // Lime Glow
- colord({ r: 70, g: 255, b: 105 }), // Light Leaf
- colord({ r: 80, g: 255, b: 115 }), // Soft Fern
- colord({ r: 90, g: 255, b: 125 }), // Pastel Green
- colord({ r: 100, g: 255, b: 135 }), // Green Melon
- colord({ r: 110, g: 255, b: 145 }), // Herbal Mist
- colord({ r: 120, g: 255, b: 155 }), // Kiwi Foam
- colord({ r: 130, g: 255, b: 165 }), // Aloe Fresh
- colord({ r: 140, g: 255, b: 175 }), // Light Mint
- colord({ r: 150, g: 200, b: 255 }), // Cornflower Mist
- colord({ r: 150, g: 255, b: 185 }), // Green Sorbet
- colord({ r: 160, g: 215, b: 255 }), // Powder Blue
- colord({ r: 160, g: 255, b: 195 }), // Pastel Apple
- colord({ r: 170, g: 190, b: 255 }), // Periwinkle Ice
- colord({ r: 170, g: 225, b: 255 }), // Baby Sky
- colord({ r: 170, g: 255, b: 205 }), // Aloe Breeze
- colord({ r: 180, g: 180, b: 255 }), // Pale Indigo
- colord({ r: 180, g: 235, b: 250 }), // Aqua Pastel
- colord({ r: 180, g: 255, b: 215 }), // Pale Mint
- colord({ r: 190, g: 140, b: 195 }), // Fuchsia Tint
- colord({ r: 190, g: 245, b: 240 }), // Ice Mint
- colord({ r: 190, g: 255, b: 225 }), // Mint Water
- colord({ r: 195, g: 145, b: 200 }), // Dusky Rose
- colord({ r: 200, g: 150, b: 205 }), // Plum Frost
- colord({ r: 200, g: 170, b: 255 }), // Lilac Bloom
- colord({ r: 200, g: 255, b: 215 }), // Cool Aloe
- colord({ r: 200, g: 255, b: 235 }), // Cool Mist
- colord({ r: 205, g: 155, b: 210 }), // Berry Foam
- colord({ r: 210, g: 160, b: 215 }), // Grape Cloud
- colord({ r: 210, g: 255, b: 245 }), // Sea Mist
- colord({ r: 215, g: 165, b: 220 }), // Light Bloom
- colord({ r: 215, g: 255, b: 200 }), // Fresh Mint
- colord({ r: 220, g: 160, b: 255 }), // Violet Mist
- colord({ r: 220, g: 170, b: 225 }), // Cherry Blossom
- colord({ r: 220, g: 255, b: 255 }), // Pale Aqua
- colord({ r: 225, g: 175, b: 230 }), // Faded Rose
- colord({ r: 225, g: 255, b: 175 }), // Soft Lime
- colord({ r: 230, g: 180, b: 235 }), // Dreamy Mauve
- colord({ r: 230, g: 250, b: 255 }), // Sky Haze
- colord({ r: 235, g: 150, b: 255 }), // Orchid Glow
- colord({ r: 235, g: 185, b: 240 }), // Powder Violet
- colord({ r: 240, g: 190, b: 245 }), // Pastel Violet
- colord({ r: 240, g: 240, b: 255 }), // Frosted Lilac
- colord({ r: 240, g: 250, b: 160 }), // Citrus Wash
- colord({ r: 245, g: 160, b: 240 }), // Rose Lilac
- colord({ r: 245, g: 195, b: 250 }), // Soft Magenta
- colord({ r: 245, g: 245, b: 175 }), // Lemon Mist
- colord({ r: 250, g: 200, b: 255 }), // Lilac Cream
- colord({ r: 250, g: 230, b: 255 }), // Misty Mauve
- colord({ r: 255, g: 170, b: 225 }), // Bubblegum Pink
- colord({ r: 255, g: 185, b: 215 }), // Blush Mist
- colord({ r: 255, g: 195, b: 235 }), // Faded Fuchsia
- colord({ r: 255, g: 200, b: 220 }), // Cotton Rose
- colord({ r: 255, g: 205, b: 245 }), // Pastel Orchid
- colord({ r: 255, g: 205, b: 255 }), // Violet Bloom
- colord({ r: 255, g: 210, b: 230 }), // Pastel Blush
- colord({ r: 255, g: 210, b: 250 }), // Lavender Mist
- colord({ r: 255, g: 210, b: 255 }), // Orchid Mist
- colord({ r: 255, g: 215, b: 195 }), // Apricot Glow
- colord({ r: 255, g: 215, b: 245 }), // Rose Whisper
- colord({ r: 255, g: 220, b: 235 }), // Pink Mist
- colord({ r: 255, g: 220, b: 250 }), // Powder Petal
- colord({ r: 255, g: 225, b: 180 }), // Butter Peach
- colord({ r: 255, g: 225, b: 255 }), // Petal Mist
- colord({ r: 255, g: 230, b: 245 }), // Light Rose
- colord({ r: 255, g: 235, b: 200 }), // Cream Peach
- colord({ r: 255, g: 235, b: 235 }), // Blushed Petal
- colord({ r: 255, g: 240, b: 220 }), // Pastel Sand
- colord({ r: 255, g: 245, b: 210 }), // Soft Banana
+ colord({ b: 0, g: 5, r: 0 }), // Black Mint
+ colord({ b: 0, g: 15, r: 0 }), // Deep Forest
+ colord({ b: 0, g: 25, r: 0 }), // Jungle
+ colord({ b: 0, g: 35, r: 0 }), // Dark Emerald
+ colord({ b: 0, g: 45, r: 0 }), // Green Moss
+ colord({ b: 0, g: 55, r: 0 }), // Moss Shadow
+ colord({ b: 0, g: 65, r: 0 }), // Dark Meadow
+ colord({ b: 0, g: 75, r: 0 }), // Forest Fern
+ colord({ b: 0, g: 85, r: 0 }), // Pine Leaf
+ colord({ b: 0, g: 95, r: 0 }), // Shadow Grass
+ colord({ b: 0, g: 105, r: 0 }), // Classic Green
+ colord({ b: 0, g: 115, r: 0 }), // Deep Lime
+ colord({ b: 0, g: 125, r: 0 }), // Dense Leaf
+ colord({ b: 0, g: 135, r: 0 }), // Basil Green
+ colord({ b: 0, g: 145, r: 0 }), // Organic Green
+ colord({ b: 0, g: 155, r: 0 }), // Bitter Herb
+ colord({ b: 0, g: 165, r: 0 }), // Raw Spinach
+ colord({ b: 0, g: 175, r: 0 }), // Woodland
+ colord({ b: 0, g: 185, r: 0 }), // Spring Weed
+ colord({ b: 5, g: 195, r: 0 }), // Apple Stem
+ colord({ b: 10, g: 205, r: 0 }), // Crisp Lettuce
+ colord({ b: 15, g: 215, r: 0 }), // Vibrant Green
+ colord({ b: 20, g: 225, r: 0 }), // Bright Herb
+ colord({ b: 25, g: 235, r: 0 }), // Green Splash
+ colord({ b: 30, g: 245, r: 0 }), // Mint Leaf
+ colord({ b: 35, g: 255, r: 0 }), // Fresh Mint
+ colord({ b: 45, g: 255, r: 10 }), // Neon Grass
+ colord({ b: 55, g: 255, r: 20 }), // Lemon Balm
+ colord({ b: 65, g: 255, r: 30 }), // Juicy Green
+ colord({ b: 75, g: 255, r: 40 }), // Pear Tint
+ colord({ b: 85, g: 255, r: 50 }), // Avocado Pastel
+ colord({ b: 95, g: 255, r: 60 }), // Lime Glow
+ colord({ b: 105, g: 255, r: 70 }), // Light Leaf
+ colord({ b: 115, g: 255, r: 80 }), // Soft Fern
+ colord({ b: 125, g: 255, r: 90 }), // Pastel Green
+ colord({ b: 135, g: 255, r: 100 }), // Green Melon
+ colord({ b: 145, g: 255, r: 110 }), // Herbal Mist
+ colord({ b: 155, g: 255, r: 120 }), // Kiwi Foam
+ colord({ b: 165, g: 255, r: 130 }), // Aloe Fresh
+ colord({ b: 175, g: 255, r: 140 }), // Light Mint
+ colord({ b: 255, g: 200, r: 150 }), // Cornflower Mist
+ colord({ b: 185, g: 255, r: 150 }), // Green Sorbet
+ colord({ b: 255, g: 215, r: 160 }), // Powder Blue
+ colord({ b: 195, g: 255, r: 160 }), // Pastel Apple
+ colord({ b: 255, g: 190, r: 170 }), // Periwinkle Ice
+ colord({ b: 255, g: 225, r: 170 }), // Baby Sky
+ colord({ b: 205, g: 255, r: 170 }), // Aloe Breeze
+ colord({ b: 255, g: 180, r: 180 }), // Pale Indigo
+ colord({ b: 250, g: 235, r: 180 }), // Aqua Pastel
+ colord({ b: 215, g: 255, r: 180 }), // Pale Mint
+ colord({ b: 195, g: 140, r: 190 }), // Fuchsia Tint
+ colord({ b: 240, g: 245, r: 190 }), // Ice Mint
+ colord({ b: 225, g: 255, r: 190 }), // Mint Water
+ colord({ b: 200, g: 145, r: 195 }), // Dusky Rose
+ colord({ b: 205, g: 150, r: 200 }), // Plum Frost
+ colord({ b: 255, g: 170, r: 200 }), // Lilac Bloom
+ colord({ b: 215, g: 255, r: 200 }), // Cool Aloe
+ colord({ b: 235, g: 255, r: 200 }), // Cool Mist
+ colord({ b: 210, g: 155, r: 205 }), // Berry Foam
+ colord({ b: 215, g: 160, r: 210 }), // Grape Cloud
+ colord({ b: 245, g: 255, r: 210 }), // Sea Mist
+ colord({ b: 220, g: 165, r: 215 }), // Light Bloom
+ colord({ b: 200, g: 255, r: 215 }), // Fresh Mint
+ colord({ b: 255, g: 160, r: 220 }), // Violet Mist
+ colord({ b: 225, g: 170, r: 220 }), // Cherry Blossom
+ colord({ b: 255, g: 255, r: 220 }), // Pale Aqua
+ colord({ b: 230, g: 175, r: 225 }), // Faded Rose
+ colord({ b: 175, g: 255, r: 225 }), // Soft Lime
+ colord({ b: 235, g: 180, r: 230 }), // Dreamy Mauve
+ colord({ b: 255, g: 250, r: 230 }), // Sky Haze
+ colord({ b: 255, g: 150, r: 235 }), // Orchid Glow
+ colord({ b: 240, g: 185, r: 235 }), // Powder Violet
+ colord({ b: 245, g: 190, r: 240 }), // Pastel Violet
+ colord({ b: 255, g: 240, r: 240 }), // Frosted Lilac
+ colord({ b: 160, g: 250, r: 240 }), // Citrus Wash
+ colord({ b: 240, g: 160, r: 245 }), // Rose Lilac
+ colord({ b: 250, g: 195, r: 245 }), // Soft Magenta
+ colord({ b: 175, g: 245, r: 245 }), // Lemon Mist
+ colord({ b: 255, g: 200, r: 250 }), // Lilac Cream
+ colord({ b: 255, g: 230, r: 250 }), // Misty Mauve
+ colord({ b: 225, g: 170, r: 255 }), // Bubblegum Pink
+ colord({ b: 215, g: 185, r: 255 }), // Blush Mist
+ colord({ b: 235, g: 195, r: 255 }), // Faded Fuchsia
+ colord({ b: 220, g: 200, r: 255 }), // Cotton Rose
+ colord({ b: 245, g: 205, r: 255 }), // Pastel Orchid
+ colord({ b: 255, g: 205, r: 255 }), // Violet Bloom
+ colord({ b: 230, g: 210, r: 255 }), // Pastel Blush
+ colord({ b: 250, g: 210, r: 255 }), // Lavender Mist
+ colord({ b: 255, g: 210, r: 255 }), // Orchid Mist
+ colord({ b: 195, g: 215, r: 255 }), // Apricot Glow
+ colord({ b: 245, g: 215, r: 255 }), // Rose Whisper
+ colord({ b: 235, g: 220, r: 255 }), // Pink Mist
+ colord({ b: 250, g: 220, r: 255 }), // Powder Petal
+ colord({ b: 180, g: 225, r: 255 }), // Butter Peach
+ colord({ b: 255, g: 225, r: 255 }), // Petal Mist
+ colord({ b: 245, g: 230, r: 255 }), // Light Rose
+ colord({ b: 200, g: 235, r: 255 }), // Cream Peach
+ colord({ b: 235, g: 235, r: 255 }), // Blushed Petal
+ colord({ b: 220, g: 240, r: 255 }), // Pastel Sand
+ colord({ b: 210, g: 245, r: 255 }), // Soft Banana
];
diff --git a/src/core/configuration/Config.ts b/src/core/configuration/Config.ts
index fe1e2525aa..4e32ca37c6 100644
--- a/src/core/configuration/Config.ts
+++ b/src/core/configuration/Config.ts
@@ -1,3 +1,5 @@
+import { Colord } from "colord";
+import { JWK } from "jose";
import {
Difficulty,
Game,
@@ -12,13 +14,11 @@ import {
UnitInfo,
UnitType,
} from "../game/Game";
-import { GameConfig, GameID, TeamCountConfig } from "../Schemas";
import { GameMap, TileRef } from "../game/GameMap";
-import { Colord } from "colord";
-import { JWK } from "jose";
-import { NukeType } from "../StatsSchemas";
import { PlayerView } from "../game/GameView";
import { UserSettings } from "../game/UserSettings";
+import { GameConfig, GameID, TeamCountConfig } from "../Schemas";
+import { NukeType } from "../StatsSchemas";
export enum GameEnv {
Dev,
diff --git a/src/core/configuration/ConfigLoader.ts b/src/core/configuration/ConfigLoader.ts
index 19667b45ec..3bb7f53fc7 100644
--- a/src/core/configuration/ConfigLoader.ts
+++ b/src/core/configuration/ConfigLoader.ts
@@ -1,9 +1,9 @@
-import { Config, GameEnv, ServerConfig } from "./Config";
-import { DevConfig, DevServerConfig } from "./DevConfig";
import { ApiEnvResponseSchema } from "../ExpressSchemas";
-import { DefaultConfig } from "./DefaultConfig";
-import { GameConfig } from "../Schemas";
import { UserSettings } from "../game/UserSettings";
+import { GameConfig } from "../Schemas";
+import { Config, GameEnv, ServerConfig } from "./Config";
+import { DefaultConfig } from "./DefaultConfig";
+import { DevConfig, DevServerConfig } from "./DevConfig";
import { preprodConfig } from "./PreprodConfig";
import { prodConfig } from "./ProdConfig";
diff --git a/src/core/configuration/DefaultConfig.ts b/src/core/configuration/DefaultConfig.ts
index eddf481fe2..9f6eb23759 100644
--- a/src/core/configuration/DefaultConfig.ts
+++ b/src/core/configuration/DefaultConfig.ts
@@ -1,5 +1,7 @@
/* eslint-disable max-lines */
-import { Config, GameEnv, NukeMagnitude, ServerConfig, Theme } from "./Config";
+
+import { JWK } from "jose";
+import { z } from "zod";
import {
Difficulty,
Duos,
@@ -12,23 +14,22 @@ import {
PlayerInfo,
PlayerType,
Quads,
- TerraNullius,
TerrainType,
+ TerraNullius,
Tick,
Trios,
UnitInfo,
UnitType,
} from "../game/Game";
+import { TileRef } from "../game/GameMap";
+import { PlayerView } from "../game/GameView";
+import { UserSettings } from "../game/UserSettings";
import { GameConfig, GameID, TeamCountConfig } from "../Schemas";
-import { assertNever, simpleHash, within } from "../Util";
-import { JWK } from "jose";
import { NukeType } from "../StatsSchemas";
+import { assertNever, simpleHash, within } from "../Util";
+import { Config, GameEnv, NukeMagnitude, ServerConfig, Theme } from "./Config";
import { PastelTheme } from "./PastelTheme";
import { PastelThemeDark } from "./PastelThemeDark";
-import { PlayerView } from "../game/GameView";
-import { TileRef } from "../game/GameMap";
-import { UserSettings } from "../game/UserSettings";
-import { z } from "zod";
const JwksSchema = z.object({
keys: z
@@ -375,7 +376,6 @@ export class DefaultConfig implements Config {
return 1_000_000;
}
- /* eslint-disable sort-keys */
unitInfo(type: UnitType): UnitInfo {
switch (type) {
case UnitType.TransportShip:
@@ -388,14 +388,14 @@ export class DefaultConfig implements Config {
cost: this.costWrapper(UnitType.Warship, (numUnits: number) =>
Math.min(1_000_000, (numUnits + 1) * 250_000),
),
- territoryBound: false,
maxHealth: 1000,
+ territoryBound: false,
};
case UnitType.Shell:
return {
cost: () => 0n,
- territoryBound: false,
damage: 250,
+ territoryBound: false,
};
case UnitType.SAMMissile:
return {
@@ -404,13 +404,13 @@ export class DefaultConfig implements Config {
};
case UnitType.Port:
return {
+ canBuildTrainStation: true,
+ constructionDuration: this.instantBuild() ? 0 : 2 * 10,
cost: this.costWrapper(UnitType.Port, (numUnits: number) =>
Math.min(1_000_000, Math.pow(2, numUnits) * 125_000),
),
territoryBound: true,
- constructionDuration: this.instantBuild() ? 0 : 2 * 10,
upgradable: true,
- canBuildTrainStation: true,
};
case UnitType.AtomBomb:
return {
@@ -439,47 +439,47 @@ export class DefaultConfig implements Config {
};
case UnitType.MissileSilo:
return {
+ constructionDuration: this.instantBuild() ? 0 : 10 * 10,
cost: this.costWrapper(UnitType.MissileSilo, () => 1_000_000),
territoryBound: true,
- constructionDuration: this.instantBuild() ? 0 : 10 * 10,
upgradable: true,
};
case UnitType.DefensePost:
return {
+ constructionDuration: this.instantBuild() ? 0 : 5 * 10,
cost: this.costWrapper(UnitType.DefensePost, (numUnits: number) =>
Math.min(250_000, (numUnits + 1) * 50_000),
),
territoryBound: true,
- constructionDuration: this.instantBuild() ? 0 : 5 * 10,
};
case UnitType.SAMLauncher:
return {
+ constructionDuration: this.instantBuild() ? 0 : 30 * 10,
cost: this.costWrapper(UnitType.SAMLauncher, (numUnits: number) =>
Math.min(3_000_000, (numUnits + 1) * 1_500_000),
),
territoryBound: true,
- constructionDuration: this.instantBuild() ? 0 : 30 * 10,
upgradable: true,
};
case UnitType.City:
return {
+ canBuildTrainStation: true,
+ constructionDuration: this.instantBuild() ? 0 : 2 * 10,
cost: this.costWrapper(UnitType.City, (numUnits: number) =>
Math.min(1_000_000, Math.pow(2, numUnits) * 125_000),
),
territoryBound: true,
- constructionDuration: this.instantBuild() ? 0 : 2 * 10,
upgradable: true,
- canBuildTrainStation: true,
};
case UnitType.Factory:
return {
+ canBuildTrainStation: true,
+ constructionDuration: this.instantBuild() ? 0 : 2 * 10,
cost: this.costWrapper(UnitType.Factory, (numUnits: number) =>
Math.min(1_000_000, Math.pow(2, numUnits) * 125_000),
),
- territoryBound: true,
- constructionDuration: this.instantBuild() ? 0 : 2 * 10,
- canBuildTrainStation: true,
experimental: true,
+ territoryBound: true,
upgradable: true,
};
case UnitType.Construction:
@@ -490,14 +490,13 @@ export class DefaultConfig implements Config {
case UnitType.Train:
return {
cost: () => 0n,
- territoryBound: false,
experimental: true,
+ territoryBound: false,
};
default:
assertNever(type);
}
}
- /* eslint-enable sort-keys */
private costWrapper(
type: UnitType,
diff --git a/src/core/configuration/DevConfig.ts b/src/core/configuration/DevConfig.ts
index 6f20d5df69..3a14b39bba 100644
--- a/src/core/configuration/DevConfig.ts
+++ b/src/core/configuration/DevConfig.ts
@@ -1,8 +1,8 @@
-import { DefaultConfig, DefaultServerConfig } from "./DefaultConfig";
-import { GameEnv, ServerConfig } from "./Config";
import { UnitInfo, UnitType } from "../game/Game";
-import { GameConfig } from "../Schemas";
import { UserSettings } from "../game/UserSettings";
+import { GameConfig } from "../Schemas";
+import { GameEnv, ServerConfig } from "./Config";
+import { DefaultConfig, DefaultServerConfig } from "./DefaultConfig";
export class DevServerConfig extends DefaultServerConfig {
adminToken(): string {
diff --git a/src/core/configuration/PastelTheme.ts b/src/core/configuration/PastelTheme.ts
index 0c72cfe139..29964a26c1 100644
--- a/src/core/configuration/PastelTheme.ts
+++ b/src/core/configuration/PastelTheme.ts
@@ -1,10 +1,10 @@
import { Colord, colord } from "colord";
-import { GameMap, TileRef } from "../game/GameMap";
import { PlayerType, Team, TerrainType } from "../game/Game";
-import { botColors, fallbackColors, humanColors, nationColors } from "./Colors";
-import { ColorAllocator } from "./ColorAllocator";
+import { GameMap, TileRef } from "../game/GameMap";
import { PlayerView } from "../game/GameView";
import { PseudoRandom } from "../PseudoRandom";
+import { ColorAllocator } from "./ColorAllocator";
+import { botColors, fallbackColors, humanColors, nationColors } from "./Colors";
import { Theme } from "./Config";
type ColorCache = Map;
@@ -12,31 +12,38 @@ type ColorCache = Map;
export class PastelTheme implements Theme {
private readonly borderColorCache: ColorCache = new Map();
private readonly rand = new PseudoRandom(123);
- private readonly humanColorAllocator = new ColorAllocator(humanColors, fallbackColors);
+ private readonly humanColorAllocator = new ColorAllocator(
+ humanColors,
+ fallbackColors,
+ );
private readonly botColorAllocator = new ColorAllocator(botColors, botColors);
- private readonly teamColorAllocator = new ColorAllocator(humanColors, fallbackColors);
- private readonly nationColorAllocator = new ColorAllocator(nationColors, nationColors);
-
- /* eslint-disable sort-keys */
- private readonly background = colord({ r: 60, g: 60, b: 60 });
- private readonly shore = colord({ r: 204, g: 203, b: 158 });
+ private readonly teamColorAllocator = new ColorAllocator(
+ humanColors,
+ fallbackColors,
+ );
+ private readonly nationColorAllocator = new ColorAllocator(
+ nationColors,
+ nationColors,
+ );
+
+ private readonly background = colord({ b: 60, g: 60, r: 60 });
+ private readonly shore = colord({ b: 158, g: 203, r: 204 });
private readonly falloutColors = [
- colord({ r: 120, g: 255, b: 71 }), // Original color
- colord({ r: 130, g: 255, b: 85 }), // Slightly lighter
- colord({ r: 110, g: 245, b: 65 }), // Slightly darker
- colord({ r: 125, g: 255, b: 75 }), // Warmer tint
- colord({ r: 115, g: 250, b: 68 }), // Cooler tint
+ colord({ b: 71, g: 255, r: 120 }), // Original color
+ colord({ b: 85, g: 255, r: 130 }), // Slightly lighter
+ colord({ b: 65, g: 245, r: 110 }), // Slightly darker
+ colord({ b: 75, g: 255, r: 125 }), // Warmer tint
+ colord({ b: 68, g: 250, r: 115 }), // Cooler tint
];
- private readonly water = colord({ r: 70, g: 132, b: 180 });
- private readonly shorelineWater = colord({ r: 100, g: 143, b: 255 });
+ private readonly water = colord({ b: 180, g: 132, r: 70 });
+ private readonly shorelineWater = colord({ b: 255, g: 143, r: 100 });
- private readonly _selfColor = colord({ r: 0, g: 255, b: 0 });
- private readonly _allyColor = colord({ r: 255, g: 255, b: 0 });
- private readonly _neutralColor = colord({ r: 128, g: 128, b: 128 });
- private readonly _enemyColor = colord({ r: 255, g: 0, b: 0 });
+ private readonly _selfColor = colord({ b: 0, g: 255, r: 0 });
+ private readonly _allyColor = colord({ b: 0, g: 255, r: 255 });
+ private readonly _neutralColor = colord({ b: 128, g: 128, r: 128 });
+ private readonly _enemyColor = colord({ b: 0, g: 0, r: 255 });
- private readonly _spawnHighlightColor = colord({ r: 255, g: 213, b: 79 });
- /* eslint-enable sort-keys */
+ private readonly _spawnHighlightColor = colord({ b: 79, g: 213, r: 255 });
teamColor(team: Team): Colord {
return this.teamColorAllocator.assignTeamColor(team);
@@ -62,24 +69,23 @@ export class PastelTheme implements Theme {
specialBuildingColor(player: PlayerView): Colord {
const tc = this.territoryColor(player).rgba;
- /* eslint-disable sort-keys */
+
return colord({
- r: Math.max(tc.r - 50, 0),
- g: Math.max(tc.g - 50, 0),
b: Math.max(tc.b - 50, 0),
+ g: Math.max(tc.g - 50, 0),
+ r: Math.max(tc.r - 50, 0),
});
- /* eslint-enable sort-keys */
}
railroadColor(player: PlayerView): Colord {
const tc = this.territoryColor(player).rgba;
- /* eslint-disable sort-keys */
+
const color = colord({
- r: Math.max(tc.r - 10, 0),
- g: Math.max(tc.g - 10, 0),
b: Math.max(tc.b - 10, 0),
+ g: Math.max(tc.g - 10, 0),
+ r: Math.max(tc.r - 10, 0),
});
- /* eslint-enable sort-keys */
+
return color;
}
@@ -88,28 +94,26 @@ export class PastelTheme implements Theme {
if (cached !== undefined) return cached;
const tc = this.territoryColor(player).rgba;
- /* eslint-disable sort-keys */
+
const color = colord({
- r: Math.max(tc.r - 40, 0),
- g: Math.max(tc.g - 40, 0),
b: Math.max(tc.b - 40, 0),
+ g: Math.max(tc.g - 40, 0),
+ r: Math.max(tc.r - 40, 0),
});
- /* eslint-enable sort-keys */
this.borderColorCache.set(player.id(), color);
return color;
}
- /* eslint-disable sort-keys */
defendedBorderColors(player: PlayerView): { light: Colord; dark: Colord } {
return {
- light: this.territoryColor(player).darken(0.2),
dark: this.territoryColor(player).darken(0.4),
+ light: this.territoryColor(player).darken(0.2),
};
}
focusedBorderColor(): Colord {
- return colord({ r: 230, g: 230, b: 230 });
+ return colord({ b: 230, g: 230, r: 230 });
}
terrainColor(gm: GameMap, tile: TileRef): Colord {
@@ -125,32 +129,31 @@ export class PastelTheme implements Theme {
return this.shorelineWater;
}
return colord({
- r: Math.max(w.r - 10 + (11 - Math.min(mag, 10)), 0),
- g: Math.max(w.g - 10 + (11 - Math.min(mag, 10)), 0),
b: Math.max(w.b - 10 + (11 - Math.min(mag, 10)), 0),
+ g: Math.max(w.g - 10 + (11 - Math.min(mag, 10)), 0),
+ r: Math.max(w.r - 10 + (11 - Math.min(mag, 10)), 0),
});
case TerrainType.Plains:
return colord({
- r: 190,
- g: 220 - 2 * mag,
b: 138,
+ g: 220 - 2 * mag,
+ r: 190,
});
case TerrainType.Highland:
return colord({
- r: 200 + 2 * mag,
- g: 183 + 2 * mag,
b: 138 + 2 * mag,
+ g: 183 + 2 * mag,
+ r: 200 + 2 * mag,
});
case TerrainType.Mountain:
return colord({
- r: 230 + mag / 2,
- g: 230 + mag / 2,
b: 230 + mag / 2,
+ g: 230 + mag / 2,
+ r: 230 + mag / 2,
});
}
}
- /* eslint-enable sort-keys */
backgroundColor(): Colord {
return this.background;
diff --git a/src/core/configuration/PastelThemeDark.ts b/src/core/configuration/PastelThemeDark.ts
index cfed90ba55..9d12b5d946 100644
--- a/src/core/configuration/PastelThemeDark.ts
+++ b/src/core/configuration/PastelThemeDark.ts
@@ -1,10 +1,10 @@
import { Colord, colord } from "colord";
-import { GameMap, TileRef } from "../game/GameMap";
import { PlayerType, Team, TerrainType } from "../game/Game";
-import { botColors, fallbackColors, humanColors, nationColors } from "./Colors";
-import { ColorAllocator } from "./ColorAllocator";
+import { GameMap, TileRef } from "../game/GameMap";
import { PlayerView } from "../game/GameView";
import { PseudoRandom } from "../PseudoRandom";
+import { ColorAllocator } from "./ColorAllocator";
+import { botColors, fallbackColors, humanColors, nationColors } from "./Colors";
import { Theme } from "./Config";
type ColorCache = Map;
@@ -12,31 +12,38 @@ type ColorCache = Map;
export class PastelThemeDark implements Theme {
private readonly borderColorCache: ColorCache = new Map();
private readonly rand = new PseudoRandom(123);
- private readonly humanColorAllocator = new ColorAllocator(humanColors, fallbackColors);
+ private readonly humanColorAllocator = new ColorAllocator(
+ humanColors,
+ fallbackColors,
+ );
private readonly botColorAllocator = new ColorAllocator(botColors, botColors);
- private readonly teamColorAllocator = new ColorAllocator(humanColors, fallbackColors);
- private readonly nationColorAllocator = new ColorAllocator(nationColors, nationColors);
-
- /* eslint-disable sort-keys */
- private readonly background = colord({ r: 0, g: 0, b: 0 });
- private readonly shore = colord({ r: 134, g: 133, b: 88 });
+ private readonly teamColorAllocator = new ColorAllocator(
+ humanColors,
+ fallbackColors,
+ );
+ private readonly nationColorAllocator = new ColorAllocator(
+ nationColors,
+ nationColors,
+ );
+
+ private readonly background = colord({ b: 0, g: 0, r: 0 });
+ private readonly shore = colord({ b: 88, g: 133, r: 134 });
private readonly falloutColors = [
- colord({ r: 120, g: 255, b: 71 }), // Original color
- colord({ r: 130, g: 255, b: 85 }), // Slightly lighter
- colord({ r: 110, g: 245, b: 65 }), // Slightly darker
- colord({ r: 125, g: 255, b: 75 }), // Warmer tint
- colord({ r: 115, g: 250, b: 68 }), // Cooler tint
+ colord({ b: 71, g: 255, r: 120 }), // Original color
+ colord({ b: 85, g: 255, r: 130 }), // Slightly lighter
+ colord({ b: 65, g: 245, r: 110 }), // Slightly darker
+ colord({ b: 75, g: 255, r: 125 }), // Warmer tint
+ colord({ b: 68, g: 250, r: 115 }), // Cooler tint
];
- private readonly water = colord({ r: 14, g: 11, b: 30 });
- private readonly shorelineWater = colord({ r: 50, g: 50, b: 50 });
+ private readonly water = colord({ b: 30, g: 11, r: 14 });
+ private readonly shorelineWater = colord({ b: 50, g: 50, r: 50 });
- private readonly _selfColor = colord({ r: 0, g: 255, b: 0 });
- private readonly _allyColor = colord({ r: 255, g: 255, b: 0 });
- private readonly _neutralColor = colord({ r: 128, g: 128, b: 128 });
- private readonly _enemyColor = colord({ r: 255, g: 0, b: 0 });
+ private readonly _selfColor = colord({ b: 0, g: 255, r: 0 });
+ private readonly _allyColor = colord({ b: 0, g: 255, r: 255 });
+ private readonly _neutralColor = colord({ b: 128, g: 128, r: 128 });
+ private readonly _enemyColor = colord({ b: 0, g: 0, r: 255 });
- private readonly _spawnHighlightColor = colord({ r: 255, g: 213, b: 79 });
- /* eslint-enable sort-keys */
+ private readonly _spawnHighlightColor = colord({ b: 79, g: 213, r: 255 });
teamColor(team: Team): Colord {
return this.teamColorAllocator.assignTeamColor(team);
@@ -60,22 +67,21 @@ export class PastelThemeDark implements Theme {
return player.type() === PlayerType.Human ? "#ffffff" : "#e6e6e6";
}
- /* eslint-disable sort-keys */
specialBuildingColor(player: PlayerView): Colord {
const tc = this.territoryColor(player).rgba;
return colord({
- r: Math.max(tc.r - 50, 0),
- g: Math.max(tc.g - 50, 0),
b: Math.max(tc.b - 50, 0),
+ g: Math.max(tc.g - 50, 0),
+ r: Math.max(tc.r - 50, 0),
});
}
railroadColor(player: PlayerView): Colord {
const tc = this.territoryColor(player).rgba;
const color = colord({
- r: Math.max(tc.r - 10, 0),
- g: Math.max(tc.g - 10, 0),
b: Math.max(tc.b - 10, 0),
+ g: Math.max(tc.g - 10, 0),
+ r: Math.max(tc.r - 10, 0),
});
return color;
}
@@ -86,9 +92,9 @@ export class PastelThemeDark implements Theme {
const tc = this.territoryColor(player).rgba;
const color = colord({
- r: Math.max(tc.r - 40, 0),
- g: Math.max(tc.g - 40, 0),
b: Math.max(tc.b - 40, 0),
+ g: Math.max(tc.g - 40, 0),
+ r: Math.max(tc.r - 40, 0),
});
this.borderColorCache.set(player.id(), color);
@@ -97,13 +103,13 @@ export class PastelThemeDark implements Theme {
defendedBorderColors(player: PlayerView): { light: Colord; dark: Colord } {
return {
- light: this.territoryColor(player).darken(0.2),
dark: this.territoryColor(player).darken(0.4),
+ light: this.territoryColor(player).darken(0.2),
};
}
focusedBorderColor(): Colord {
- return colord({ r: 255, g: 255, b: 255 });
+ return colord({ b: 255, g: 255, r: 255 });
}
terrainColor(gm: GameMap, tile: TileRef): Colord {
@@ -120,33 +126,32 @@ export class PastelThemeDark implements Theme {
}
if (gm.magnitude(tile) < 10) {
return colord({
- r: Math.max(w.r + 9 - mag, 0),
- g: Math.max(w.g + 9 - mag, 0),
b: Math.max(w.b + 9 - mag, 0),
+ g: Math.max(w.g + 9 - mag, 0),
+ r: Math.max(w.r + 9 - mag, 0),
});
}
return this.water;
case TerrainType.Plains:
return colord({
- r: 140,
- g: 170 - 2 * mag,
b: 88,
+ g: 170 - 2 * mag,
+ r: 140,
});
case TerrainType.Highland:
return colord({
- r: 150 + 2 * mag,
- g: 133 + 2 * mag,
b: 88 + 2 * mag,
+ g: 133 + 2 * mag,
+ r: 150 + 2 * mag,
});
case TerrainType.Mountain:
return colord({
- r: 180 + mag / 2,
- g: 180 + mag / 2,
b: 180 + mag / 2,
+ g: 180 + mag / 2,
+ r: 180 + mag / 2,
});
}
}
- /* eslint-enable sort-keys */
backgroundColor(): Colord {
return this.background;
diff --git a/src/core/configuration/PreprodConfig.ts b/src/core/configuration/PreprodConfig.ts
index 75467cecb0..a0567aaa98 100644
--- a/src/core/configuration/PreprodConfig.ts
+++ b/src/core/configuration/PreprodConfig.ts
@@ -1,5 +1,5 @@
-import { DefaultServerConfig } from "./DefaultConfig";
import { GameEnv } from "./Config";
+import { DefaultServerConfig } from "./DefaultConfig";
export const preprodConfig = new (class extends DefaultServerConfig {
env(): GameEnv {
diff --git a/src/core/configuration/ProdConfig.ts b/src/core/configuration/ProdConfig.ts
index 24a6719332..7bea841a84 100644
--- a/src/core/configuration/ProdConfig.ts
+++ b/src/core/configuration/ProdConfig.ts
@@ -1,5 +1,5 @@
-import { DefaultServerConfig } from "./DefaultConfig";
import { GameEnv } from "./Config";
+import { DefaultServerConfig } from "./DefaultConfig";
export const prodConfig = new (class extends DefaultServerConfig {
numWorkers(): number {
diff --git a/src/core/execution/AttackExecution.ts b/src/core/execution/AttackExecution.ts
index 44bddccda0..0991a1e2b8 100644
--- a/src/core/execution/AttackExecution.ts
+++ b/src/core/execution/AttackExecution.ts
@@ -1,3 +1,4 @@
+import { renderTroops } from "../../client/Utils";
import {
Attack,
Execution,
@@ -6,13 +7,12 @@ import {
Player,
PlayerID,
PlayerType,
- TerraNullius,
TerrainType,
+ TerraNullius,
} from "../game/Game";
-import { FlatBinaryHeap } from "./utils/FlatBinaryHeap"; // adjust path if needed
-import { PseudoRandom } from "../PseudoRandom";
import { TileRef } from "../game/GameMap";
-import { renderTroops } from "../../client/Utils";
+import { PseudoRandom } from "../PseudoRandom";
+import { FlatBinaryHeap } from "./utils/FlatBinaryHeap"; // adjust path if needed
const malusForRetreat = 25;
export class AttackExecution implements Execution {
@@ -209,7 +209,9 @@ export class AttackExecution implements Execution {
throw new Error("Attack not initialized");
}
let troopCount = this.attack.troops(); // cache troop count
- const targetPlayer: Player | null = this.target.isPlayer() ? this.target : null; // cache target player
+ const targetPlayer: Player | null = this.target.isPlayer()
+ ? this.target
+ : null; // cache target player
if (this.attack.retreated()) {
if (targetPlayer !== null) {
@@ -230,9 +232,10 @@ export class AttackExecution implements Execution {
return;
}
- const alliance = this.target && this.target.isPlayer()
- ? this._owner.allianceWith(this.target)
- : null;
+ const alliance =
+ this.target && this.target.isPlayer()
+ ? this._owner.allianceWith(this.target)
+ : null;
if (this.breakAlliance && alliance !== null) {
this.breakAlliance = false;
this._owner.breakAlliance(alliance);
diff --git a/src/core/execution/BotExecution.ts b/src/core/execution/BotExecution.ts
index 75d8436324..f1685ddbb8 100644
--- a/src/core/execution/BotExecution.ts
+++ b/src/core/execution/BotExecution.ts
@@ -1,7 +1,7 @@
import { Execution, Game, Player } from "../game/Game";
-import { BotBehavior } from "./utils/BotBehavior";
import { PseudoRandom } from "../PseudoRandom";
import { simpleHash } from "../Util";
+import { BotBehavior } from "./utils/BotBehavior";
export class BotExecution implements Execution {
private active = true;
diff --git a/src/core/execution/BotSpawner.ts b/src/core/execution/BotSpawner.ts
index a0e9eeaafe..67b13eb95c 100644
--- a/src/core/execution/BotSpawner.ts
+++ b/src/core/execution/BotSpawner.ts
@@ -1,10 +1,10 @@
-import { BOT_NAME_PREFIXES, BOT_NAME_SUFFIXES } from "./utils/BotNames";
import { Game, PlayerInfo, PlayerType } from "../game/Game";
-import { GameID } from "../Schemas";
-import { PseudoRandom } from "../PseudoRandom";
-import { SpawnExecution } from "./SpawnExecution";
import { TileRef } from "../game/GameMap";
+import { PseudoRandom } from "../PseudoRandom";
+import { GameID } from "../Schemas";
import { simpleHash } from "../Util";
+import { SpawnExecution } from "./SpawnExecution";
+import { BOT_NAME_PREFIXES, BOT_NAME_SUFFIXES } from "./utils/BotNames";
export class BotSpawner {
private readonly random: PseudoRandom;
diff --git a/src/core/execution/ConstructionExecution.ts b/src/core/execution/ConstructionExecution.ts
index 033505ff4e..9f08a660c4 100644
--- a/src/core/execution/ConstructionExecution.ts
+++ b/src/core/execution/ConstructionExecution.ts
@@ -7,6 +7,7 @@ import {
Unit,
UnitType,
} from "../game/Game";
+import { TileRef } from "../game/GameMap";
import { CityExecution } from "./CityExecution";
import { DefensePostExecution } from "./DefensePostExecution";
import { FactoryExecution } from "./FactoryExecution";
@@ -15,7 +16,6 @@ import { MissileSiloExecution } from "./MissileSiloExecution";
import { NukeExecution } from "./NukeExecution";
import { PortExecution } from "./PortExecution";
import { SAMLauncherExecution } from "./SAMLauncherExecution";
-import { TileRef } from "../game/GameMap";
import { WarshipExecution } from "./WarshipExecution";
export class ConstructionExecution implements Execution {
@@ -97,7 +97,8 @@ export class ConstructionExecution implements Execution {
this.active = false;
return;
}
- if (this.ticksUntilComplete === undefined) throw new Error("Not initialized");
+ if (this.ticksUntilComplete === undefined)
+ throw new Error("Not initialized");
this.ticksUntilComplete--;
}
diff --git a/src/core/execution/DefensePostExecution.ts b/src/core/execution/DefensePostExecution.ts
index 62243c3fcd..0cb2a99694 100644
--- a/src/core/execution/DefensePostExecution.ts
+++ b/src/core/execution/DefensePostExecution.ts
@@ -1,6 +1,6 @@
import { Execution, Game, Player, Unit, UnitType } from "../game/Game";
-import { ShellExecution } from "./ShellExecution";
import { TileRef } from "../game/GameMap";
+import { ShellExecution } from "./ShellExecution";
export class DefensePostExecution implements Execution {
private mg: Game | undefined;
diff --git a/src/core/execution/ExecutionManager.ts b/src/core/execution/ExecutionManager.ts
index 122448eda7..11c76fafa2 100644
--- a/src/core/execution/ExecutionManager.ts
+++ b/src/core/execution/ExecutionManager.ts
@@ -1,12 +1,14 @@
-import { ClientID, GameID, Intent, Turn } from "../Schemas";
import { Execution, Game } from "../game/Game";
+import { PseudoRandom } from "../PseudoRandom";
+import { ClientID, GameID, Intent, Turn } from "../Schemas";
+import { simpleHash } from "../Util";
+import { AttackExecution } from "./AttackExecution";
import { AllianceExtensionExecution } from "./alliance/AllianceExtensionExecution";
import { AllianceRequestExecution } from "./alliance/AllianceRequestExecution";
import { AllianceRequestReplyExecution } from "./alliance/AllianceRequestReplyExecution";
-import { AttackExecution } from "./AttackExecution";
+import { BreakAllianceExecution } from "./alliance/BreakAllianceExecution";
import { BoatRetreatExecution } from "./BoatRetreatExecution";
import { BotSpawner } from "./BotSpawner";
-import { BreakAllianceExecution } from "./alliance/BreakAllianceExecution";
import { ConstructionExecution } from "./ConstructionExecution";
import { DeleteUnitExecution } from "./DeleteUnitExecution";
import { DonateGoldExecution } from "./DonateGoldExecution";
@@ -17,14 +19,12 @@ import { FakeHumanExecution } from "./FakeHumanExecution";
import { MarkDisconnectedExecution } from "./MarkDisconnectedExecution";
import { MoveWarshipExecution } from "./MoveWarshipExecution";
import { NoOpExecution } from "./NoOpExecution";
-import { PseudoRandom } from "../PseudoRandom";
import { QuickChatExecution } from "./QuickChatExecution";
import { RetreatExecution } from "./RetreatExecution";
import { SpawnExecution } from "./SpawnExecution";
import { TargetPlayerExecution } from "./TargetPlayerExecution";
import { TransportShipExecution } from "./TransportShipExecution";
import { UpgradeStructureExecution } from "./UpgradeStructureExecution";
-import { simpleHash } from "../Util";
export class Executor {
// private random = new PseudoRandom(999)
diff --git a/src/core/execution/FakeHumanExecution.ts b/src/core/execution/FakeHumanExecution.ts
index dac000a3d9..c266cf129d 100644
--- a/src/core/execution/FakeHumanExecution.ts
+++ b/src/core/execution/FakeHumanExecution.ts
@@ -14,17 +14,17 @@ import {
Unit,
UnitType,
} from "../game/Game";
-import { TileRef, euclDistFN, manhattanDistFN } from "../game/GameMap";
+import { euclDistFN, manhattanDistFN, TileRef } from "../game/GameMap";
+import { PseudoRandom } from "../PseudoRandom";
+import { GameID } from "../Schemas";
import { calculateBoundingBox, flattenedEmojiTable, simpleHash } from "../Util";
-import { BotBehavior } from "./utils/BotBehavior";
import { ConstructionExecution } from "./ConstructionExecution";
import { EmojiExecution } from "./EmojiExecution";
-import { GameID } from "../Schemas";
import { NukeExecution } from "./NukeExecution";
-import { PseudoRandom } from "../PseudoRandom";
import { SpawnExecution } from "./SpawnExecution";
import { TransportShipExecution } from "./TransportShipExecution";
import { closestTwoTiles } from "./Util";
+import { BotBehavior } from "./utils/BotBehavior";
export class FakeHumanExecution implements Execution {
private active = true;
@@ -174,8 +174,7 @@ export class FakeHumanExecution implements Execution {
const enemyborder = Array.from(this.player.borderTiles())
.flatMap((t) => game.neighbors(t))
.filter(
- (t) =>
- game.isLand(t) && game.ownerID(t) !== this.player?.smallID(),
+ (t) => game.isLand(t) && game.ownerID(t) !== this.player?.smallID(),
);
if (enemyborder.length === 0) {
@@ -306,7 +305,9 @@ export class FakeHumanExecution implements Execution {
UnitType.SAMLauncher,
);
const structureTiles = structures.map((u) => u.tile());
- const randomTiles: (TileRef | null)[] = new Array(10).fill(null);
+ const randomTiles: (TileRef | null)[] = new Array(10).fill(
+ null,
+ );
for (let i = 0; i < randomTiles.length; i++) {
randomTiles[i] = this.randTerritoryTile(other);
}
@@ -413,7 +414,9 @@ export class FakeHumanExecution implements Execution {
if (this.player.isOnSameTeam(other)) return;
const closest = closestTwoTiles(
this.mg,
- Array.from(this.player.borderTiles()).filter((t) => this.mg?.isOceanShore(t)),
+ Array.from(this.player.borderTiles()).filter((t) =>
+ this.mg?.isOceanShore(t),
+ ),
Array.from(other.borderTiles()).filter((t) => this.mg?.isOceanShore(t)),
);
if (closest === null) {
@@ -467,8 +470,8 @@ export class FakeHumanExecution implements Execution {
const tiles =
type === UnitType.Port
? Array.from(this.player.borderTiles()).filter((t) =>
- this.mg?.isOceanShore(t),
- )
+ this.mg?.isOceanShore(t),
+ )
: Array.from(this.player.tiles());
if (tiles.length === 0) return null;
const valueFunction = this.structureSpawnTileValue(type);
@@ -486,7 +489,7 @@ export class FakeHumanExecution implements Execution {
return bestTile;
}
- private * arraySampler(a: T[], sampleSize = 50): Generator {
+ private *arraySampler(a: T[], sampleSize = 50): Generator {
if (a.length <= sampleSize) {
// Return all elements
yield* a;
@@ -508,7 +511,9 @@ export class FakeHumanExecution implements Execution {
const { mg } = this;
const otherUnits = this.player.units(type);
// Prefer spacing structures out of atom bomb range
- const borderSpacing = this.mg.config().nukeMagnitudes(UnitType.AtomBomb).outer;
+ const borderSpacing = this.mg
+ .config()
+ .nukeMagnitudes(UnitType.AtomBomb).outer;
const structureSpacing = borderSpacing * 2;
switch (type) {
case UnitType.Port:
@@ -516,7 +521,9 @@ export class FakeHumanExecution implements Execution {
let w = 0;
// Prefer to be far away from other structures of the same type
- const otherTiles: Set = new Set(otherUnits.map((u) => u.tile()));
+ const otherTiles: Set = new Set(
+ otherUnits.map((u) => u.tile()),
+ );
otherTiles.delete(tile);
const closestOther = closestTwoTiles(mg, otherTiles, [tile]);
if (closestOther !== null) {
@@ -543,7 +550,9 @@ export class FakeHumanExecution implements Execution {
}
// Prefer to be away from other structures of the same type
- const otherTiles: Set = new Set(otherUnits.map((u) => u.tile()));
+ const otherTiles: Set = new Set(
+ otherUnits.map((u) => u.tile()),
+ );
otherTiles.delete(tile);
const closestOther = closestTwoTiles(mg, otherTiles, [tile]);
if (closestOther !== null) {
diff --git a/src/core/execution/MIRVExecution.ts b/src/core/execution/MIRVExecution.ts
index 6360ba826e..5067d66d31 100644
--- a/src/core/execution/MIRVExecution.ts
+++ b/src/core/execution/MIRVExecution.ts
@@ -7,11 +7,11 @@ import {
Unit,
UnitType,
} from "../game/Game";
-import { NukeExecution } from "./NukeExecution";
-import { ParabolaPathFinder } from "../pathfinding/PathFinding";
-import { PseudoRandom } from "../PseudoRandom";
import { TileRef } from "../game/GameMap";
+import { PseudoRandom } from "../PseudoRandom";
+import { ParabolaPathFinder } from "../pathfinding/PathFinding";
import { simpleHash } from "../Util";
+import { NukeExecution } from "./NukeExecution";
export class MirvExecution implements Execution {
private active = true;
diff --git a/src/core/execution/NukeExecution.ts b/src/core/execution/NukeExecution.ts
index 575cbaf866..6020e78125 100644
--- a/src/core/execution/NukeExecution.ts
+++ b/src/core/execution/NukeExecution.ts
@@ -1,18 +1,18 @@
import {
Execution,
Game,
+ isStructureType,
MessageType,
Player,
TerraNullius,
TrajectoryTile,
Unit,
UnitType,
- isStructureType,
} from "../game/Game";
-import { NukeType } from "../StatsSchemas";
-import { ParabolaPathFinder } from "../pathfinding/PathFinding";
-import { PseudoRandom } from "../PseudoRandom";
import { TileRef } from "../game/GameMap";
+import { PseudoRandom } from "../PseudoRandom";
+import { ParabolaPathFinder } from "../pathfinding/PathFinding";
+import { NukeType } from "../StatsSchemas";
const SPRITE_RADIUS = 16;
diff --git a/src/core/execution/PlayerExecution.ts b/src/core/execution/PlayerExecution.ts
index 457a79222f..f8945adea9 100644
--- a/src/core/execution/PlayerExecution.ts
+++ b/src/core/execution/PlayerExecution.ts
@@ -1,8 +1,8 @@
+import { Config } from "../configuration/Config";
import { Execution, Game, Player, UnitType } from "../game/Game";
+import { GameImpl } from "../game/GameImpl";
import { GameMap, TileRef } from "../game/GameMap";
import { calculateBoundingBox, getMode, inscribed, simpleHash } from "../Util";
-import { Config } from "../configuration/Config";
-import { GameImpl } from "../game/GameImpl";
export class PlayerExecution implements Execution {
private readonly ticksPerClusterCalc = 20;
diff --git a/src/core/execution/PortExecution.ts b/src/core/execution/PortExecution.ts
index 5c7dfc566c..7dcff805dc 100644
--- a/src/core/execution/PortExecution.ts
+++ b/src/core/execution/PortExecution.ts
@@ -1,6 +1,6 @@
import { Execution, Game, Player, Unit, UnitType } from "../game/Game";
-import { PseudoRandom } from "../PseudoRandom";
import { TileRef } from "../game/GameMap";
+import { PseudoRandom } from "../PseudoRandom";
import { TradeShipExecution } from "./TradeShipExecution";
import { TrainStationExecution } from "./TrainStationExecution";
diff --git a/src/core/execution/RailroadExecution.ts b/src/core/execution/RailroadExecution.ts
index 33ddaa8049..1f3bc8d29e 100644
--- a/src/core/execution/RailroadExecution.ts
+++ b/src/core/execution/RailroadExecution.ts
@@ -1,7 +1,7 @@
import { Execution, Game } from "../game/Game";
+import { TileRef } from "../game/GameMap";
import { GameUpdateType, RailTile, RailType } from "../game/GameUpdates";
import { Railroad } from "../game/Railroad";
-import { TileRef } from "../game/GameMap";
export class RailroadExecution implements Execution {
private mg: Game | undefined;
@@ -18,17 +18,16 @@ export class RailroadExecution implements Execution {
return this.active;
}
- /* eslint-disable sort-keys */
init(mg: Game, ticks: number): void {
this.mg = mg;
const { tiles } = this.railRoad;
// Inverse direction computation for the first tile
this.railTiles.push({
- tile: tiles[0],
railType:
tiles.length > 0
? this.computeExtremityDirection(tiles[0], tiles[1])
: RailType.VERTICAL,
+ tile: tiles[0],
});
for (let i = 1; i < tiles.length - 1; i++) {
const direction = this.computeDirection(
@@ -36,20 +35,19 @@ export class RailroadExecution implements Execution {
tiles[i],
tiles[i + 1],
);
- this.railTiles.push({ tile: tiles[i], railType: direction });
+ this.railTiles.push({ railType: direction, tile: tiles[i] });
}
this.railTiles.push({
- tile: tiles[tiles.length - 1],
railType:
tiles.length > 0
? this.computeExtremityDirection(
- tiles[tiles.length - 1],
- tiles[tiles.length - 2],
- )
+ tiles[tiles.length - 1],
+ tiles[tiles.length - 2],
+ )
: RailType.VERTICAL,
+ tile: tiles[tiles.length - 1],
});
}
- /* eslint-enable sort-keys */
private computeExtremityDirection(tile: TileRef, next: TileRef): RailType {
if (this.mg === undefined) throw new Error("Not initialized");
diff --git a/src/core/execution/SAMLauncherExecution.ts b/src/core/execution/SAMLauncherExecution.ts
index 744021ce3e..ef1b5fdfa1 100644
--- a/src/core/execution/SAMLauncherExecution.ts
+++ b/src/core/execution/SAMLauncherExecution.ts
@@ -1,15 +1,15 @@
import {
Execution,
Game,
+ isUnit,
MessageType,
Player,
Unit,
UnitType,
- isUnit,
} from "../game/Game";
+import { TileRef } from "../game/GameMap";
import { PseudoRandom } from "../PseudoRandom";
import { SAMMissileExecution } from "./SAMMissileExecution";
-import { TileRef } from "../game/GameMap";
type Target = {
unit: Unit;
@@ -97,8 +97,7 @@ class SAMTargetingSystem {
}
const interceptionTile = this.computeInterceptionTile(nuke.unit);
if (interceptionTile !== undefined) {
- // eslint-disable-next-line sort-keys
- targets.push({ unit: nuke.unit, tile: interceptionTile });
+ targets.push({ tile: interceptionTile, unit: nuke.unit });
} else {
// Store unreachable nukes in order to prevent useless interception computation
this.storeUnreachableNukes(nuke.unit.id());
diff --git a/src/core/execution/SAMMissileExecution.ts b/src/core/execution/SAMMissileExecution.ts
index 0b598f072b..8ca029f79e 100644
--- a/src/core/execution/SAMMissileExecution.ts
+++ b/src/core/execution/SAMMissileExecution.ts
@@ -6,10 +6,10 @@ import {
Unit,
UnitType,
} from "../game/Game";
+import { TileRef } from "../game/GameMap";
+import { PseudoRandom } from "../PseudoRandom";
import { AirPathFinder } from "../pathfinding/PathFinding";
import { NukeType } from "../StatsSchemas";
-import { PseudoRandom } from "../PseudoRandom";
-import { TileRef } from "../game/GameMap";
export class SAMMissileExecution implements Execution {
private active = true;
diff --git a/src/core/execution/ShellExecution.ts b/src/core/execution/ShellExecution.ts
index 3573a0690a..3abc1e63e4 100644
--- a/src/core/execution/ShellExecution.ts
+++ b/src/core/execution/ShellExecution.ts
@@ -1,7 +1,7 @@
import { Execution, Game, Player, Unit, UnitType } from "../game/Game";
-import { AirPathFinder } from "../pathfinding/PathFinding";
-import { PseudoRandom } from "../PseudoRandom";
import { TileRef } from "../game/GameMap";
+import { PseudoRandom } from "../PseudoRandom";
+import { AirPathFinder } from "../pathfinding/PathFinding";
export class ShellExecution implements Execution {
private active = true;
diff --git a/src/core/execution/SpawnExecution.ts b/src/core/execution/SpawnExecution.ts
index 3ed33dd38d..3eac33ca14 100644
--- a/src/core/execution/SpawnExecution.ts
+++ b/src/core/execution/SpawnExecution.ts
@@ -1,7 +1,7 @@
import { Execution, Game, Player, PlayerInfo, PlayerType } from "../game/Game";
+import { TileRef } from "../game/GameMap";
import { BotExecution } from "./BotExecution";
import { PlayerExecution } from "./PlayerExecution";
-import { TileRef } from "../game/GameMap";
import { getSpawnTiles } from "./Util";
export class SpawnExecution implements Execution {
diff --git a/src/core/execution/TradeShipExecution.ts b/src/core/execution/TradeShipExecution.ts
index 04e9fbbc7e..3815b35c3a 100644
--- a/src/core/execution/TradeShipExecution.ts
+++ b/src/core/execution/TradeShipExecution.ts
@@ -1,3 +1,4 @@
+import { renderNumber } from "../../client/Utils";
import {
Execution,
Game,
@@ -6,11 +7,10 @@ import {
Unit,
UnitType,
} from "../game/Game";
+import { TileRef } from "../game/GameMap";
import { PathFindResultType } from "../pathfinding/AStar";
import { PathFinder } from "../pathfinding/PathFinding";
-import { TileRef } from "../game/GameMap";
import { distSortUnit } from "../Util";
-import { renderNumber } from "../../client/Utils";
export class TradeShipExecution implements Execution {
private active = true;
diff --git a/src/core/execution/TrainExecution.ts b/src/core/execution/TrainExecution.ts
index 2fafd2af31..707c6a3bbf 100644
--- a/src/core/execution/TrainExecution.ts
+++ b/src/core/execution/TrainExecution.ts
@@ -6,9 +6,9 @@ import {
Unit,
UnitType,
} from "../game/Game";
-import { OrientedRailroad, getOrientedRailroad } from "../game/Railroad";
-import { RailNetwork } from "../game/RailNetwork";
import { TileRef } from "../game/GameMap";
+import { RailNetwork } from "../game/RailNetwork";
+import { getOrientedRailroad, OrientedRailroad } from "../game/Railroad";
import { TrainStation } from "../game/TrainStation";
export class TrainExecution implements Execution {
diff --git a/src/core/execution/TrainStationExecution.ts b/src/core/execution/TrainStationExecution.ts
index 163a73bad4..b77ee962e4 100644
--- a/src/core/execution/TrainStationExecution.ts
+++ b/src/core/execution/TrainStationExecution.ts
@@ -1,7 +1,7 @@
import { Execution, Game, Unit } from "../game/Game";
+import { TrainStation } from "../game/TrainStation";
import { PseudoRandom } from "../PseudoRandom";
import { TrainExecution } from "./TrainExecution";
-import { TrainStation } from "../game/TrainStation";
export class TrainStationExecution implements Execution {
private mg: Game | undefined;
diff --git a/src/core/execution/TransportShipExecution.ts b/src/core/execution/TransportShipExecution.ts
index 4862d53af4..5ed3938aef 100644
--- a/src/core/execution/TransportShipExecution.ts
+++ b/src/core/execution/TransportShipExecution.ts
@@ -8,11 +8,11 @@ import {
Unit,
UnitType,
} from "../game/Game";
-import { AttackExecution } from "./AttackExecution";
-import { PathFindResultType } from "../pathfinding/AStar";
-import { PathFinder } from "../pathfinding/PathFinding";
import { TileRef } from "../game/GameMap";
import { targetTransportTile } from "../game/TransportShipUtils";
+import { PathFindResultType } from "../pathfinding/AStar";
+import { PathFinder } from "../pathfinding/PathFinding";
+import { AttackExecution } from "./AttackExecution";
export class TransportShipExecution implements Execution {
private lastMove: number | undefined;
diff --git a/src/core/execution/Util.ts b/src/core/execution/Util.ts
index 302ea00006..f1b6e87eb5 100644
--- a/src/core/execution/Util.ts
+++ b/src/core/execution/Util.ts
@@ -1,4 +1,4 @@
-import { GameMap, TileRef, euclDistFN } from "../game/GameMap";
+import { euclDistFN, GameMap, TileRef } from "../game/GameMap";
export function getSpawnTiles(gm: GameMap, tile: TileRef): TileRef[] {
return Array.from(gm.bfs(tile, euclDistFN(tile, 4, true))).filter(
diff --git a/src/core/execution/WarshipExecution.ts b/src/core/execution/WarshipExecution.ts
index 2ba6dacfc4..6ba5ba0564 100644
--- a/src/core/execution/WarshipExecution.ts
+++ b/src/core/execution/WarshipExecution.ts
@@ -1,17 +1,17 @@
import {
Execution,
Game,
+ isUnit,
OwnerComp,
Unit,
UnitParams,
UnitType,
- isUnit,
} from "../game/Game";
+import { TileRef } from "../game/GameMap";
+import { PseudoRandom } from "../PseudoRandom";
import { PathFindResultType } from "../pathfinding/AStar";
import { PathFinder } from "../pathfinding/PathFinding";
-import { PseudoRandom } from "../PseudoRandom";
import { ShellExecution } from "./ShellExecution";
-import { TileRef } from "../game/GameMap";
export class WarshipExecution implements Execution {
private random: PseudoRandom | undefined;
@@ -108,10 +108,8 @@ export class WarshipExecution implements Execution {
const patrolTile = this.warship.patrolTile();
if (
patrolTile !== undefined &&
- this.mg.euclideanDistSquared(
- patrolTile,
- unit.tile(),
- ) > patrolRangeSquared
+ this.mg.euclideanDistSquared(patrolTile, unit.tile()) >
+ patrolRangeSquared
) {
// Prevent warship from chasing trade ship that is too far away from
// the patrol tile to prevent warships from wandering around the map.
@@ -224,10 +222,7 @@ export class WarshipExecution implements Execution {
return;
}
}
- const result = this.pathfinder.nextTile(
- this.warship.tile(),
- targetTile,
- );
+ const result = this.pathfinder.nextTile(this.warship.tile(), targetTile);
switch (result.type) {
case PathFindResultType.Completed:
this.warship.setTargetTile(undefined);
diff --git a/src/core/execution/WinCheckExecution.ts b/src/core/execution/WinCheckExecution.ts
index 996cc45273..8c2159a71c 100644
--- a/src/core/execution/WinCheckExecution.ts
+++ b/src/core/execution/WinCheckExecution.ts
@@ -1,3 +1,4 @@
+import { GameEvent } from "../EventBus";
import {
ColoredTeams,
Execution,
@@ -6,7 +7,6 @@ import {
Player,
Team,
} from "../game/Game";
-import { GameEvent } from "../EventBus";
export class WinEvent implements GameEvent {
constructor(public readonly winner: Player) {}
diff --git a/src/core/execution/utils/BotBehavior.ts b/src/core/execution/utils/BotBehavior.ts
index 76497968c7..2c7f6057cb 100644
--- a/src/core/execution/utils/BotBehavior.ts
+++ b/src/core/execution/utils/BotBehavior.ts
@@ -7,11 +7,11 @@ import {
TerraNullius,
Tick,
} from "../../game/Game";
-import { AllianceExtensionExecution } from "../alliance/AllianceExtensionExecution";
-import { AttackExecution } from "../AttackExecution";
-import { EmojiExecution } from "../EmojiExecution";
import { PseudoRandom } from "../../PseudoRandom";
import { flattenedEmojiTable } from "../../Util";
+import { AttackExecution } from "../AttackExecution";
+import { AllianceExtensionExecution } from "../alliance/AllianceExtensionExecution";
+import { EmojiExecution } from "../EmojiExecution";
export class BotBehavior {
private enemy: Player | null = null;
diff --git a/src/core/game/AllianceRequestImpl.ts b/src/core/game/AllianceRequestImpl.ts
index 591c383c9c..23d717addf 100644
--- a/src/core/game/AllianceRequestImpl.ts
+++ b/src/core/game/AllianceRequestImpl.ts
@@ -1,6 +1,6 @@
import { AllianceRequest, Player, Tick } from "./Game";
-import { AllianceRequestUpdate, GameUpdateType } from "./GameUpdates";
import { GameImpl } from "./GameImpl";
+import { AllianceRequestUpdate, GameUpdateType } from "./GameUpdates";
export class AllianceRequestImpl implements AllianceRequest {
private status_: "pending" | "accepted" | "rejected" = "pending";
diff --git a/src/core/game/AttackImpl.ts b/src/core/game/AttackImpl.ts
index 6ab6dd56d3..7bb4cc1e9b 100644
--- a/src/core/game/AttackImpl.ts
+++ b/src/core/game/AttackImpl.ts
@@ -1,7 +1,7 @@
import { Attack, Cell, Player, TerraNullius } from "./Game";
import { GameImpl } from "./GameImpl";
-import { PlayerImpl } from "./PlayerImpl";
import { TileRef } from "./GameMap";
+import { PlayerImpl } from "./PlayerImpl";
export class AttackImpl implements Attack {
private _isActive = true;
diff --git a/src/core/game/BinaryLoaderGameMapLoader.ts b/src/core/game/BinaryLoaderGameMapLoader.ts
index 233adbd984..8089860328 100644
--- a/src/core/game/BinaryLoaderGameMapLoader.ts
+++ b/src/core/game/BinaryLoaderGameMapLoader.ts
@@ -1,5 +1,5 @@
-import { GameMapLoader, MapData } from "./GameMapLoader";
import { GameMapType } from "./Game";
+import { GameMapLoader, MapData } from "./GameMapLoader";
import { MapManifest } from "./TerrainMapLoader";
export type BinModule = {
diff --git a/src/core/game/FetchGameMapLoader.ts b/src/core/game/FetchGameMapLoader.ts
index 5bdeed62dc..096f974475 100644
--- a/src/core/game/FetchGameMapLoader.ts
+++ b/src/core/game/FetchGameMapLoader.ts
@@ -1,5 +1,5 @@
-import { GameMapLoader, MapData } from "./GameMapLoader";
import { GameMapType } from "./Game";
+import { GameMapLoader, MapData } from "./GameMapLoader";
import { MapManifestSchema } from "./TerrainMapLoader";
export class FetchGameMapLoader implements GameMapLoader {
diff --git a/src/core/game/Game.ts b/src/core/game/Game.ts
index 2416371daf..70434288df 100644
--- a/src/core/game/Game.ts
+++ b/src/core/game/Game.ts
@@ -1,3 +1,4 @@
+import { Config } from "../configuration/Config";
import { AllPlayersStats, ClientID } from "../Schemas";
import { GameMap, TileRef } from "./GameMap";
import {
@@ -6,7 +7,6 @@ import {
PlayerUpdate,
UnitUpdate,
} from "./GameUpdates";
-import { Config } from "../configuration/Config";
import { RailNetwork } from "./RailNetwork";
import { Stats } from "./Stats";
import { UnitPredicate } from "./UnitGrid";
@@ -44,18 +44,16 @@ export const Duos = "Duos" as const;
export const Trios = "Trios" as const;
export const Quads = "Quads" as const;
-/* eslint-disable sort-keys */
export const ColoredTeams: Record = {
- Red: "Red",
Blue: "Blue",
- Teal: "Teal",
+ Bot: "Bot",
+ Green: "Green",
+ Orange: "Orange",
Purple: "Purple",
+ Red: "Red",
+ Teal: "Teal",
Yellow: "Yellow",
- Orange: "Orange",
- Green: "Green",
- Bot: "Bot",
} as const;
-/* eslint-enable sort-keys */
export enum GameMapType {
World = "World",
@@ -103,6 +101,14 @@ export const mapCategories: Record = {
GameMapType.Africa,
GameMapType.Oceania,
],
+
+ fantasy: [
+ GameMapType.Pangaea,
+ GameMapType.Pluto,
+ GameMapType.MarsRevised,
+ GameMapType.Mars,
+ GameMapType.DeglaciatedAntarctica,
+ ],
regional: [
GameMapType.BlackSea,
GameMapType.Britannia,
@@ -120,14 +126,6 @@ export const mapCategories: Record = {
GameMapType.Italia,
GameMapType.Yenisei,
],
- // eslint-disable-next-line sort-keys
- fantasy: [
- GameMapType.Pangaea,
- GameMapType.Pluto,
- GameMapType.MarsRevised,
- GameMapType.Mars,
- GameMapType.DeglaciatedAntarctica,
- ],
};
export enum GameType {
diff --git a/src/core/game/GameImpl.ts b/src/core/game/GameImpl.ts
index 9d18989105..dca0dcee75 100644
--- a/src/core/game/GameImpl.ts
+++ b/src/core/game/GameImpl.ts
@@ -1,5 +1,11 @@
/* eslint-disable max-lines */
+
+import { renderNumber } from "../../client/Utils";
+import { Config } from "../configuration/Config";
import { AllPlayersStats, ClientID, Winner } from "../Schemas";
+import { simpleHash } from "../Util";
+import { AllianceImpl } from "./AllianceImpl";
+import { AllianceRequestImpl } from "./AllianceRequestImpl";
import {
Alliance,
AllianceRequest,
@@ -20,8 +26,8 @@ import {
PlayerType,
Quads,
Team,
- TerraNullius,
TerrainType,
+ TerraNullius,
Trios,
Unit,
UnitInfo,
@@ -29,19 +35,14 @@ import {
} from "./Game";
import { GameMap, TileRef, TileUpdate } from "./GameMap";
import { GameUpdate, GameUpdateType } from "./GameUpdates";
-import { UnitGrid, UnitPredicate } from "./UnitGrid";
-import { AllianceImpl } from "./AllianceImpl";
-import { AllianceRequestImpl } from "./AllianceRequestImpl";
-import { Config } from "../configuration/Config";
import { PlayerImpl } from "./PlayerImpl";
import { RailNetwork } from "./RailNetwork";
+import { createRailNetwork } from "./RailNetworkImpl";
import { Stats } from "./Stats";
import { StatsImpl } from "./StatsImpl";
-import { TerraNulliusImpl } from "./TerraNulliusImpl";
import { assignTeams } from "./TeamAssignment";
-import { createRailNetwork } from "./RailNetworkImpl";
-import { renderNumber } from "../../client/Utils";
-import { simpleHash } from "../Util";
+import { TerraNulliusImpl } from "./TerraNulliusImpl";
+import { UnitGrid, UnitPredicate } from "./UnitGrid";
export function createGame(
humans: PlayerInfo[],
diff --git a/src/core/game/GameView.ts b/src/core/game/GameView.ts
index 01a08f59e1..dedec770b7 100644
--- a/src/core/game/GameView.ts
+++ b/src/core/game/GameView.ts
@@ -1,11 +1,9 @@
-import {
- AllianceView,
- AttackUpdate,
- GameUpdateType,
- GameUpdateViewData,
- PlayerUpdate,
- UnitUpdate,
-} from "./GameUpdates";
+import { base64url } from "jose";
+import { Config } from "../configuration/Config";
+import { PatternDecoder } from "../PatternDecoder";
+import { ClientID, GameID, Player } from "../Schemas";
+import { createRandomName } from "../Util";
+import { WorkerClient } from "../worker/WorkerClient";
import {
Cell,
EmojiMessage,
@@ -18,24 +16,26 @@ import {
PlayerProfile,
PlayerType,
Team,
- TerraNullius,
TerrainType,
+ TerraNullius,
Tick,
TrainType,
UnitInfo,
UnitType,
} from "./Game";
-import { ClientID, GameID, Player } from "../Schemas";
import { GameMap, TileRef, TileUpdate } from "./GameMap";
-import { UnitGrid, UnitPredicate } from "./UnitGrid";
-import { Config } from "../configuration/Config";
-import { PatternDecoder } from "../PatternDecoder";
-import { TerraNulliusImpl } from "./TerraNulliusImpl";
+import {
+ AllianceView,
+ AttackUpdate,
+ GameUpdateType,
+ GameUpdateViewData,
+ PlayerUpdate,
+ UnitUpdate,
+} from "./GameUpdates";
import { TerrainMapData } from "./TerrainMapLoader";
+import { TerraNulliusImpl } from "./TerraNulliusImpl";
+import { UnitGrid, UnitPredicate } from "./UnitGrid";
import { UserSettings } from "./UserSettings";
-import { WorkerClient } from "../worker/WorkerClient";
-import { base64url } from "jose";
-import { createRandomName } from "../Util";
const userSettings: UserSettings = new UserSettings();
diff --git a/src/core/game/PlayerImpl.ts b/src/core/game/PlayerImpl.ts
index bb906acb3d..db931ebcff 100644
--- a/src/core/game/PlayerImpl.ts
+++ b/src/core/game/PlayerImpl.ts
@@ -1,8 +1,22 @@
/* eslint-disable max-lines */
+
+import { renderNumber, renderTroops } from "../../client/Utils";
+import { PseudoRandom } from "../PseudoRandom";
+import { ClientID } from "../Schemas";
+import {
+ assertNever,
+ distSortUnit,
+ minInt,
+ simpleHash,
+ toInt,
+ within,
+} from "../Util";
+import { sanitizeUsername } from "../validations/username";
+import { AttackImpl } from "./AttackImpl";
import {
- AllPlayers,
Alliance,
AllianceRequest,
+ AllPlayers,
Attack,
BuildableUnit,
Cell,
@@ -27,32 +41,19 @@ import {
UnitParams,
UnitType,
} from "./Game";
+import { GameImpl } from "./GameImpl";
+import { andFN, manhattanDistFN, TileRef } from "./GameMap";
import {
AllianceView,
AttackUpdate,
GameUpdateType,
PlayerUpdate,
} from "./GameUpdates";
-import { TileRef, andFN, manhattanDistFN } from "./GameMap";
-import {
- assertNever,
- distSortUnit,
- minInt,
- simpleHash,
- toInt,
- within,
-} from "../Util";
import {
bestShoreDeploymentSource,
canBuildTransportShip,
} from "./TransportShipUtils";
-import { renderNumber, renderTroops } from "../../client/Utils";
-import { AttackImpl } from "./AttackImpl";
-import { ClientID } from "../Schemas";
-import { GameImpl } from "./GameImpl";
-import { PseudoRandom } from "../PseudoRandom";
import { UnitImpl } from "./UnitImpl";
-import { sanitizeUsername } from "../validations/username";
type Target = {
tick: Tick;
@@ -127,58 +128,56 @@ export class PlayerImpl implements Player {
);
const stats = this.mg.stats().getPlayerStats(this);
- /* eslint-disable sort-keys */
return {
- type: GameUpdateType.Player,
+ alliances: this.alliances().map(
+ (a) =>
+ ({
+ createdAt: a.createdAt(),
+ expiresAt: a.expiresAt(),
+ id: a.id(),
+ other: a.other(this).id(),
+ }) satisfies AllianceView,
+ ),
+ allies: this.alliances().map((a) => a.other(this).smallID()),
+ betrayals: stats?.betrayals,
clientID: this.clientID(),
- name: this.name(),
displayName: this.displayName(),
- id: this.id(),
- team: this.team() ?? undefined,
- smallID: this.smallID(),
- playerType: this.type(),
- isAlive: this.isAlive(),
- isDisconnected: this.isDisconnected(),
- tilesOwned: this.numTilesOwned(),
- gold: this._gold,
- troops: this.troops(),
- allies: this.alliances().map((a) => a.other(this).smallID()),
embargoes: new Set([...this.embargoes.keys()].map((p) => p.toString())),
- isTraitor: this.isTraitor(),
- targets: this.targets().map((p) => p.smallID()),
- outgoingEmojis: this.outgoingEmojis(),
- outgoingAttacks: this._outgoingAttacks.map((a) => {
+ gold: this._gold,
+ hasSpawned: this.hasSpawned(),
+ id: this.id(),
+ incomingAttacks: this._incomingAttacks.map((a) => {
return {
attackerID: a.attacker().smallID(),
- targetID: a.target().smallID(),
- troops: a.troops(),
id: a.id(),
retreating: a.retreating(),
+ targetID: a.target().smallID(),
+ troops: a.troops(),
} satisfies AttackUpdate;
}),
- incomingAttacks: this._incomingAttacks.map((a) => {
+ isAlive: this.isAlive(),
+ isDisconnected: this.isDisconnected(),
+ isTraitor: this.isTraitor(),
+ name: this.name(),
+ outgoingAllianceRequests,
+ outgoingAttacks: this._outgoingAttacks.map((a) => {
return {
attackerID: a.attacker().smallID(),
- targetID: a.target().smallID(),
- troops: a.troops(),
id: a.id(),
retreating: a.retreating(),
+ targetID: a.target().smallID(),
+ troops: a.troops(),
} satisfies AttackUpdate;
}),
- outgoingAllianceRequests,
- alliances: this.alliances().map(
- (a) =>
- ({
- id: a.id(),
- other: a.other(this).id(),
- createdAt: a.createdAt(),
- expiresAt: a.expiresAt(),
- }) satisfies AllianceView,
- ),
- hasSpawned: this.hasSpawned(),
- betrayals: stats?.betrayals,
+ outgoingEmojis: this.outgoingEmojis(),
+ playerType: this.type(),
+ smallID: this.smallID(),
+ targets: this.targets().map((p) => p.smallID()),
+ team: this.team() ?? undefined,
+ tilesOwned: this.numTilesOwned(),
+ troops: this.troops(),
+ type: GameUpdateType.Player,
};
- /* eslint-enable sort-keys */
}
smallID(): number {
@@ -511,8 +510,7 @@ export class PlayerImpl implements Player {
}
target(other: Player): void {
- // eslint-disable-next-line sort-keys
- this.targets_.push({ tick: this.mg.ticks(), target: other });
+ this.targets_.push({ target: other, tick: this.mg.ticks() });
this.mg.target(this, other);
}
diff --git a/src/core/game/RailNetwork.ts b/src/core/game/RailNetwork.ts
index 1606180e75..00c2e6f5e9 100644
--- a/src/core/game/RailNetwork.ts
+++ b/src/core/game/RailNetwork.ts
@@ -1,5 +1,5 @@
-import { TrainStation } from "./TrainStation";
import { Unit } from "./Game";
+import { TrainStation } from "./TrainStation";
export type RailNetwork = {
connectStation(station: TrainStation): void;
diff --git a/src/core/game/RailNetworkImpl.ts b/src/core/game/RailNetworkImpl.ts
index a77d218a0f..5cb2a300c2 100644
--- a/src/core/game/RailNetworkImpl.ts
+++ b/src/core/game/RailNetworkImpl.ts
@@ -1,12 +1,12 @@
-import { Cluster, TrainStation, TrainStationMapAdapter } from "./TrainStation";
-import { Game, Unit, UnitType } from "./Game";
-import { MiniAStar } from "../pathfinding/MiniAStar";
-import { PathFindResultType } from "../pathfinding/AStar";
-import { RailNetwork } from "./RailNetwork";
-import { Railroad } from "./Railroad";
import { RailroadExecution } from "../execution/RailroadExecution";
+import { PathFindResultType } from "../pathfinding/AStar";
+import { MiniAStar } from "../pathfinding/MiniAStar";
import { SerialAStar } from "../pathfinding/SerialAStar";
+import { Game, Unit, UnitType } from "./Game";
import { TileRef } from "./GameMap";
+import { RailNetwork } from "./RailNetwork";
+import { Railroad } from "./Railroad";
+import { Cluster, TrainStation, TrainStationMapAdapter } from "./TrainStation";
/**
* The Stations handle their own neighbors so the graph is naturally traversable,
@@ -216,8 +216,7 @@ export class RailNetworkImpl implements RailNetwork {
const visited = new Set();
const queue: Array<{ station: TrainStation; distance: number }> = [
- // eslint-disable-next-line sort-keys
- { station: start, distance: 0 },
+ { distance: 0, station: start },
];
let head = 0;
@@ -231,8 +230,7 @@ export class RailNetworkImpl implements RailNetwork {
for (const neighbor of station.neighbors()) {
if (neighbor === dest) return distance + 1;
if (!visited.has(neighbor)) {
- // eslint-disable-next-line sort-keys
- queue.push({ station: neighbor, distance: distance + 1 });
+ queue.push({ distance: distance + 1, station: neighbor });
}
}
}
diff --git a/src/core/game/Railroad.ts b/src/core/game/Railroad.ts
index f415eede38..f862c01471 100644
--- a/src/core/game/Railroad.ts
+++ b/src/core/game/Railroad.ts
@@ -1,6 +1,6 @@
-import { GameUpdateType, RailTile, RailType } from "./GameUpdates";
import { Game } from "./Game";
import { TileRef } from "./GameMap";
+import { GameUpdateType, RailTile, RailType } from "./GameUpdates";
import { TrainStation } from "./TrainStation";
export class Railroad {
diff --git a/src/core/game/Stats.ts b/src/core/game/Stats.ts
index fbde0d9728..63a8aac793 100644
--- a/src/core/game/Stats.ts
+++ b/src/core/game/Stats.ts
@@ -1,6 +1,6 @@
+import { AllPlayersStats } from "../Schemas";
import { NukeType, OtherUnitType, PlayerStats } from "../StatsSchemas";
import { Player, TerraNullius } from "./Game";
-import { AllPlayersStats } from "../Schemas";
export type Stats = {
getPlayerStats(player: Player): PlayerStats | null;
diff --git a/src/core/game/StatsImpl.ts b/src/core/game/StatsImpl.ts
index bae57a81a1..5b33dd6245 100644
--- a/src/core/game/StatsImpl.ts
+++ b/src/core/game/StatsImpl.ts
@@ -1,3 +1,4 @@
+import { AllPlayersStats } from "../Schemas";
import {
ATTACK_INDEX_CANCEL,
ATTACK_INDEX_RECV,
@@ -26,7 +27,6 @@ import {
unitTypeToOtherUnit,
} from "../StatsSchemas";
import { Player, TerraNullius } from "./Game";
-import { AllPlayersStats } from "../Schemas";
import { Stats } from "./Stats";
type BigIntLike = bigint | number;
diff --git a/src/core/game/TeamAssignment.ts b/src/core/game/TeamAssignment.ts
index fcef06c552..f5a12f221c 100644
--- a/src/core/game/TeamAssignment.ts
+++ b/src/core/game/TeamAssignment.ts
@@ -1,6 +1,6 @@
-import { PlayerInfo, PlayerType, Team } from "./Game";
import { PseudoRandom } from "../PseudoRandom";
import { simpleHash } from "../Util";
+import { PlayerInfo, PlayerType, Team } from "./Game";
export function assignTeams(
players: PlayerInfo[],
diff --git a/src/core/game/TerrainMapLoader.ts b/src/core/game/TerrainMapLoader.ts
index dc4bc4156c..0fd01b6dcf 100644
--- a/src/core/game/TerrainMapLoader.ts
+++ b/src/core/game/TerrainMapLoader.ts
@@ -1,7 +1,7 @@
+import { z } from "zod";
+import { GameMapType } from "./Game";
import { GameMap, GameMapImpl } from "./GameMap";
import { GameMapLoader } from "./GameMapLoader";
-import { GameMapType } from "./Game";
-import { z } from "zod";
export type TerrainMapData = {
manifest: MapManifest;
@@ -66,7 +66,8 @@ export async function genTerrainFromBin(
): Promise {
if (data.length !== mapData.width * mapData.height) {
throw new Error(
- `Invalid data: buffer size ${data.length} incorrect for ${mapData.width}x${mapData.height
+ `Invalid data: buffer size ${data.length} incorrect for ${mapData.width}x${
+ mapData.height
} terrain plus 4 bytes for dimensions.`,
);
}
diff --git a/src/core/game/TrainStation.ts b/src/core/game/TrainStation.ts
index 7e844439ca..f0b28eced6 100644
--- a/src/core/game/TrainStation.ts
+++ b/src/core/game/TrainStation.ts
@@ -1,10 +1,10 @@
+import { TrainExecution } from "../execution/TrainExecution";
+import { PseudoRandom } from "../PseudoRandom";
+import { GraphAdapter } from "../pathfinding/SerialAStar";
import { Game, Player, Unit, UnitType } from "./Game";
+import { TileRef } from "./GameMap";
import { GameUpdateType, RailTile, RailType } from "./GameUpdates";
-import { GraphAdapter } from "../pathfinding/SerialAStar";
-import { PseudoRandom } from "../PseudoRandom";
import { Railroad } from "./Railroad";
-import { TileRef } from "./GameMap";
-import { TrainExecution } from "../execution/TrainExecution";
/**
* Handle train stops at various station types
diff --git a/src/core/game/TransportShipUtils.ts b/src/core/game/TransportShipUtils.ts
index 861cfadc80..df335b714a 100644
--- a/src/core/game/TransportShipUtils.ts
+++ b/src/core/game/TransportShipUtils.ts
@@ -1,7 +1,7 @@
-import { Game, Player, UnitType } from "./Game";
-import { GameMap, TileRef, andFN, manhattanDistFN } from "./GameMap";
-import { MiniAStar } from "../pathfinding/MiniAStar";
import { PathFindResultType } from "../pathfinding/AStar";
+import { MiniAStar } from "../pathfinding/MiniAStar";
+import { Game, Player, UnitType } from "./Game";
+import { andFN, GameMap, manhattanDistFN, TileRef } from "./GameMap";
export function canBuildTransportShip(
game: Game,
diff --git a/src/core/game/UnitGrid.ts b/src/core/game/UnitGrid.ts
index bb8b52d0d3..b790c2a825 100644
--- a/src/core/game/UnitGrid.ts
+++ b/src/core/game/UnitGrid.ts
@@ -1,5 +1,5 @@
-import { GameMap, TileRef } from "./GameMap";
import { PlayerID, Unit, UnitType } from "./Game";
+import { GameMap, TileRef } from "./GameMap";
import { UnitView } from "./GameView";
export type UnitPredicate = (value: {
@@ -159,8 +159,8 @@ export class UnitGrid {
if (!unit.isActive()) continue;
const distSquared = this.squaredDistanceFromTile(unit, tile);
if (distSquared > rangeSquared) continue;
- // eslint-disable-next-line sort-keys
- const value = { unit, distSquared };
+
+ const value = { distSquared, unit };
if (predicate !== undefined && !predicate(value)) continue;
nearby.push(value);
}
diff --git a/src/core/game/UnitImpl.ts b/src/core/game/UnitImpl.ts
index 037f0e23bc..df5819d2e8 100644
--- a/src/core/game/UnitImpl.ts
+++ b/src/core/game/UnitImpl.ts
@@ -1,3 +1,4 @@
+import { simpleHash, toInt, withinInt } from "../Util";
import {
AllUnitParams,
MessageType,
@@ -9,11 +10,10 @@ import {
UnitInfo,
UnitType,
} from "./Game";
-import { GameUpdateType, UnitUpdate } from "./GameUpdates";
-import { simpleHash, toInt, withinInt } from "../Util";
import { GameImpl } from "./GameImpl";
-import { PlayerImpl } from "./PlayerImpl";
import { TileRef } from "./GameMap";
+import { GameUpdateType, UnitUpdate } from "./GameUpdates";
+import { PlayerImpl } from "./PlayerImpl";
export class UnitImpl implements Unit {
private _active = true;
@@ -114,33 +114,31 @@ export class UnitImpl implements Unit {
return this._id;
}
- /* eslint-disable sort-keys */
toUpdate(): UnitUpdate {
return {
- type: GameUpdateType.Unit,
- unitType: this._type,
+ constructionType: this._constructionType,
+ hasTrainStation: this._hasTrainStation,
+ health: this.hasHealth() ? Number(this._health) : undefined,
id: this._id,
- troops: this._troops,
- ownerID: this._owner.smallID(),
- lastOwnerID: this._lastOwner?.smallID(),
isActive: this._active,
+ lastOwnerID: this._lastOwner?.smallID(),
+ lastPos: this._lastTile,
+ level: this.level(),
+ loaded: this._loaded,
+ missileTimerQueue: this._missileTimerQueue,
+ ownerID: this._owner.smallID(),
+ pos: this._tile,
reachedTarget: this._reachedTarget,
retreating: this._retreating,
- pos: this._tile,
targetable: this._targetable,
- lastPos: this._lastTile,
- health: this.hasHealth() ? Number(this._health) : undefined,
- constructionType: this._constructionType,
- targetUnitId: this._targetUnit?.id() ?? undefined,
targetTile: this.targetTile() ?? undefined,
- missileTimerQueue: this._missileTimerQueue,
- level: this.level(),
- hasTrainStation: this._hasTrainStation,
+ targetUnitId: this._targetUnit?.id() ?? undefined,
trainType: this._trainType,
- loaded: this._loaded,
+ troops: this._troops,
+ type: GameUpdateType.Unit,
+ unitType: this._type,
};
}
- /* eslint-enable sort-keys */
type(): UnitType {
return this._type;
diff --git a/src/core/pathfinding/AStar.ts b/src/core/pathfinding/AStar.ts
index 63fbf907f5..4056c684fc 100644
--- a/src/core/pathfinding/AStar.ts
+++ b/src/core/pathfinding/AStar.ts
@@ -11,19 +11,19 @@ export enum PathFindResultType {
}
export type AStarResult =
| {
- type: PathFindResultType.NextTile;
- node: NodeType;
- }
+ type: PathFindResultType.NextTile;
+ node: NodeType;
+ }
| {
- type: PathFindResultType.Pending;
- }
+ type: PathFindResultType.Pending;
+ }
| {
- type: PathFindResultType.Completed;
- node: NodeType;
- }
+ type: PathFindResultType.Completed;
+ node: NodeType;
+ }
| {
- type: PathFindResultType.PathNotFound;
- };
+ type: PathFindResultType.PathNotFound;
+ };
export type Point = {
x: number;
diff --git a/src/core/pathfinding/MiniAStar.ts b/src/core/pathfinding/MiniAStar.ts
index c4c227b043..826edc6bc8 100644
--- a/src/core/pathfinding/MiniAStar.ts
+++ b/src/core/pathfinding/MiniAStar.ts
@@ -1,7 +1,7 @@
-import { AStar, PathFindResultType } from "./AStar";
+import { Cell } from "../game/Game";
import { GameMap, TileRef } from "../game/GameMap";
+import { AStar, PathFindResultType } from "./AStar";
import { GraphAdapter, SerialAStar } from "./SerialAStar";
-import { Cell } from "../game/Game";
export class GameMapAdapter implements GraphAdapter {
constructor(
diff --git a/src/core/pathfinding/PathFinding.ts b/src/core/pathfinding/PathFinding.ts
index 2711b8b39d..e788a5985d 100644
--- a/src/core/pathfinding/PathFinding.ts
+++ b/src/core/pathfinding/PathFinding.ts
@@ -1,9 +1,9 @@
-import { AStar, AStarResult, PathFindResultType } from "./AStar";
+import { Game } from "../game/Game";
import { GameMap, TileRef } from "../game/GameMap";
+import { PseudoRandom } from "../PseudoRandom";
import { DistanceBasedBezierCurve } from "../utilities/Line";
-import { Game } from "../game/Game";
+import { AStar, AStarResult, PathFindResultType } from "./AStar";
import { MiniAStar } from "./MiniAStar";
-import { PseudoRandom } from "../PseudoRandom";
const parabolaMinHeight = 50;
@@ -148,8 +148,7 @@ export class PathFinder {
}
if (this.game.manhattanDist(curr, dst) < dist) {
- // eslint-disable-next-line sort-keys
- return { type: PathFindResultType.Completed, node: curr };
+ return { node: curr, type: PathFindResultType.Completed };
}
if (this.computeFinished) {
@@ -165,8 +164,8 @@ export class PathFinder {
if (tile === undefined) {
throw new Error("missing tile");
}
- // eslint-disable-next-line sort-keys
- return { type: PathFindResultType.NextTile, node: tile };
+
+ return { node: tile, type: PathFindResultType.NextTile };
}
}
diff --git a/src/core/pathfinding/SerialAStar.ts b/src/core/pathfinding/SerialAStar.ts
index 13439c818a..703cca73a4 100644
--- a/src/core/pathfinding/SerialAStar.ts
+++ b/src/core/pathfinding/SerialAStar.ts
@@ -1,5 +1,5 @@
-import { AStar, PathFindResultType } from "./AStar";
import FastPriorityQueue from "fastpriorityqueue";
+import { AStar, PathFindResultType } from "./AStar";
/**
* Implement this interface with your graph to find paths with A*
@@ -48,18 +48,16 @@ export class SerialAStar implements AStar {
this.sources.forEach((startPoint) => {
this.fwdGScore.set(startPoint, 0);
this.fwdOpenSet.add({
- tile: startPoint,
- // eslint-disable-next-line sort-keys
fScore: this.heuristic(startPoint, dst),
+ tile: startPoint,
});
});
// Initialize backward search from destination
this.bwdGScore.set(dst, 0);
this.bwdOpenSet.add({
- tile: dst,
- // eslint-disable-next-line sort-keys
fScore: this.heuristic(dst, this.findClosestSource(dst)),
+ tile: dst,
});
}
@@ -128,7 +126,8 @@ export class SerialAStar implements AStar {
const openSet = isForward ? this.fwdOpenSet : this.bwdOpenSet;
const cameFrom = isForward ? this.fwdCameFrom : this.bwdCameFrom;
- const tentativeGScore = (gScore.get(current) ?? 0) + this.graph.cost(neighbor);
+ const tentativeGScore =
+ (gScore.get(current) ?? 0) + this.graph.cost(neighbor);
let penalty = 0;
// With a direction change penalty, the path will get as straight as possible
if (this.directionChangePenalty > 0) {
@@ -150,8 +149,8 @@ export class SerialAStar implements AStar {
const fScore =
totalG +
this.heuristic(neighbor, isForward ? this.dst : this.closestSource);
- // eslint-disable-next-line sort-keys
- openSet.add({ tile: neighbor, fScore });
+
+ openSet.add({ fScore, tile: neighbor });
}
}
}
diff --git a/src/core/validations/username.ts b/src/core/validations/username.ts
index c587267a85..6e73dd296b 100644
--- a/src/core/validations/username.ts
+++ b/src/core/validations/username.ts
@@ -1,14 +1,14 @@
import {
- RegExpMatcher,
collapseDuplicatesTransformer,
englishDataset,
englishRecommendedTransformers,
+ RegExpMatcher,
resolveConfusablesTransformer,
resolveLeetSpeakTransformer,
skipNonAlphabeticTransformer,
} from "obscenity";
-import { simpleHash } from "../Util";
import { translateText } from "../../client/Utils";
+import { simpleHash } from "../Util";
const matcher = new RegExpMatcher({
...englishDataset.build(),
@@ -50,8 +50,7 @@ export function validateUsername(username: string): {
error?: string;
} {
if (typeof username !== "string") {
- // eslint-disable-next-line sort-keys
- return { isValid: false, error: translateText("username.not_string") };
+ return { error: translateText("username.not_string"), isValid: false };
}
if (username.length < MIN_USERNAME_LENGTH) {
diff --git a/src/core/worker/Worker.worker.ts b/src/core/worker/Worker.worker.ts
index 28e979c7ec..ad1f7ff725 100644
--- a/src/core/worker/Worker.worker.ts
+++ b/src/core/worker/Worker.worker.ts
@@ -1,3 +1,7 @@
+import version from "../../../resources/version.txt";
+import { createGameRunner, GameRunner } from "../GameRunner";
+import { FetchGameMapLoader } from "../game/FetchGameMapLoader";
+import { ErrorUpdate, GameUpdateViewData } from "../game/GameUpdates";
import {
AttackAveragePositionResultMessage,
InitializedMessage,
@@ -8,10 +12,6 @@ import {
TransportShipSpawnResultMessage,
WorkerMessage,
} from "./WorkerMessages";
-import { ErrorUpdate, GameUpdateViewData } from "../game/GameUpdates";
-import { GameRunner, createGameRunner } from "../GameRunner";
-import { FetchGameMapLoader } from "../game/FetchGameMapLoader";
-import version from "../../../resources/version.txt";
const ctx: Worker = self as unknown as Worker;
let gameRunner: Promise | null = null;
diff --git a/src/core/worker/WorkerClient.ts b/src/core/worker/WorkerClient.ts
index 1017cc7f18..f4cc16ab7c 100644
--- a/src/core/worker/WorkerClient.ts
+++ b/src/core/worker/WorkerClient.ts
@@ -5,16 +5,19 @@ import {
PlayerID,
PlayerProfile,
} from "../game/Game";
-import { ClientID, GameStartInfo, Turn } from "../Schemas";
-import { ErrorUpdate, GameUpdateViewData } from "../game/GameUpdates";
import { TileRef } from "../game/GameMap";
-import { WorkerMessage } from "./WorkerMessages";
+import { ErrorUpdate, GameUpdateViewData } from "../game/GameUpdates";
+import { ClientID, GameStartInfo, Turn } from "../Schemas";
import { generateID } from "../Util";
+import { WorkerMessage } from "./WorkerMessages";
export class WorkerClient {
private readonly worker: Worker;
private isInitialized = false;
- private readonly messageHandlers: Map void>;
+ private readonly messageHandlers: Map<
+ string,
+ (message: WorkerMessage) => void
+ >;
private gameUpdateCallback?: (
update: GameUpdateViewData | ErrorUpdate,
) => void;
diff --git a/src/core/worker/WorkerMessages.ts b/src/core/worker/WorkerMessages.ts
index 3f24796c02..059fbe3f75 100644
--- a/src/core/worker/WorkerMessages.ts
+++ b/src/core/worker/WorkerMessages.ts
@@ -1,12 +1,12 @@
-import { ClientID, GameStartInfo, Turn } from "../Schemas";
import {
PlayerActions,
PlayerBorderTiles,
PlayerID,
PlayerProfile,
} from "../game/Game";
-import { GameUpdateViewData } from "../game/GameUpdates";
import { TileRef } from "../game/GameMap";
+import { GameUpdateViewData } from "../game/GameUpdates";
+import { ClientID, GameStartInfo, Turn } from "../Schemas";
export type WorkerMessageType =
| "heartbeat"
diff --git a/src/server/Archive.ts b/src/server/Archive.ts
index bda347292a..ecc4f958b8 100644
--- a/src/server/Archive.ts
+++ b/src/server/Archive.ts
@@ -1,8 +1,8 @@
-import { AnalyticsRecord, GameID, GameRecord } from "../core/Schemas";
import { S3 } from "@aws-sdk/client-s3";
import { getServerConfigFromServer } from "../core/configuration/ConfigLoader";
-import { logger } from "./Logger";
+import { AnalyticsRecord, GameID, GameRecord } from "../core/Schemas";
import { replacer } from "../core/Util";
+import { logger } from "./Logger";
const config = getServerConfigFromServer();
@@ -10,14 +10,13 @@ const log = logger.child({ component: "Archive" });
// R2 client configuration
const r2 = new S3({
- region: "auto", // R2 ignores region, but it's required by the SDK
- /* eslint-disable sort-keys */
- endpoint: config.r2Endpoint(),
credentials: {
accessKeyId: config.r2AccessKey(),
secretAccessKey: config.r2SecretKey(),
},
- /* eslint-disable sort-keys */
+
+ endpoint: config.r2Endpoint(),
+ region: "auto", // R2 ignores region, but it's required by the SDK
});
const bucket = config.r2Bucket();
@@ -49,8 +48,8 @@ export async function archive(gameRecord: GameRecord) {
const { message, stack, name } = error;
log.error(`${gameRecord.info.gameID}: Final archive error: ${error}`, {
message,
- stack,
name,
+ stack,
...(error && typeof error === "object" ? error : {}),
});
}
@@ -60,11 +59,11 @@ async function archiveAnalyticsToR2(gameRecord: GameRecord) {
// Create analytics data object
const { info, version, gitCommit, subdomain, domain } = gameRecord;
const analyticsData: AnalyticsRecord = {
- info,
- version,
+ domain,
gitCommit,
+ info,
subdomain,
- domain,
+ version,
};
try {
@@ -72,10 +71,10 @@ async function archiveAnalyticsToR2(gameRecord: GameRecord) {
const analyticsKey = `${info.gameID}.json`;
await r2.putObject({
- Bucket: bucket,
- Key: `${analyticsFolder}/${analyticsKey}`,
Body: JSON.stringify(analyticsData, replacer),
+ Bucket: bucket,
ContentType: "application/json",
+ Key: `${analyticsFolder}/${analyticsKey}`,
});
log.info(`${info.gameID}: successfully wrote game analytics to R2`);
@@ -91,8 +90,8 @@ async function archiveAnalyticsToR2(gameRecord: GameRecord) {
const { message, stack, name } = error;
log.error(`${info.gameID}: Error writing game analytics to R2: ${error}`, {
message,
- stack,
name,
+ stack,
...(error && typeof error === "object" ? error : {}),
});
throw error;
@@ -110,10 +109,10 @@ async function archiveFullGameToR2(gameRecord: GameRecord) {
try {
await r2.putObject({
- Bucket: bucket,
- Key: `${gameFolder}/${recordCopy.info.gameID}`,
Body: JSON.stringify(recordCopy, replacer),
+ Bucket: bucket,
ContentType: "application/json",
+ Key: `${gameFolder}/${recordCopy.info.gameID}`,
});
} catch (error) {
log.error(`error saving game ${gameRecord.info.gameID}`);
@@ -148,8 +147,8 @@ export async function readGameRecord(
// Log the error for monitoring purposes
log.error(`${gameId}: Error reading game record from R2: ${error}`, {
message,
- stack,
name,
+ stack,
...(error && typeof error === "object" ? error : {}),
});
@@ -179,8 +178,8 @@ export async function gameRecordExists(gameId: GameID): Promise {
}
log.error(`${gameId}: Error checking archive existence: ${error}`, {
message,
- stack,
name,
+ stack,
...(error && typeof error === "object" ? error : {}),
});
return false;
diff --git a/src/server/Client.ts b/src/server/Client.ts
index af38b3a82e..ecac7f885e 100644
--- a/src/server/Client.ts
+++ b/src/server/Client.ts
@@ -1,7 +1,7 @@
-import { ClientID, Winner } from "../core/Schemas";
-import { Tick } from "../core/game/Game";
-import { TokenPayload } from "../core/ApiSchemas";
import WebSocket from "ws";
+import { TokenPayload } from "../core/ApiSchemas";
+import { Tick } from "../core/game/Game";
+import { ClientID, Winner } from "../core/Schemas";
export class Client {
public lastPing: number = Date.now();
diff --git a/src/server/Cloudflare.ts b/src/server/Cloudflare.ts
index 2de807f05e..6ca1f1fd0c 100644
--- a/src/server/Cloudflare.ts
+++ b/src/server/Cloudflare.ts
@@ -1,8 +1,8 @@
-import { promises as fs } from "fs";
-import { logger } from "./Logger";
import { spawn } from "child_process";
+import { promises as fs } from "fs";
import yaml from "js-yaml";
import { z } from "zod";
+import { logger } from "./Logger";
const log = logger.child({
module: "cloudflare",
@@ -70,7 +70,7 @@ export class Cloudflare {
const response = await fetch(url, {
body: data ? JSON.stringify(data) : undefined,
headers: {
- "Authorization": `Bearer ${this.apiToken}`,
+ Authorization: `Bearer ${this.apiToken}`,
"Content-Type": "application/json",
},
method,
@@ -185,7 +185,7 @@ export class Cloudflare {
const tunnelConfig: CloudflaredConfig = {
"credentials-file": this.credsPath,
- "ingress": [
+ ingress: [
...Array.from(subdomainToService.entries()).map(
([subdomain, service]) => ({
hostname: `${subdomain}.${domain}`,
@@ -196,7 +196,7 @@ export class Cloudflare {
service: "http_status:404",
},
],
- "tunnel": tunnelId,
+ tunnel: tunnelId,
};
// Write config file
diff --git a/src/server/GameManager.ts b/src/server/GameManager.ts
index cf9865af19..f9f941ef1d 100644
--- a/src/server/GameManager.ts
+++ b/src/server/GameManager.ts
@@ -1,9 +1,9 @@
+import { Logger } from "winston";
+import { ServerConfig } from "../core/configuration/Config";
import { Difficulty, GameMapType, GameMode, GameType } from "../core/game/Game";
import { GameConfig, GameID } from "../core/Schemas";
-import { GamePhase, GameServer } from "./GameServer";
import { Client } from "./Client";
-import { Logger } from "winston";
-import { ServerConfig } from "../core/configuration/Config";
+import { GamePhase, GameServer } from "./GameServer";
export class GameManager {
private games: Map = new Map();
@@ -41,8 +41,8 @@ export class GameManager {
{
bots: 400,
difficulty: Difficulty.Medium,
- disableNPCs: false,
disabledUnits: [],
+ disableNPCs: false,
donateGold: false,
donateTroops: false,
gameMap: GameMapType.World,
diff --git a/src/server/GameServer.ts b/src/server/GameServer.ts
index dd8d0d81ba..033a554c8f 100644
--- a/src/server/GameServer.ts
+++ b/src/server/GameServer.ts
@@ -1,3 +1,9 @@
+import ipAnonymize from "ip-anonymize";
+import { Logger } from "winston";
+import WebSocket from "ws";
+import { z } from "zod";
+import { GameEnv, ServerConfig } from "../core/configuration/Config";
+import { GameType } from "../core/game/Game";
import {
ClientID,
ClientSendWinnerMessage,
@@ -14,17 +20,11 @@ import {
ServerTurnMessage,
Turn,
} from "../core/Schemas";
-import { GameEnv, ServerConfig } from "../core/configuration/Config";
-import { Client } from "./Client";
-import { GameType } from "../core/game/Game";
-import { Logger } from "winston";
-import WebSocket from "ws";
-import { archive } from "./Archive";
import { createGameRecord } from "../core/Util";
+import { archive } from "./Archive";
+import { Client } from "./Client";
import { gatekeeper } from "./Gatekeeper";
-import ipAnonymize from "ip-anonymize";
import { postJoinMessageHandler } from "./worker/websocket/handler/message/PostJoinHandler";
-import { z } from "zod";
export enum GamePhase {
Lobby = "LOBBY",
@@ -44,7 +44,8 @@ export class GameServer {
public activeClients: Client[] = [];
lobbyCreatorID: string | undefined;
private readonly allClients: Map = new Map();
- private readonly clientsDisconnectedStatus: Map = new Map();
+ private readonly clientsDisconnectedStatus: Map =
+ new Map();
private _hasStarted = false;
private _startTime: number | null = null;
diff --git a/src/server/Gatekeeper.ts b/src/server/Gatekeeper.ts
index 047baa94b1..dccf45cb9f 100644
--- a/src/server/Gatekeeper.ts
+++ b/src/server/Gatekeeper.ts
@@ -1,9 +1,9 @@
// src/server/Security.ts
import { NextFunction, Request, Response } from "express";
-import { fileURLToPath } from "url";
import fs from "fs";
import http from "http";
import path from "path";
+import { fileURLToPath } from "url";
export enum LimiterType {
Get = "get",
diff --git a/src/server/Logger.ts b/src/server/Logger.ts
index 193b54c49f..5a4de59a76 100644
--- a/src/server/Logger.ts
+++ b/src/server/Logger.ts
@@ -1,14 +1,15 @@
-import * as dotenv from "dotenv";
import * as logsAPI from "@opentelemetry/api-logs";
+import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
import {
LoggerProvider,
SimpleLogRecordProcessor,
} from "@opentelemetry/sdk-logs";
-import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
import { OpenTelemetryTransportV3 } from "@opentelemetry/winston-transport";
-import { getOtelResource } from "./OtelResource";
-import { getServerConfigFromServer } from "../core/configuration/ConfigLoader";
+import * as dotenv from "dotenv";
import winston from "winston";
+import { getServerConfigFromServer } from "../core/configuration/ConfigLoader";
+import { getOtelResource } from "./OtelResource";
+
dotenv.config();
const config = getServerConfigFromServer();
@@ -28,9 +29,8 @@ if (config.otelEnabled()) {
// Add OTLP exporter for logs
const logExporter = new OTLPLogExporter({
- url: `${config.otelEndpoint()}/v1/logs`,
- // eslint-disable-next-line sort-keys
headers,
+ url: `${config.otelEndpoint()}/v1/logs`,
});
// Add a log processor with the exporter
@@ -56,18 +56,18 @@ const addSeverityFormat = winston.format((info) => {
// Define your base/parent logger
const logger = winston.createLogger({
- level: "info",
- /* eslint-disable sort-keys */
+ defaultMeta: {
+ environment: process.env.GAME_ENV ?? "prod",
+ service: "openfront",
+ },
+
format: winston.format.combine(
winston.format.timestamp(),
addSeverityFormat(),
winston.format.json(),
),
- defaultMeta: {
- service: "openfront",
- environment: process.env.GAME_ENV ?? "prod",
- },
- /* eslint-enable sort-keys */
+ level: "info",
+
transports: [
new winston.transports.Console(),
new OpenTelemetryTransportV3(),
diff --git a/src/server/MapPlaylist.ts b/src/server/MapPlaylist.ts
index b87dd4c99b..ef2e574563 100644
--- a/src/server/MapPlaylist.ts
+++ b/src/server/MapPlaylist.ts
@@ -1,3 +1,4 @@
+import { getServerConfigFromServer } from "../core/configuration/ConfigLoader";
import {
Difficulty,
Duos,
@@ -8,9 +9,8 @@ import {
Quads,
Trios,
} from "../core/game/Game";
-import { GameConfig, TeamCountConfig } from "../core/Schemas";
import { PseudoRandom } from "../core/PseudoRandom";
-import { getServerConfigFromServer } from "../core/configuration/ConfigLoader";
+import { GameConfig, TeamCountConfig } from "../core/Schemas";
import { logger } from "./Logger";
const log = logger.child({});
@@ -78,8 +78,8 @@ export class MapPlaylist {
return {
bots: 400,
difficulty: Difficulty.Medium,
- disableNPCs: mode === GameMode.Team,
disabledUnits: [],
+ disableNPCs: mode === GameMode.Team,
donateGold: true,
donateTroops: true,
gameMap: map,
@@ -105,7 +105,9 @@ export class MapPlaylist {
log.info(`Generated map playlist in ${i + 1} attempts`);
const next = this.mapsPlaylist.shift();
if (next !== undefined) return next;
- log.error("Playlist unexpectedly empty after successful shuffle; using fallback.");
+ log.error(
+ "Playlist unexpectedly empty after successful shuffle; using fallback.",
+ );
return { map: GameMapType.World, mode: GameMode.FFA };
}
}
diff --git a/src/server/Master.ts b/src/server/Master.ts
index b33ac52413..4d76404b92 100644
--- a/src/server/Master.ts
+++ b/src/server/Master.ts
@@ -1,18 +1,22 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
-import { ApiEnvResponse, ApiPublicLobbiesResponse } from "../core/ExpressSchemas";
-import { LimiterType, gatekeeper } from "./Gatekeeper";
-import { GameInfo } from "../core/Schemas";
-import { ID } from "../core/BaseSchemas";
-import { MapPlaylist } from "./MapPlaylist";
+
import cluster from "cluster";
import express from "express";
+import rateLimit from "express-rate-limit";
+import http from "http";
+import path from "path";
import { fileURLToPath } from "url";
-import { generateID } from "../core/Util";
+import { ID } from "../core/BaseSchemas";
import { getServerConfigFromServer } from "../core/configuration/ConfigLoader";
-import http from "http";
+import {
+ ApiEnvResponse,
+ ApiPublicLobbiesResponse,
+} from "../core/ExpressSchemas";
+import { GameInfo } from "../core/Schemas";
+import { generateID } from "../core/Util";
+import { gatekeeper, LimiterType } from "./Gatekeeper";
import { logger } from "./Logger";
-import path from "path";
-import rateLimit from "express-rate-limit";
+import { MapPlaylist } from "./MapPlaylist";
const config = getServerConfigFromServer();
const playlist = new MapPlaylist();
diff --git a/src/server/OtelResource.ts b/src/server/OtelResource.ts
index 8bd49d4d46..6d48fb4424 100644
--- a/src/server/OtelResource.ts
+++ b/src/server/OtelResource.ts
@@ -1,9 +1,9 @@
+import { resourceFromAttributes } from "@opentelemetry/resources";
import {
ATTR_SERVICE_NAME,
ATTR_SERVICE_VERSION,
} from "@opentelemetry/semantic-conventions";
import { getServerConfigFromServer } from "../core/configuration/ConfigLoader";
-import { resourceFromAttributes } from "@opentelemetry/resources";
const config = getServerConfigFromServer();
@@ -17,15 +17,14 @@ export function getOtelResource() {
export function getPromLabels() {
return {
- "service.instance.id": process.env.HOSTNAME,
- /* eslint-disable sort-keys */
- "openfront.environment": config.env(),
- "openfront.host": process.env.HOST,
- "openfront.domain": process.env.DOMAIN,
- "openfront.subdomain": process.env.SUBDOMAIN,
"openfront.component": process.env.WORKER_ID
? "Worker " + process.env.WORKER_ID
: "Master",
- /* eslint-enable sort-keys */
+ "openfront.domain": process.env.DOMAIN,
+
+ "openfront.environment": config.env(),
+ "openfront.host": process.env.HOST,
+ "openfront.subdomain": process.env.SUBDOMAIN,
+ "service.instance.id": process.env.HOSTNAME,
};
}
diff --git a/src/server/PrivilegeRefresher.ts b/src/server/PrivilegeRefresher.ts
index a8043fd3d4..51c270a565 100644
--- a/src/server/PrivilegeRefresher.ts
+++ b/src/server/PrivilegeRefresher.ts
@@ -1,11 +1,11 @@
+import { base64url } from "jose";
+import { Logger } from "winston";
+import { CosmeticsSchema } from "../core/CosmeticSchemas";
import {
FailOpenPrivilegeChecker,
PrivilegeChecker,
PrivilegeCheckerImpl,
} from "./Privilege";
-import { CosmeticsSchema } from "../core/CosmeticSchemas";
-import { Logger } from "winston";
-import { base64url } from "jose";
// Refreshes the privilege checker every 5 minutes.
// WARNING: This fails open if cosmetics.json is not available.
diff --git a/src/server/Server.ts b/src/server/Server.ts
index 5a9da84493..8a00653ead 100644
--- a/src/server/Server.ts
+++ b/src/server/Server.ts
@@ -1,8 +1,8 @@
+import cluster from "cluster";
import * as dotenv from "dotenv";
-import { Cloudflare, TunnelConfig } from "./Cloudflare";
import { GameEnv } from "../core/configuration/Config";
-import cluster from "cluster";
import { getServerConfigFromServer } from "../core/configuration/ConfigLoader";
+import { Cloudflare, TunnelConfig } from "./Cloudflare";
import { startMaster } from "./Master";
import { startWorker } from "./Worker";
diff --git a/src/server/Worker.ts b/src/server/Worker.ts
index 202dd184a8..858e4f0763 100644
--- a/src/server/Worker.ts
+++ b/src/server/Worker.ts
@@ -1,28 +1,28 @@
+import express, { NextFunction, Request, Response } from "express";
+import rateLimit from "express-rate-limit";
+import http from "http";
+import ipAnonymize from "ip-anonymize";
+import path from "path";
+import { fileURLToPath } from "url";
+import { WebSocket, WebSocketServer } from "ws";
+import { z } from "zod";
+import { ID } from "../core/BaseSchemas";
+import { GameEnv } from "../core/configuration/Config";
+import { getServerConfigFromServer } from "../core/configuration/ConfigLoader";
+import { GameType } from "../core/game/Game";
+import { GameRecord, GameRecordSchema } from "../core/Schemas";
import {
CreateGameInputSchema,
GameInputSchema,
WorkerApiGameIdExists,
} from "../core/WorkerSchemas";
-import { GameRecord, GameRecordSchema } from "../core/Schemas";
-import { LimiterType, gatekeeper } from "./Gatekeeper";
-import { WebSocket, WebSocketServer } from "ws";
import { archive, readGameRecord } from "./Archive";
-import express, { NextFunction, Request, Response } from "express";
-import { GameEnv } from "../core/configuration/Config";
import { GameManager } from "./GameManager";
-import { GameType } from "../core/game/Game";
-import { ID } from "../core/BaseSchemas";
+import { gatekeeper, LimiterType } from "./Gatekeeper";
+import { logger } from "./Logger";
import { PrivilegeRefresher } from "./PrivilegeRefresher";
-import { fileURLToPath } from "url";
-import { getServerConfigFromServer } from "../core/configuration/ConfigLoader";
-import http from "http";
import { initWorkerMetrics } from "./WorkerMetrics";
-import ipAnonymize from "ip-anonymize";
-import { logger } from "./Logger";
-import path from "path";
import { preJoinMessageHandler } from "./worker/websocket/handler/message/PreJoinHandler";
-import rateLimit from "express-rate-limit";
-import { z } from "zod";
const config = getServerConfigFromServer();
@@ -134,17 +134,9 @@ export async function startWorker() {
const game = gm.createGame(id, gc, creatorClientID);
log.info(
- `Worker ${
- workerId
- }: IP ${
- ipAnonymize(clientIP)
- } creating ${
+ `Worker ${workerId}: IP ${ipAnonymize(clientIP)} creating ${
game.isPublic() ? "Public" : "Private"
- }${
- gc?.gameMode ? ` ${gc.gameMode}` : ""
- } game with id ${
- id
- }${
+ }${gc?.gameMode ? ` ${gc.gameMode}` : ""} game with id ${id}${
creatorClientID ? `, creator: ${creatorClientID}` : ""
}`,
);
diff --git a/src/server/WorkerMetrics.ts b/src/server/WorkerMetrics.ts
index e233f8ac98..4af92f551e 100644
--- a/src/server/WorkerMetrics.ts
+++ b/src/server/WorkerMetrics.ts
@@ -1,9 +1,12 @@
-import * as dotenv from "dotenv";
-import { MeterProvider, PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
-import { getOtelResource, getPromLabels } from "./OtelResource";
-import { GameManager } from "./GameManager";
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
+import {
+ MeterProvider,
+ PeriodicExportingMetricReader,
+} from "@opentelemetry/sdk-metrics";
+import * as dotenv from "dotenv";
import { getServerConfigFromServer } from "../core/configuration/ConfigLoader";
+import { GameManager } from "./GameManager";
+import { getOtelResource, getPromLabels } from "./OtelResource";
dotenv.config();
@@ -28,8 +31,8 @@ export function initWorkerMetrics(gameManager: GameManager): void {
// Configure the metric reader
const metricReader = new PeriodicExportingMetricReader({
- exportIntervalMillis: 15000, // Export metrics every 15 seconds
exporter: metricExporter,
+ exportIntervalMillis: 15000, // Export metrics every 15 seconds
});
// Create a meter provider
diff --git a/src/server/jwt.ts b/src/server/jwt.ts
index e259accbef..a1ea941d56 100644
--- a/src/server/jwt.ts
+++ b/src/server/jwt.ts
@@ -1,19 +1,19 @@
+import { jwtVerify } from "jose";
+import { z } from "zod";
import {
TokenPayload,
TokenPayloadSchema,
UserMeResponse,
UserMeResponseSchema,
} from "../core/ApiSchemas";
-import { PersistentIdSchema } from "../core/Schemas";
import { ServerConfig } from "../core/configuration/Config";
-import { jwtVerify } from "jose";
-import { z } from "zod";
+import { PersistentIdSchema } from "../core/Schemas";
type TokenVerificationResult =
| {
- persistentId: string;
- claims: TokenPayload | null;
- }
+ persistentId: string;
+ claims: TokenPayload | null;
+ }
| false;
export async function verifyClientToken(
@@ -21,8 +21,7 @@ export async function verifyClientToken(
config: ServerConfig,
): Promise {
if (PersistentIdSchema.safeParse(token).success) {
- // eslint-disable-next-line sort-keys
- return { persistentId: token, claims: null };
+ return { claims: null, persistentId: token };
}
try {
const issuer = config.jwtIssuer();
diff --git a/src/server/worker/websocket/handler/message/PostJoinHandler.ts b/src/server/worker/websocket/handler/message/PostJoinHandler.ts
index 00b5b783a8..cea44173ad 100644
--- a/src/server/worker/websocket/handler/message/PostJoinHandler.ts
+++ b/src/server/worker/websocket/handler/message/PostJoinHandler.ts
@@ -1,3 +1,5 @@
+import { Logger } from "winston";
+import { z } from "zod";
import {
ClientMessageSchema,
ClientSendWinnerMessage,
@@ -5,8 +7,6 @@ import {
} from "../../../../../core/Schemas";
import { Client } from "../../../../Client";
import { GameServer } from "../../../../GameServer";
-import { Logger } from "winston";
-import { z } from "zod";
export async function postJoinMessageHandler(
gs: GameServer,
@@ -118,7 +118,9 @@ export async function postJoinMessageHandler(
function handleWinner(
gs: GameServer,
log: Logger,
- client: Client, clientMsg: ClientSendWinnerMessage) {
+ client: Client,
+ clientMsg: ClientSendWinnerMessage,
+) {
if (
gs.outOfSyncClients.has(client.clientID) ||
gs.kickedClients.has(client.clientID) ||
diff --git a/src/server/worker/websocket/handler/message/PreJoinHandler.ts b/src/server/worker/websocket/handler/message/PreJoinHandler.ts
index c4896942df..7c869b54f5 100644
--- a/src/server/worker/websocket/handler/message/PreJoinHandler.ts
+++ b/src/server/worker/websocket/handler/message/PreJoinHandler.ts
@@ -1,17 +1,17 @@
+import http from "http";
+import ipAnonymize from "ip-anonymize";
+import { WebSocket } from "ws";
+import { z } from "zod";
+import { getServerConfigFromServer } from "../../../../../core/configuration/ConfigLoader";
import {
ClientMessageSchema,
ServerErrorMessage,
} from "../../../../../core/Schemas";
-import { getUserMe, verifyClientToken } from "../../../../jwt";
import { Client } from "../../../../Client";
import { GameManager } from "../../../../GameManager";
-import { PrivilegeRefresher } from "../../../../PrivilegeRefresher";
-import { WebSocket } from "ws";
-import { getServerConfigFromServer } from "../../../../../core/configuration/ConfigLoader";
-import http from "http";
-import ipAnonymize from "ip-anonymize";
+import { getUserMe, verifyClientToken } from "../../../../jwt";
import { logger } from "../../../../Logger";
-import { z } from "zod";
+import { PrivilegeRefresher } from "../../../../PrivilegeRefresher";
const config = getServerConfigFromServer();
@@ -62,13 +62,13 @@ async function handleJoinMessage(
): Promise<
| undefined
| {
- success: true;
- }
+ success: true;
+ }
| {
- success: false;
- code: 1002;
- error: string;
- reason:
+ success: false;
+ code: 1002;
+ error: string;
+ reason:
| "ClientJoinMessageSchema"
| "Flag invalid"
| "Flag restricted"
@@ -78,19 +78,19 @@ async function handleJoinMessage(
| "Pattern restricted"
| "Pattern unlisted"
| "Unauthorized";
- }
+ }
| {
- success: false;
- code: 1011;
- reason: "Internal server error";
- error: string;
- }
+ success: false;
+ code: 1011;
+ reason: "Internal server error";
+ error: string;
+ }
> {
const forwarded = req.headers["x-forwarded-for"];
const ip = Array.isArray(forwarded)
? forwarded[0]
: // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
- forwarded || req.socket.remoteAddress || "unknown";
+ forwarded || req.socket.remoteAddress || "unknown";
try {
// Parse and handle client messages
@@ -121,8 +121,8 @@ async function handleJoinMessage(
const expectedWorkerId = config.workerIndex(clientMsg.gameID);
if (expectedWorkerId !== workerId) {
log.warn(
- `Worker mismatch: Game ${clientMsg.gameID
- } should be on worker ${expectedWorkerId
+ `Worker mismatch: Game ${clientMsg.gameID} should be on worker ${
+ expectedWorkerId
}, but this is worker ${workerId}`,
);
return;
diff --git a/tests/AllianceExtensionExecution.test.ts b/tests/AllianceExtensionExecution.test.ts
index 7b60df7efa..35fc3fe82b 100644
--- a/tests/AllianceExtensionExecution.test.ts
+++ b/tests/AllianceExtensionExecution.test.ts
@@ -1,8 +1,8 @@
-import { Game, Player, PlayerType } from "../src/core/game/Game";
-import { playerInfo, setup } from "./util/Setup";
import { AllianceExtensionExecution } from "../src/core/execution/alliance/AllianceExtensionExecution";
import { AllianceRequestExecution } from "../src/core/execution/alliance/AllianceRequestExecution";
import { AllianceRequestReplyExecution } from "../src/core/execution/alliance/AllianceRequestReplyExecution";
+import { Game, Player, PlayerType } from "../src/core/game/Game";
+import { playerInfo, setup } from "./util/Setup";
let game: Game;
let player1: Player;
@@ -15,8 +15,8 @@ describe("AllianceExtensionExecution", () => {
"ocean_and_land",
{
infiniteGold: true,
- instantBuild: true,
infiniteTroops: true,
+ instantBuild: true,
},
[
playerInfo("player1", PlayerType.Human),
diff --git a/tests/AllianceRequestExecution.test.ts b/tests/AllianceRequestExecution.test.ts
index b6df1e657a..21bae39031 100644
--- a/tests/AllianceRequestExecution.test.ts
+++ b/tests/AllianceRequestExecution.test.ts
@@ -1,7 +1,7 @@
-import { Game, Player, PlayerType } from "../src/core/game/Game";
-import { playerInfo, setup } from "./util/Setup";
import { AllianceRequestExecution } from "../src/core/execution/alliance/AllianceRequestExecution";
import { AllianceRequestReplyExecution } from "../src/core/execution/alliance/AllianceRequestReplyExecution";
+import { Game, Player, PlayerType } from "../src/core/game/Game";
+import { playerInfo, setup } from "./util/Setup";
let game: Game;
let player1: Player;
@@ -13,8 +13,8 @@ describe("AllianceRequestExecution", () => {
"plains",
{
infiniteGold: true,
- instantBuild: true,
infiniteTroops: true,
+ instantBuild: true,
},
[
playerInfo("player1", PlayerType.Human),
diff --git a/tests/Attack.test.ts b/tests/Attack.test.ts
index 727fc955ac..4c83f57176 100644
--- a/tests/Attack.test.ts
+++ b/tests/Attack.test.ts
@@ -1,3 +1,6 @@
+import { AttackExecution } from "../src/core/execution/AttackExecution";
+import { SpawnExecution } from "../src/core/execution/SpawnExecution";
+import { TransportShipExecution } from "../src/core/execution/TransportShipExecution";
import {
Game,
Player,
@@ -5,13 +8,10 @@ import {
PlayerType,
UnitType,
} from "../src/core/game/Game";
-import { AttackExecution } from "../src/core/execution/AttackExecution";
-import { SpawnExecution } from "../src/core/execution/SpawnExecution";
-import { TestConfig } from "./util/TestConfig";
import { TileRef } from "../src/core/game/GameMap";
-import { TransportShipExecution } from "../src/core/execution/TransportShipExecution";
-import { constructionExecution } from "./util/utils";
import { setup } from "./util/Setup";
+import { TestConfig } from "./util/TestConfig";
+import { constructionExecution } from "./util/utils";
let game: Game;
let attacker: Player;
@@ -29,8 +29,8 @@ describe("Attack", () => {
beforeEach(async () => {
game = await setup("ocean_and_land", {
infiniteGold: true,
- instantBuild: true,
infiniteTroops: true,
+ instantBuild: true,
});
const attackerInfo = new PlayerInfo(
"attacker dude",
@@ -130,8 +130,8 @@ describe("Attack race condition with alliance requests", () => {
beforeEach(async () => {
game = await setup("ocean_and_land", {
infiniteGold: true,
- instantBuild: true,
infiniteTroops: true,
+ instantBuild: true,
});
const playerAInfo = new PlayerInfo(
diff --git a/tests/AttackStats.test.ts b/tests/AttackStats.test.ts
index 785851e9a6..1955aec111 100644
--- a/tests/AttackStats.test.ts
+++ b/tests/AttackStats.test.ts
@@ -1,7 +1,7 @@
-import { GOLD_INDEX_WAR, GOLD_INDEX_WORK } from "../src/core/StatsSchemas";
-import { Game, Player, PlayerInfo, PlayerType } from "../src/core/game/Game";
import { AttackExecution } from "../src/core/execution/AttackExecution";
import { SpawnExecution } from "../src/core/execution/SpawnExecution";
+import { Game, Player, PlayerInfo, PlayerType } from "../src/core/game/Game";
+import { GOLD_INDEX_WAR, GOLD_INDEX_WORK } from "../src/core/StatsSchemas";
import { setup } from "./util/Setup";
let game: Game;
diff --git a/tests/BotBehavior.test.ts b/tests/BotBehavior.test.ts
index eb1ea8dd15..701b66958d 100644
--- a/tests/BotBehavior.test.ts
+++ b/tests/BotBehavior.test.ts
@@ -1,3 +1,5 @@
+import { AllianceExtensionExecution } from "../src/core/execution/alliance/AllianceExtensionExecution";
+import { BotBehavior } from "../src/core/execution/utils/BotBehavior";
import {
AllianceRequest,
Game,
@@ -7,8 +9,6 @@ import {
Relation,
Tick,
} from "../src/core/game/Game";
-import { AllianceExtensionExecution } from "../src/core/execution/alliance/AllianceExtensionExecution";
-import { BotBehavior } from "../src/core/execution/utils/BotBehavior";
import { PseudoRandom } from "../src/core/PseudoRandom";
import { setup } from "./util/Setup";
@@ -77,11 +77,11 @@ describe("BotBehavior.handleAllianceRequests", () => {
.mockReturnValue(new Array(alliancesCount));
const mockRequest = {
- requestor: () => requestor,
- recipient: () => player,
- createdAt: () => 0 as unknown as Tick,
accept: jest.fn(),
+ createdAt: () => 0 as unknown as Tick,
+ recipient: () => player,
reject: jest.fn(),
+ requestor: () => requestor,
} as unknown as AllianceRequest;
jest
@@ -120,8 +120,8 @@ describe("BotBehavior.handleAllianceRequests", () => {
test("should accept alliance if requestor is much larger (> 3 times size of recipient) and has too many alliances (>= 3)", () => {
const request = setupAllianceRequest({
- numTilesRequestor: 40,
alliancesCount: 4,
+ numTilesRequestor: 40,
});
botBehavior.handleAllianceRequests();
@@ -132,8 +132,8 @@ describe("BotBehavior.handleAllianceRequests", () => {
test("should accept alliance if requestor is much larger (> 3 times size of recipient) and does not have too many alliances (< 3)", () => {
const request = setupAllianceRequest({
- numTilesRequestor: 40,
alliancesCount: 2,
+ numTilesRequestor: 40,
});
botBehavior.handleAllianceRequests();
@@ -171,8 +171,8 @@ describe("BotBehavior.handleAllianceExtensionRequests", () => {
mockPlayer = {
alliances: jest.fn(() => [mockAlliance]),
- relation: jest.fn(),
id: jest.fn(() => "bot_id"),
+ relation: jest.fn(),
type: jest.fn(() => PlayerType.FakeHuman),
};
diff --git a/tests/Censor.test.ts b/tests/Censor.test.ts
index fc23b7172f..165c74765a 100644
--- a/tests/Censor.test.ts
+++ b/tests/Censor.test.ts
@@ -1,6 +1,9 @@
// Mocking the obscenity library to control its behavior in tests.
jest.mock("obscenity", () => {
return {
+ collapseDuplicatesTransformer: () => ({}),
+ englishDataset: { build: () => ({}) },
+ englishRecommendedTransformers: {},
RegExpMatcher: class {
private readonly dummy: string[] = ["foo", "bar", "leet", "code"];
constructor(_opts: any) {}
@@ -16,9 +19,6 @@ jest.mock("obscenity", () => {
return this.dummy.some((token) => decoded.includes(token));
}
},
- collapseDuplicatesTransformer: () => ({}),
- englishRecommendedTransformers: {},
- englishDataset: { build: () => ({}) },
resolveConfusablesTransformer: () => ({}),
resolveLeetSpeakTransformer: () => ({}),
skipNonAlphabeticTransformer: () => ({}),
@@ -32,10 +32,10 @@ jest.mock("../src/client/Utils", () => ({
}));
import {
- MAX_USERNAME_LENGTH,
- MIN_USERNAME_LENGTH,
fixProfaneUsername,
isProfaneUsername,
+ MAX_USERNAME_LENGTH,
+ MIN_USERNAME_LENGTH,
sanitizeUsername,
validateUsername,
} from "../src/core/validations/username";
@@ -53,14 +53,14 @@ describe("username.ts functions", () => {
describe("isProfaneUsername & fixProfaneUsername with leet decoding (mocked)", () => {
test.each([
- { username: "l33t", profane: true }, // decodes to "leet"
- { username: "L33T", profane: true },
- { username: "l33tc0de", profane: true }, // decodes to "leetcode", contains "leet" and "code"
- { username: "L33TC0DE", profane: true },
- { username: "foo123", profane: true }, // contains "foo"
- { username: "b4r", profane: true }, // decodes to "bar"
- { username: "safeName", profane: false },
- { username: "s4f3", profane: false }, // decodes to "safe" but "safe" not in dummy list
+ { profane: true, username: "l33t" }, // decodes to "leet"
+ { profane: true, username: "L33T" },
+ { profane: true, username: "l33tc0de" }, // decodes to "leetcode", contains "leet" and "code"
+ { profane: true, username: "L33TC0DE" },
+ { profane: true, username: "foo123" }, // contains "foo"
+ { profane: true, username: "b4r" }, // decodes to "bar"
+ { profane: false, username: "safeName" },
+ { profane: false, username: "s4f3" }, // decodes to "safe" but "safe" not in dummy list
])('isProfaneUsername("%s") → %s', ({ username, profane }) => {
expect(isProfaneUsername(username)).toBe(profane);
});
@@ -113,17 +113,17 @@ describe("username.ts functions", () => {
describe("sanitizeUsername", () => {
test.each([
- { input: "GoodName", expected: "GoodName" },
- { input: "a!", expected: "axx" },
- { input: "a$%b", expected: "abx" },
+ { expected: "GoodName", input: "GoodName" },
+ { expected: "axx", input: "a!" },
+ { expected: "abx", input: "a$%b" },
{
- input: "abc".repeat(10),
expected: "abc"
.repeat(Math.floor(MAX_USERNAME_LENGTH / 3))
.slice(0, MAX_USERNAME_LENGTH),
+ input: "abc".repeat(10),
},
- { input: "", expected: "xxx" },
- { input: "Ünicode🐈Test!", expected: "Ünicode🐈Test" },
+ { expected: "xxx", input: "" },
+ { expected: "Ünicode🐈Test", input: "Ünicode🐈Test!" },
])('sanitizeUsername("%s") → "%s"', ({ input, expected }) => {
const out = sanitizeUsername(input);
expect(out).toBe(expected);
diff --git a/tests/Colors.test.ts b/tests/Colors.test.ts
index 515d193370..762eea9c9d 100644
--- a/tests/Colors.test.ts
+++ b/tests/Colors.test.ts
@@ -1,8 +1,8 @@
+import { Colord, colord } from "colord";
import {
ColorAllocator,
selectDistinctColorIndex,
} from "../src/core/configuration/ColorAllocator";
-import { Colord, colord } from "colord";
import {
blue,
botColor,
@@ -16,14 +16,14 @@ import {
import { ColoredTeams } from "../src/core/game/Game";
const mockColors: Colord[] = [
- colord({ r: 255, g: 0, b: 0 }),
- colord({ r: 0, g: 255, b: 0 }),
- colord({ r: 0, g: 0, b: 255 }),
+ colord({ b: 0, g: 0, r: 255 }),
+ colord({ b: 0, g: 255, r: 0 }),
+ colord({ b: 255, g: 0, r: 0 }),
];
const fallbackMockColors: Colord[] = [
- colord({ r: 0, g: 0, b: 0 }),
- colord({ r: 255, g: 255, b: 255 }),
+ colord({ b: 0, g: 0, r: 0 }),
+ colord({ b: 255, g: 255, r: 255 }),
];
const fallbackColors = [...fallbackMockColors, ...mockColors];
@@ -148,19 +148,19 @@ describe("ColorAllocator", () => {
describe("selectDistinctColor", () => {
test("returns the most distant color", () => {
- const assignedColors = [colord({ r: 255, g: 0, b: 0 })]; // bright red
+ const assignedColors = [colord({ b: 0, g: 0, r: 255 })]; // bright red
const availableColors = [
- colord({ r: 254, g: 1, b: 1 }), // too close
- colord({ r: 0, g: 255, b: 0 }), // distinct green
- colord({ r: 0, g: 0, b: 255 }), // distinct blue
+ colord({ b: 1, g: 1, r: 254 }), // too close
+ colord({ b: 0, g: 255, r: 0 }), // distinct green
+ colord({ b: 255, g: 0, r: 0 }), // distinct blue
];
const result = selectDistinctColorIndex(availableColors, assignedColors);
expect(result).not.toBeNull();
const rgb = availableColors[result!].toRgb();
expect([
- { r: 0, g: 255, b: 0, a: 1 },
- { r: 0, g: 0, b: 255, a: 1 },
+ { a: 1, b: 0, g: 255, r: 0 },
+ { a: 1, b: 255, g: 0, r: 0 },
]).toContainEqual(rgb);
});
});
diff --git a/tests/DeleteUnitExecution.test.ts b/tests/DeleteUnitExecution.test.ts
index f529e6112e..f2ad5cc550 100644
--- a/tests/DeleteUnitExecution.test.ts
+++ b/tests/DeleteUnitExecution.test.ts
@@ -1,3 +1,5 @@
+import { DeleteUnitExecution } from "../src/core/execution/DeleteUnitExecution";
+import { SpawnExecution } from "../src/core/execution/SpawnExecution";
import {
Game,
Player,
@@ -6,8 +8,6 @@ import {
Unit,
UnitType,
} from "../src/core/game/Game";
-import { DeleteUnitExecution } from "../src/core/execution/DeleteUnitExecution";
-import { SpawnExecution } from "../src/core/execution/SpawnExecution";
import { TileRef } from "../src/core/game/GameMap";
import { setup } from "./util/Setup";
@@ -20,8 +20,8 @@ describe("DeleteUnitExecution Security Tests", () => {
beforeEach(async () => {
game = await setup("plains", {
infiniteGold: true,
- instantBuild: true,
infiniteTroops: true,
+ instantBuild: true,
});
const player1Info = new PlayerInfo(
diff --git a/tests/Disconnected.test.ts b/tests/Disconnected.test.ts
index e2a6012408..e03138efa8 100644
--- a/tests/Disconnected.test.ts
+++ b/tests/Disconnected.test.ts
@@ -1,8 +1,8 @@
-import { Game, Player, PlayerInfo, PlayerType } from "../src/core/game/Game";
import { MarkDisconnectedExecution } from "../src/core/execution/MarkDisconnectedExecution";
import { SpawnExecution } from "../src/core/execution/SpawnExecution";
-import { executeTicks } from "./util/utils";
+import { Game, Player, PlayerInfo, PlayerType } from "../src/core/game/Game";
import { setup } from "./util/Setup";
+import { executeTicks } from "./util/utils";
let game: Game;
let player1: Player;
diff --git a/tests/Donate.test.ts b/tests/Donate.test.ts
index 2523e7c82c..6634b564db 100644
--- a/tests/Donate.test.ts
+++ b/tests/Donate.test.ts
@@ -1,14 +1,14 @@
-import { PlayerInfo, PlayerType } from "../src/core/game/Game";
import { DonateGoldExecution } from "../src/core/execution/DonateGoldExecution";
import { DonateTroopsExecution } from "../src/core/execution/DonateTroopExecution";
import { SpawnExecution } from "../src/core/execution/SpawnExecution";
+import { PlayerInfo, PlayerType } from "../src/core/game/Game";
import { setup } from "./util/Setup";
describe("Donate troops to an ally", () => {
it("Troops should be successfully donated", async () => {
const game = await setup("ocean_and_land", {
- infiniteTroops: false,
donateTroops: true,
+ infiniteTroops: false,
});
const donorInfo = new PlayerInfo(
@@ -70,8 +70,8 @@ describe("Donate troops to an ally", () => {
describe("Donate gold to an ally", () => {
it("Gold should be successfully donated", async () => {
const game = await setup("ocean_and_land", {
- infiniteGold: false,
donateGold: true,
+ infiniteGold: false,
});
const donorInfo = new PlayerInfo(
@@ -134,8 +134,8 @@ describe("Donate gold to an ally", () => {
describe("Donate troops to a non ally", () => {
it("Troops should not be donated", async () => {
const game = await setup("ocean_and_land", {
- infiniteTroops: false,
donateTroops: true,
+ infiniteTroops: false,
});
const donorInfo = new PlayerInfo(
@@ -194,8 +194,8 @@ describe("Donate troops to a non ally", () => {
describe("Donate Gold to a non ally", () => {
it("Gold should not be donated", async () => {
const game = await setup("ocean_and_land", {
- infiniteGold: false,
donateGold: true,
+ infiniteGold: false,
});
const donorInfo = new PlayerInfo(
diff --git a/tests/MissileSilo.test.ts b/tests/MissileSilo.test.ts
index 7731b2549a..1459a25430 100644
--- a/tests/MissileSilo.test.ts
+++ b/tests/MissileSilo.test.ts
@@ -1,3 +1,6 @@
+import { NukeExecution } from "../src/core/execution/NukeExecution";
+import { SpawnExecution } from "../src/core/execution/SpawnExecution";
+import { UpgradeStructureExecution } from "../src/core/execution/UpgradeStructureExecution";
import {
Game,
Player,
@@ -5,12 +8,9 @@ import {
PlayerType,
UnitType,
} from "../src/core/game/Game";
-import { constructionExecution, executeTicks } from "./util/utils";
-import { NukeExecution } from "../src/core/execution/NukeExecution";
-import { SpawnExecution } from "../src/core/execution/SpawnExecution";
import { TileRef } from "../src/core/game/GameMap";
-import { UpgradeStructureExecution } from "../src/core/execution/UpgradeStructureExecution";
import { setup } from "./util/Setup";
+import { constructionExecution, executeTicks } from "./util/utils";
let game: Game;
let attacker: Player;
diff --git a/tests/ShellRandom.test.ts b/tests/ShellRandom.test.ts
index a8546c1744..5c55903833 100644
--- a/tests/ShellRandom.test.ts
+++ b/tests/ShellRandom.test.ts
@@ -1,3 +1,6 @@
+import { DefensePostExecution } from "../src/core/execution/DefensePostExecution";
+import { ShellExecution } from "../src/core/execution/ShellExecution";
+import { WarshipExecution } from "../src/core/execution/WarshipExecution";
import {
Game,
Player,
@@ -5,9 +8,6 @@ import {
PlayerType,
UnitType,
} from "../src/core/game/Game";
-import { DefensePostExecution } from "../src/core/execution/DefensePostExecution";
-import { ShellExecution } from "../src/core/execution/ShellExecution";
-import { WarshipExecution } from "../src/core/execution/WarshipExecution";
import { setup } from "./util/Setup";
const coastX = 7;
diff --git a/tests/TerritoryCapture.test.ts b/tests/TerritoryCapture.test.ts
index 5724dea323..e46678c08a 100644
--- a/tests/TerritoryCapture.test.ts
+++ b/tests/TerritoryCapture.test.ts
@@ -1,5 +1,5 @@
-import { Player, PlayerInfo, PlayerType } from "../src/core/game/Game";
import { SpawnExecution } from "../src/core/execution/SpawnExecution";
+import { Player, PlayerInfo, PlayerType } from "../src/core/game/Game";
import { setup } from "./util/Setup";
describe("Territory management", () => {
diff --git a/tests/Warship.test.ts b/tests/Warship.test.ts
index fbfc26e80d..b883b65871 100644
--- a/tests/Warship.test.ts
+++ b/tests/Warship.test.ts
@@ -1,3 +1,5 @@
+import { MoveWarshipExecution } from "../src/core/execution/MoveWarshipExecution";
+import { WarshipExecution } from "../src/core/execution/WarshipExecution";
import {
Game,
Player,
@@ -5,10 +7,8 @@ import {
PlayerType,
UnitType,
} from "../src/core/game/Game";
-import { MoveWarshipExecution } from "../src/core/execution/MoveWarshipExecution";
-import { WarshipExecution } from "../src/core/execution/WarshipExecution";
-import { executeTicks } from "./util/utils";
import { setup } from "./util/Setup";
+import { executeTicks } from "./util/utils";
const coastX = 7;
let game: Game;
diff --git a/tests/client/graphics/RadialMenuElements.test.ts b/tests/client/graphics/RadialMenuElements.test.ts
index 29d6b893dc..2fc297d33f 100644
--- a/tests/client/graphics/RadialMenuElements.test.ts
+++ b/tests/client/graphics/RadialMenuElements.test.ts
@@ -2,20 +2,20 @@
* @jest-environment jsdom
*/
import {
- COLORS,
- MenuElementParams,
- Slot,
attackMenuElement,
buildMenuElement,
+ COLORS,
+ MenuElementParams,
rootMenuElement,
+ Slot,
} from "../../../src/client/graphics/layers/RadialMenuElements";
-import { GameView, PlayerView } from "../../../src/core/game/GameView";
-import { TileRef } from "../../../src/core/game/GameMap";
import { UnitType } from "../../../src/core/game/Game";
+import { TileRef } from "../../../src/core/game/GameMap";
+import { GameView, PlayerView } from "../../../src/core/game/GameView";
jest.mock("../../../src/client/Utils", () => ({
- translateText: jest.fn((key: string) => key),
renderNumber: jest.fn((num: number) => num.toString()),
+ translateText: jest.fn((key: string) => key),
}));
jest.mock("../../../src/client/graphics/layers/BuildMenu", () => {
@@ -23,46 +23,46 @@ jest.mock("../../../src/client/graphics/layers/BuildMenu", () => {
return {
flattenedBuildTable: [
{
- unitType: UnitType.City,
- key: "unit_type.city",
+ countable: true,
description: "unit_type.city_desc",
icon: "city-icon",
- countable: true,
+ key: "unit_type.city",
+ unitType: UnitType.City,
},
{
- unitType: UnitType.Factory,
- key: "unit_type.factory",
+ countable: true,
description: "unit_type.factory_desc",
icon: "factory-icon",
- countable: true,
+ key: "unit_type.factory",
+ unitType: UnitType.Factory,
},
{
- unitType: UnitType.AtomBomb,
- key: "unit_type.atom_bomb",
+ countable: false,
description: "unit_type.atom_bomb_desc",
icon: "atom-bomb-icon",
- countable: false,
+ key: "unit_type.atom_bomb",
+ unitType: UnitType.AtomBomb,
},
{
- unitType: UnitType.Warship,
- key: "unit_type.warship",
+ countable: true,
description: "unit_type.warship_desc",
icon: "warship-icon",
- countable: true,
+ key: "unit_type.warship",
+ unitType: UnitType.Warship,
},
{
- unitType: UnitType.HydrogenBomb,
- key: "unit_type.hydrogen_bomb",
+ countable: false,
description: "unit_type.hydrogen_bomb_desc",
icon: "hydrogen-bomb-icon",
- countable: false,
+ key: "unit_type.hydrogen_bomb",
+ unitType: UnitType.HydrogenBomb,
},
{
- unitType: UnitType.MIRV,
- key: "unit_type.mirv",
+ countable: false,
description: "unit_type.mirv_desc",
icon: "mirv-icon",
- countable: false,
+ key: "unit_type.mirv",
+ unitType: UnitType.MIRV,
},
],
};
@@ -95,17 +95,17 @@ describe("RadialMenuElements", () => {
} as unknown as PlayerView;
mockGame = {
- inSpawnPhase: jest.fn(() => false),
- owner: jest.fn(() => mockPlayer),
- isLand: jest.fn(() => true),
config: jest.fn(() => ({
+ isUnitDisabled: jest.fn(() => false),
theme: () => ({
territoryColor: () => ({
lighten: () => ({ alpha: () => ({ toRgbString: () => "#fff" }) }),
}),
}),
- isUnitDisabled: jest.fn(() => false),
})),
+ inSpawnPhase: jest.fn(() => false),
+ isLand: jest.fn(() => true),
+ owner: jest.fn(() => mockPlayer),
} as unknown as GameView;
mockBuildMenu = {
@@ -117,38 +117,38 @@ describe("RadialMenuElements", () => {
mockPlayerActions = {
buildableUnits: [
- { type: UnitType.City, canBuild: true },
- { type: UnitType.Factory, canBuild: true },
- { type: UnitType.AtomBomb, canBuild: true },
- { type: UnitType.Warship, canBuild: true },
- { type: UnitType.HydrogenBomb, canBuild: true },
- { type: UnitType.MIRV, canBuild: true },
- { type: UnitType.TransportShip, canBuild: true },
+ { canBuild: true, type: UnitType.City },
+ { canBuild: true, type: UnitType.Factory },
+ { canBuild: true, type: UnitType.AtomBomb },
+ { canBuild: true, type: UnitType.Warship },
+ { canBuild: true, type: UnitType.HydrogenBomb },
+ { canBuild: true, type: UnitType.MIRV },
+ { canBuild: true, type: UnitType.TransportShip },
],
canAttack: true,
interaction: {
- canSendAllianceRequest: true,
canBreakAlliance: false,
- canDonateTroops: true,
canDonateGold: true,
+ canDonateTroops: true,
+ canSendAllianceRequest: true,
},
};
mockTile = {} as TileRef;
mockParams = {
- myPlayer: mockPlayer,
- selected: mockPlayer,
- tile: mockTile,
- playerActions: mockPlayerActions,
- game: mockGame,
buildMenu: mockBuildMenu,
+ chatIntegration: {} as any,
+ closeMenu: jest.fn(),
emojiTable: {} as any,
+ eventBus: {} as any,
+ game: mockGame,
+ myPlayer: mockPlayer,
playerActionHandler: {} as any,
+ playerActions: mockPlayerActions,
playerPanel: {} as any,
- chatIntegration: {} as any,
- eventBus: {} as any,
- closeMenu: jest.fn(),
+ selected: mockPlayer,
+ tile: mockTile,
};
});
diff --git a/tests/client/graphics/UILayer.test.ts b/tests/client/graphics/UILayer.test.ts
index 6a25048a52..81b5ec98ce 100644
--- a/tests/client/graphics/UILayer.test.ts
+++ b/tests/client/graphics/UILayer.test.ts
@@ -11,8 +11,6 @@ describe("UILayer", () => {
beforeEach(() => {
game = {
- width: () => 100,
- height: () => 100,
config: () => ({
theme: () => ({
territoryColor: () => ({
@@ -20,12 +18,14 @@ describe("UILayer", () => {
}),
}),
}),
- x: () => 10,
- y: () => 10,
- unitInfo: () => ({ maxHealth: 10, constructionDuration: 5 }),
+ height: () => 100,
myPlayer: () => ({ id: () => 1 }),
ticks: () => 1,
+ unitInfo: () => ({ constructionDuration: 5, maxHealth: 10 }),
updatesSinceLastTick: () => undefined,
+ width: () => 100,
+ x: () => 10,
+ y: () => 10,
};
eventBus = { on: jest.fn() };
});
@@ -46,10 +46,10 @@ describe("UILayer", () => {
const ui = new UILayer(game, eventBus);
ui.redraw();
const unit = {
- type: () => "Warship",
isActive: () => true,
- tile: () => ({}),
owner: () => ({}),
+ tile: () => ({}),
+ type: () => "Warship",
};
const event = { isSelected: true, unit };
ui.drawSelectionBox = jest.fn();
@@ -61,13 +61,13 @@ describe("UILayer", () => {
const ui = new UILayer(game, eventBus);
ui.redraw();
const unit = {
- id: () => 1,
- type: () => "Warship",
+ createdAt: () => 1,
health: () => 5,
- tile: () => ({}),
- owner: () => ({}),
+ id: () => 1,
isActive: () => true,
- createdAt: () => 1,
+ owner: () => ({}),
+ tile: () => ({}),
+ type: () => "Warship",
} as unknown as UnitView;
ui.drawHealthBar(unit);
expect(ui["allHealthBars"].has(1)).toBe(true);
@@ -90,12 +90,12 @@ describe("UILayer", () => {
const ui = new UILayer(game, eventBus);
ui.redraw();
const unit = {
- id: () => 1,
- type: () => "Warship",
health: () => 5,
- tile: () => ({}),
- owner: () => ({}),
+ id: () => 1,
isActive: () => true,
+ owner: () => ({}),
+ tile: () => ({}),
+ type: () => "Warship",
} as unknown as UnitView;
ui.drawHealthBar(unit);
expect(ui["allHealthBars"].has(1)).toBe(true);
@@ -111,8 +111,8 @@ describe("UILayer", () => {
ui.redraw();
const unit = {
id: () => 2,
- tile: () => ({}),
isActive: () => true,
+ tile: () => ({}),
} as unknown as UnitView;
ui.createLoadingBar(unit);
expect(ui["allProgressBars"].has(2)).toBe(true);
@@ -122,12 +122,12 @@ describe("UILayer", () => {
const ui = new UILayer(game, eventBus);
ui.redraw();
const unit = {
- id: () => 2,
- type: () => "Construction",
constructionType: () => "City",
+ id: () => 2,
+ isActive: () => true,
owner: () => ({ id: () => 1 }),
tile: () => ({}),
- isActive: () => true,
+ type: () => "Construction",
} as unknown as UnitView;
ui.onUnitEvent(unit);
expect(ui["allProgressBars"].has(2)).toBe(true);
@@ -142,13 +142,13 @@ describe("UILayer", () => {
const ui = new UILayer(game, eventBus);
ui.redraw();
const unit = {
- id: () => 2,
- type: () => "Construction",
constructionType: () => "City",
+ createdAt: () => 1,
+ id: () => 2,
+ isActive: () => true,
owner: () => ({ id: () => 1 }),
tile: () => ({}),
- isActive: () => true,
- createdAt: () => 1,
+ type: () => "Construction",
} as unknown as UnitView;
ui.onUnitEvent(unit);
expect(ui["allProgressBars"].has(2)).toBe(true);
diff --git a/tests/core/executions/NukeExecution.test.ts b/tests/core/executions/NukeExecution.test.ts
index 789fb043c0..5ed577f447 100644
--- a/tests/core/executions/NukeExecution.test.ts
+++ b/tests/core/executions/NukeExecution.test.ts
@@ -1,3 +1,4 @@
+import { NukeExecution } from "../../../src/core/execution/NukeExecution";
import {
Game,
Player,
@@ -5,10 +6,9 @@ import {
PlayerType,
UnitType,
} from "../../../src/core/game/Game";
-import { NukeExecution } from "../../../src/core/execution/NukeExecution";
+import { setup } from "../../util/Setup";
import { TestConfig } from "../../util/TestConfig";
import { executeTicks } from "../../util/utils";
-import { setup } from "../../util/Setup";
let game: Game;
let player: Player;
diff --git a/tests/core/executions/SAMLauncherExecution.test.ts b/tests/core/executions/SAMLauncherExecution.test.ts
index a98eddf1e4..41822bc985 100644
--- a/tests/core/executions/SAMLauncherExecution.test.ts
+++ b/tests/core/executions/SAMLauncherExecution.test.ts
@@ -1,3 +1,7 @@
+import { NukeExecution } from "../../../src/core/execution/NukeExecution";
+import { SAMLauncherExecution } from "../../../src/core/execution/SAMLauncherExecution";
+import { SpawnExecution } from "../../../src/core/execution/SpawnExecution";
+import { UpgradeStructureExecution } from "../../../src/core/execution/UpgradeStructureExecution";
import {
Game,
Player,
@@ -5,12 +9,8 @@ import {
PlayerType,
UnitType,
} from "../../../src/core/game/Game";
-import { constructionExecution, executeTicks } from "../../util/utils";
-import { NukeExecution } from "../../../src/core/execution/NukeExecution";
-import { SAMLauncherExecution } from "../../../src/core/execution/SAMLauncherExecution";
-import { SpawnExecution } from "../../../src/core/execution/SpawnExecution";
-import { UpgradeStructureExecution } from "../../../src/core/execution/UpgradeStructureExecution";
import { setup } from "../../util/Setup";
+import { constructionExecution, executeTicks } from "../../util/utils";
let game: Game;
let attacker: Player;
@@ -86,9 +86,9 @@ describe("SAM", () => {
const nuke = attacker.buildUnit(UnitType.AtomBomb, game.ref(1, 1), {
targetTile: game.ref(3, 1),
trajectory: [
- { tile: game.ref(1, 1), targetable: true },
- { tile: game.ref(2, 1), targetable: true },
- { tile: game.ref(3, 1), targetable: true },
+ { targetable: true, tile: game.ref(1, 1) },
+ { targetable: true, tile: game.ref(2, 1) },
+ { targetable: true, tile: game.ref(3, 1) },
],
});
executeTicks(game, 3);
@@ -102,17 +102,17 @@ describe("SAM", () => {
attacker.buildUnit(UnitType.AtomBomb, game.ref(2, 1), {
targetTile: game.ref(3, 1),
trajectory: [
- { tile: game.ref(1, 1), targetable: true },
- { tile: game.ref(2, 1), targetable: true },
- { tile: game.ref(3, 1), targetable: true },
+ { targetable: true, tile: game.ref(1, 1) },
+ { targetable: true, tile: game.ref(2, 1) },
+ { targetable: true, tile: game.ref(3, 1) },
],
});
attacker.buildUnit(UnitType.AtomBomb, game.ref(1, 2), {
targetTile: game.ref(1, 3),
trajectory: [
- { tile: game.ref(1, 1), targetable: true },
- { tile: game.ref(1, 2), targetable: true },
- { tile: game.ref(1, 3), targetable: true },
+ { targetable: true, tile: game.ref(1, 1) },
+ { targetable: true, tile: game.ref(1, 2) },
+ { targetable: true, tile: game.ref(1, 3) },
],
});
expect(attacker.units(UnitType.AtomBomb)).toHaveLength(2);
@@ -130,9 +130,9 @@ describe("SAM", () => {
const nuke = attacker.buildUnit(UnitType.AtomBomb, game.ref(1, 1), {
targetTile: game.ref(1, 3),
trajectory: [
- { tile: game.ref(1, 1), targetable: true },
- { tile: game.ref(2, 1), targetable: true },
- { tile: game.ref(3, 1), targetable: true },
+ { targetable: true, tile: game.ref(1, 1) },
+ { targetable: true, tile: game.ref(2, 1) },
+ { targetable: true, tile: game.ref(3, 1) },
],
});
@@ -158,9 +158,9 @@ describe("SAM", () => {
const nuke = attacker.buildUnit(UnitType.AtomBomb, game.ref(1, 1), {
targetTile: game.ref(1, 3),
trajectory: [
- { tile: game.ref(1, 1), targetable: true },
- { tile: game.ref(1, 2), targetable: true },
- { tile: game.ref(1, 3), targetable: true },
+ { targetable: true, tile: game.ref(1, 1) },
+ { targetable: true, tile: game.ref(1, 2) },
+ { targetable: true, tile: game.ref(1, 3) },
],
});
diff --git a/tests/core/executions/TradeShipExecution.test.ts b/tests/core/executions/TradeShipExecution.test.ts
index 43879162dd..c23443dc3e 100644
--- a/tests/core/executions/TradeShipExecution.test.ts
+++ b/tests/core/executions/TradeShipExecution.test.ts
@@ -1,5 +1,5 @@
-import { Game, Player, Unit } from "../../../src/core/game/Game";
import { TradeShipExecution } from "../../../src/core/execution/TradeShipExecution";
+import { Game, Player, Unit } from "../../../src/core/game/Game";
import { setup } from "../../util/Setup";
describe("TradeShipExecution", () => {
@@ -22,66 +22,66 @@ describe("TradeShipExecution", () => {
});
game.displayMessage = jest.fn();
origOwner = {
- canBuild: jest.fn(() => true),
+ addGold: jest.fn(),
buildUnit: jest.fn((type, spawn, opts) => tradeShip),
+ canBuild: jest.fn(() => true),
+ canTrade: jest.fn(() => true),
displayName: jest.fn(() => "Origin"),
- addGold: jest.fn(),
- units: jest.fn(() => [dstPort]),
- unitCount: jest.fn(() => 1),
id: jest.fn(() => 1),
- canTrade: jest.fn(() => true),
+ unitCount: jest.fn(() => 1),
+ units: jest.fn(() => [dstPort]),
} as any;
dstOwner = {
- id: jest.fn(() => 2),
addGold: jest.fn(),
+ canTrade: jest.fn(() => true),
displayName: jest.fn(() => "Destination"),
- units: jest.fn(() => [dstPort]),
+ id: jest.fn(() => 2),
unitCount: jest.fn(() => 1),
- canTrade: jest.fn(() => true),
+ units: jest.fn(() => [dstPort]),
} as any;
pirate = {
- id: jest.fn(() => 3),
addGold: jest.fn(),
+ canTrade: jest.fn(() => true),
displayName: jest.fn(() => "Destination"),
- units: jest.fn(() => [piratePort]),
+ id: jest.fn(() => 3),
unitCount: jest.fn(() => 1),
- canTrade: jest.fn(() => true),
+ units: jest.fn(() => [piratePort]),
} as any;
piratePort = {
- tile: jest.fn(() => 40011),
- owner: jest.fn(() => pirate),
isActive: jest.fn(() => true),
+ owner: jest.fn(() => pirate),
+ tile: jest.fn(() => 40011),
} as any;
srcPort = {
- tile: jest.fn(() => 20011),
- owner: jest.fn(() => origOwner),
isActive: jest.fn(() => true),
+ owner: jest.fn(() => origOwner),
+ tile: jest.fn(() => 20011),
} as any;
dstPort = {
- tile: jest.fn(() => 30015), // 15x15
- owner: jest.fn(() => dstOwner),
isActive: jest.fn(() => true),
+ owner: jest.fn(() => dstOwner),
+ tile: jest.fn(() => 30015), // 15x15
} as any;
tradeShip = {
+ delete: jest.fn(),
isActive: jest.fn(() => true),
- owner: jest.fn(() => origOwner),
move: jest.fn(),
- setTargetUnit: jest.fn(),
+ owner: jest.fn(() => origOwner),
setSafeFromPirates: jest.fn(),
- delete: jest.fn(),
+ setTargetUnit: jest.fn(),
tile: jest.fn(() => 2001),
} as any;
tradeShipExecution = new TradeShipExecution(origOwner, srcPort, dstPort);
tradeShipExecution.init(game, 0);
tradeShipExecution["pathFinder"] = {
- nextTile: jest.fn(() => ({ type: 0, node: 2001 })),
+ nextTile: jest.fn(() => ({ node: 2001, type: 0 })),
} as any;
tradeShipExecution["tradeShip"] = tradeShip;
});
@@ -112,7 +112,7 @@ describe("TradeShipExecution", () => {
it("should complete trade and award gold", () => {
tradeShipExecution["pathFinder"] = {
- nextTile: jest.fn(() => ({ type: 2, node: 2001 })),
+ nextTile: jest.fn(() => ({ node: 2001, type: 2 })),
} as any;
tradeShipExecution.tick(1);
expect(tradeShip.delete).toHaveBeenCalledWith(false);
diff --git a/tests/core/game/Cluster.test.ts b/tests/core/game/Cluster.test.ts
index 95758f1fc1..1cb36dd19a 100644
--- a/tests/core/game/Cluster.test.ts
+++ b/tests/core/game/Cluster.test.ts
@@ -2,9 +2,9 @@ import { Cluster, TrainStation } from "../../../src/core/game/TrainStation";
const createMockStation = (id: string): jest.Mocked => {
return {
+ getCluster: jest.fn(() => null),
id,
setCluster: jest.fn(),
- getCluster: jest.fn(() => null),
} as any;
};
diff --git a/tests/core/game/GameImpl.test.ts b/tests/core/game/GameImpl.test.ts
index ae30392326..20f9c253c2 100644
--- a/tests/core/game/GameImpl.test.ts
+++ b/tests/core/game/GameImpl.test.ts
@@ -1,13 +1,13 @@
+import { AttackExecution } from "../../../src/core/execution/AttackExecution";
+import { AllianceRequestExecution } from "../../../src/core/execution/alliance/AllianceRequestExecution";
+import { AllianceRequestReplyExecution } from "../../../src/core/execution/alliance/AllianceRequestReplyExecution";
+import { SpawnExecution } from "../../../src/core/execution/SpawnExecution";
import {
Game,
Player,
PlayerInfo,
PlayerType,
} from "../../../src/core/game/Game";
-import { AllianceRequestExecution } from "../../../src/core/execution/alliance/AllianceRequestExecution";
-import { AllianceRequestReplyExecution } from "../../../src/core/execution/alliance/AllianceRequestReplyExecution";
-import { AttackExecution } from "../../../src/core/execution/AttackExecution";
-import { SpawnExecution } from "../../../src/core/execution/SpawnExecution";
import { TileRef } from "../../../src/core/game/GameMap";
import { setup } from "../../util/Setup";
@@ -21,8 +21,8 @@ describe("GameImpl", () => {
beforeEach(async () => {
game = await setup("ocean_and_land", {
infiniteGold: true,
- instantBuild: true,
infiniteTroops: true,
+ instantBuild: true,
});
const attackerInfo = new PlayerInfo(
"attacker dude",
diff --git a/tests/core/game/RailNetwork.test.ts b/tests/core/game/RailNetwork.test.ts
index 9cd724f697..a253559652 100644
--- a/tests/core/game/RailNetwork.test.ts
+++ b/tests/core/game/RailNetwork.test.ts
@@ -1,24 +1,27 @@
-import { RailNetworkImpl, StationManagerImpl } from "../../../src/core/game/RailNetworkImpl";
-import { Cluster } from "../../../src/core/game/TrainStation";
-import { Railroad } from "../../../src/core/game/Railroad";
import { Unit } from "../../../src/core/game/Game";
+import {
+ RailNetworkImpl,
+ StationManagerImpl,
+} from "../../../src/core/game/RailNetworkImpl";
+import { Railroad } from "../../../src/core/game/Railroad";
+import { Cluster } from "../../../src/core/game/TrainStation";
// Mock types
const createMockStation = (unitId: number): any => {
const cluster = new Cluster();
const railroads = new Set();
return {
+ addRailroad: jest.fn(),
+ clearRailroads: jest.fn(),
+ getCluster: jest.fn(() => cluster),
+ getRailroads: jest.fn(() => railroads),
+ neighbors: jest.fn(() => []),
+ setCluster: jest.fn(),
+ tile: jest.fn(),
unit: {
id: unitId,
setTrainStation: jest.fn(),
},
- tile: jest.fn(),
- neighbors: jest.fn(() => []),
- getCluster: jest.fn(() => cluster),
- setCluster: jest.fn(),
- addRailroad: jest.fn(),
- getRailroads: jest.fn(() => railroads),
- clearRailroads: jest.fn(),
};
};
@@ -52,22 +55,22 @@ describe("RailNetworkImpl", () => {
beforeEach(() => {
stationManager = {
addStation: jest.fn(),
- removeStation: jest.fn(),
findStation: jest.fn(),
getAll: jest.fn(() => new Set()),
+ removeStation: jest.fn(),
};
pathService = {
- findTilePath: jest.fn(() => [0]),
findStationsPath: jest.fn(() => [0]),
+ findTilePath: jest.fn(() => [0]),
};
game = {
- nearbyUnits: jest.fn(() => []),
addExecution: jest.fn(),
config: () => ({
+ railroadMaxSize: () => 100,
trainStationMaxRange: () => 80,
trainStationMinRange: () => 10,
- railroadMaxSize: () => 100,
}),
+ nearbyUnits: jest.fn(() => []),
};
network = new RailNetworkImpl(game, stationManager, pathService);
@@ -150,7 +153,7 @@ describe("RailNetworkImpl", () => {
neighborStation.getCluster = jest.fn(() => cluster);
cluster.has = jest.fn(() => false);
- const neighborUnit = { unit: neighborStation.unit, distSquared: 20 };
+ const neighborUnit = { distSquared: 20, unit: neighborStation.unit };
game.nearbyUnits.mockReturnValue([neighborUnit]);
stationManager.findStation.mockReturnValue(neighborStation);
diff --git a/tests/core/game/TrainStation.test.ts b/tests/core/game/TrainStation.test.ts
index 738abf3f07..549d7e2f2b 100644
--- a/tests/core/game/TrainStation.test.ts
+++ b/tests/core/game/TrainStation.test.ts
@@ -1,6 +1,6 @@
-import { Cluster, TrainStation } from "../../../src/core/game/TrainStation";
-import { Game, Player, Unit, UnitType } from "../../../src/core/game/Game";
import { TrainExecution } from "../../../src/core/execution/TrainExecution";
+import { Game, Player, Unit, UnitType } from "../../../src/core/game/Game";
+import { Cluster, TrainStation } from "../../../src/core/game/TrainStation";
jest.mock("../../../src/core/game/Game");
jest.mock("../../../src/core/execution/TrainExecution");
@@ -14,34 +14,34 @@ describe("TrainStation", () => {
beforeEach(() => {
game = {
- ticks: jest.fn().mockReturnValue(123),
+ addExecution: jest.fn(),
+ addUpdate: jest.fn(),
config: jest.fn().mockReturnValue({
trainGold: (isFriendly: boolean) =>
isFriendly ? BigInt(1000) : BigInt(500),
}),
- addUpdate: jest.fn(),
- addExecution: jest.fn(),
+ ticks: jest.fn().mockReturnValue(123),
} as any;
player = {
addGold: jest.fn(),
- id: 1,
canTrade: jest.fn().mockReturnValue(true),
+ id: 1,
isFriendly: jest.fn().mockReturnValue(false),
} as any;
unit = {
- owner: jest.fn().mockReturnValue(player),
+ isActive: jest.fn().mockReturnValue(true),
level: jest.fn().mockReturnValue(1),
+ owner: jest.fn().mockReturnValue(player),
tile: jest.fn().mockReturnValue({ x: 0, y: 0 }),
type: jest.fn(),
- isActive: jest.fn().mockReturnValue(true),
} as any;
trainExecution = {
+ level: jest.fn(),
loadCargo: jest.fn(),
owner: jest.fn().mockReturnValue(player),
- level: jest.fn(),
} as any;
});
@@ -82,7 +82,7 @@ describe("TrainStation", () => {
it("adds and retrieves neighbors", () => {
const stationA = new TrainStation(game, unit);
const stationB = new TrainStation(game, unit);
- const railRoad = { from: stationA, to: stationB, tiles: [] } as any;
+ const railRoad = { from: stationA, tiles: [], to: stationB } as any;
stationA.addRailroad(railRoad);
@@ -96,8 +96,8 @@ describe("TrainStation", () => {
const railRoad = {
from: stationA,
- to: stationB,
tiles: [{ x: 1, y: 1 }],
+ to: stationB,
} as any;
stationA.addRailroad(railRoad);
diff --git a/tests/perf/AstarPerf.ts b/tests/perf/AstarPerf.ts
index 457399ac1f..b6a8a92dc5 100644
--- a/tests/perf/AstarPerf.ts
+++ b/tests/perf/AstarPerf.ts
@@ -1,7 +1,7 @@
import Benchmark from "benchmark";
-import { PathFinder } from "../../src/core/pathfinding/PathFinding";
import { dirname } from "path";
import { fileURLToPath } from "url";
+import { PathFinder } from "../../src/core/pathfinding/PathFinding";
import { setup } from "../util/Setup";
const game = await setup(
diff --git a/tests/server/Privilege.customFlag.test.ts b/tests/server/Privilege.customFlag.test.ts
index b314b499fa..ce5908fa2b 100644
--- a/tests/server/Privilege.customFlag.test.ts
+++ b/tests/server/Privilege.customFlag.test.ts
@@ -7,22 +7,22 @@ describe("PrivilegeChecker.isCustomFlagAllowed (with mock cosmetics)", () => {
};
const mockCosmetics: Cosmetics = {
- patterns: {},
flag: {
+ color: {
+ a: { color: "#ff0000", flares: ["cosmetic:red"], name: "red" },
+ b: { color: "#00ff00", name: "green" },
+ c: { color: "#0000ff", flares: ["cosmetic:blue"], name: "blue" },
+ },
layers: {
a: {
- name: "chocolate",
flares: ["cosmetic:flags"],
+ name: "chocolate",
},
b: { name: "center_hline" },
c: { name: "admin_layer" },
},
- color: {
- a: { color: "#ff0000", name: "red", flares: ["cosmetic:red"] },
- b: { color: "#00ff00", name: "green" },
- c: { color: "#0000ff", name: "blue", flares: ["cosmetic:blue"] },
- },
},
+ patterns: {},
};
const checker = new PrivilegeCheckerImpl(mockCosmetics, dummyPatternDecoder);
diff --git a/tests/util/Setup.ts b/tests/util/Setup.ts
index e509048646..c170a2dd31 100644
--- a/tests/util/Setup.ts
+++ b/tests/util/Setup.ts
@@ -1,3 +1,6 @@
+import fs from "fs";
+import path from "path";
+import { z } from "zod";
import {
Difficulty,
Game,
@@ -7,18 +10,15 @@ import {
PlayerInfo,
PlayerType,
} from "../../src/core/game/Game";
+import { createGame } from "../../src/core/game/GameImpl";
import {
- MapManifestSchema,
genTerrainFromBin,
+ MapManifestSchema,
} from "../../src/core/game/TerrainMapLoader";
+import { UserSettings } from "../../src/core/game/UserSettings";
import { GameConfig } from "../../src/core/Schemas";
import { TestConfig } from "./TestConfig";
import { TestServerConfig } from "./TestServerConfig";
-import { UserSettings } from "../../src/core/game/UserSettings";
-import { createGame } from "../../src/core/game/GameImpl";
-import fs from "fs";
-import path from "path";
-import { z } from "zod";
export async function setup(
mapName: string,
diff --git a/tests/util/TestConfig.ts b/tests/util/TestConfig.ts
index 3b6bd9373a..69b23f3cdd 100644
--- a/tests/util/TestConfig.ts
+++ b/tests/util/TestConfig.ts
@@ -1,3 +1,5 @@
+import { NukeMagnitude } from "../../src/core/configuration/Config";
+import { DefaultConfig } from "../../src/core/configuration/DefaultConfig";
import {
Game,
Player,
@@ -5,8 +7,6 @@ import {
Tick,
UnitType,
} from "../../src/core/game/Game";
-import { DefaultConfig } from "../../src/core/configuration/DefaultConfig";
-import { NukeMagnitude } from "../../src/core/configuration/Config";
import { TileRef } from "../../src/core/game/GameMap";
export class TestConfig extends DefaultConfig {
diff --git a/tests/util/TestServerConfig.ts b/tests/util/TestServerConfig.ts
index 2f0a23ee1e..86a277d65a 100644
--- a/tests/util/TestServerConfig.ts
+++ b/tests/util/TestServerConfig.ts
@@ -1,7 +1,7 @@
+import { JWK } from "jose";
import { GameEnv, ServerConfig } from "../../src/core/configuration/Config";
-import { GameID } from "../../src/core/Schemas";
import { GameMapType } from "../../src/core/game/Game";
-import { JWK } from "jose";
+import { GameID } from "../../src/core/Schemas";
export class TestServerConfig implements ServerConfig {
allowedFlares(): string[] | undefined {
diff --git a/tests/util/utils.ts b/tests/util/utils.ts
index 3a8f3a2e39..dbdfb3d1dc 100644
--- a/tests/util/utils.ts
+++ b/tests/util/utils.ts
@@ -3,8 +3,8 @@
// However buildUnit do not create executions (e.g.: WarshipExecution)
// If you also need execution use function below. Does not work with things not
-import { Game, Player, UnitType } from "../../src/core/game/Game";
import { ConstructionExecution } from "../../src/core/execution/ConstructionExecution";
+import { Game, Player, UnitType } from "../../src/core/game/Game";
// built via UI (e.g.: trade ships)
export function constructionExecution(
diff --git a/webpack.config.js b/webpack.config.js
index a60ae5367b..0820e8cd00 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -1,9 +1,9 @@
+import { execSync } from "child_process";
import CopyPlugin from "copy-webpack-plugin";
import ESLintPlugin from "eslint-webpack-plugin";
import HtmlWebpackPlugin from "html-webpack-plugin";
-import { execSync } from "child_process";
-import { fileURLToPath } from "url";
import path from "path";
+import { fileURLToPath } from "url";
import webpack from "webpack";
const __filename = fileURLToPath(import.meta.url);
@@ -111,13 +111,13 @@ export default async (env, argv) => {
// Add optimization for HTML
minify: isProduction
? {
- collapseWhitespace: true,
- removeComments: true,
- removeRedundantAttributes: true,
- removeScriptTypeAttributes: true,
- removeStyleLinkTypeAttributes: true,
- useShortDoctype: true,
- }
+ collapseWhitespace: true,
+ removeComments: true,
+ removeRedundantAttributes: true,
+ removeScriptTypeAttributes: true,
+ removeStyleLinkTypeAttributes: true,
+ useShortDoctype: true,
+ }
: false,
}),
new webpack.DefinePlugin({
@@ -160,91 +160,91 @@ export default async (env, argv) => {
devServer: isProduction
? {}
: {
- devMiddleware: { writeToDisk: true },
- static: {
- directory: path.join(__dirname, "static"),
- },
- historyApiFallback: true,
- compress: true,
- port: 9000,
- proxy: [
- // WebSocket proxies
- {
- context: ["/socket"],
- target: "ws://localhost:3000",
- ws: true,
- changeOrigin: true,
- logLevel: "debug",
- },
- // Worker WebSocket proxies - using direct paths without /socket suffix
- {
- context: ["/w0"],
- target: "ws://localhost:3001",
- ws: true,
- secure: false,
- changeOrigin: true,
- logLevel: "debug",
- },
- {
- context: ["/w1"],
- target: "ws://localhost:3002",
- ws: true,
- secure: false,
- changeOrigin: true,
- logLevel: "debug",
- },
- {
- context: ["/w2"],
- target: "ws://localhost:3003",
- ws: true,
- secure: false,
- changeOrigin: true,
- logLevel: "debug",
- },
- // Worker proxies for HTTP requests
- {
- context: ["/w0"],
- target: "http://localhost:3001",
- pathRewrite: { "^/w0": "" },
- secure: false,
- changeOrigin: true,
- logLevel: "debug",
- },
- {
- context: ["/w1"],
- target: "http://localhost:3002",
- pathRewrite: { "^/w1": "" },
- secure: false,
- changeOrigin: true,
- logLevel: "debug",
- },
- {
- context: ["/w2"],
- target: "http://localhost:3003",
- pathRewrite: { "^/w2": "" },
- secure: false,
- changeOrigin: true,
- logLevel: "debug",
- },
- // Original API endpoints
- {
- context: [
- "/api/env",
- "/api/game",
- "/api/public_lobbies",
- "/api/join_game",
- "/api/start_game",
- "/api/create_game",
- "/api/archive_singleplayer_game",
- "/api/auth/callback",
- "/api/auth/discord",
- "/api/kick_player",
- ],
- target: "http://localhost:3000",
- secure: false,
- changeOrigin: true,
+ devMiddleware: { writeToDisk: true },
+ static: {
+ directory: path.join(__dirname, "static"),
},
- ],
- },
+ historyApiFallback: true,
+ compress: true,
+ port: 9000,
+ proxy: [
+ // WebSocket proxies
+ {
+ context: ["/socket"],
+ target: "ws://localhost:3000",
+ ws: true,
+ changeOrigin: true,
+ logLevel: "debug",
+ },
+ // Worker WebSocket proxies - using direct paths without /socket suffix
+ {
+ context: ["/w0"],
+ target: "ws://localhost:3001",
+ ws: true,
+ secure: false,
+ changeOrigin: true,
+ logLevel: "debug",
+ },
+ {
+ context: ["/w1"],
+ target: "ws://localhost:3002",
+ ws: true,
+ secure: false,
+ changeOrigin: true,
+ logLevel: "debug",
+ },
+ {
+ context: ["/w2"],
+ target: "ws://localhost:3003",
+ ws: true,
+ secure: false,
+ changeOrigin: true,
+ logLevel: "debug",
+ },
+ // Worker proxies for HTTP requests
+ {
+ context: ["/w0"],
+ target: "http://localhost:3001",
+ pathRewrite: { "^/w0": "" },
+ secure: false,
+ changeOrigin: true,
+ logLevel: "debug",
+ },
+ {
+ context: ["/w1"],
+ target: "http://localhost:3002",
+ pathRewrite: { "^/w1": "" },
+ secure: false,
+ changeOrigin: true,
+ logLevel: "debug",
+ },
+ {
+ context: ["/w2"],
+ target: "http://localhost:3003",
+ pathRewrite: { "^/w2": "" },
+ secure: false,
+ changeOrigin: true,
+ logLevel: "debug",
+ },
+ // Original API endpoints
+ {
+ context: [
+ "/api/env",
+ "/api/game",
+ "/api/public_lobbies",
+ "/api/join_game",
+ "/api/start_game",
+ "/api/create_game",
+ "/api/archive_singleplayer_game",
+ "/api/auth/callback",
+ "/api/auth/discord",
+ "/api/kick_player",
+ ],
+ target: "http://localhost:3000",
+ secure: false,
+ changeOrigin: true,
+ },
+ ],
+ },
};
};