export interface PresencePoseState { position: { x: number; y: number; z: number; }; rotationY: number; rotationPitch?: number; lastSeenAtMs?: number; appearance?: Record; } export interface IncomingPose { position: { x: number; z: number; y?: number; }; rotationY?: number; rotationPitch?: number; appearance?: Record; } export interface PoseSyncRules { /** Speed cap (units/sec) for client-authoritative movement. */ maxSpeed: number; /** Minimum time between accepted pose writes. Defaults to 100 ms. */ minIntervalMs?: number; /** Vertical offset clamp above floorY (e.g. peak jump height). */ maxVerticalOffset: number; /** World-floor Y used as the base of the jump band. Defaults to 0. */ floorY?: number; /** Elapsed-time clamp so stale or bursty clients cannot teleport. */ minElapsedSec: number; maxElapsedSec: number; /** Unchanged poses refresh the keep-alive stamp at most this often. */ keepAliveRefreshMs: number; } /** Canonical client-authoritative pose-sync tuning shared by every host transport (WS, Convex). */ export declare const DEFAULT_POSE_SYNC_RULES: PoseSyncRules; export interface PoseSyncDecision { position: { x: number; y: number; z: number; }; rotationY: number; rotationPitch: number; appearance?: Record; /** True when the pose differs and a pose write is needed. */ changed: boolean; /** True when only the keep-alive stamp should be written. */ refreshKeepAlive: boolean; } export declare const DEFAULT_SPAWN_ORIGIN: { readonly x: 0; readonly y: 0; readonly z: 0; }; /** @internal */ export declare function spawnPresenceState(origin: { x: number; y: number; z: number; } | undefined, nowMs: number, rules: Pick): PresencePoseState; /** @internal */ export declare function decidePoseSync(current: PresencePoseState, incoming: IncomingPose, rules: PoseSyncRules, nowMs: number, floorY?: number): PoseSyncDecision; /** @internal */ export declare function shouldRefreshKeepAlive(lastSeenAtMs: number | undefined, nowMs: number, rules: Pick): boolean; /** @internal */ export declare function shouldPersistWorldSnapshot(lastSavedAtMs: number | undefined, nowMs: number, intervalMs: number): boolean; export interface ActivePresenceResolution { active: T | null; /** Other unrevoked rows for the same actor — a session may only have one. */ extras: T[]; } /** @internal */ export declare function resolveActivePresence(rows: readonly T[]): ActivePresenceResolution; /** @internal */ export declare function isPresenceExpired(lastSeenAtMs: number, nowMs: number, idleCutoffMs: number): boolean; /** Most-recently-seen row across an actor's rows, to reuse instead of inserting a new one. * @internal */ export declare function pickReusablePresence(rows: readonly T[]): T | undefined;