diff --git a/src/client/Main.ts b/src/client/Main.ts index 68e16f421..2474d5d24 100644 --- a/src/client/Main.ts +++ b/src/client/Main.ts @@ -24,7 +24,7 @@ import { SinglePlayerModal } from "./SinglePlayerModal"; import { UserSettingModal } from "./UserSettingModal"; import "./UsernameInput"; import { UsernameInput } from "./UsernameInput"; -import { generateCryptoRandomUUID } from "./Utils"; +import { generateCryptoRandomUUID, incrementGamesPlayed } from "./Utils"; import "./components/NewsButton"; import { NewsButton } from "./components/NewsButton"; import "./components/baseComponents/Button"; @@ -365,6 +365,7 @@ class Client { () => { this.joinModal.close(); this.publicLobby.stop(); + incrementGamesPlayed(); try { window.PageOS.session.newPageView(); diff --git a/src/client/Utils.ts b/src/client/Utils.ts index d8e782f16..c6445c170 100644 --- a/src/client/Utils.ts +++ b/src/client/Utils.ts @@ -168,3 +168,20 @@ export function getAltKey(): string { return "Alt"; } } + +export function getGamesPlayed(): number { + try { + return parseInt(localStorage.getItem("gamesPlayed") || "0", 10) || 0; + } catch (error) { + console.warn("Failed to read games played from localStorage:", error); + return 0; + } +} + +export function incrementGamesPlayed(): void { + try { + localStorage.setItem("gamesPlayed", (getGamesPlayed() + 1).toString()); + } catch (error) { + console.warn("Failed to increment games played in localStorage:", error); + } +} diff --git a/src/client/graphics/GameRenderer.ts b/src/client/graphics/GameRenderer.ts index ce808df29..200239e74 100644 --- a/src/client/graphics/GameRenderer.ts +++ b/src/client/graphics/GameRenderer.ts @@ -16,7 +16,6 @@ import { GutterAdModal } from "./layers/GutterAdModal"; import { HeadsUpMessage } from "./layers/HeadsUpMessage"; import { Layer } from "./layers/Layer"; import { Leaderboard } from "./layers/Leaderboard"; -import { LeftInGameAd } from "./layers/LeftInGameAd"; import { MainRadialMenu } from "./layers/MainRadialMenu"; import { MultiTabModal } from "./layers/MultiTabModal"; import { NameLayer } from "./layers/NameLayer"; @@ -24,6 +23,7 @@ import { OptionsMenu } from "./layers/OptionsMenu"; import { PlayerInfoOverlay } from "./layers/PlayerInfoOverlay"; import { PlayerPanel } from "./layers/PlayerPanel"; import { ReplayPanel } from "./layers/ReplayPanel"; +import { SpawnAd } from "./layers/SpawnAd"; import { SpawnTimer } from "./layers/SpawnTimer"; import { StructureLayer } from "./layers/StructureLayer"; import { TeamStats } from "./layers/TeamStats"; @@ -198,13 +198,11 @@ export function createRenderer( unitInfoModal.structureLayer = structureLayer; // unitInfoModal.eventBus = eventBus; - const leftInGameAd = document.querySelector( - "left-in-game-ad", - ) as LeftInGameAd; - if (!(leftInGameAd instanceof LeftInGameAd)) { - console.error("left in game ad not found"); + const spawnAd = document.querySelector("spawn-ad") as SpawnAd; + if (!(spawnAd instanceof SpawnAd)) { + console.error("spawn ad not found"); } - leftInGameAd.g = game; + spawnAd.g = game; const gutterAdModal = document.querySelector( "gutter-ad-modal", @@ -249,7 +247,7 @@ export function createRenderer( headsUpMessage, unitInfoModal, multiTabModal, - leftInGameAd, + spawnAd, gutterAdModal, ]; diff --git a/src/client/graphics/layers/GutterAdModal.ts b/src/client/graphics/layers/GutterAdModal.ts index 3c2c6dd24..707a04054 100644 --- a/src/client/graphics/layers/GutterAdModal.ts +++ b/src/client/graphics/layers/GutterAdModal.ts @@ -1,6 +1,7 @@ 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 { @@ -29,13 +30,15 @@ export class GutterAdModal extends LitElement implements Layer { } init() { - this.eventBus.on(GutterAdModalEvent, (event) => { - if (event.isVisible) { - this.show(); - } else { - this.hide(); - } - }); + if (getGamesPlayed() > 1) { + this.eventBus.on(GutterAdModalEvent, (event) => { + if (event.isVisible) { + this.show(); + } else { + this.hide(); + } + }); + } } tick() {} diff --git a/src/client/graphics/layers/LeftInGameAd.ts b/src/client/graphics/layers/SpawnAd.ts similarity index 71% rename from src/client/graphics/layers/LeftInGameAd.ts rename to src/client/graphics/layers/SpawnAd.ts index 2e370d8cc..eb8533937 100644 --- a/src/client/graphics/layers/LeftInGameAd.ts +++ b/src/client/graphics/layers/SpawnAd.ts @@ -1,18 +1,14 @@ import { LitElement, css, html } from "lit"; import { customElement, state } from "lit/decorators.js"; import { GameView } from "../../../core/game/GameView"; +import { getGamesPlayed } from "../../Utils"; import { Layer } from "./Layer"; -const BREAKPOINT = { - width: 1000, - height: 800, -}; +const AD_TYPE = "bottom_rail"; +const AD_CONTAINER_ID = "bottom-rail-ad-container"; -const AD_TYPE = "standard_iab_modl2"; // 320x50/320x100 - better for bottom positioning -const AD_CONTAINER_ID = "bottom-left-ad-container"; - -@customElement("left-in-game-ad") -export class LeftInGameAd extends LitElement implements Layer { +@customElement("spawn-ad") +export class SpawnAd extends LitElement implements Layer { public g: GameView; @state() @@ -21,6 +17,8 @@ export class LeftInGameAd extends LitElement implements Layer { @state() private adLoaded: boolean = false; + private gamesPlayed: number = 0; + // Override createRenderRoot to disable shadow DOM createRenderRoot() { return this; @@ -32,39 +30,40 @@ export class LeftInGameAd extends LitElement implements Layer { super(); } + init() { + this.gamesPlayed = getGamesPlayed(); + } + public show(): void { this.isVisible = true; + this.loadAd(); this.requestUpdate(); - // Load the ad when showing (with small delay to ensure DOM is ready) - setTimeout(() => this.loadAd(), 100); } public hide(): void { + // Destroy the ad when hiding + this.destroyAd(); this.isVisible = false; this.adLoaded = false; this.requestUpdate(); - // Destroy the ad when hiding - this.destroyAd(); } public async tick() { - if (!this.isVisible && !this.g.inSpawnPhase() && this.screenLargeEnough()) { + if ( + !this.isVisible && + this.g.inSpawnPhase() && + this.g.ticks() > 10 && + this.gamesPlayed > 5 + ) { console.log("showing bottom left ad"); this.show(); } - if (this.isVisible && !this.screenLargeEnough()) { + if (this.isVisible && !this.g.inSpawnPhase()) { console.log("hiding bottom left ad"); this.hide(); } } - private screenLargeEnough(): boolean { - return ( - window.innerWidth > BREAKPOINT.width && - window.innerHeight > BREAKPOINT.height - ); - } - private loadAd(): void { if (!window.ramp) { console.warn("Playwire RAMP not available"); @@ -96,8 +95,8 @@ export class LeftInGameAd extends LitElement implements Layer { } try { window.ramp.que.push(() => { - window.ramp.destroyUnits(AD_TYPE); - console.log("Playwire ad destroyed:", AD_TYPE); + window.ramp.destroyUnits("all"); + console.log("Playwire spawn ad destroyed"); }); } catch (error) { console.error("Failed to destroy Playwire ad:", error); @@ -117,7 +116,7 @@ export class LeftInGameAd extends LitElement implements Layer { return html`
-
@@ -368,6 +367,7 @@ +