import type { PointerAxisState } from "../input/pointerAxis.js"; import { type AxisBinding, type AxisRange } from "../input/axisInput.js"; import { type HapticChannels } from "../input/haptics.js"; /** One discrete press, identified across retransmitted live input frames. */ export interface InputPress { action: string; seq: number; } /** One client's serializable held state and discrete edges for a simulation tick. */ export interface InputFrame { held: readonly string[]; pointer: PointerAxisState | null; /** Discrete presses retained through release until the host accepts them. Each identity applies once, on its recorded simulation tick. */ presses?: readonly InputPress[]; /** Analog per-action magnitudes (0..1) for actions driven by a continuous source (virtual joystick, gamepad stick); absent/null means every held action is fully pressed. */ analog?: Readonly> | null; /** Simulation tick (`ctx.sim.tick()`) the frame was captured for; hosts and replay align inputs on it. Absent from senders that predate the fixed-step loop. */ tick?: number; } export interface InputSnapshot { /** Trigger controller vibration for a local user's gamepad when supported. */ rumble(userId: string, options: { strong: number; weak: number; ms: number; }): Promise; /** * Continuous rumble channels for a local user (`engine`, `road`, `impact`, …): set levels each tick * and the shell mixes them by priority onto that user's pad. Local only — never in a snapshot or on the wire. */ haptics(userId: string): HapticChannels; /** Replaces held state without notifying subscribers. Supplying `edges` buffers short presses until `beginStep`; `reset` discards the current owner's pending edges. Without `edges`, legacy publication-based edge detection is preserved. */ publish(held: readonly string[], edges?: { pressed?: readonly string[]; reset?: boolean; }): void; /** Sample buffered input once before a simulation step. Zero-step render frames retain presses; subsequent steps retire the sampled edges. */ beginStep(): void; /** Replaces the normalized pointer-position state for this frame (#293). Same no-notify contract as `publish`. */ publishPointer(state: PointerAxisState | null): void; /** Replaces the analog per-action magnitudes for this frame (#1370) — the virtual joystick's continuous vector, split into 0..1 values per movement action. `null` clears back to digital-only. Same no-notify contract as `publish`. */ publishAnalog(values: Readonly> | null): void; isDown(action: string): boolean; /** The held-action set for this frame — an owned, frozen array; the array {@link publish} was called with is never aliased or returned. */ held(): readonly string[]; /** True on the sampled simulation step containing a press; legacy publishers use the last two held sets. */ justPressed(action: string): boolean; /** True only on the frame `action` transitions from down to up (#671); mirrors {@link justPressed}. */ justReleased(action: string): boolean; /** This frame's magnitude for `action`: its published analog value when one exists, else 1 while held / 0 while up. What `axis()` samples per code, so an analog stick steers proportionally where a key is all-or-nothing. */ value(action: string): number; /** The published analog map for this frame, `null` when input is digital-only — an owned, frozen copy. */ analog(): Readonly> | null; /** Pointer position over the play surface, `[-1, 1]` per axis with `+y` down, published by the shell each frame; `null` until the first pointer move. Frozen — an owned copy of what {@link publishPointer} was called with. */ pointer(): Readonly | null; /** * Instantaneous analog axis sample against the held-action set and current pointer (#533.7) — bind * throttle/steer/handbrake (or any axes) to *action names*, not raw key codes, since the held set is * semantic actions. Feed the result into an `AxisChannel` for smoothing; unlisted ranges default to * bipolar `[-1, 1]`, so pass `{ min: 0, max: 1 }` for one-directional pedals. Actions with a published * analog magnitude contribute that value instead of 0/1, so a virtual joystick steers proportionally. */ axis(bindings: Record, ranges?: Partial>): Record; } export declare function createInputSnapshot(): InputSnapshot;