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: "⚙️", - })} -
-
- -
- ${button({ - onClick: this.onTerrainButtonClick, - title: "Toggle Terrain", - children: "🌲: " + (this.alternateView ? "On" : "Off"), - })} - ${button({ - onClick: this.onToggleEmojisButtonClick, - title: "Toggle Emojis", - children: "🙂: " + (this.userSettings.emojis() ? "On" : "Off"), - })} - ${button({ - onClick: this.onToggleAlertFrameButtonClick, - title: "Toggle Alert frame", - children: "🚨: " + (this.userSettings.alertFrame() ? "On" : "Off"), - })} - ${button({ - onClick: this.onToggleSpecialEffectsButtonClick, - title: "Toggle Special effects", - children: "💥: " + (this.userSettings.fxLayer() ? "On" : "Off"), - })} - ${button({ - onClick: this.onToggleTerritoryPatterns, - title: "Territory Patterns", - children: - "🏳️: " + (this.userSettings.territoryPatterns() ? "On" : "Off"), - })} - ${button({ - onClick: this.onToggleDarkModeButtonClick, - title: "Dark Mode", - children: "🌙: " + (this.userSettings.darkMode() ? "On" : "Off"), - })} - ${button({ - onClick: this.onToggleRandomNameModeButtonClick, - title: "Random name mode", - children: - "🥷: " + (this.userSettings.anonymousNames() ? "On" : "Off"), - })} - ${button({ - onClick: this.onToggleLeftClickOpensMenu, - title: "Left click", - children: - "🖱️: " + - (this.userSettings.leftClickOpensMenu() - ? "Opens menu" - : "Attack"), - })} - ${button({ - onClick: this.onTogglePerformanceOverlayButtonClick, - title: "Performance Overlay", - children: - "🚀: " + (this.userSettings.performanceOverlay() ? "On" : "Off"), - })} - -
-
- `; - } -} 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"; - - + + - - -