diff --git a/index.html b/index.html
index 46eca8f14..5db9deb74 100644
--- a/index.html
+++ b/index.html
@@ -320,7 +320,6 @@
-
diff --git a/src/client/components/VideoPromo.ts b/src/client/components/VideoPromo.ts
deleted file mode 100644
index 6fa108e8b..000000000
--- a/src/client/components/VideoPromo.ts
+++ /dev/null
@@ -1,213 +0,0 @@
-import { LitElement, html } from "lit";
-import { customElement, property, state } from "lit/decorators.js";
-
-const VIDEO_AD_UNIT_TYPE = "precontent_ad_video";
-
-@customElement("video-ad")
-export class VideoAd extends LitElement {
- @state()
- private isVisible: boolean = true;
-
- @property({ attribute: false })
- onComplete?: () => void;
-
- @property({ attribute: false })
- onMidpoint?: () => void;
-
- @property({ attribute: false })
- onAdBlocked?: () => void;
-
- private adLoadTimeout: ReturnType | null = null;
- private rampCheckInterval: ReturnType | null = null;
- private rampWaitTimeout: ReturnType | null = null;
- private adStarted = false;
-
- // How long to wait for ad to start before assuming it's blocked
- private static readonly AD_LOAD_TIMEOUT_MS = 8000;
-
- createRenderRoot() {
- return this;
- }
-
- connectedCallback() {
- super.connectedCallback();
- // Set dimensions on the custom element itself (required by Playwire)
- // Playwire requires explicit pixel dimensions, use max-width for responsiveness
- this.style.display = "block";
- this.style.width = "100%";
- this.style.maxWidth = "800px";
- this.style.aspectRatio = "16/9";
- this.showVideoAd();
- }
-
- disconnectedCallback() {
- super.disconnectedCallback();
- // Clean up timeout if component is removed
- if (this.adLoadTimeout) {
- clearTimeout(this.adLoadTimeout);
- this.adLoadTimeout = null;
- }
- if (this.rampCheckInterval) {
- clearInterval(this.rampCheckInterval);
- this.rampCheckInterval = null;
- }
- if (this.rampWaitTimeout) {
- clearTimeout(this.rampWaitTimeout);
- this.rampWaitTimeout = null;
- }
- }
-
- public showVideoAd(): void {
- if (!window.ramp) {
- // Wait for ramp to be available, but give up after timeout
- this.rampCheckInterval = setInterval(() => {
- if (window.ramp && window.ramp.que) {
- if (this.rampCheckInterval) {
- clearInterval(this.rampCheckInterval);
- this.rampCheckInterval = null;
- }
- if (this.rampWaitTimeout) {
- clearTimeout(this.rampWaitTimeout);
- this.rampWaitTimeout = null;
- }
- this.loadVideoAd();
- }
- }, 100);
-
- // Stop polling after timeout (e.g. adblocker preventing ramp from loading)
- this.rampWaitTimeout = setTimeout(() => {
- if (this.rampCheckInterval) {
- clearInterval(this.rampCheckInterval);
- this.rampCheckInterval = null;
- }
- console.log("[VideoAd] Ramp SDK never loaded - possible adblocker");
- this.handleAdBlocked();
- }, VideoAd.AD_LOAD_TIMEOUT_MS);
- return;
- }
-
- this.loadVideoAd();
- }
-
- private loadVideoAd(): void {
- // Start timeout to detect if ad doesn't load (e.g., due to adblocker)
- this.adLoadTimeout = setTimeout(() => {
- if (!this.adStarted) {
- console.log("[VideoAd] Ad load timeout - possible adblocker detected");
- this.handleAdBlocked();
- }
- }, VideoAd.AD_LOAD_TIMEOUT_MS);
-
- // Set up event listeners when player is ready, chaining any existing handler
- const prevOnPlayerReady = window.ramp.onPlayerReady;
- window.ramp.onPlayerReady = () => {
- if (prevOnPlayerReady) prevOnPlayerReady();
- if (window.Bolt) {
- // Listen for ad start to know ad is loading successfully
- window.Bolt.on(
- VIDEO_AD_UNIT_TYPE,
- window.Bolt.BOLT_AD_STARTED ?? "boltAdStarted",
- () => {
- console.log("[VideoAd] Ad started");
- this.adStarted = true;
- // Clear the timeout since ad is playing
- if (this.adLoadTimeout) {
- clearTimeout(this.adLoadTimeout);
- this.adLoadTimeout = null;
- }
- },
- );
-
- window.Bolt.on(VIDEO_AD_UNIT_TYPE, window.Bolt.BOLT_AD_COMPLETE, () => {
- console.log("[VideoAd] Ad completed");
- this.hideElement();
- });
-
- window.Bolt.on(VIDEO_AD_UNIT_TYPE, window.Bolt.BOLT_AD_ERROR, () => {
- console.log("[VideoAd] Ad error/no fill");
- this.handleAdBlocked();
- });
-
- window.Bolt.on(VIDEO_AD_UNIT_TYPE, window.Bolt.BOLT_MIDPOINT, () => {
- console.log("[VideoAd] Ad midpoint");
- if (this.onMidpoint) {
- this.onMidpoint();
- }
- });
-
- window.Bolt.on(
- VIDEO_AD_UNIT_TYPE,
- window.Bolt.SHOW_HIDDEN_CONTAINER ?? "showHiddenContainer",
- () => {
- console.log("[VideoAd] Ad finished");
- this.hideElement();
- },
- );
- }
- };
-
- // Queue the video ad initialization
- window.ramp.que.push(() => {
- const pwUnits = [{ type: VIDEO_AD_UNIT_TYPE }];
-
- window.ramp
- .addUnits(pwUnits)
- .then(() => {
- window.ramp.displayUnits();
- })
- .catch((e: Error) => {
- console.error("[VideoAd] Error adding units:", e);
- window.ramp.displayUnits();
- });
- });
- }
-
- private handleAdBlocked(): void {
- // Clear timeout if still pending
- if (this.adLoadTimeout) {
- clearTimeout(this.adLoadTimeout);
- this.adLoadTimeout = null;
- }
-
- // Call the callback if provided
- if (this.onAdBlocked) {
- this.onAdBlocked();
- }
- }
-
- private hideElement(): void {
- this.style.display = "none";
- this.isVisible = false;
- // Call the callback if provided
- if (this.onComplete) {
- this.onComplete();
- }
- // Also dispatch event for backwards compatibility
- this.dispatchEvent(
- new CustomEvent("ad-complete", {
- bubbles: true,
- composed: true,
- }),
- );
- }
-
- render() {
- if (!this.isVisible) {
- return html``;
- }
-
- // Provide a container for the Playwire video player to render into
- // Structure matches Playwire example: wrapper > game-video-ad > precontent-video-location
- return html`
-
- `;
- }
-}
diff --git a/src/client/graphics/GameRenderer.ts b/src/client/graphics/GameRenderer.ts
index fb0c96810..81d12fc79 100644
--- a/src/client/graphics/GameRenderer.ts
+++ b/src/client/graphics/GameRenderer.ts
@@ -36,7 +36,6 @@ import { ReplayPanel } from "./layers/ReplayPanel";
import { SAMRadiusLayer } from "./layers/SAMRadiusLayer";
import { SettingsModal } from "./layers/SettingsModal";
import { SpawnTimer } from "./layers/SpawnTimer";
-import { SpawnVideoAd } from "./layers/SpawnVideoReward";
import { StructureIconsLayer } from "./layers/StructureIconsLayer";
import { StructureLayer } from "./layers/StructureLayer";
import { TeamStats } from "./layers/TeamStats";
@@ -268,12 +267,6 @@ export function createRenderer(
}
inGamePromo.game = game;
- const spawnVideoAd = document.querySelector("spawn-video-ad") as SpawnVideoAd;
- if (!(spawnVideoAd instanceof SpawnVideoAd)) {
- console.error("spawn video ad not found");
- }
- spawnVideoAd.game = game;
-
// When updating these layers please be mindful of the order.
// Try to group layers by the return value of shouldTransform.
// Not grouping the layers may cause excessive calls to context.save() and context.restore().
@@ -320,7 +313,6 @@ export function createRenderer(
headsUpMessage,
multiTabModal,
inGamePromo,
- spawnVideoAd,
alertFrame,
performanceOverlay,
];
diff --git a/src/client/graphics/layers/SpawnVideoReward.ts b/src/client/graphics/layers/SpawnVideoReward.ts
deleted file mode 100644
index 028ec89bc..000000000
--- a/src/client/graphics/layers/SpawnVideoReward.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-import { LitElement, html } from "lit";
-import { customElement, state } from "lit/decorators.js";
-import { crazyGamesSDK } from "src/client/CrazyGamesSDK";
-import { Platform } from "src/client/Platform";
-import { getGamesPlayed } from "src/client/Utils";
-import { GameType } from "src/core/game/Game";
-import { GameView } from "../../../core/game/GameView";
-import "../../components/VideoPromo";
-import { Layer } from "./Layer";
-
-@customElement("spawn-video-ad")
-export class SpawnVideoAd extends LitElement implements Layer {
- public game: GameView;
-
- @state() private shouldShow = false;
- @state() private adComplete = false;
-
- createRenderRoot() {
- return this;
- }
-
- init() {
- if (
- !window.adsEnabled ||
- Platform.isMobileWidth ||
- crazyGamesSDK.isOnCrazyGames() ||
- this.game.config().gameConfig().gameType === GameType.Singleplayer ||
- getGamesPlayed() < 3 // Don't show to new players
- ) {
- return;
- }
- this.shouldShow = true;
- }
-
- tick() {
- if (this.adComplete) return;
- // Hide when spawn phase ends
- if (this.shouldShow && !this.game.inSpawnPhase()) {
- this.shouldShow = false;
- this.requestUpdate();
- }
- }
-
- private handleComplete = () => {
- this.adComplete = true;
- this.shouldShow = false;
- };
-
- shouldTransform(): boolean {
- return false;
- }
-
- render() {
- if (!this.shouldShow || this.adComplete) {
- return html``;
- }
-
- return html`
-
-
-
- `;
- }
-}