import { type AuthoredAnimationDiagnostic } from "./authoredAnimation.js"; import type { ModelAnimationConfig } from "../game/playableGame.js"; import type { SceneMarkerLike } from "./sceneShapes.js"; /** A placement's authored rig animation override — the stored `marker.meta.animation` contract (#1274). */ export type AuthoredAnimation = ModelAnimationConfig | "auto" | "none"; /** * One authored catalog prop resolved from an editor marker — grounded at `x`/`z` with yaw, ready * for `ctx.scene.object.place` or {@link placeAuthoredObjects}. */ export interface AuthoredObject { catalogId: string; x: number; z: number; rotationY: number; instanceId: string; /** Extra lift in meters from the marker (`catalogId` field / meta), applied on top of terrain height. */ verticalOffset: number; /** * Per-placement rig animation override authored at `marker.meta.animation` (#1274), threaded onto the * placed object's `ModelConfig.animation` so the override applies in game. `undefined` when the marker * carries no override — behavior is exactly the catalog-resolved default. */ animation?: AuthoredAnimation; } /** Minimal marker shape {@link resolveAuthoredObjects} reads; any `EditorMarker` satisfies it. */ export interface AuthoredObjectMarkerLike extends SceneMarkerLike { catalogId?: string; rotationY?: number; } /** Minimal document shape {@link resolveAuthoredObjects} walks; any `EditorDocument` satisfies it. */ export interface AuthoredObjectsDocumentLike { markers: readonly AuthoredObjectMarkerLike[]; } /** Structural place target — any `ObjectStore` satisfies it. */ export interface AuthoredObjectPlaceTarget { place(catalogId: string, x: number, y: number, z: number, options?: { instanceId?: string; rotation?: number; animation?: AuthoredAnimation; onExisting?: "throw" | "replace" | "keep"; }): string; } /** Options for {@link placeAuthoredObjects}. */ export interface PlaceAuthoredObjectsOptions { /** Extra lift in meters applied to every placement after terrain height + per-object offset. */ verticalOffset?: number; /** How to treat instance ids already in the store. Default `"throw"` (ObjectStore default). */ onExisting?: "throw" | "replace" | "keep"; } /** * Catalog id for a marker: first-class `catalogId` field, else `meta.catalogId` migration alias. * Returns null when the marker is not an authored catalog prop (spawn, mob, generator, …). * @capability authored-objects place catalog mesh props from an editor document */ export declare function markerCatalogId(marker: AuthoredObjectMarkerLike): string | null; /** * Validated per-placement animation from `marker.meta.animation`. Missing or malformed overrides * return undefined so the placed object retains its catalog animation; valid data replaces it whole. * @capability authored-objects per-placement animation override from marker.meta.animation */ export declare function markerAnimation(marker: AuthoredObjectMarkerLike): AuthoredAnimation | undefined; /** * Marker kinds that are spawnable entities (materialized by `authoredEntitySpawns`), not static * catalog props. {@link resolveAuthoredObjects} skips them by default so a placed `mob`/`boss` is * spawned once as an entity and never also placed as a static mesh. * @capability authored-objects marker kinds resolved as entity spawns, not static props */ export declare const ENTITY_MARKER_KINDS: readonly string[]; /** Options for {@link resolveAuthoredObjects}. */ export interface ResolveAuthoredObjectsOptions { /** Marker kinds to skip (they are handled elsewhere). Default {@link ENTITY_MARKER_KINDS}. */ excludeKinds?: readonly string[]; } /** * Every marker carrying a catalog id, as placeable props — pure, no terrain sample. Parallel to * {@link resolveScatter}: games and headless tests read the same list `` places. * Entity-spawn kinds (`mob`/`boss`) are skipped by default — they carry a `catalogId` for their * entity definition, but are spawned via `authoredEntitySpawns`, not placed as static meshes. * @capability authored-objects place catalog mesh props from an editor document */ export declare function resolveAuthoredObjects(document: AuthoredObjectsDocumentLike, options?: ResolveAuthoredObjectsOptions): AuthoredObject[]; /** Resolved catalog props and located repairs for rejected per-placement animation overrides. */ export interface AuthoredObjectsResult { objects: AuthoredObject[]; diagnostics: readonly AuthoredAnimationDiagnostic[]; } /** * Resolves catalog props and validates their animation in one document pass. Rejected overrides * are omitted so each model inherits its original catalog setting. Excluded and unplaced markers * remain the responsibility of their own consumers. * @capability authored-objects resolve static placements with located animation repairs */ export declare function resolveAuthoredObjectsWithDiagnostics(document: AuthoredObjectsDocumentLike, options?: ResolveAuthoredObjectsOptions): AuthoredObjectsResult; /** * Places resolved authored objects into an object store, grounding each on `sampleHeight(x,z)` plus * per-object and options vertical offsets. Returns the instance ids that were placed (or kept). * @capability authored-objects place catalog mesh props from an editor document */ export declare function placeAuthoredObjects(store: AuthoredObjectPlaceTarget, objects: readonly AuthoredObject[], sampleHeight: (x: number, z: number) => number, options?: PlaceAuthoredObjectsOptions): string[]; /** Convenience: resolve a document then place every authored catalog prop. */ export declare function placeAuthoredObjectsFromDocument(store: AuthoredObjectPlaceTarget, document: AuthoredObjectsDocumentLike, sampleHeight: (x: number, z: number) => number, options?: PlaceAuthoredObjectsOptions): string[]; /** * Update changed authored placements and remove previous authored ids absent from the next document. * Initial placement keeps game onInit state; unrelated document edits preserve runtime prop state. * Call on document changes, never on simulation ticks; runtime-created objects remain untouched. * @capability sync-authored-objects synchronize edited catalog prop poses, elevation and removal through the existing object store */ export declare function syncAuthoredObjects(store: AuthoredObjectPlaceTarget & { remove(instanceId: string): boolean; }, objects: readonly AuthoredObject[], previousObjects: readonly AuthoredObject[], sampleHeight: (x: number, z: number) => number, options?: Pick): AuthoredObject[];