@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
90 lines • 3.71 kB
TypeScript
/**
* Per-player ring of input bytes, one frame per slot.
*
* An "input" is a game-defined blob of bytes representing a single tick's
* worth of player intent (button bits, mouse deltas, view angles, etc.). The
* application owns the encoding; the ring just stores and indexes by frame.
*
* Used for:
* - **Input redundancy**: the most recent N unacked frames of input get
* packed into every outgoing packet from the client, so a single dropped
* packet doesn't cause a stutter.
* - **Reconciliation replay**: after the client rewinds to an authoritative
* state, it replays inputs from `[acked + 1, current]` through the
* simulation to catch back up to "now".
*
* Distinct from {@link ActionLog} despite a similar shape: inputs are raw
* player intent (sender side), actions are state mutations (sim side). One
* input may produce zero or many actions when the simulation processes it.
*
* Sized to `frame_capacity` frames; oldest is overwritten on wrap.
*
* @author Alex Goldring
* @copyright Company Named Limited (c) 2025
*/
export class InputRing {
/**
* @param {{ frame_capacity: number, initial_buffer_size?: number }} options
*/
constructor({ frame_capacity, initial_buffer_size }: {
frame_capacity: number;
initial_buffer_size?: number;
});
/**
* @readonly
* @type {number}
*/
readonly frame_capacity: number;
/**
* Write input bytes for a given frame. The callback receives the buffer
* positioned at 0 and is expected to write input bytes via the buffer's
* `writeXxx` methods. The buffer's `position` after the callback is the
* recorded length; data beyond that is ignored on read.
*
* Overwrites any prior data for that frame slot.
*
* **Writer must not throw.** The slot's buffer has already been positioned
* at 0 by the time the writer runs, and the prior frame's bytes are being
* overwritten in-place. If the writer throws partway, the slot's metadata
* (frame number, length) still reflects the previous occupant while the
* leading bytes have been clobbered with the partial new write — a torn
* state that downstream readers cannot detect. A try/catch wrapper here
* would force a V8 deopt on the hot write path, which is a worse trade
* than the "writer is trusted" contract; treat any throw in a writer
* callback as a programming error.
*
* @param {number} frame
* @param {function(BinaryBuffer): void} writer
*/
write(frame: number, writer: (arg0: BinaryBuffer) => void): void;
/**
* @param {number} frame
* @returns {boolean}
*/
has(frame: number): boolean;
/**
* Read-only access to a frame's buffer. Throws if not present.
* Caller must respect the byte length reported by {@link write_end_for}.
*
* @param {number} frame
* @returns {BinaryBuffer}
*/
buffer_for(frame: number): BinaryBuffer;
/**
* @param {number} frame
* @returns {number}
*/
write_end_for(frame: number): number;
/**
* Iterate frames in `[start_frame, end_frame]` (inclusive) that are present
* in the ring. Order is ascending by frame.
*
* @param {number} start_frame
* @param {number} end_frame
* @param {function(number, BinaryBuffer, number): void} fn callback receives (frame, buffer_at_pos_0, byte_length)
*/
for_each_in_range(start_frame: number, end_frame: number, fn: (arg0: number, arg1: BinaryBuffer, arg2: number) => void): void;
#private;
}
import { BinaryBuffer } from "../../../core/binary/BinaryBuffer.js";
//# sourceMappingURL=InputRing.d.ts.map