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"; import { crazyGamesSDK } from "../../CrazyGamesSDK"; import { TogglePauseIntentEvent } from "../../InputHandler"; import { PauseGameIntentEvent, SendWinnerEvent } from "../../Transport"; import { translateText } from "../../Utils"; import { ImmunityBarVisibleEvent } from "./ImmunityTimer"; import { Layer } from "./Layer"; import { ShowReplayPanelEvent } from "./ReplayPanel"; import { ShowSettingsModalEvent } from "./SettingsModal"; import { SpawnBarVisibleEvent } from "./SpawnTimer"; 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 { public game: GameView; public eventBus: EventBus; @state() private _isSinglePlayer: boolean = false; @state() private _isReplayVisible: boolean = false; @state() private _isVisible: boolean = true; @state() private isPaused: boolean = false; @state() private timer: number = 0; private hasWinner = false; private isLobbyCreator = false; private spawnBarVisible = false; private immunityBarVisible = false; createRenderRoot() { return this; } init() { this._isSinglePlayer = this.game?.config()?.gameConfig()?.gameType === GameType.Singleplayer || this.game.config().isReplay(); this._isVisible = true; this.game.inSpawnPhase(); this.eventBus.on(SpawnBarVisibleEvent, (e) => { this.spawnBarVisible = e.visible; this.updateParentOffset(); }); this.eventBus.on(ImmunityBarVisibleEvent, (e) => { this.immunityBarVisible = e.visible; this.updateParentOffset(); }); this.eventBus.on(SendWinnerEvent, () => { this.hasWinner = true; this.requestUpdate(); }); this.eventBus.on(TogglePauseIntentEvent, () => { const isReplayOrSingleplayer = this._isSinglePlayer || this.game?.config()?.isReplay(); if (isReplayOrSingleplayer || this.isLobbyCreator) { this.onPauseButtonClick(); } }); this.requestUpdate(); } getTickIntervalMs() { return 250; } tick() { // Timer logic // Check if the player is the lobby creator if (!this.isLobbyCreator && this.game.myPlayer()?.isLobbyCreator()) { this.isLobbyCreator = true; this.requestUpdate(); } const maxTimerValue = this.game.config().gameConfig().maxTimerValue; const spawnPhaseTurns = this.game.config().numSpawnPhaseTurns(); const ticks = this.game.ticks(); const gameTicks = Math.max(0, ticks - spawnPhaseTurns); const elapsedSeconds = Math.floor(gameTicks / 10); // 10 ticks per second if (this.game.inSpawnPhase()) { this.timer = maxTimerValue !== null && maxTimerValue !== undefined ? maxTimerValue * 60 : 0; return; } if (this.hasWinner) { return; } if (maxTimerValue !== null && maxTimerValue !== undefined) { this.timer = Math.max(0, maxTimerValue * 60 - elapsedSeconds); } else { this.timer = elapsedSeconds; } } private updateParentOffset(): void { const offset = (this.spawnBarVisible ? 7 : 0) + (this.immunityBarVisible ? 7 : 0); const parent = this.parentElement as HTMLElement; if (parent) { parent.style.marginTop = `${offset}px`; } } private secondsToHms = (d: number): string => { const pad = (n: number) => (n < 10 ? `0${n}` : n); const h = Math.floor(d / 3600); const m = Math.floor((d % 3600) / 60); const s = Math.floor((d % 3600) % 60); if (h !== 0) { return `${pad(h)}:${pad(m)}:${pad(s)}`; } else { return `${pad(m)}:${pad(s)}`; } }; private toggleReplayPanel(): void { this._isReplayVisible = !this._isReplayVisible; this.eventBus.emit( new ShowReplayPanelEvent(this._isReplayVisible, this._isSinglePlayer), ); } private onPauseButtonClick() { this.isPaused = !this.isPaused; if (this.isPaused) { crazyGamesSDK.gameplayStop(); } else { crazyGamesSDK.gameplayStart(); } this.eventBus.emit(new PauseGameIntentEvent(this.isPaused)); } private async onExitButtonClick() { const isAlive = this.game.myPlayer()?.isAlive(); if (isAlive) { const isConfirmed = confirm( translateText("help_modal.exit_confirmation"), ); if (!isConfirmed) return; } await crazyGamesSDK.requestMidgameAd(); await crazyGamesSDK.gameplayStop(); // redirect to the home page window.location.href = "/"; } private onSettingsButtonClick() { this.eventBus.emit( new ShowSettingsModalEvent(true, this._isSinglePlayer, this.isPaused), ); } render() { if (this.game === undefined) return html``; const timerColor = this.game.config().gameConfig().maxTimerValue !== undefined && this.game.config().gameConfig().maxTimerValue !== null && this.timer < 60 ? "text-red-400" : ""; return html` `; } maybeRenderReplayButtons() { const isReplayOrSingleplayer = this._isSinglePlayer || this.game?.config()?.isReplay(); const showPauseButton = isReplayOrSingleplayer || this.isLobbyCreator; return html` ${isReplayOrSingleplayer ? html`