export interface RecordingFrame { /** Game-time seconds (from `ctx.time`), so pause/fast-forward scrub the recording consistently with the sim. */ t: number; data: T; } export interface RecordingBufferOptions { /** Evict frames older than `latestT - maxDurationSeconds`. Default unlimited. */ maxDurationSeconds?: number; /** Hard cap on frame count, oldest evicted first. Default unlimited. */ maxFrames?: number; } export interface RecordingPair { before: RecordingFrame | null; after: RecordingFrame | null; } export interface RecordingBuffer { append(t: number, data: T): void; /** Nearest frame at or before `t`, or null if the buffer is empty or `t` precedes every frame. */ seek(t: number): RecordingFrame | null; /** The frames bracketing `t` for interpolated playback: `before` is `seek(t)`, `after` is the next recorded frame (null past the end). */ seekPair(t: number): RecordingPair; /** Frames with `fromT <= t <= toT`, in recorded order. */ range(fromT: number, toT: number): RecordingFrame[]; clear(): void; duration(): number; frames(): readonly RecordingFrame[]; /** Copies the frame list; each frame's `data` is shared, since the buffer never mutates it. */ snapshot(): RecordingFrame[]; restore(next: readonly RecordingFrame[]): void; } /** * A session-recording buffer for replay / photo mode / kill-cam: append * timestamped snapshots (poses, camera state, whatever `T` is) on game-time, * then seek/scrub the recording independent of the live sim. Frames are * expected in non-decreasing `t` order (one push per tick); `seek`/`range` * binary-search on that assumption. * @internal */ export declare function createRecordingBuffer(options?: RecordingBufferOptions): RecordingBuffer;