diff --git a/eslint.config.js b/eslint.config.js
index c707ee03e..3caf4b48d 100644
--- a/eslint.config.js
+++ b/eslint.config.js
@@ -40,7 +40,6 @@ export default [
rules: {
// Disable rules that would fail. The failures should be fixed, and the entries here removed.
"@typescript-eslint/no-explicit-any": "off",
- "@typescript-eslint/no-unused-expressions": "off",
"no-unused-vars": "off",
},
},
diff --git a/src/client/ClientGameRunner.ts b/src/client/ClientGameRunner.ts
index f4f6f119e..fbb1b83aa 100644
--- a/src/client/ClientGameRunner.ts
+++ b/src/client/ClientGameRunner.ts
@@ -426,13 +426,6 @@ export class ClientGameRunner {
} else if (this.canAutoBoat(actions, tile)) {
this.sendBoatAttackIntent(tile);
}
-
- const owner = this.gameView.owner(tile);
- if (owner.isPlayer()) {
- this.gameView.setFocusedPlayer(owner as PlayerView);
- } else {
- this.gameView.setFocusedPlayer(null);
- }
});
}
@@ -612,45 +605,6 @@ export class ClientGameRunner {
private onMouseMove(event: MouseMoveEvent) {
this.lastMousePosition = { x: event.x, y: event.y };
- this.checkTileUnderCursor();
- }
-
- private checkTileUnderCursor() {
- if (!this.lastMousePosition || !this.renderer.transformHandler) return;
-
- const cell = this.renderer.transformHandler.screenToWorldCoordinates(
- this.lastMousePosition.x,
- this.lastMousePosition.y,
- );
-
- if (!cell || !this.gameView.isValidCoord(cell.x, cell.y)) {
- return;
- }
-
- const tile = this.gameView.ref(cell.x, cell.y);
-
- if (this.gameView.isLand(tile)) {
- const owner = this.gameView.owner(tile);
- if (owner.isPlayer()) {
- this.gameView.setFocusedPlayer(owner as PlayerView);
- } else {
- this.gameView.setFocusedPlayer(null);
- }
- } else {
- const units = this.gameView
- .nearbyUnits(tile, 50, [
- UnitType.Warship,
- UnitType.TradeShip,
- UnitType.TransportShip,
- ])
- .sort((a, b) => a.distSquared - b.distSquared);
-
- if (units.length > 0) {
- this.gameView.setFocusedPlayer(units[0].unit.owner() as PlayerView);
- } else {
- this.gameView.setFocusedPlayer(null);
- }
- }
}
private onConnectionCheck() {
diff --git a/src/client/GutterAds.ts b/src/client/GutterAds.ts
new file mode 100644
index 000000000..f0f2f779f
--- /dev/null
+++ b/src/client/GutterAds.ts
@@ -0,0 +1,114 @@
+import { LitElement, html } from "lit";
+import { customElement, state } from "lit/decorators.js";
+import { isInIframe } from "./Utils";
+
+const LEFT_FUSE = "gutter-ad-container-left";
+const RIGHT_FUSE = "gutter-ad-container-right";
+// Minimum screen width to show ads (larger than typical Chromebook)
+const MIN_SCREEN_WIDTH = 1400;
+
+@customElement("gutter-ads")
+export class GutterAds extends LitElement {
+ @state()
+ private isVisible: boolean = false;
+
+ // Override createRenderRoot to disable shadow DOM
+ createRenderRoot() {
+ return this;
+ }
+
+ private isScreenLargeEnough(): boolean {
+ return window.innerWidth >= MIN_SCREEN_WIDTH;
+ }
+
+ // Called after the component's DOM is first rendered
+ firstUpdated() {
+ // DOM is guaranteed to be available here
+ console.log("GutterAd DOM is ready");
+ }
+
+ public show(): void {
+ if (!this.isScreenLargeEnough()) {
+ console.log("Screen too small for gutter ads, skipping");
+ return;
+ }
+
+ if (isInIframe()) {
+ console.log("In iframe, showing gutter ads");
+ return;
+ }
+
+ console.log("showing GutterAds");
+ this.isVisible = true;
+ this.requestUpdate();
+
+ // Wait for the update to complete, then load ads
+ this.updateComplete.then(() => {
+ this.loadAds();
+ });
+ }
+
+ public hide(): void {
+ console.log("hiding GutterAds");
+ this.destroyAds();
+ this.requestUpdate();
+ }
+
+ private loadAds(): void {
+ // Ensure the container elements exist before loading ads
+ const leftContainer = this.querySelector(`#${LEFT_FUSE}`);
+ const rightContainer = this.querySelector(`#${RIGHT_FUSE}`);
+
+ if (!leftContainer || !rightContainer) {
+ console.warn("Ad containers not found in DOM");
+ return;
+ }
+
+ if (!window.fusetag) {
+ console.warn("Fuse tag not available");
+ return;
+ }
+
+ try {
+ console.log("registering zones");
+ window.fusetag.que.push(() => {
+ window.fusetag.registerZone(LEFT_FUSE);
+ window.fusetag.registerZone(RIGHT_FUSE);
+ });
+ } catch (error) {
+ console.error("Failed to load fuse ads:", error);
+ this.hide();
+ }
+ }
+
+ private destroyAds(): void {
+ if (!window.fusetag) {
+ return;
+ }
+ window.fusetag.que.push(() => {
+ window.fusetag.destroyZone(LEFT_FUSE);
+ window.fusetag.destroyZone(RIGHT_FUSE);
+ });
+ this.requestUpdate();
+ }
+
+ disconnectedCallback() {
+ super.disconnectedCallback();
+ this.destroyAds();
+ }
+
+ render() {
+ if (!this.isVisible) {
+ return html``;
+ }
+
+ return html`
+
+
+ `;
+ }
+}
diff --git a/src/client/Main.ts b/src/client/Main.ts
index d5acbe4ab..37ae29027 100644
--- a/src/client/Main.ts
+++ b/src/client/Main.ts
@@ -15,6 +15,7 @@ import { FlagInput } from "./FlagInput";
import { FlagInputModal } from "./FlagInputModal";
import { GameStartingModal } from "./GameStartingModal";
import "./GoogleAdElement";
+import { GutterAds } from "./GutterAds";
import { HelpModal } from "./HelpModal";
import { HostLobbyModal as HostPrivateLobbyModal } from "./HostLobbyModal";
import { JoinPrivateLobbyModal } from "./JoinPrivateLobbyModal";
@@ -51,6 +52,12 @@ declare global {
newPageView: () => void;
};
};
+ fusetag: {
+ registerZone: (id: string) => void;
+ destroyZone: (id: string) => void;
+ pageInit: (options?: any) => void;
+ que: Array<() => void>;
+ };
ramp: {
que: Array<() => void>;
passiveMode: boolean;
@@ -94,6 +101,8 @@ class Client {
private patternsModal: TerritoryPatternsModal;
private tokenLoginModal: TokenLoginModal;
+ private gutterAds: GutterAds;
+
constructor() {}
initialize(): void {
@@ -106,10 +115,9 @@ class Client {
gameVersion.innerText = version;
const newsModal = document.querySelector("news-modal") as NewsModal;
- if (!newsModal) {
+ if (!newsModal || !(newsModal instanceof NewsModal)) {
console.warn("News modal element not found");
}
- newsModal instanceof NewsModal;
const newsButton = document.querySelector("news-button") as NewsButton;
if (!newsButton) {
console.warn("News button element not found");
@@ -161,6 +169,11 @@ class Client {
}
});
+ const gutterAds = document.querySelector("gutter-ads");
+ if (!(gutterAds instanceof GutterAds))
+ throw new Error("Missing gutter-ads");
+ this.gutterAds = gutterAds;
+
document.addEventListener("join-lobby", this.handleJoinLobby.bind(this));
document.addEventListener("leave-lobby", this.handleLeaveLobby.bind(this));
document.addEventListener("kick-player", this.handleKickPlayer.bind(this));
@@ -168,7 +181,9 @@ class Client {
const spModal = document.querySelector(
"single-player-modal",
) as SinglePlayerModal;
- spModal instanceof SinglePlayerModal;
+ if (!spModal || !(spModal instanceof SinglePlayerModal)) {
+ console.warn("Singleplayer modal element not found");
+ }
const singlePlayer = document.getElementById("single-player");
if (singlePlayer === null) throw new Error("Missing single-player");
@@ -178,14 +193,10 @@ class Client {
}
});
- // const ctModal = document.querySelector("chat-modal") as ChatModal;
- // ctModal instanceof ChatModal;
- // document.getElementById("chat-button").addEventListener("click", () => {
- // ctModal.open();
- // });
-
const hlpModal = document.querySelector("help-modal") as HelpModal;
- hlpModal instanceof HelpModal;
+ if (!hlpModal || !(hlpModal instanceof HelpModal)) {
+ console.warn("Help modal element not found");
+ }
const helpButton = document.getElementById("help-button");
if (helpButton === null) throw new Error("Missing help-button");
helpButton.addEventListener("click", () => {
@@ -195,7 +206,10 @@ class Client {
const flagInputModal = document.querySelector(
"flag-input-modal",
) as FlagInputModal;
- flagInputModal instanceof FlagInputModal;
+ if (!flagInputModal || !(flagInputModal instanceof FlagInputModal)) {
+ console.warn("Flag input modal element not found");
+ }
+
const flgInput = document.getElementById("flag-input_");
if (flgInput === null) throw new Error("Missing flag-input_");
flgInput.addEventListener("click", () => {
@@ -205,6 +219,12 @@ class Client {
this.patternsModal = document.querySelector(
"territory-patterns-modal",
) as TerritoryPatternsModal;
+ if (
+ !this.patternsModal ||
+ !(this.patternsModal instanceof TerritoryPatternsModal)
+ ) {
+ console.warn("Territory patterns modal element not found");
+ }
const patternButton = document.getElementById(
"territory-patterns-input-preview-button",
);
@@ -212,7 +232,12 @@ class Client {
patternButton.style.display = "none";
}
- this.patternsModal instanceof TerritoryPatternsModal;
+ if (
+ !this.patternsModal ||
+ !(this.patternsModal instanceof TerritoryPatternsModal)
+ ) {
+ console.warn("Territory patterns modal element not found");
+ }
if (patternButton === null)
throw new Error("territory-patterns-input-preview-button");
this.patternsModal.previewButton = patternButton;
@@ -224,7 +249,12 @@ class Client {
this.tokenLoginModal = document.querySelector(
"token-login",
) as TokenLoginModal;
- this.tokenLoginModal instanceof TokenLoginModal;
+ if (
+ !this.tokenLoginModal ||
+ !(this.tokenLoginModal instanceof TokenLoginModal)
+ ) {
+ console.warn("Token login modal element not found");
+ }
const onUserMe = async (userMeResponse: UserMeResponse | false) => {
document.dispatchEvent(
@@ -335,7 +365,9 @@ class Client {
const settingsModal = document.querySelector(
"user-setting",
) as UserSettingModal;
- settingsModal instanceof UserSettingModal;
+ if (!settingsModal || !(settingsModal instanceof UserSettingModal)) {
+ console.warn("User settings modal element not found");
+ }
document
.getElementById("settings-button")
?.addEventListener("click", () => {
@@ -345,7 +377,9 @@ class Client {
const hostModal = document.querySelector(
"host-lobby-modal",
) as HostPrivateLobbyModal;
- hostModal instanceof HostPrivateLobbyModal;
+ if (!hostModal || !(hostModal instanceof HostPrivateLobbyModal)) {
+ console.warn("Host private lobby modal element not found");
+ }
const hostLobbyButton = document.getElementById("host-lobby-button");
if (hostLobbyButton === null) throw new Error("Missing host-lobby-button");
hostLobbyButton.addEventListener("click", () => {
@@ -358,7 +392,9 @@ class Client {
this.joinModal = document.querySelector(
"join-private-lobby-modal",
) as JoinPrivateLobbyModal;
- this.joinModal instanceof JoinPrivateLobbyModal;
+ if (!this.joinModal || !(this.joinModal instanceof JoinPrivateLobbyModal)) {
+ console.warn("Join private lobby modal element not found");
+ }
const joinPrivateLobbyButton = document.getElementById(
"join-private-lobby-button",
);
@@ -410,6 +446,8 @@ class Client {
updateSliderProgress(slider);
slider.addEventListener("input", () => updateSliderProgress(slider));
});
+
+ this.initializeFuseTag();
}
private handleHash() {
@@ -573,8 +611,10 @@ class Client {
const startingModal = document.querySelector(
"game-starting-modal",
) as GameStartingModal;
- startingModal instanceof GameStartingModal;
- startingModal.show();
+ if (startingModal && startingModal instanceof GameStartingModal) {
+ startingModal.show();
+ }
+ this.gutterAds.hide();
},
() => {
this.joinModal.close();
@@ -607,6 +647,7 @@ class Client {
console.log("leaving lobby, cancelling game");
this.gameStop();
this.gameStop = null;
+ this.gutterAds.hide();
this.publicLobby.leaveLobby();
}
@@ -618,6 +659,29 @@ class Client {
this.eventBus.emit(new SendKickPlayerIntentEvent(target));
}
}
+
+ private initializeFuseTag() {
+ const tryInitFuseTag = (): boolean => {
+ if (window.fusetag && typeof window.fusetag.pageInit === "function") {
+ console.log("initializing fuse tag");
+ window.fusetag.que.push(() => {
+ window.fusetag.pageInit({
+ blockingFuseIds: ["lhs_sticky_vrec", "rhs_sticky_vrec"],
+ });
+ this.gutterAds.show();
+ });
+ return true;
+ } else {
+ return false;
+ }
+ };
+
+ const interval = setInterval(() => {
+ if (tryInitFuseTag()) {
+ clearInterval(interval);
+ }
+ }, 100);
+ }
}
// Initialize the client when the DOM is loaded
diff --git a/src/client/graphics/GameRenderer.ts b/src/client/graphics/GameRenderer.ts
index dd0954980..4491dede9 100644
--- a/src/client/graphics/GameRenderer.ts
+++ b/src/client/graphics/GameRenderer.ts
@@ -16,7 +16,6 @@ import { FPSDisplay } from "./layers/FPSDisplay";
import { FxLayer } from "./layers/FxLayer";
import { GameLeftSidebar } from "./layers/GameLeftSidebar";
import { GameRightSidebar } from "./layers/GameRightSidebar";
-import { GutterAdModal } from "./layers/GutterAdModal";
import { HeadsUpMessage } from "./layers/HeadsUpMessage";
import { Layer } from "./layers/Layer";
import { Leaderboard } from "./layers/Leaderboard";
@@ -216,14 +215,6 @@ export function createRenderer(
}
spawnAd.g = game;
- const gutterAdModal = document.querySelector(
- "gutter-ad-modal",
- ) as GutterAdModal;
- if (!(gutterAdModal instanceof GutterAdModal)) {
- console.error("gutter ad modal not found");
- }
- gutterAdModal.eventBus = eventBus;
-
const alertFrame = document.querySelector("alert-frame") as AlertFrame;
if (!(alertFrame instanceof AlertFrame)) {
console.error("alert frame not found");
@@ -270,7 +261,6 @@ export function createRenderer(
headsUpMessage,
multiTabModal,
spawnAd,
- gutterAdModal,
alertFrame,
fpsDisplay,
];
diff --git a/src/client/graphics/TransformHandler.ts b/src/client/graphics/TransformHandler.ts
index 47b569d5a..a493b64fc 100644
--- a/src/client/graphics/TransformHandler.ts
+++ b/src/client/graphics/TransformHandler.ts
@@ -158,7 +158,6 @@ export class TransformHandler {
}
onGoToPlayer(event: GoToPlayerEvent) {
- this.game.setFocusedPlayer(event.player);
this.clearTarget();
const nameLocation = event.player.nameLocation();
if (!nameLocation) {
diff --git a/src/client/graphics/layers/EventsDisplay.ts b/src/client/graphics/layers/EventsDisplay.ts
index a9b8c85e1..31ef319b2 100644
--- a/src/client/graphics/layers/EventsDisplay.ts
+++ b/src/client/graphics/layers/EventsDisplay.ts
@@ -1051,7 +1051,7 @@ export class EventsDisplay extends LitElement implements Layer {
? this.renderButton({
content: this.getEventDescription(event),
onClick: () => {
- event.focusID &&
+ if (event.focusID)
this.emitGoToPlayerEvent(event.focusID);
},
className: "text-left",
@@ -1060,7 +1060,7 @@ export class EventsDisplay extends LitElement implements Layer {
? this.renderButton({
content: this.getEventDescription(event),
onClick: () => {
- event.unitView &&
+ if (event.unitView)
this.emitGoToUnitEvent(
event.unitView,
);
diff --git a/src/client/graphics/layers/GutterAdModal.ts b/src/client/graphics/layers/GutterAdModal.ts
deleted file mode 100644
index 707a04054..000000000
--- a/src/client/graphics/layers/GutterAdModal.ts
+++ /dev/null
@@ -1,160 +0,0 @@
-import { LitElement, css, html } from "lit";
-import { customElement, state } from "lit/decorators.js";
-import { EventBus, GameEvent } from "../../../core/EventBus";
-import { getGamesPlayed } from "../../Utils";
-import { Layer } from "./Layer";
-
-export class GutterAdModalEvent implements GameEvent {
- constructor(public readonly isVisible: boolean) {}
-}
-
-@customElement("gutter-ad-modal")
-export class GutterAdModal extends LitElement implements Layer {
- public eventBus: EventBus;
-
- @state()
- private isVisible: boolean = false;
-
- @state()
- private adLoaded: boolean = false;
-
- private leftAdType: string = "left_rail";
- private rightAdType: string = "right_rail";
- private leftContainerId: string = "gutter-ad-container-left";
- private rightContainerId: string = "gutter-ad-container-right";
- private margin: string = "10px";
-
- // Override createRenderRoot to disable shadow DOM
- createRenderRoot() {
- return this;
- }
-
- init() {
- if (getGamesPlayed() > 1) {
- this.eventBus.on(GutterAdModalEvent, (event) => {
- if (event.isVisible) {
- this.show();
- } else {
- this.hide();
- }
- });
- }
- }
-
- tick() {}
-
- static styles = css``;
-
- // Called after the component's DOM is first rendered
- firstUpdated() {
- // DOM is guaranteed to be available here
- console.log("GutterAdModal DOM is ready");
- }
-
- public show(): void {
- console.log("showing GutterAdModal");
- this.isVisible = true;
- this.requestUpdate();
-
- // Wait for the update to complete, then load ads
- this.updateComplete.then(() => {
- this.loadAds();
- });
- }
-
- public hide(): void {
- console.log("hiding GutterAdModal");
- this.isVisible = false;
- this.destroyAds();
- this.adLoaded = false;
- this.requestUpdate();
- }
-
- private loadAds(): void {
- // Ensure the container elements exist before loading ads
- const leftContainer = this.querySelector(`#${this.leftContainerId}`);
- const rightContainer = this.querySelector(`#${this.rightContainerId}`);
-
- if (!leftContainer || !rightContainer) {
- console.warn("Ad containers not found in DOM");
- return;
- }
-
- if (!window.ramp) {
- console.warn("Playwire RAMP not available");
- this.hide();
- return;
- }
-
- if (this.adLoaded) {
- console.log("Ads already loaded, skipping");
- return;
- }
-
- try {
- window.ramp.que.push(() => {
- window.ramp.spaAddAds([
- {
- type: this.leftAdType,
- selectorId: this.leftContainerId,
- },
- {
- type: this.rightAdType,
- selectorId: this.rightContainerId,
- },
- ]);
- this.adLoaded = true;
- console.log("Playwire ads loaded:", this.leftAdType, this.rightAdType);
- });
- } catch (error) {
- console.error("Failed to load Playwire ads:", error);
- this.hide();
- }
- }
-
- private destroyAds(): void {
- if (!window.ramp || !this.adLoaded) {
- return;
- }
- try {
- window.ramp.destroyUnits("all");
- } catch (error) {
- console.error("Failed to destroy Playwire ad:", error);
- }
- }
-
- disconnectedCallback() {
- super.disconnectedCallback();
- this.destroyAds();
- }
-
- render() {
- if (!this.isVisible) {
- return html``;
- }
-
- return html`
-
-
-
-
-
- `;
- }
-}
diff --git a/src/client/graphics/layers/OptionsMenu.ts b/src/client/graphics/layers/OptionsMenu.ts
deleted file mode 100644
index e0ee2004f..000000000
--- a/src/client/graphics/layers/OptionsMenu.ts
+++ /dev/null
@@ -1,278 +0,0 @@
-import { html, LitElement } from "lit";
-import { customElement, state } from "lit/decorators.js";
-import { EventBus } from "../../../core/EventBus";
-import { GameType } from "../../../core/game/Game";
-import { GameUpdateType } from "../../../core/game/GameUpdates";
-import { GameView } from "../../../core/game/GameView";
-import { UserSettings } from "../../../core/game/UserSettings";
-import { AlternateViewEvent, RefreshGraphicsEvent } from "../../InputHandler";
-import { PauseGameEvent } from "../../Transport";
-import { translateText } from "../../Utils";
-import { Layer } from "./Layer";
-
-const button = ({
- classes = "",
- onClick = () => {},
- title = "",
- children = "",
-}) => html`
-
-`;
-
-const secondsToHms = (d: number): string => {
- const h = Math.floor(d / 3600);
- const m = Math.floor((d % 3600) / 60);
- const s = Math.floor((d % 3600) % 60);
- let time = d === 0 ? "-" : `${s}s`;
- if (m > 0) time = `${m}m` + time;
- if (h > 0) time = `${h}h` + time;
- return time;
-};
-
-@customElement("options-menu")
-export class OptionsMenu extends LitElement implements Layer {
- public game: GameView;
- public eventBus: EventBus;
- private userSettings: UserSettings = new UserSettings();
-
- @state()
- private showPauseButton: boolean = true;
-
- @state()
- private isPaused: boolean = false;
-
- @state()
- private timer: number = 0;
-
- @state()
- private showSettings: boolean = false;
-
- private isVisible = false;
-
- private hasWinner = false;
-
- @state()
- private alternateView: boolean = false;
-
- private onTerrainButtonClick() {
- this.alternateView = !this.alternateView;
- this.eventBus.emit(new AlternateViewEvent(this.alternateView));
- this.requestUpdate();
- }
-
- private onExitButtonClick() {
- const isAlive = this.game.myPlayer()?.isAlive();
- if (isAlive) {
- const isConfirmed = confirm(
- translateText("help_modal.exit_confirmation"),
- );
- if (!isConfirmed) return;
- }
- // redirect to the home page
- window.location.href = "/";
- }
-
- createRenderRoot() {
- return this;
- }
-
- private onSettingsButtonClick() {
- this.showSettings = !this.showSettings;
- this.requestUpdate();
- }
-
- private onPauseButtonClick() {
- this.isPaused = !this.isPaused;
- this.eventBus.emit(new PauseGameEvent(this.isPaused));
- }
-
- private onToggleEmojisButtonClick() {
- this.userSettings.toggleEmojis();
- this.requestUpdate();
- }
-
- private onToggleAlertFrameButtonClick() {
- this.userSettings.toggleAlertFrame();
- this.requestUpdate();
- }
-
- private onToggleSpecialEffectsButtonClick() {
- this.userSettings.toggleFxLayer();
- this.requestUpdate();
- }
-
- private onToggleDarkModeButtonClick() {
- this.userSettings.toggleDarkMode();
- this.requestUpdate();
- this.eventBus.emit(new RefreshGraphicsEvent());
- }
-
- private onToggleRandomNameModeButtonClick() {
- this.userSettings.toggleRandomName();
- }
-
- private onToggleFocusLockedButtonClick() {
- this.userSettings.toggleFocusLocked();
- this.requestUpdate();
- }
-
- private onToggleLeftClickOpensMenu() {
- this.userSettings.toggleLeftClickOpenMenu();
- }
-
- private onToggleTerritoryPatterns() {
- this.userSettings.toggleTerritoryPatterns();
- this.requestUpdate();
- }
-
- private onTogglePerformanceOverlayButtonClick() {
- this.userSettings.togglePerformanceOverlay();
- this.requestUpdate();
- }
-
- init() {
- console.log("init called from OptionsMenu");
- this.showPauseButton =
- this.game.config().gameConfig().gameType === GameType.Singleplayer ||
- this.game.config().isReplay();
- this.isVisible = true;
- this.requestUpdate();
- }
-
- tick() {
- const updates = this.game.updatesSinceLastTick();
- if (updates) {
- this.hasWinner = this.hasWinner || updates[GameUpdateType.Win].length > 0;
- }
- if (this.game.inSpawnPhase()) {
- this.timer = 0;
- } else if (!this.hasWinner && this.game.ticks() % 10 === 0) {
- this.timer++;
- }
- this.isVisible = true;
- this.requestUpdate();
- }
-
- render() {
- if (!this.isVisible) {
- return html``;
- }
- return html`
- e.preventDefault()}
- >
-
-
- ${button({
- classes: !this.showPauseButton ? "hidden" : "",
- onClick: this.onPauseButtonClick,
- title: this.isPaused ? "Resume game" : "Pause game",
- children: this.isPaused ? "▶️" : "⏸",
- })}
-
- ${secondsToHms(this.timer)}
-
- ${button({
- onClick: this.onExitButtonClick,
- title: "Exit game",
- children: "❌",
- })}
- ${button({
- onClick: this.onSettingsButtonClick,
- title: "Settings",
- children: "⚙️",
- })}
-
-
-
-
-
- `;
- }
-}
diff --git a/src/client/graphics/layers/PlayerActionHandler.ts b/src/client/graphics/layers/PlayerActionHandler.ts
index 1bba3300e..2ea2e8970 100644
--- a/src/client/graphics/layers/PlayerActionHandler.ts
+++ b/src/client/graphics/layers/PlayerActionHandler.ts
@@ -12,7 +12,6 @@ import {
SendDonateTroopsIntentEvent,
SendEmbargoIntentEvent,
SendEmojiIntentEvent,
- SendQuickChatEvent,
SendSpawnIntentEvent,
SendTargetPlayerIntentEvent,
} from "../../Transport";
@@ -97,10 +96,6 @@ export class PlayerActionHandler {
this.eventBus.emit(new SendEmojiIntentEvent(targetPlayer, emojiIndex));
}
- handleQuickChat(recipient: PlayerView, chatKey: string, params: any = {}) {
- this.eventBus.emit(new SendQuickChatEvent(recipient, chatKey, params));
- }
-
handleDeleteUnit(unitId: number) {
this.eventBus.emit(new SendDeleteUnitIntentEvent(unitId));
}
diff --git a/src/client/graphics/layers/StructureIconsLayer.ts b/src/client/graphics/layers/StructureIconsLayer.ts
index df6634461..4f86c8070 100644
--- a/src/client/graphics/layers/StructureIconsLayer.ts
+++ b/src/client/graphics/layers/StructureIconsLayer.ts
@@ -255,7 +255,9 @@ export class StructureIconsLayer implements Layer {
this.potentialUpgrade.iconContainer.filters = [];
this.potentialUpgrade.dotContainer.filters = [];
}
- this.ghostUnit?.container && (this.ghostUnit.container.filters = []);
+ if (this.ghostUnit?.container) {
+ this.ghostUnit.container.filters = [];
+ }
if (!this.ghostUnit) return;
diff --git a/src/client/index.html b/src/client/index.html
index 01f6b5fa9..2dcf835e7 100644
--- a/src/client/index.html
+++ b/src/client/index.html
@@ -91,12 +91,11 @@
document.documentElement.className = "preload";
-
-
+
+
-
-
-