/** * Turn the game engine's own scene-editing replies into a `WorldJsonModification[]`. * * This is the CLI lane's counterpart to the Creator's `useSave.ts saveSceneModifications` and the * spawn-point/world-config half of `useTabSwitching.ts deactivateScene`. The web lane posts its * modifications to `POST /api/edit-world-config`, which rebuilds `predicateField`/`predicateValue` * into real predicates server-side because functions cannot cross HTTP. Here there is no server: * the shell page posts the engine's replies VERBATIM to the local sidecar, and this module — which * runs in Node, in the same process that writes the file — builds the predicates directly. * * That split is deliberate. Everything that knows what world.json means lives on this side, so it * is plain, synchronous, dependency-free code that can be unit-tested without a browser; the shell * stays a dumb relay of `SCENE_HAS_CHANGES` and `SCENE_EDITING_STATUS`. */ import type { WorldJsonModification, WorldJsonShape } from '@bitmagic/world-forger/pipeline/index.js'; /** The engine's `SCENE_HAS_CHANGES` reply (`CreatorMessageHandler.ts`, `CHECK_SCENE_CHANGES`). */ export interface SceneChangeReport { hasChanges?: boolean; modifiedObjectIds?: string[]; deletedObjectIds?: string[]; fullSaveNeeded?: boolean; pendingWorldConfig?: { settings: unknown; path: string[]; title?: string; } | null; pendingSpawnPoints?: Array> | null; } /** The engine's `SCENE_EDITING_STATUS` reply (`CreatorMessageHandler.ts`, line ~1463). */ export interface SceneEditingStatus { unlocked?: boolean; environmentObjects?: Array>; /** * WHICH level `environmentObjects` covers. `serializeEnvironmentObjects()` walks the LIVE scene * and a multi-level game only instantiates one level, so a non-null id means the array is this * level plus untagged globals — never the whole world. `null` (single-level or legacy) means it * genuinely is the whole world. */ activeLevelId?: string | null; markers?: Array>; } /** What the shell POSTs to `/api/scene/save`. Just the two engine replies, plus one flag. */ export interface ScenePayload { changes: SceneChangeReport; status: SceneEditingStatus; /** Set by the shell when the engine posted `ADD_MARKER` / `UPDATE_MARKER` since the last save. */ markersDirty?: boolean; } /** * Build the write for one scene-editing flush. Returns `[]` when there is nothing to persist, so * the caller can skip the file write entirely. * * `world` is the CURRENT parsed world.json, needed only to resolve the levels registry. Everything * else comes from the engine, which is the source of truth for scene state — this never invents a * position, rotation or scale. */ export declare function buildSceneModifications(payload: ScenePayload, world: WorldJsonShape): WorldJsonModification[];