import type { Quat, Vec3 } from './state.js'; /** * Compact, additive universal-avatar tracking state. This is deliberately hardware/runtime neutral: a headset, * controller, optical hand, native client, or future tracker may all produce the same semantic pose. * * Root space is the avatar's feet/facing frame: +X right, +Y up, +Z forward. Palm quaternions are root-local, * right-handed, and ordered x/y/z/w. Wrist positions stay on the existing world-space reachLeft/reachRight fields. */ export declare const AVATAR_POSE_VERSION: 1; export declare const AvatarPoseMask: { readonly Head: number; readonly LeftPalm: number; readonly RightPalm: number; readonly LeftFingers: number; readonly RightFingers: number; }; export declare const AvatarPoseSource: { readonly Headset: number; readonly LeftController: number; readonly RightController: number; readonly LeftHand: number; readonly RightHand: number; }; export declare const AVATAR_POSE_MASK_ALL: number; export declare const AVATAR_POSE_SOURCE_ALL: number; export declare const AVATAR_POSE_LIMITS: { /** Root-local head lean in centimetres. */ readonly headHorizontalCm: 200; /** Root-local headset height in centimetres, including seated/crouched tracking. */ readonly minHeadHeightCm: -50; readonly maxHeadHeightCm: 300; /** Head roll uses tenths of a degree on the wire. */ readonly headRollDeciDeg: 1800; /** Signed-int16 normalized quaternion scale. */ readonly quaternionScale: 32767; readonly curlMax: 255; }; /** Thumb, index, middle, ring, little. Semantic/public curls are normalized 0..1. */ export type FingerCurls = readonly [number, number, number, number, number]; export type FingerCurlsU8 = [number, number, number, number, number]; export type QuatI16 = [number, number, number, number]; export type HeadPoseI16 = [number, number, number, number]; /** Engine-facing input. The SDK alone owns the compact representation below. */ export interface AvatarPoseInputV1 { v: typeof AVATAR_POSE_VERSION; mask: number; sources: number; headOffset?: Vec3; headRollDeg?: number; leftPalm?: Quat; rightPalm?: Quat; leftCurls?: FingerCurls; rightCurls?: FingerCurls; } /** Existing StateMessage payload member. Short keys + tuples keep the 10/20 Hz upload small. */ export interface AvatarPoseWireV1 { v: typeof AVATAR_POSE_VERSION; /** AvatarPoseMask bitset. */ m: number; /** AvatarPoseSource bitset. */ s: number; /** [root-local x/y/z centimetres, head roll tenths-of-a-degree]. */ h?: HeadPoseI16; /** Root-local xyzw unit quaternions, each component normalized to signed int16. */ lp?: QuatI16; rp?: QuatI16; /** Thumb/index/middle/ring/little curl, 0..255. */ lc?: FingerCurlsU8; rc?: FingerCurlsU8; } /** * The reflected PlayerState mirror. Scalars use uint8/int16 in the Colyseus schema, so changed finger curls cost * one byte each and tracked rotations avoid float64 churn. `mask === 0` is the one neutral/inactive reading. */ export interface AvatarPoseReplicaStateV1 { version: number; mask: number; sources: number; headXCm: number; headYCm: number; headZCm: number; headRollDeciDeg: number; leftPalmX: number; leftPalmY: number; leftPalmZ: number; leftPalmW: number; rightPalmX: number; rightPalmY: number; rightPalmZ: number; rightPalmW: number; leftThumb: number; leftIndex: number; leftMiddle: number; leftRing: number; leftLittle: number; rightThumb: number; rightIndex: number; rightMiddle: number; rightRing: number; rightLittle: number; } /** * Validate an untrusted compact group without throwing. The room treats `null` as a neutral avatar pose while * still applying the ordinary locomotion frame; malformed optional embodiment must never freeze movement. */ export declare function sanitizeAvatarPoseWire(value: unknown): AvatarPoseWireV1 | null; /** Encode the engine-facing float pose into the compact state-lane group. Invalid semantics fail neutral. */ export declare function encodeAvatarPose(input: AvatarPoseInputV1 | null | undefined): AvatarPoseWireV1 | null; /** Decode an inbound compact group for tests/non-Colyseus consumers. Invalid input returns neutral. */ export declare function decodeAvatarPoseWire(value: unknown): AvatarPoseInputV1 | null; /** Decode the reflected, quantized PlayerState child. Missing/old-room/neutral state returns null. */ export declare function decodeAvatarPoseReplica(value: AvatarPoseReplicaStateV1 | null | undefined): AvatarPoseInputV1 | null;