/** * BrowserClient - Main orchestrator for browser-based IF games * * Wires together all managers (save, theme, dialog, menu, input, display) * and provides a simple API for story entry points. */ import type { GameEngine } from '@sharpee/engine'; import type { WorldModel } from '@sharpee/world-model'; import type { ISaveRestoreHooks } from '@sharpee/core'; import type { ClientCapabilities } from '@sharpee/if-domain'; import { type IRenderer } from '@sharpee/channel-service'; import type { BrowserClientConfig, BrowserClientInterface, DOMElements } from './types'; import { AudioManager } from './audio/AudioManager'; /** * Default `ClientCapabilities` profile for the browser surface — full * graphical capabilities so every standard + media channel appears in * the per-client manifest. Authors override per `BrowserClientConfig. * clientCapabilities` for specialized surfaces (text-only kiosks, etc.). */ export declare const BROWSER_CAPABILITIES: ClientCapabilities; export declare class BrowserClient implements BrowserClientInterface { private config; private themeManager; private saveManager; private dialogManager; private menuManager; private inputManager; private textDisplay; private statusLine; private audioManager; private engine; private world; private currentTurn; private currentScore; private turnOffset; /** * The `ISaveData` produced by the engine for the in-flight save * request. Set by `onSaveRequested` while the save dialog is open; * cleared in the hook's `finally`. Reused by `performSave` so the * persisted blob matches what the engine actually serialized for * this request, not whatever the world looked like by the time the * dialog returned. */ private pendingEngineSave; private elements; /** * ADR-165 channel renderer host. Constructed in `connectEngine()` * to drive the visible DOM via channel:manifest / channel:packet * (R5-C — primary rendering path). */ private channelRenderer?; private channelLayout?; constructor(config: BrowserClientConfig); /** * Initialize the browser client with DOM elements. * Call after DOMContentLoaded. */ initialize(elements: DOMElements): void; /** * Connect to game engine and set up event handlers. * Call after creating the engine. */ connectEngine(engine: GameEngine, world: WorldModel): void; /** * Append a platform-signal message to the main slot. Mirrors the * `mainChannelRenderer`'s DOM shape (`
` with
* `pre-line` whitespace) plus a `system-message` class for theme
* styling. Used for save/restore feedback strings that aren't
* routed through the engine's text-service block production.
*
* Falls back to no-op if the channel layout hasn't been initialized
* (engine not yet started).
*/
private appendSystemMessage;
/**
* Build the ADR-165 channel renderer wired to the host page's
* existing DOM elements (R5-C cutover).
*
* The host page provides three slots directly (`textContent`,
* `statusLocation`, `statusScore`, `commandInput`). The remaining
* slots needed by the platform-default renderers (notify, media,
* meta, separate prompt label, separate turn element) are mounted
* as hidden children of the existing main window.
*
* Score / turn override: the host page typically has a single
* combined `Score: X | Turns: Y` element. After
* `registerDefaultBrowserRenderers` we replace the platform-default
* `score` and `turn` renderers with composites that update the
* combined element. Stories that supply two separate elements get
* the platform default by overriding back.
*
* Hotspot commands route through `engine.executeTurn` so UI
* gestures synthesize typed-equivalent commands per ADR-163 §10.
*
* Auto-save migrates here from the legacy `text:output` listener:
* `channel:packet` fires on every turn boundary (including idle
* turns), so this is the single dependable signal.
*/
private setupChannelRenderer;
/**
* Build a `BrowserDefaultLayout` from the existing host elements,
* synthesizing hidden children for slots the host page doesn't
* provide. Lets the platform-default renderers run against the
* same DOM the legacy path used.
*/
private adaptHostLayout;
/**
* True when channel-debug logging is enabled. Three opt-in paths
* (any one is sufficient):
* 1. `BrowserClientConfig.debugChannels: true`
* 2. URL query string `?debug-channels=1` (or any truthy value)
* 3. `localStorage['sharpee-debug-channels']` set to a truthy value
*
* Lets authors flip on/off without rebuilding — useful when
* inspecting an installed bundle's per-turn channel emissions.
*/
private shouldDebugChannels;
/**
* Render the combined `Score: X | Turns: Y` string into the host
* page's combined status element. The host's traditional layout
* uses one element; the score and turn channel renderers feed this
* function rather than writing directly.
*/
private renderCombinedStatus;
/**
* Start the game (check for autosave, show initial look)
*/
start(): Promise