narraleaf-react
Version:
A React visual novel player framework
193 lines (192 loc) • 7.87 kB
TypeScript
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 { 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";
type Legacy_PlayerStateElement = {
texts: Clickable<TextElement>[];
menus: Clickable<MenuElement, Chosen>[];
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<Layer, LogicAction.DisplayableElements[]>;
texts: Clickable<TextElement>[];
menus: Clickable<MenuElement, Chosen>[];
};
export type PlayerStateData = {
scenes: {
sceneId: string;
elements: {
/**@deprecated */
displayable?: string[];
/**
* { [layerName]: [displayableId][] }
*/
layers: Record<string, string[]>;
};
}[];
audio: AudioManagerDataRaw;
videos: [videoId: string, videoState: VideoStateRaw][];
};
interface StageUtils {
update: () => void;
forceUpdate: () => void;
forceRemount: () => void;
next: () => void;
}
type GameStateEvents = {
"event:state.end": [];
"event:state.player.skip": [force?: boolean];
"event:state.player.requestFlush": [];
"event.state.onExpose": [unknown, ExposedState[ExposedStateType]];
"event:state.onRender": [];
"event:state:flushPreloadedScenes": [];
};
/**
* 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;
currentHandling: CalledActionResult | null;
stage: StageUtils;
game: Game;
playerCurrent: HTMLDivElement | null;
mainContentNode: HTMLDivElement | null;
exposedState: Map<Values<ExposedKeys>, object>;
guard: GameStateGuard;
timelines: Timelines;
preloadingScene: Scene | null;
flushDep: number;
rollLock: Lock;
readonly notificationMgr: NotificationManager;
readonly events: EventDispatcher<GameStateEvents>;
readonly logger: Logger;
readonly audioManager: AudioManager;
readonly htmlToImage: typeof htmlToImage;
readonly idManager: IdManager;
readonly actionHistory: ActionHistoryManager;
readonly gameHistory: GameHistoryManager;
pageRouter: null;
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;
sceneExists(scene?: Scene): boolean;
isSceneActive(scene: Scene): boolean;
wait(ms: number): Promise<void>;
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;
};
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<T extends ExposedStateType>(key: ExposedKeys[T], state: ExposedState[T]): {
unMount: () => void;
};
unMountState(key: Values<ExposedKeys>): this;
initVideo(video: Video): this;
isStateMounted(key: Values<ExposedKeys>): boolean;
getExposedState<T extends ExposedStateType>(key: ExposedKeys[T]): ExposedState[T] | null;
getExposedStateForce<T extends ExposedStateType>(key: ExposedKeys[T]): ExposedState[T];
getExposedStateAsync<T extends ExposedStateType>(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<string, LogicAction.GameElement>): void;
getLastSceneIfNot(scene: Scene | null | void): Scene;
createElementSnapshot(element: PlayerStateElement): PlayerStateElementSnapshot;
fromElementSnapshot(snapshot: PlayerStateElementSnapshot): PlayerStateElement;
private removeElements;
private resetLayers;
private createWaitableAction;
private sceneNotFound;
private layerNotFound;
private constructLayerMap;
}
export {};