import type { PhysicsConfig } from "../game/defineGame.js"; import type { PlayerMovementConfig, VoxelCollisionConfig } from "../game/playableGame.js"; import type { GameContext } from "../runtime/gameContext.js"; import type { InputFrame } from "../runtime/inputSnapshot.js"; import { type InputBufferSnapshot } from "../input/inputBuffer.js"; import { type CharacterControllerConfig, type CharacterControllerState } from "./characterController.js"; import { type TerrainField } from "../world/terrain.js"; import type { WorldFeature } from "../world/features.js"; import type { PhysicsBackend } from "../physics/physicsBackend.js"; import { type MovementTuningOverrides, type PlayerMotionState } from "./movementModel.js"; import { type FreeFlightState } from "./freeFlight.js"; import { type VoxelPlayerBody } from "./voxelController.js"; /** The resolved, per-world movement configuration {@link stepPlayerMovement} integrates against — the same inputs the shell FrameDriver used to read piecemeal, gathered into one struct so single-player and host movement run identical math. */ export interface PlayerMovementTuning { /** The simulation driver already clamps frame stalls; integrate its scaled step in full. */ authoritativeStep?: boolean; collision?: VoxelCollisionConfig; movement?: PlayerMovementConfig; physics?: MovementTuningOverrides; /** Optional physics-backed capsule controller; when present it replaces terrain/AABB walking collision. */ controller?: { backend: PhysicsBackend; capsule: CharacterControllerConfig; }; ground: TerrainField; hasTerrain: boolean; } /** * Maps a game's declared `physics` onto the movement controllers' tuning. `PhysicsConfig.gravity` is a signed * world acceleration (negative points down), but the controllers integrate `velocityY -= gravityAcceleration * dt` * and expect a positive downward magnitude — so gravity is negated here to keep down-pointing gravity pulling down. */ export declare function resolvePhysicsTuning(physics: PhysicsConfig | undefined): MovementTuningOverrides | undefined; /** Gather a game's collision/movement/physics/world config into a {@link PlayerMovementTuning} — call once per world; both the shell and a host pass the result to {@link stepPlayerMovement}. */ export declare function resolvePlayerMovementTuning(opts: { collision?: VoxelCollisionConfig; movement?: PlayerMovementConfig; physics?: PhysicsConfig; world?: WorldFeature; }): PlayerMovementTuning; /** Last completed shared movement step for one entity; a live read-only view, not a save snapshot. */ export interface PlayerMovementTelemetry { grounded: boolean; verticalVelocity: number; crouching: boolean; /** Accepted physical height for heightfield walking; absent for other collision paths. */ collisionHeight?: number; /** Live authored height requested for this completed heightfield step. */ requestedCollisionHeight?: number; /** Growth is waiting for headroom; the accepted physical height remains collisionHeight. */ collisionHeightBlocked?: boolean; } /** * Read the entity's last shared movement result through indexed possession ownership. Returns `null` before a * step, after movement restore/forget, when a commit policy replaces the motor proposal, or for an entity not * currently driven by this motor. Reuses one live view; * custom movers supply their own animation parameters. Flight never reports ground contact or a walking crouch. * * @capability movement-telemetry read physical grounded, vertical velocity and crouch state without animation-store writes */ export declare function playerMovementTelemetry(ctx: GameContext, entityId: string): Readonly | null; /** One player's current heading (radians), integrated by {@link stepPlayerMovement} — the shell reads it back into its camera/aim yaw. */ export declare function playerMovementHeading(ctx: GameContext, userId: string): number; /** One player's serializable movement state: heading, facing, velocities, jump latch and controller capsule. The entity pose lives in the entity store. */ export interface PlayerMovementSnapshot { heading: number; facing: number | null; voxelBody: VoxelPlayerBody | null; motion: PlayerMotionState | null; flight: FreeFlightState | null; controller: CharacterControllerState | null; controllerJumpHeld: boolean; /** Buffered jump presses; absent in snapshots taken before jump buffering existed. */ jumpBuffer?: InputBufferSnapshot | null; /** Accepted heightfield body height. Older walking snapshots retain their historical 1.8m span. */ heightfieldHeight?: number | null; /** Pawn that accepted heightfieldHeight; omission binds legacy dimensions to the active pawn on restore. */ heightfieldEntityId?: string | null; } /** Copy one player's movement state for prediction, rollback or a save; `null` when the player has not moved yet. */ export declare function snapshotPlayerMovement(ctx: GameContext, userId: string): PlayerMovementSnapshot | null; /** Put a player's movement state back to a {@link snapshotPlayerMovement} copy. Pending state survives until first spawn; a driven actor's despawn clears it. */ export declare function restorePlayerMovement(ctx: GameContext, userId: string, snapshot: PlayerMovementSnapshot): void; /** Drop a player's retained movement state (heading + kinematic body) — call on leave so a rejoin starts fresh instead of resuming stale velocity. */ export declare function forgetPlayerMovement(ctx: GameContext, userId: string): void; /** * Integrate one player's movement for a tick from their held-input frame and commit the pose — the single * genre-agnostic controller both the shell (its local player) and a host (each connected player in `onTick`) call, * so single-player and server-authoritative movement are identical. Reads the player's controlled entity, terrain, * scene solids, and pending motion impulses; writes the entity pose via `setPose`. Retains heading + kinematic body * per `userId` on the `ctx`. Pass `heading` to override the internally-integrated yaw (the shell owns yaw for its * camera); omit it and the controller turns from the frame's `turnLeft`/`turnRight` actions. Pass `pitch` for * 6DOF spectator flight when `alignWithLook` is set. */ export declare function stepPlayerMovement(ctx: GameContext, userId: string, input: InputFrame, dt: number, tuning: PlayerMovementTuning, heading?: number, pitch?: number): void;