import { CalledActionResult } from "../nlcore/gameTypes"; import { Awaitable, EventDispatcher, IdManager, Lock, Values } from "../../util/data"; import { MenuData } from "../nlcore/elements/menu"; import { Scene } from "../nlcore/elements/scene"; import { Sound } from "../nlcore/elements/sound"; import * as Howler from "howler"; import { SrcManager } from "../nlcore/action/srcManager"; import { LogicAction } from "../nlcore/action/logicAction"; import { Storable } from "../nlcore/elements/persistent/storable"; import { Game } from "../nlcore/game"; import { Clickable, MenuElement, TextElement } from "./gameState.type"; import { Sentence } from "../nlcore/elements/character/sentence"; import { type SceneSnapshot } from "../nlcore/action/actions/sceneAction"; import { Logger } from "../../util/logger"; import { Story } from "../nlcore/elements/story"; import { LiveGame } from "../nlcore/game/liveGame"; import { Chosen, ExposedKeys, ExposedState, ExposedStateType } from "./type"; import { AudioManager, AudioManagerDataRaw } from "./lib/AudioManager"; import { Layer } from "../nlcore/elements/layer"; import { GameStateGuard } from "./guard"; import { LiveGameEventToken } from "../nlcore/types"; import * as htmlToImage from "html-to-image"; import { Video, VideoStateRaw } from "../nlcore/elements/video"; import { Timelines } from "./Tasks"; import { Notification, NotificationManager } from "./lib/notification"; import { ActionHistoryManager } from "../../game/nlcore/action/actionHistory"; import { GameHistoryManager } from "../../game/nlcore/action/gameHistory"; import type { Character } from "../nlcore/elements/character"; import type { TransformDefinitions } from "../nlcore/elements/transform/type"; import type { NvlBlockOptions } from "../nlcore/action/actionTypes"; export type NvlDialogEntry = { id: string; actionId: string; character: Character | null; sentence: Sentence; text: string; }; export type NvlDialogPhase = "idle" | "typing" | "awaitAdvance"; export type NvlState = { active: boolean; visible: boolean; sessionId: string | null; dialogs: NvlDialogEntry[]; options: NvlBlockOptions | null; activeDialogId: string | null; phase: NvlDialogPhase; pendingAdvance: boolean; isTyping: boolean; }; type Legacy_PlayerStateElement = { texts: Clickable[]; menus: Clickable[]; displayable: LogicAction.DisplayableElements[]; }; type ScheduleHandle = { retry: () => void; onCleanup: (fn: VoidFunction) => void; }; export type PlayerState = { sounds: Sound[]; videos: Video[]; srcManagers: SrcManager[]; elements: PlayerStateElement[]; }; export type PlayerStateElement = { scene: Scene; /**@deprecated */ ele?: Legacy_PlayerStateElement; layers: Map; texts: Clickable[]; menus: Clickable[]; }; export type NvlStateData = { active: boolean; visible: boolean; sessionId: string | null; options?: NvlBlockOptions | null; activeDialogId?: string | null; phase?: NvlDialogPhase; pendingAdvance?: boolean; dialogIds?: string[]; dialogs?: NvlDialogEntryData[]; }; export type NvlDialogEntryData = { id: string; actionId?: string; text: string; characterId: string | null; }; export type PlayerStateData = { scenes: { sceneId: string; elements: { /**@deprecated */ displayable?: string[]; /** * { [layerName]: [displayableId][] } */ layers: Record; }; }[]; audio: AudioManagerDataRaw; videos: [videoId: string, videoState: VideoStateRaw][]; nvlState?: NvlStateData; }; export type PresentationSnapshot = { scenes: SceneSnapshot[]; nvlState: NvlState; }; interface StageUtils { update: () => void; forceUpdate: () => void; forceRemount: () => void; next: () => void; } type GameStateEvents = { "event:state.end": []; "event:state.player.skip": [force?: boolean]; "event:state.player.lineEnd": []; "event:state.player.requestFlush": []; "event:state.player.stageClick": []; "event.state.onExpose": [unknown, ExposedState[ExposedStateType]]; "event:state.onRender": []; "event:state:flushPreloadedScenes": []; "event:state.nvl.enter": [sessionId: string, options: NvlBlockOptions | null]; "event:state.nvl.exit": []; "event:state.nvl.dialogComplete": [dialogId: string]; "event:state.nvl.dialogAppend": [entry: NvlDialogEntry]; "event:state.nvl.visibilityChange": [visible: boolean, options?: Partial]; "event:state.nvl.change": [state: NvlState]; }; /** * Core game state management class * Manages all game-related states including sounds, videos, elements and their lifecycle */ export declare class GameState { static EventTypes: { [K in keyof GameStateEvents]: K; }; private state; private nvlState; private _suppressNextNvlTyping; currentHandling: CalledActionResult | null; stage: StageUtils; game: Game; playerCurrent: HTMLDivElement | null; mainContentNode: HTMLDivElement | null; exposedState: Map, object>; guard: GameStateGuard; timelines: Timelines; preloadingScene: Scene | null; flushDep: number; rollLock: Lock; readonly notificationMgr: NotificationManager; readonly events: EventDispatcher; readonly logger: Logger; readonly audioManager: AudioManager; readonly htmlToImage: typeof htmlToImage; readonly idManager: IdManager; readonly actionHistory: ActionHistoryManager; readonly gameHistory: GameHistoryManager; pageRouter: null; private stageClickBuffer; private readonly nvlAdvanceWaiters; constructor(game: Game, stage: StageUtils); get deps(): number; addVideo(video: Video): this; removeVideo(video: Video): this; isVideoAdded(video: Video): boolean; getVideos(): Video[]; findElementByScene(scene: Scene): PlayerStateElement | null; findElementByDisplayable(displayable: LogicAction.DisplayableElements, layer?: Layer | null): PlayerStateElement | null; getLiveGame(): LiveGame; removeElement(element: PlayerStateElement): this; preloadScene(arg: Scene | Story): this; getPreloadingScene(): Scene | null; addElement(element: PlayerStateElement): this; addScene(scene: Scene): this; flush(): this; popScene(): this; removeScene(scene: Scene): this; getSceneElements(): PlayerStateElement[]; getLastScene(): Scene | null; getCurrentScene(): Scene | null; sceneExists(scene?: Scene): boolean; isSceneActive(scene: Scene): boolean; wait(ms: number): Promise; schedule(callback: (scheduleHandle: ScheduleHandle) => void, ms: number): () => void; notify(notification: Notification): void; handle(action: PlayerAction): this; createDialog(id: string, sentence: Sentence, afterClick?: () => void, scene?: Scene): LiveGameEventToken & { text: string; }; createMenu(menu: MenuData, afterChoose?: (choice: Chosen) => void, scene?: Scene): LiveGameEventToken & { prompt: null | string; }; /** * Enter NVL mode * @param options - Optional block options for transitions */ enterNvlMode(options?: NvlBlockOptions | null): this; /** * Exit NVL mode * @param options - Optional block options for transitions */ exitNvlMode(options?: NvlBlockOptions | null): this; /** * Set NVL layer visibility without exiting NVL mode * @param visible - Whether to show or hide the NVL layer * @param options - Optional transition properties */ setNvlVisibility(visible: boolean, options?: Partial): this; /** * Append a dialog to the NVL dialog list * @param entry - The dialog entry to append */ appendNvlDialog(entry: NvlDialogEntry): this; /** * Remove a dialog from the NVL dialog list * @param id - The dialog id to remove */ removeNvlDialog(id: string): this; /** * Get current NVL dialogs */ getNvlDialogs(): NvlDialogEntry[]; /** * Check if currently in NVL mode */ isNvlMode(): boolean; /** * Get NVL state */ getNvlState(): NvlState; /** * Create a snapshot of the current NVL state. */ createNvlSnapshot(): NvlState; createPresentationSnapshot(): PresentationSnapshot; /** * Restore NVL state and refresh UI. */ restoreNvlSnapshot(snapshot: NvlState): this; restorePresentationSnapshot(snapshot: PresentationSnapshot): this; /** * Clear NVL dialogs */ clearNvlDialogs(): this; setNvlActiveDialog(dialogId: string | null, isTyping: boolean): this; setNvlTyping(isTyping: boolean): this; getNvlDialog(dialogId: string): NvlDialogEntry | null; getActiveNvlDialogForAction(actionId: string): NvlDialogEntry | null; getLatestNvlDialogForAction(actionId: string): NvlDialogEntry | null; allocateNvlDialogId(actionId: string): string; ensureNvlDialog(entry: NvlDialogEntry): { created: boolean; entry: NvlDialogEntry; }; activateNvlDialog(dialogId: string, phase?: Exclude, preserveProgress?: boolean): this; waitForNvlAdvance(dialogId: string, resolve: () => void): LiveGameEventToken; requestNvlAdvance(dialogId: string): "ignore" | "typing" | "advance"; requestNvlSkip(dialogId: string): "ignore" | "typing" | "advance"; completeNvlTyping(dialogId: string): boolean; settleNvlDialog(dialogId: string): this; suppressNextNvlTyping(): this; consumeNvlTypingSuppression(): boolean; recordStageClick(): this; consumeStageClick(maxAgeMs?: number): boolean; createDisplayable(displayable: LogicAction.DisplayableElements, scene?: Scene | null, layer?: Layer | null): this; disposeDisplayable(displayable: LogicAction.DisplayableElements, scene?: Scene | null, layer?: Layer | null): this; forceReset(): void; getHowl(): typeof Howler.Howl; registerSrcManager(srcManager: SrcManager): this; offSrcManager(srcManager: SrcManager): this; getStorable(): Storable; getSceneByName(name: string): Scene | null; getStory(): Story; setInterval(callback: () => void, delay: number): NodeJS.Timeout; clearInterval(interval: NodeJS.Timeout): void; setTimeout(callback: () => void, delay: number): NodeJS.Timeout; clearTimeout(timeout: NodeJS.Timeout): void; forceAnimation(): Awaitable; /** * Mounts a new state to the game state manager * @param key - Unique identifier for the state * @param state - State object to be mounted * @returns Object containing unmount function */ mountState(key: ExposedKeys[T], state: ExposedState[T]): { unMount: () => void; }; unMountState(key: Values): this; initVideo(video: Video): this; isStateMounted(key: Values): boolean; getExposedState(key: ExposedKeys[T]): ExposedState[T] | null; getExposedStateForce(key: ExposedKeys[T]): ExposedState[T]; getExposedStateAsync(key: ExposedKeys[T], onExpose: (state: ExposedState[T]) => void): LiveGameEventToken; /** * Dispose of the game state * * This is an irreversible action; once disposed of, the game state can't be used again. * * Don't call this method directly */ dispose(): void; /** * Converts current game state to serializable data format * @returns PlayerStateData object containing all state information */ toData(): PlayerStateData; loadData(data: PlayerStateData, elementMap: Map): void; getLastSceneIfNot(scene: Scene | null | void): Scene; createElementSnapshot(element: PlayerStateElement): PlayerStateElementSnapshot; fromElementSnapshot(snapshot: PlayerStateElementSnapshot): PlayerStateElement; private removeElements; private resetLayers; private syncNvlDerivedState; private emitNvlStateChange; private resolveNvlAdvance; private createWaitableAction; private sceneNotFound; private layerNotFound; private constructLayerMap; } export {};