build: migrate build system to Vite and test runner to Vitest & Remove depracated husky usage (#2703)

- Replace Webpack with Vite for faster client bundling and HMR.
- Migrate tests from Jest to Vitest and update configuration.
- Update Web Worker instantiation to standard ESM syntax.
- Implement Env utility in `src/core` for safe, hybrid environment
variable access (Vite vs Node).
- Refactor configuration loaders to remove direct `process.env`
dependencies in shared code.
- Update TypeScript environment definitions and project scripts for the
new toolchain.
- Remove the [depracated usage of the
husky](https://github.com/typicode/husky/releases/tag/v9.0.1).

## Description:

migrate build system to Vite and test runner to Vitest & Remove
depracated husky usage

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [ ] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

wraith4081

---------

Co-authored-by: evanpelle <evanpelle@gmail.com>
This commit is contained in:
Wraith
2025-12-28 22:10:26 -08:00
committed by GitHub
co-authored by evanpelle
parent f6412a5979
commit 26f5d40819
75 changed files with 2765 additions and 10503 deletions
+11 -11
View File
@@ -1,16 +1,5 @@
import { LitElement, css, html } from "lit";
import { customElement, state } from "lit/decorators.js";
import warshipIcon from "../../../../resources/images/BattleshipIconWhite.svg";
import cityIcon from "../../../../resources/images/CityIconWhite.svg";
import factoryIcon from "../../../../resources/images/FactoryIconWhite.svg";
import goldCoinIcon from "../../../../resources/images/GoldCoinIcon.svg";
import mirvIcon from "../../../../resources/images/MIRVIcon.svg";
import missileSiloIcon from "../../../../resources/images/MissileSiloIconWhite.svg";
import hydrogenBombIcon from "../../../../resources/images/MushroomCloudIconWhite.svg";
import atomBombIcon from "../../../../resources/images/NukeIconWhite.svg";
import portIcon from "../../../../resources/images/PortIcon.svg";
import samlauncherIcon from "../../../../resources/images/SamLauncherIconWhite.svg";
import shieldIcon from "../../../../resources/images/ShieldIconWhite.svg";
import { translateText } from "../../../client/Utils";
import { EventBus } from "../../../core/EventBus";
import {
@@ -34,6 +23,17 @@ import {
import { renderNumber } from "../../Utils";
import { TransformHandler } from "../TransformHandler";
import { Layer } from "./Layer";
import warshipIcon from "/images/BattleshipIconWhite.svg?url";
import cityIcon from "/images/CityIconWhite.svg?url";
import factoryIcon from "/images/FactoryIconWhite.svg?url";
import goldCoinIcon from "/images/GoldCoinIcon.svg?url";
import mirvIcon from "/images/MIRVIcon.svg?url";
import missileSiloIcon from "/images/MissileSiloIconWhite.svg?url";
import hydrogenBombIcon from "/images/MushroomCloudIconWhite.svg?url";
import atomBombIcon from "/images/NukeIconWhite.svg?url";
import portIcon from "/images/PortIcon.svg?url";
import samlauncherIcon from "/images/SamLauncherIconWhite.svg?url";
import shieldIcon from "/images/ShieldIconWhite.svg?url";
export interface BuildItemDisplay {
unitType: UnitType;
+1 -1
View File
@@ -4,7 +4,7 @@ import { customElement, query } from "lit/decorators.js";
import { PlayerType } from "../../../core/game/Game";
import { GameView, PlayerView } from "../../../core/game/GameView";
import quickChatData from "../../../../resources/QuickChat.json";
import quickChatData from "../../../assets/data/QuickChat.json" with { type: "json" };
import { EventBus } from "../../../core/EventBus";
import { CloseViewEvent } from "../../InputHandler";
import { SendQuickChatEvent } from "../../Transport";
+5 -5
View File
@@ -2,11 +2,6 @@ import { html, LitElement } from "lit";
import { customElement, query, state } from "lit/decorators.js";
import { DirectiveResult } from "lit/directive.js";
import { unsafeHTML, UnsafeHTMLDirective } from "lit/directives/unsafe-html.js";
import allianceIcon from "../../../../resources/images/AllianceIconWhite.svg";
import chatIcon from "../../../../resources/images/ChatIconWhite.svg";
import donateGoldIcon from "../../../../resources/images/DonateGoldIconWhite.svg";
import nukeIcon from "../../../../resources/images/NukeIconWhite.svg";
import swordIcon from "../../../../resources/images/SwordIconWhite.svg";
import { EventBus } from "../../../core/EventBus";
import {
AllPlayers,
@@ -50,6 +45,11 @@ import {
import { getMessageTypeClasses, translateText } from "../../Utils";
import { UIState } from "../UIState";
import allianceIcon from "/images/AllianceIconWhite.svg?url";
import chatIcon from "/images/ChatIconWhite.svg?url";
import donateGoldIcon from "/images/DonateGoldIconWhite.svg?url";
import nukeIcon from "/images/NukeIconWhite.svg?url";
import swordIcon from "/images/SwordIconWhite.svg?url";
interface GameEvent {
description: string;
@@ -1,14 +1,14 @@
import { Colord } from "colord";
import { html, LitElement } from "lit";
import { customElement, state } from "lit/decorators.js";
import leaderboardRegularIcon from "../../../../resources/images/LeaderboardIconRegularWhite.svg";
import leaderboardSolidIcon from "../../../../resources/images/LeaderboardIconSolidWhite.svg";
import teamRegularIcon from "../../../../resources/images/TeamIconRegularWhite.svg";
import teamSolidIcon from "../../../../resources/images/TeamIconSolidWhite.svg";
import { GameMode } from "../../../core/game/Game";
import { GameView } from "../../../core/game/GameView";
import { translateText } from "../../Utils";
import { Layer } from "./Layer";
import leaderboardRegularIcon from "/images/LeaderboardIconRegularWhite.svg?url";
import leaderboardSolidIcon from "/images/LeaderboardIconSolidWhite.svg?url";
import teamRegularIcon from "/images/TeamIconRegularWhite.svg?url";
import teamSolidIcon from "/images/TeamIconSolidWhite.svg?url";
@customElement("game-left-sidebar")
export class GameLeftSidebar extends LitElement implements Layer {
@@ -1,10 +1,5 @@
import { html, LitElement } from "lit";
import { customElement, state } from "lit/decorators.js";
import exitIcon from "../../../../resources/images/ExitIconWhite.svg";
import FastForwardIconSolid from "../../../../resources/images/FastForwardIconSolidWhite.svg";
import pauseIcon from "../../../../resources/images/PauseIconWhite.svg";
import playIcon from "../../../../resources/images/PlayIconWhite.svg";
import settingsIcon from "../../../../resources/images/SettingIconWhite.svg";
import { EventBus } from "../../../core/EventBus";
import { GameType } from "../../../core/game/Game";
import { GameUpdateType } from "../../../core/game/GameUpdates";
@@ -15,6 +10,11 @@ import { translateText } from "../../Utils";
import { Layer } from "./Layer";
import { ShowReplayPanelEvent } from "./ReplayPanel";
import { ShowSettingsModalEvent } from "./SettingsModal";
import exitIcon from "/images/ExitIconWhite.svg?url";
import FastForwardIconSolid from "/images/FastForwardIconSolidWhite.svg?url";
import pauseIcon from "/images/PauseIconWhite.svg?url";
import playIcon from "/images/PlayIconWhite.svg?url";
import settingsIcon from "/images/SettingIconWhite.svg?url";
@customElement("game-right-sidebar")
export class GameRightSidebar extends LitElement implements Layer {
+2 -2
View File
@@ -19,9 +19,9 @@ import {
MenuElementParams,
rootMenuElement,
} from "./RadialMenuElements";
import donateTroopIcon from "/images/DonateTroopIconWhite.svg?url";
import swordIcon from "/images/SwordIconWhite.svg?url";
import donateTroopIcon from "../../../../resources/images/DonateTroopIconWhite.svg";
import swordIcon from "../../../../resources/images/SwordIconWhite.svg";
import { ContextMenuEvent } from "../../InputHandler";
@customElement("main-radial-menu")
+1 -1
View File
@@ -1,4 +1,3 @@
import shieldIcon from "../../../../resources/images/ShieldIconBlack.svg";
import { renderPlayerFlag } from "../../../core/CustomFlag";
import { EventBus } from "../../../core/EventBus";
import { PseudoRandom } from "../../../core/PseudoRandom";
@@ -17,6 +16,7 @@ import {
} from "../PlayerIcons";
import { TransformHandler } from "../TransformHandler";
import { Layer } from "./Layer";
import shieldIcon from "/images/ShieldIconBlack.svg?url";
class RenderInfo {
public icons: Map<PlayerIconId, HTMLElement> = new Map(); // Track icon elements
@@ -1,14 +1,6 @@
import { LitElement, TemplateResult, html } from "lit";
import { ref } from "lit-html/directives/ref.js";
import { customElement, property, state } from "lit/decorators.js";
import allianceIcon from "../../../../resources/images/AllianceIcon.svg";
import warshipIcon from "../../../../resources/images/BattleshipIconWhite.svg";
import cityIcon from "../../../../resources/images/CityIconWhite.svg";
import factoryIcon from "../../../../resources/images/FactoryIconWhite.svg";
import goldCoinIcon from "../../../../resources/images/GoldCoinIcon.svg";
import missileSiloIcon from "../../../../resources/images/MissileSiloIconWhite.svg";
import portIcon from "../../../../resources/images/PortIcon.svg";
import samLauncherIcon from "../../../../resources/images/SamLauncherIconWhite.svg";
import { renderPlayerFlag } from "../../../core/CustomFlag";
import { EventBus } from "../../../core/EventBus";
import {
@@ -32,6 +24,14 @@ import { getFirstPlacePlayer, getPlayerIcons } from "../PlayerIcons";
import { TransformHandler } from "../TransformHandler";
import { Layer } from "./Layer";
import { CloseRadialMenuEvent } from "./RadialMenu";
import allianceIcon from "/images/AllianceIcon.svg?url";
import warshipIcon from "/images/BattleshipIconWhite.svg?url";
import cityIcon from "/images/CityIconWhite.svg?url";
import factoryIcon from "/images/FactoryIconWhite.svg?url";
import goldCoinIcon from "/images/GoldCoinIcon.svg?url";
import missileSiloIcon from "/images/MissileSiloIconWhite.svg?url";
import portIcon from "/images/PortIcon.svg?url";
import samLauncherIcon from "/images/SamLauncherIconWhite.svg?url";
function euclideanDistWorld(
coord: { x: number; y: number },
+12 -12
View File
@@ -1,15 +1,6 @@
import { html, LitElement } from "lit";
import { customElement, state } from "lit/decorators.js";
import allianceIcon from "../../../../resources/images/AllianceIconWhite.svg";
import chatIcon from "../../../../resources/images/ChatIconWhite.svg";
import donateGoldIcon from "../../../../resources/images/DonateGoldIconWhite.svg";
import donateTroopIcon from "../../../../resources/images/DonateTroopIconWhite.svg";
import emojiIcon from "../../../../resources/images/EmojiIconWhite.svg";
import stopTradingIcon from "../../../../resources/images/StopIconWhite.png";
import targetIcon from "../../../../resources/images/TargetIconWhite.svg";
import startTradingIcon from "../../../../resources/images/TradingIconWhite.png";
import traitorIcon from "../../../../resources/images/TraitorIconLightRed.svg";
import breakAllianceIcon from "../../../../resources/images/TraitorIconWhite.svg";
import Countries from "../../../assets/data/countries.json" with { type: "json" };
import { EventBus } from "../../../core/EventBus";
import {
AllPlayers,
@@ -23,7 +14,6 @@ import { GameView, PlayerView } from "../../../core/game/GameView";
import { Emoji, flattenedEmojiTable } from "../../../core/Util";
import { actionButton } from "../../components/ui/ActionButton";
import "../../components/ui/Divider";
import Countries from "../../data/countries.json";
import { CloseViewEvent, MouseUpEvent } from "../../InputHandler";
import {
SendAllianceRequestIntentEvent,
@@ -44,6 +34,16 @@ import { ChatModal } from "./ChatModal";
import { EmojiTable } from "./EmojiTable";
import { Layer } from "./Layer";
import "./SendResourceModal";
import allianceIcon from "/images/AllianceIconWhite.svg?url";
import chatIcon from "/images/ChatIconWhite.svg?url";
import donateGoldIcon from "/images/DonateGoldIconWhite.svg?url";
import donateTroopIcon from "/images/DonateTroopIconWhite.svg?url";
import emojiIcon from "/images/EmojiIconWhite.svg?url";
import stopTradingIcon from "/images/StopIconWhite.png?url";
import targetIcon from "/images/TargetIconWhite.svg?url";
import startTradingIcon from "/images/TradingIconWhite.png?url";
import traitorIcon from "/images/TraitorIconLightRed.svg?url";
import breakAllianceIcon from "/images/TraitorIconWhite.svg?url";
@customElement("player-panel")
export class PlayerPanel extends LitElement implements Layer {
@@ -445,7 +445,7 @@ export class PlayerPanel extends LitElement implements Layer {
${country && typeof flagCode === "string"
? html`<img
src="/flags/${encodeURIComponent(flagCode)}.svg"
alt=${country?.name || "Flag"}
alt=${country?.name ?? "Flag"}
class="h-10 w-10 rounded-full object-cover"
@error=${(e: Event) => {
(e.target as HTMLImageElement).style.display = "none";
+1 -1
View File
@@ -1,5 +1,4 @@
import * as d3 from "d3";
import backIcon from "../../../../resources/images/BackIconWhite.svg";
import { EventBus, GameEvent } from "../../../core/EventBus";
import { CloseViewEvent } from "../../InputHandler";
import { getSvgAspectRatio, translateText } from "../../Utils";
@@ -10,6 +9,7 @@ import {
MenuElementParams,
TooltipKey,
} from "./RadialMenuElements";
import backIcon from "/images/BackIconWhite.svg?url";
export class CloseRadialMenuEvent implements GameEvent {
constructor() {}
@@ -12,19 +12,19 @@ import { PlayerActionHandler } from "./PlayerActionHandler";
import { PlayerPanel } from "./PlayerPanel";
import { TooltipItem } from "./RadialMenu";
import allianceIcon from "../../../../resources/images/AllianceIconWhite.svg";
import boatIcon from "../../../../resources/images/BoatIconWhite.svg";
import buildIcon from "../../../../resources/images/BuildIconWhite.svg";
import chatIcon from "../../../../resources/images/ChatIconWhite.svg";
import donateGoldIcon from "../../../../resources/images/DonateGoldIconWhite.svg";
import donateTroopIcon from "../../../../resources/images/DonateTroopIconWhite.svg";
import emojiIcon from "../../../../resources/images/EmojiIconWhite.svg";
import infoIcon from "../../../../resources/images/InfoIcon.svg";
import swordIcon from "../../../../resources/images/SwordIconWhite.svg";
import targetIcon from "../../../../resources/images/TargetIconWhite.svg";
import traitorIcon from "../../../../resources/images/TraitorIconWhite.svg";
import xIcon from "../../../../resources/images/XIcon.svg";
import { EventBus } from "../../../core/EventBus";
import allianceIcon from "/images/AllianceIconWhite.svg?url";
import boatIcon from "/images/BoatIconWhite.svg?url";
import buildIcon from "/images/BuildIconWhite.svg?url";
import chatIcon from "/images/ChatIconWhite.svg?url";
import donateGoldIcon from "/images/DonateGoldIconWhite.svg?url";
import donateTroopIcon from "/images/DonateTroopIconWhite.svg?url";
import emojiIcon from "/images/EmojiIconWhite.svg?url";
import infoIcon from "/images/InfoIcon.svg?url";
import swordIcon from "/images/SwordIconWhite.svg?url";
import targetIcon from "/images/TargetIconWhite.svg?url";
import traitorIcon from "/images/TraitorIconWhite.svg?url";
import xIcon from "/images/XIcon.svg?url";
export interface MenuElementParams {
myPlayer: PlayerView;
+12 -12
View File
@@ -1,17 +1,5 @@
import { html, LitElement } from "lit";
import { customElement, property, query, state } from "lit/decorators.js";
import structureIcon from "../../../../resources/images/CityIconWhite.svg";
import cursorPriceIcon from "../../../../resources/images/CursorPriceIconWhite.svg";
import darkModeIcon from "../../../../resources/images/DarkModeIconWhite.svg";
import emojiIcon from "../../../../resources/images/EmojiIconWhite.svg";
import exitIcon from "../../../../resources/images/ExitIconWhite.svg";
import explosionIcon from "../../../../resources/images/ExplosionIconWhite.svg";
import mouseIcon from "../../../../resources/images/MouseIconWhite.svg";
import ninjaIcon from "../../../../resources/images/NinjaIconWhite.svg";
import settingsIcon from "../../../../resources/images/SettingIconWhite.svg";
import sirenIcon from "../../../../resources/images/SirenIconWhite.svg";
import treeIcon from "../../../../resources/images/TreeIconWhite.svg";
import musicIcon from "../../../../resources/images/music.svg";
import { EventBus } from "../../../core/EventBus";
import { UserSettings } from "../../../core/game/UserSettings";
import { AlternateViewEvent, RefreshGraphicsEvent } from "../../InputHandler";
@@ -19,6 +7,18 @@ import { PauseGameIntentEvent } from "../../Transport";
import { translateText } from "../../Utils";
import SoundManager from "../../sound/SoundManager";
import { Layer } from "./Layer";
import structureIcon from "/images/CityIconWhite.svg?url";
import cursorPriceIcon from "/images/CursorPriceIconWhite.svg?url";
import darkModeIcon from "/images/DarkModeIconWhite.svg?url";
import emojiIcon from "/images/EmojiIconWhite.svg?url";
import exitIcon from "/images/ExitIconWhite.svg?url";
import explosionIcon from "/images/ExplosionIconWhite.svg?url";
import mouseIcon from "/images/MouseIconWhite.svg?url";
import ninjaIcon from "/images/NinjaIconWhite.svg?url";
import settingsIcon from "/images/SettingIconWhite.svg?url";
import sirenIcon from "/images/SirenIconWhite.svg?url";
import treeIcon from "/images/TreeIconWhite.svg?url";
import musicIcon from "/images/music.svg?url";
export class ShowSettingsModalEvent {
constructor(
@@ -3,13 +3,12 @@ import { Theme } from "../../../core/configuration/Config";
import { Cell, UnitType } from "../../../core/game/Game";
import { GameView, PlayerView, UnitView } from "../../../core/game/GameView";
import { TransformHandler } from "../TransformHandler";
import anchorIcon from "../../../../resources/images/AnchorIcon.png";
import cityIcon from "../../../../resources/images/CityIcon.png";
import factoryIcon from "../../../../resources/images/FactoryUnit.png";
import missileSiloIcon from "../../../../resources/images/MissileSiloUnit.png";
import SAMMissileIcon from "../../../../resources/images/SamLauncherUnit.png";
import shieldIcon from "../../../../resources/images/ShieldIcon.png";
import anchorIcon from "/images/AnchorIcon.png?url";
import cityIcon from "/images/CityIcon.png?url";
import factoryIcon from "/images/FactoryUnit.png?url";
import missileSiloIcon from "/images/MissileSiloUnit.png?url";
import SAMMissileIcon from "/images/SamLauncherUnit.png?url";
import shieldIcon from "/images/ShieldIcon.png?url";
export const STRUCTURE_SHAPES: Partial<Record<UnitType, ShapeType>> = {
[UnitType.City]: "circle",
@@ -2,7 +2,6 @@ import { extend } from "colord";
import a11yPlugin from "colord/plugins/a11y";
import { OutlineFilter } from "pixi-filters";
import * as PIXI from "pixi.js";
import bitmapFont from "../../../../resources/fonts/round_6x6_modified.xml";
import { Theme } from "../../../core/configuration/Config";
import { EventBus } from "../../../core/EventBus";
import {
@@ -40,6 +39,7 @@ import {
STRUCTURE_SHAPES,
ZOOM_THRESHOLD,
} from "./StructureDrawingUtils";
import bitmapFont from "/fonts/round_6x6_modified.xml?url";
extend([a11yPlugin]);
@@ -75,7 +75,8 @@ export class StructureIconsLayer implements Layer {
public playerActions: PlayerActions | null = null;
private dotsStage: PIXI.Container;
private readonly theme: Theme;
private renderer: PIXI.Renderer;
private renderer: PIXI.Renderer | null = null;
private rendererInitialized: boolean = false;
private renders: StructureRenderInfo[] = [];
private readonly seenUnits: Set<UnitView> = new Set();
private readonly mousePos = { x: 0, y: 0 };
@@ -113,7 +114,7 @@ export class StructureIconsLayer implements Layer {
} catch (error) {
console.error("Failed to load bitmap font:", error);
}
this.renderer = new PIXI.WebGLRenderer();
const renderer = new PIXI.WebGLRenderer();
this.pixicanvas = document.createElement("canvas");
this.pixicanvas.width = window.innerWidth;
this.pixicanvas.height = window.innerHeight;
@@ -143,7 +144,7 @@ export class StructureIconsLayer implements Layer {
this.rootStage.position.set(0, 0);
this.rootStage.setSize(this.pixicanvas.width, this.pixicanvas.height);
await this.renderer.init({
await renderer.init({
canvas: this.pixicanvas,
resolution: 1,
width: this.pixicanvas.width,
@@ -153,6 +154,9 @@ export class StructureIconsLayer implements Layer {
backgroundAlpha: 0,
backgroundColor: 0x00000000,
});
this.renderer = renderer;
this.rendererInitialized = true;
}
shouldTransform(): boolean {
@@ -202,7 +206,7 @@ export class StructureIconsLayer implements Layer {
}
renderLayer(mainContext: CanvasRenderingContext2D) {
if (!this.renderer) {
if (!this.renderer || !this.rendererInitialized) {
return;
}
+6 -6
View File
@@ -4,16 +4,16 @@ import { EventBus } from "../../../core/EventBus";
import { TransformHandler } from "../TransformHandler";
import { Layer } from "./Layer";
import cityIcon from "../../../../resources/images/buildings/cityAlt1.png";
import factoryIcon from "../../../../resources/images/buildings/factoryAlt1.png";
import shieldIcon from "../../../../resources/images/buildings/fortAlt3.png";
import anchorIcon from "../../../../resources/images/buildings/port1.png";
import missileSiloIcon from "../../../../resources/images/buildings/silo1.png";
import SAMMissileIcon from "../../../../resources/images/buildings/silo4.png";
import { Cell, UnitType } from "../../../core/game/Game";
import { euclDistFN, isometricDistFN } from "../../../core/game/GameMap";
import { GameUpdateType } from "../../../core/game/GameUpdates";
import { GameView, UnitView } from "../../../core/game/GameView";
import cityIcon from "/images/buildings/cityAlt1.png?url";
import factoryIcon from "/images/buildings/factoryAlt1.png?url";
import shieldIcon from "/images/buildings/fortAlt3.png?url";
import anchorIcon from "/images/buildings/port1.png?url";
import missileSiloIcon from "/images/buildings/silo1.png?url";
import SAMMissileIcon from "/images/buildings/silo4.png?url";
const underConstructionColor = colord("rgb(150,150,150)");
+10 -10
View File
@@ -1,15 +1,5 @@
import { LitElement, html } from "lit";
import { customElement } from "lit/decorators.js";
import warshipIcon from "../../../../resources/images/BattleshipIconWhite.svg";
import cityIcon from "../../../../resources/images/CityIconWhite.svg";
import factoryIcon from "../../../../resources/images/FactoryIconWhite.svg";
import mirvIcon from "../../../../resources/images/MIRVIcon.svg";
import missileSiloIcon from "../../../../resources/images/MissileSiloIconWhite.svg";
import hydrogenBombIcon from "../../../../resources/images/MushroomCloudIconWhite.svg";
import atomBombIcon from "../../../../resources/images/NukeIconWhite.svg";
import portIcon from "../../../../resources/images/PortIcon.svg";
import samLauncherIcon from "../../../../resources/images/SamLauncherIconWhite.svg";
import defensePostIcon from "../../../../resources/images/ShieldIconWhite.svg";
import { EventBus } from "../../../core/EventBus";
import { Gold, PlayerActions, UnitType } from "../../../core/game/Game";
import { GameView } from "../../../core/game/GameView";
@@ -20,6 +10,16 @@ import {
import { renderNumber, translateText } from "../../Utils";
import { UIState } from "../UIState";
import { Layer } from "./Layer";
import warshipIcon from "/images/BattleshipIconWhite.svg?url";
import cityIcon from "/images/CityIconWhite.svg?url";
import factoryIcon from "/images/FactoryIconWhite.svg?url";
import mirvIcon from "/images/MIRVIcon.svg?url";
import missileSiloIcon from "/images/MissileSiloIconWhite.svg?url";
import hydrogenBombIcon from "/images/MushroomCloudIconWhite.svg?url";
import atomBombIcon from "/images/NukeIconWhite.svg?url";
import portIcon from "/images/PortIcon.svg?url";
import samLauncherIcon from "/images/SamLauncherIconWhite.svg?url";
import defensePostIcon from "/images/ShieldIconWhite.svg?url";
@customElement("unit-display")
export class UnitDisplay extends LitElement implements Layer {