diff --git a/src/client/NewsModal.ts b/src/client/NewsModal.ts
index 1eae8e744..e5eafdac1 100644
--- a/src/client/NewsModal.ts
+++ b/src/client/NewsModal.ts
@@ -3,12 +3,11 @@ import { resolveMarkdown } from "lit-markdown";
import { customElement, property, query } from "lit/decorators.js";
import version from "resources/version.txt?raw";
import { translateText } from "../client/Utils";
+import { assetUrl } from "../core/AssetUrls";
import "./components/baseComponents/Modal";
import { BaseModal } from "./components/BaseModal";
import { modalHeader } from "./components/ui/ModalHeader";
import { normalizeNewsMarkdown } from "./NewsMarkdown";
-import changelog from "/changelog.md?url";
-import megaphone from "/images/Megaphone.svg?url";
@customElement("news-modal")
export class NewsModal extends BaseModal {
@@ -62,7 +61,7 @@ export class NewsModal extends BaseModal {
protected onOpen(): void {
if (!this.initialized) {
this.initialized = true;
- fetch(changelog)
+ fetch(assetUrl("changelog.md"))
.then((response) => (response.ok ? response.text() : "Failed to load"))
.then((markdown) => normalizeNewsMarkdown(markdown))
.then((markdown) => (this.markdown = markdown))
@@ -102,7 +101,7 @@ export class NewsButton extends LitElement {
>
diff --git a/src/client/TroubleshootingModal.ts b/src/client/TroubleshootingModal.ts
index 6c3343e76..30bb6da3c 100644
--- a/src/client/TroubleshootingModal.ts
+++ b/src/client/TroubleshootingModal.ts
@@ -1,5 +1,6 @@
import { html } from "lit";
import { customElement, property } from "lit/decorators.js";
+import { assetUrl } from "../core/AssetUrls";
import { translateText } from "./Utils";
import { BaseModal } from "./components/BaseModal";
import "./components/baseComponents/Modal";
@@ -8,7 +9,7 @@ import {
collectGraphicsDiagnostics,
GraphicsDiagnostics,
} from "./utilities/Diagnostic";
-import infoIcon from "/images/InfoIcon.svg?url";
+const infoIcon = assetUrl("images/InfoIcon.svg");
@customElement("troubleshooting-modal")
export class TroubleshootingModal extends BaseModal {
diff --git a/src/client/components/map/MapPicker.ts b/src/client/components/map/MapPicker.ts
index 7661cc0d5..2ad8da146 100644
--- a/src/client/components/map/MapPicker.ts
+++ b/src/client/components/map/MapPicker.ts
@@ -1,5 +1,6 @@
import { LitElement, html } from "lit";
import { customElement, property, state } from "lit/decorators.js";
+import { assetUrl } from "../../../core/AssetUrls";
import {
Difficulty,
GameMapType,
@@ -7,7 +8,7 @@ import {
} from "../../../core/game/Game";
import { translateText } from "../../Utils";
import "./MapDisplay";
-import randomMap from "/images/RandomMap.webp?url";
+const randomMap = assetUrl("images/RandomMap.webp");
const featuredMaps: GameMapType[] = [
GameMapType.World,
diff --git a/src/client/graphics/PlayerIcons.ts b/src/client/graphics/PlayerIcons.ts
index 672d82f2e..827974eff 100644
--- a/src/client/graphics/PlayerIcons.ts
+++ b/src/client/graphics/PlayerIcons.ts
@@ -1,18 +1,23 @@
+import { assetUrl } from "../../core/AssetUrls";
import { AllPlayers, Nukes } from "../../core/game/Game";
import { GameView, PlayerView } from "../../core/game/GameView";
-import allianceIcon from "/images/AllianceIcon.svg?url";
-import allianceIconFaded from "/images/AllianceIconFaded.svg?url";
-import allianceRequestBlackIcon from "/images/AllianceRequestBlackIcon.svg?url";
-import allianceRequestWhiteIcon from "/images/AllianceRequestWhiteIcon.svg?url";
-import crownIcon from "/images/CrownIcon.svg?url";
-import disconnectedIcon from "/images/DisconnectedIcon.svg?url";
-import embargoBlackIcon from "/images/EmbargoBlackIcon.svg?url";
-import embargoWhiteIcon from "/images/EmbargoWhiteIcon.svg?url";
-import nukeRedIcon from "/images/NukeIconRed.svg?url";
-import nukeWhiteIcon from "/images/NukeIconWhite.svg?url";
-import questionMarkIcon from "/images/QuestionMarkIcon.svg?url";
-import targetIcon from "/images/TargetIcon.svg?url";
-import traitorIcon from "/images/TraitorIcon.svg?url";
+const allianceIcon = assetUrl("images/AllianceIcon.svg");
+const allianceIconFaded = assetUrl("images/AllianceIconFaded.svg");
+const allianceRequestBlackIcon = assetUrl(
+ "images/AllianceRequestBlackIcon.svg",
+);
+const allianceRequestWhiteIcon = assetUrl(
+ "images/AllianceRequestWhiteIcon.svg",
+);
+const crownIcon = assetUrl("images/CrownIcon.svg");
+const disconnectedIcon = assetUrl("images/DisconnectedIcon.svg");
+const embargoBlackIcon = assetUrl("images/EmbargoBlackIcon.svg");
+const embargoWhiteIcon = assetUrl("images/EmbargoWhiteIcon.svg");
+const nukeRedIcon = assetUrl("images/NukeIconRed.svg");
+const nukeWhiteIcon = assetUrl("images/NukeIconWhite.svg");
+const questionMarkIcon = assetUrl("images/QuestionMarkIcon.svg");
+const targetIcon = assetUrl("images/TargetIcon.svg");
+const traitorIcon = assetUrl("images/TraitorIcon.svg");
export type PlayerIconId =
| "crown"
diff --git a/src/client/graphics/SpriteLoader.ts b/src/client/graphics/SpriteLoader.ts
index 36c4aca54..3d3d44669 100644
--- a/src/client/graphics/SpriteLoader.ts
+++ b/src/client/graphics/SpriteLoader.ts
@@ -1,17 +1,18 @@
import { Colord } from "colord";
+import { assetUrl } from "../../core/AssetUrls";
import { Theme } from "../../core/configuration/Config";
import { TrainType, UnitType } from "../../core/game/Game";
import { UnitView } from "../../core/game/GameView";
-import atomBombSprite from "/sprites/atombomb.png?url";
-import hydrogenBombSprite from "/sprites/hydrogenbomb.png?url";
-import mirvSprite from "/sprites/mirv2.png?url";
-import samMissileSprite from "/sprites/samMissile.png?url";
-import tradeShipSprite from "/sprites/tradeship.png?url";
-import trainCarriageSprite from "/sprites/trainCarriage.png?url";
-import trainLoadedCarriageSprite from "/sprites/trainCarriageLoaded.png?url";
-import trainEngineSprite from "/sprites/trainEngine.png?url";
-import transportShipSprite from "/sprites/transportship.png?url";
-import warshipSprite from "/sprites/warship.png?url";
+const atomBombSprite = assetUrl("sprites/atombomb.png");
+const hydrogenBombSprite = assetUrl("sprites/hydrogenbomb.png");
+const mirvSprite = assetUrl("sprites/mirv2.png");
+const samMissileSprite = assetUrl("sprites/samMissile.png");
+const tradeShipSprite = assetUrl("sprites/tradeship.png");
+const trainCarriageSprite = assetUrl("sprites/trainCarriage.png");
+const trainLoadedCarriageSprite = assetUrl("sprites/trainCarriageLoaded.png");
+const trainEngineSprite = assetUrl("sprites/trainEngine.png");
+const transportShipSprite = assetUrl("sprites/transportship.png");
+const warshipSprite = assetUrl("sprites/warship.png");
// Can't reuse TrainType because "loaded" is not a type, just an attribute
const TrainTypeSprite = {
diff --git a/src/client/graphics/layers/AttackingTroopsOverlay.ts b/src/client/graphics/layers/AttackingTroopsOverlay.ts
index ccad9f38b..09b33d897 100644
--- a/src/client/graphics/layers/AttackingTroopsOverlay.ts
+++ b/src/client/graphics/layers/AttackingTroopsOverlay.ts
@@ -1,3 +1,4 @@
+import { assetUrl } from "../../../core/AssetUrls";
import { EventBus } from "../../../core/EventBus";
import { Cell } from "../../../core/game/Game";
import { GameView } from "../../../core/game/GameView";
@@ -6,8 +7,8 @@ import { AlternateViewEvent } from "../../InputHandler";
import { renderTroops } from "../../Utils";
import { TransformHandler } from "../TransformHandler";
import { Layer } from "./Layer";
-import shieldIcon from "/images/ShieldIconWhite.svg?url";
-import swordIcon from "/images/SwordIconWhite.svg?url";
+const shieldIcon = assetUrl("images/ShieldIconWhite.svg");
+const swordIcon = assetUrl("images/SwordIconWhite.svg");
export function troopAttackColor(
attackerTroops: number,
diff --git a/src/client/graphics/layers/AttacksDisplay.ts b/src/client/graphics/layers/AttacksDisplay.ts
index f7f2a68e7..3fe621226 100644
--- a/src/client/graphics/layers/AttacksDisplay.ts
+++ b/src/client/graphics/layers/AttacksDisplay.ts
@@ -1,5 +1,6 @@
import { html, LitElement } from "lit";
import { customElement, state } from "lit/decorators.js";
+import { assetUrl } from "../../../core/AssetUrls";
import { EventBus } from "../../../core/EventBus";
import { MessageType, PlayerType, UnitType } from "../../../core/game/Game";
import {
@@ -22,8 +23,8 @@ import {
GoToPositionEvent,
GoToUnitEvent,
} from "./Leaderboard";
-import soldierIcon from "/images/SoldierIcon.svg?url";
-import swordIcon from "/images/SwordIcon.svg?url";
+const soldierIcon = assetUrl("images/SoldierIcon.svg");
+const swordIcon = assetUrl("images/SwordIcon.svg");
@customElement("attacks-display")
export class AttacksDisplay extends LitElement implements Layer {
diff --git a/src/client/graphics/layers/BuildMenu.ts b/src/client/graphics/layers/BuildMenu.ts
index 2d67f2b3c..797b4e568 100644
--- a/src/client/graphics/layers/BuildMenu.ts
+++ b/src/client/graphics/layers/BuildMenu.ts
@@ -1,6 +1,7 @@
import { css, html, LitElement } from "lit";
import { customElement, state } from "lit/decorators.js";
import { translateText } from "../../../client/Utils";
+import { assetUrl } from "../../../core/AssetUrls";
import { EventBus } from "../../../core/EventBus";
import {
BuildableUnit,
@@ -25,17 +26,17 @@ import { renderNumber } from "../../Utils";
import { TransformHandler } from "../TransformHandler";
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 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";
+const warshipIcon = assetUrl("images/BattleshipIconWhite.svg");
+const cityIcon = assetUrl("images/CityIconWhite.svg");
+const factoryIcon = assetUrl("images/FactoryIconWhite.svg");
+const goldCoinIcon = assetUrl("images/GoldCoinIcon.svg");
+const mirvIcon = assetUrl("images/MIRVIcon.svg");
+const missileSiloIcon = assetUrl("images/MissileSiloIconWhite.svg");
+const hydrogenBombIcon = assetUrl("images/MushroomCloudIconWhite.svg");
+const atomBombIcon = assetUrl("images/NukeIconWhite.svg");
+const portIcon = assetUrl("images/PortIcon.svg");
+const samlauncherIcon = assetUrl("images/SamLauncherIconWhite.svg");
+const shieldIcon = assetUrl("images/ShieldIconWhite.svg");
export interface BuildItemDisplay {
unitType: PlayerBuildableUnitType;
diff --git a/src/client/graphics/layers/ControlPanel.ts b/src/client/graphics/layers/ControlPanel.ts
index 719272804..033e34771 100644
--- a/src/client/graphics/layers/ControlPanel.ts
+++ b/src/client/graphics/layers/ControlPanel.ts
@@ -1,5 +1,6 @@
import { LitElement, html } from "lit";
import { customElement, state } from "lit/decorators.js";
+import { assetUrl } from "../../../core/AssetUrls";
import { EventBus } from "../../../core/EventBus";
import { Gold } from "../../../core/game/Game";
import { GameView } from "../../../core/game/GameView";
@@ -8,9 +9,9 @@ import { AttackRatioEvent } from "../../InputHandler";
import { renderNumber, renderTroops } from "../../Utils";
import { UIState } from "../UIState";
import { Layer } from "./Layer";
-import goldCoinIcon from "/images/GoldCoinIcon.svg?url";
-import soldierIcon from "/images/SoldierIcon.svg?url";
-import swordIcon from "/images/SwordIcon.svg?url";
+const goldCoinIcon = assetUrl("images/GoldCoinIcon.svg");
+const soldierIcon = assetUrl("images/SoldierIcon.svg");
+const swordIcon = assetUrl("images/SwordIcon.svg");
@customElement("control-panel")
export class ControlPanel extends LitElement implements Layer {
diff --git a/src/client/graphics/layers/EventsDisplay.ts b/src/client/graphics/layers/EventsDisplay.ts
index 14e546ce9..0524c992a 100644
--- a/src/client/graphics/layers/EventsDisplay.ts
+++ b/src/client/graphics/layers/EventsDisplay.ts
@@ -2,6 +2,7 @@ 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 { assetUrl } from "../../../core/AssetUrls";
import { EventBus } from "../../../core/EventBus";
import {
AllPlayers,
@@ -37,11 +38,11 @@ import { GoToPlayerEvent, GoToUnitEvent } from "./Leaderboard";
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";
+const allianceIcon = assetUrl("images/AllianceIconWhite.svg");
+const chatIcon = assetUrl("images/ChatIconWhite.svg");
+const donateGoldIcon = assetUrl("images/DonateGoldIconWhite.svg");
+const nukeIcon = assetUrl("images/NukeIconWhite.svg");
+const swordIcon = assetUrl("images/SwordIconWhite.svg");
interface GameEvent {
description: string;
diff --git a/src/client/graphics/layers/GameLeftSidebar.ts b/src/client/graphics/layers/GameLeftSidebar.ts
index 9092670e8..79b7bf76e 100644
--- a/src/client/graphics/layers/GameLeftSidebar.ts
+++ b/src/client/graphics/layers/GameLeftSidebar.ts
@@ -1,6 +1,7 @@
import { Colord } from "colord";
import { html, LitElement } from "lit";
import { customElement, state } from "lit/decorators.js";
+import { assetUrl } from "../../../core/AssetUrls";
import { EventBus } from "../../../core/EventBus";
import { GameMode, Team } from "../../../core/game/Game";
import { GameView } from "../../../core/game/GameView";
@@ -9,10 +10,12 @@ import { getTranslatedPlayerTeamLabel, translateText } from "../../Utils";
import { ImmunityBarVisibleEvent } from "./ImmunityTimer";
import { Layer } from "./Layer";
import { SpawnBarVisibleEvent } from "./SpawnTimer";
-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";
+const leaderboardRegularIcon = assetUrl(
+ "images/LeaderboardIconRegularWhite.svg",
+);
+const leaderboardSolidIcon = assetUrl("images/LeaderboardIconSolidWhite.svg");
+const teamRegularIcon = assetUrl("images/TeamIconRegularWhite.svg");
+const teamSolidIcon = assetUrl("images/TeamIconSolidWhite.svg");
@customElement("game-left-sidebar")
export class GameLeftSidebar extends LitElement implements Layer {
diff --git a/src/client/graphics/layers/GameRightSidebar.ts b/src/client/graphics/layers/GameRightSidebar.ts
index 8b1fc3169..67f5ed1dc 100644
--- a/src/client/graphics/layers/GameRightSidebar.ts
+++ b/src/client/graphics/layers/GameRightSidebar.ts
@@ -1,5 +1,6 @@
import { html, LitElement } from "lit";
import { customElement, state } from "lit/decorators.js";
+import { assetUrl } from "../../../core/AssetUrls";
import { EventBus } from "../../../core/EventBus";
import { GameType } from "../../../core/game/Game";
import { GameView } from "../../../core/game/GameView";
@@ -12,11 +13,11 @@ import { Layer } from "./Layer";
import { ShowReplayPanelEvent } from "./ReplayPanel";
import { ShowSettingsModalEvent } from "./SettingsModal";
import { SpawnBarVisibleEvent } from "./SpawnTimer";
-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";
+const exitIcon = assetUrl("images/ExitIconWhite.svg");
+const FastForwardIconSolid = assetUrl("images/FastForwardIconSolidWhite.svg");
+const pauseIcon = assetUrl("images/PauseIconWhite.svg");
+const playIcon = assetUrl("images/PlayIconWhite.svg");
+const settingsIcon = assetUrl("images/SettingIconWhite.svg");
@customElement("game-right-sidebar")
export class GameRightSidebar extends LitElement implements Layer {
diff --git a/src/client/graphics/layers/MainRadialMenu.ts b/src/client/graphics/layers/MainRadialMenu.ts
index 15ffd7b6e..b6adba929 100644
--- a/src/client/graphics/layers/MainRadialMenu.ts
+++ b/src/client/graphics/layers/MainRadialMenu.ts
@@ -1,5 +1,6 @@
import { LitElement } from "lit";
import { customElement } from "lit/decorators.js";
+import { assetUrl } from "../../../core/AssetUrls";
import { EventBus } from "../../../core/EventBus";
import { PlayerActions } from "../../../core/game/Game";
import { TileRef } from "../../../core/game/GameMap";
@@ -19,8 +20,8 @@ import {
MenuElementParams,
rootMenuElement,
} from "./RadialMenuElements";
-import donateTroopIcon from "/images/DonateTroopIconWhite.svg?url";
-import swordIcon from "/images/SwordIconWhite.svg?url";
+const donateTroopIcon = assetUrl("images/DonateTroopIconWhite.svg");
+const swordIcon = assetUrl("images/SwordIconWhite.svg");
import { ContextMenuEvent } from "../../InputHandler";
diff --git a/src/client/graphics/layers/PlayerInfoOverlay.ts b/src/client/graphics/layers/PlayerInfoOverlay.ts
index aa0682c58..a332eaaad 100644
--- a/src/client/graphics/layers/PlayerInfoOverlay.ts
+++ b/src/client/graphics/layers/PlayerInfoOverlay.ts
@@ -32,15 +32,15 @@ import { ImmunityBarVisibleEvent } from "./ImmunityTimer";
import { Layer } from "./Layer";
import { CloseRadialMenuEvent } from "./RadialMenu";
import { SpawnBarVisibleEvent } from "./SpawnTimer";
-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";
-import soldierIcon from "/images/SoldierIcon.svg?url";
+const allianceIcon = assetUrl("images/AllianceIcon.svg");
+const warshipIcon = assetUrl("images/BattleshipIconWhite.svg");
+const cityIcon = assetUrl("images/CityIconWhite.svg");
+const factoryIcon = assetUrl("images/FactoryIconWhite.svg");
+const goldCoinIcon = assetUrl("images/GoldCoinIcon.svg");
+const missileSiloIcon = assetUrl("images/MissileSiloIconWhite.svg");
+const portIcon = assetUrl("images/PortIcon.svg");
+const samLauncherIcon = assetUrl("images/SamLauncherIconWhite.svg");
+const soldierIcon = assetUrl("images/SoldierIcon.svg");
function euclideanDistWorld(
coord: { x: number; y: number },
diff --git a/src/client/graphics/layers/PlayerModerationModal.ts b/src/client/graphics/layers/PlayerModerationModal.ts
index e08230ce2..2bf570e31 100644
--- a/src/client/graphics/layers/PlayerModerationModal.ts
+++ b/src/client/graphics/layers/PlayerModerationModal.ts
@@ -1,13 +1,14 @@
import { html, LitElement } from "lit";
import { customElement, property } from "lit/decorators.js";
+import { assetUrl } from "../../../core/AssetUrls";
import { EventBus } from "../../../core/EventBus";
import { PlayerType } from "../../../core/game/Game";
import { PlayerView } from "../../../core/game/GameView";
import { actionButton } from "../../components/ui/ActionButton";
import { SendKickPlayerIntentEvent } from "../../Transport";
import { translateText } from "../../Utils";
-import kickIcon from "/images/ExitIconWhite.svg?url";
-import shieldIcon from "/images/ShieldIconWhite.svg?url";
+const kickIcon = assetUrl("images/ExitIconWhite.svg");
+const shieldIcon = assetUrl("images/ShieldIconWhite.svg");
@customElement("player-moderation-modal")
export class PlayerModerationModal extends LitElement {
diff --git a/src/client/graphics/layers/PlayerPanel.ts b/src/client/graphics/layers/PlayerPanel.ts
index 38268d163..17dc419bd 100644
--- a/src/client/graphics/layers/PlayerPanel.ts
+++ b/src/client/graphics/layers/PlayerPanel.ts
@@ -40,17 +40,17 @@ import { EmojiTable } from "./EmojiTable";
import { Layer } from "./Layer";
import "./PlayerModerationModal";
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 shieldIcon from "/images/ShieldIconWhite.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";
+const allianceIcon = assetUrl("images/AllianceIconWhite.svg");
+const chatIcon = assetUrl("images/ChatIconWhite.svg");
+const donateGoldIcon = assetUrl("images/DonateGoldIconWhite.svg");
+const donateTroopIcon = assetUrl("images/DonateTroopIconWhite.svg");
+const emojiIcon = assetUrl("images/EmojiIconWhite.svg");
+const shieldIcon = assetUrl("images/ShieldIconWhite.svg");
+const stopTradingIcon = assetUrl("images/StopIconWhite.png");
+const targetIcon = assetUrl("images/TargetIconWhite.svg");
+const startTradingIcon = assetUrl("images/TradingIconWhite.png");
+const traitorIcon = assetUrl("images/TraitorIconLightRed.svg");
+const breakAllianceIcon = assetUrl("images/TraitorIconWhite.svg");
@customElement("player-panel")
export class PlayerPanel extends LitElement implements Layer {
diff --git a/src/client/graphics/layers/RadialMenu.ts b/src/client/graphics/layers/RadialMenu.ts
index 8cebec9c5..9f8b6c654 100644
--- a/src/client/graphics/layers/RadialMenu.ts
+++ b/src/client/graphics/layers/RadialMenu.ts
@@ -1,4 +1,5 @@
import * as d3 from "d3";
+import { assetUrl } from "../../../core/AssetUrls";
import { EventBus, GameEvent } from "../../../core/EventBus";
import { CloseViewEvent } from "../../InputHandler";
import { getSvgAspectRatio, translateText } from "../../Utils";
@@ -9,7 +10,7 @@ import {
MenuElementParams,
TooltipKey,
} from "./RadialMenuElements";
-import backIcon from "/images/BackIconWhite.svg?url";
+const backIcon = assetUrl("images/BackIconWhite.svg");
function resolveColor(
item: MenuElement,
diff --git a/src/client/graphics/layers/RadialMenuElements.ts b/src/client/graphics/layers/RadialMenuElements.ts
index 2f55a55e6..b24c24b03 100644
--- a/src/client/graphics/layers/RadialMenuElements.ts
+++ b/src/client/graphics/layers/RadialMenuElements.ts
@@ -1,3 +1,4 @@
+import { assetUrl } from "../../../core/AssetUrls";
import { Config } from "../../../core/configuration/Config";
import {
AllPlayers,
@@ -20,18 +21,18 @@ import { PlayerPanel } from "./PlayerPanel";
import { TooltipItem } from "./RadialMenu";
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";
+const allianceIcon = assetUrl("images/AllianceIconWhite.svg");
+const boatIcon = assetUrl("images/BoatIconWhite.svg");
+const buildIcon = assetUrl("images/BuildIconWhite.svg");
+const chatIcon = assetUrl("images/ChatIconWhite.svg");
+const donateGoldIcon = assetUrl("images/DonateGoldIconWhite.svg");
+const donateTroopIcon = assetUrl("images/DonateTroopIconWhite.svg");
+const emojiIcon = assetUrl("images/EmojiIconWhite.svg");
+const infoIcon = assetUrl("images/InfoIcon.svg");
+const swordIcon = assetUrl("images/SwordIconWhite.svg");
+const targetIcon = assetUrl("images/TargetIconWhite.svg");
+const traitorIcon = assetUrl("images/TraitorIconWhite.svg");
+const xIcon = assetUrl("images/XIcon.svg");
export interface MenuElementParams {
myPlayer: PlayerView;
diff --git a/src/client/graphics/layers/SettingsModal.ts b/src/client/graphics/layers/SettingsModal.ts
index 8a285a661..2e3c9f532 100644
--- a/src/client/graphics/layers/SettingsModal.ts
+++ b/src/client/graphics/layers/SettingsModal.ts
@@ -2,25 +2,26 @@ import { html, LitElement } from "lit";
import { customElement, property, query, state } from "lit/decorators.js";
import { crazyGamesSDK } from "src/client/CrazyGamesSDK";
import { PauseGameIntentEvent } from "src/client/Transport";
+import { assetUrl } from "../../../core/AssetUrls";
import { EventBus } from "../../../core/EventBus";
import { UserSettings } from "../../../core/game/UserSettings";
import { AlternateViewEvent, RefreshGraphicsEvent } from "../../InputHandler";
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 swordIcon from "/images/SwordIconWhite.svg?url";
-import treeIcon from "/images/TreeIconWhite.svg?url";
-import musicIcon from "/images/music.svg?url";
+const structureIcon = assetUrl("images/CityIconWhite.svg");
+const cursorPriceIcon = assetUrl("images/CursorPriceIconWhite.svg");
+const darkModeIcon = assetUrl("images/DarkModeIconWhite.svg");
+const emojiIcon = assetUrl("images/EmojiIconWhite.svg");
+const exitIcon = assetUrl("images/ExitIconWhite.svg");
+const explosionIcon = assetUrl("images/ExplosionIconWhite.svg");
+const mouseIcon = assetUrl("images/MouseIconWhite.svg");
+const ninjaIcon = assetUrl("images/NinjaIconWhite.svg");
+const settingsIcon = assetUrl("images/SettingIconWhite.svg");
+const sirenIcon = assetUrl("images/SirenIconWhite.svg");
+const swordIcon = assetUrl("images/SwordIconWhite.svg");
+const treeIcon = assetUrl("images/TreeIconWhite.svg");
+const musicIcon = assetUrl("images/music.svg");
export class ShowSettingsModalEvent {
constructor(
diff --git a/src/client/graphics/layers/StructureDrawingUtils.ts b/src/client/graphics/layers/StructureDrawingUtils.ts
index 663547170..52a1b4951 100644
--- a/src/client/graphics/layers/StructureDrawingUtils.ts
+++ b/src/client/graphics/layers/StructureDrawingUtils.ts
@@ -1,4 +1,5 @@
import * as PIXI from "pixi.js";
+import { assetUrl } from "../../../core/AssetUrls";
import { Theme } from "../../../core/configuration/Config";
import {
Cell,
@@ -7,12 +8,12 @@ import {
} from "../../../core/game/Game";
import { GameView, PlayerView, UnitView } from "../../../core/game/GameView";
import { TransformHandler } from "../TransformHandler";
-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";
+const anchorIcon = assetUrl("images/AnchorIcon.png");
+const cityIcon = assetUrl("images/CityIcon.png");
+const factoryIcon = assetUrl("images/FactoryUnit.png");
+const missileSiloIcon = assetUrl("images/MissileSiloUnit.png");
+const SAMMissileIcon = assetUrl("images/SamLauncherUnit.png");
+const shieldIcon = assetUrl("images/ShieldIcon.png");
export const STRUCTURE_SHAPES: Partial> = {
[UnitType.City]: "circle",
diff --git a/src/client/graphics/layers/StructureIconsLayer.ts b/src/client/graphics/layers/StructureIconsLayer.ts
index a3018d542..3430fae28 100644
--- a/src/client/graphics/layers/StructureIconsLayer.ts
+++ b/src/client/graphics/layers/StructureIconsLayer.ts
@@ -2,6 +2,7 @@ import { extend } from "colord";
import a11yPlugin from "colord/plugins/a11y";
import { OutlineFilter } from "pixi-filters";
import * as PIXI from "pixi.js";
+import { assetUrl } from "../../../core/AssetUrls";
import { Theme } from "../../../core/configuration/Config";
import { EventBus } from "../../../core/EventBus";
import { wouldNukeBreakAlliance } from "../../../core/execution/Util";
@@ -42,7 +43,7 @@ import {
STRUCTURE_SHAPES,
ZOOM_THRESHOLD,
} from "./StructureDrawingUtils";
-import bitmapFont from "/fonts/round_6x6_modified.xml?url";
+const bitmapFont = assetUrl("fonts/round_6x6_modified.xml");
/** True for nuke types (AtomBomb, HydrogenBomb): ghost is preserved after placement so user can place multiple or keep selection (Enter/key confirm). */
export function shouldPreserveGhostAfterBuild(unitType: UnitType): boolean {
diff --git a/src/client/graphics/layers/StructureLayer.ts b/src/client/graphics/layers/StructureLayer.ts
index 819c4e3f7..32d836256 100644
--- a/src/client/graphics/layers/StructureLayer.ts
+++ b/src/client/graphics/layers/StructureLayer.ts
@@ -1,4 +1,5 @@
import { colord, Colord } from "colord";
+import { assetUrl } from "../../../core/AssetUrls";
import { Theme } from "../../../core/configuration/Config";
import { EventBus } from "../../../core/EventBus";
import { TransformHandler } from "../TransformHandler";
@@ -8,12 +9,12 @@ 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 cityIcon = assetUrl("images/buildings/cityAlt1.png");
+const factoryIcon = assetUrl("images/buildings/factoryAlt1.png");
+const shieldIcon = assetUrl("images/buildings/fortAlt3.png");
+const anchorIcon = assetUrl("images/buildings/port1.png");
+const missileSiloIcon = assetUrl("images/buildings/silo1.png");
+const SAMMissileIcon = assetUrl("images/buildings/silo4.png");
const underConstructionColor = colord("rgb(150,150,150)");
diff --git a/src/client/graphics/layers/UnitDisplay.ts b/src/client/graphics/layers/UnitDisplay.ts
index d243ec94b..88f965f98 100644
--- a/src/client/graphics/layers/UnitDisplay.ts
+++ b/src/client/graphics/layers/UnitDisplay.ts
@@ -1,5 +1,6 @@
import { html, LitElement } from "lit";
import { customElement } from "lit/decorators.js";
+import { assetUrl } from "../../../core/AssetUrls";
import { EventBus } from "../../../core/EventBus";
import {
BuildableUnit,
@@ -16,17 +17,17 @@ 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 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 defensePostIcon from "/images/ShieldIconWhite.svg?url";
+const warshipIcon = assetUrl("images/BattleshipIconWhite.svg");
+const cityIcon = assetUrl("images/CityIconWhite.svg");
+const factoryIcon = assetUrl("images/FactoryIconWhite.svg");
+const goldCoinIcon = assetUrl("images/GoldCoinIcon.svg");
+const mirvIcon = assetUrl("images/MIRVIcon.svg");
+const missileSiloIcon = assetUrl("images/MissileSiloIconWhite.svg");
+const hydrogenBombIcon = assetUrl("images/MushroomCloudIconWhite.svg");
+const atomBombIcon = assetUrl("images/NukeIconWhite.svg");
+const portIcon = assetUrl("images/PortIcon.svg");
+const samLauncherIcon = assetUrl("images/SamLauncherIconWhite.svg");
+const defensePostIcon = assetUrl("images/ShieldIconWhite.svg");
@customElement("unit-display")
export class UnitDisplay extends LitElement implements Layer {
diff --git a/src/client/sound/SoundManager.ts b/src/client/sound/SoundManager.ts
index 3624efcad..6e6e0e912 100644
--- a/src/client/sound/SoundManager.ts
+++ b/src/client/sound/SoundManager.ts
@@ -2,7 +2,8 @@ import { Howl } from "howler";
import of4 from "../../../proprietary/sounds/music/of4.mp3";
import openfront from "../../../proprietary/sounds/music/openfront.mp3";
import war from "../../../proprietary/sounds/music/war.mp3";
-import kaChingSound from "/sounds/effects/ka-ching.mp3?url";
+import { assetUrl } from "../../core/AssetUrls";
+const kaChingSound = assetUrl("sounds/effects/ka-ching.mp3");
export enum SoundEffect {
KaChing = "ka-ching",
diff --git a/src/client/vite-env.d.ts b/src/client/vite-env.d.ts
index 83679d71c..d00e00e09 100644
--- a/src/client/vite-env.d.ts
+++ b/src/client/vite-env.d.ts
@@ -10,11 +10,6 @@ declare module "*.md" {
export default mdContent;
}
-declare module "*.md?url" {
- const mdUrl: string;
- export default mdUrl;
-}
-
declare module "*.html" {
const htmlContent: string;
export default htmlContent;
@@ -39,8 +34,3 @@ declare module "*.webp" {
const webpContent: string;
export default webpContent;
}
-
-declare module "*.svg?url" {
- const svgUrl: string;
- export default svgUrl;
-}