/**
 * Reliable, at-least-once delivery layer over a {@link Channel}.
 *
 * Used for messages that must arrive: chat, lobby/room state changes,
 * level transitions, kick / disconnect notifications. Distinct from the
 * action-stream traffic the rest of the netcode uses, which is UDP-style
 * best-effort with per-frame back-fill compensating for losses.
 *
 * Wire layout (after the {@link Channel}'s 8-byte header and the
 * `packet_type` byte that {@link NetworkPeer}'s dispatcher consumes):
 *
 *   uintVar logical_seq    sender-assigned, monotonically increasing
 *   bytes   command_payload
 *
 * Reliability mechanism: each outgoing command goes out as one
 * Channel.send call. The returned channel-level seq is tracked in
 * `__unacked`. When the Channel later fires:
 *   - `onPacketAcked(seq)`: drop the entry — the command was delivered
 *     (the receiver de-duplicated by logical_seq, so a "duplicate" from
 *     a previous retransmit is harmless).
 *   - `onPacketLost(seq)`: the Channel's 33-packet ack window aged out
 *     this seq without seeing it acked. Re-send the same logical
 *     command on a fresh channel seq.
 *
 * Receiver side: a sliding-window de-dupe of recent `logical_seq` values.
 * Anything seen within the last `max_received_history` is silently
 * dropped; first-time arrivals fire `onCommand` with the payload bytes.
 *
 * Ordering: NOT guaranteed. Commands may arrive in any order. If you
 * need in-order delivery (level transitions before subsequent chat),
 * key payloads with a counter and reorder in the application handler.
 *
 * Lifecycle constraints:
 *   - `max_unacked` caps outstanding commands. Send throws when full
 *     (signals real backpressure — receiver gone or path is broken).
 *   - `max_received_history` caps the de-dupe set. A retransmit older
 *     than this window will be re-delivered as a duplicate to the
 *     application; not a problem in practice because the sender's
 *     `max_unacked` keeps the inflight set bounded too.
 *
 * Caveats:
 *   - Loss detection relies on the Channel's seq window, which advances
 *     when subsequent packets are sent. Under sustained no-traffic
 *     conditions a single lost reliable command may stay unacked
 *     indefinitely — by convention the action-stream's per-tick traffic
 *     keeps the window moving even when the application is otherwise
 *     idle. Real production code may want a timer-based retransmit
 *     fallback layered on top of this.
 *
 * @author Alex Goldring
 * @copyright Company Named Limited (c) 2025
 */
export class ReliableCommandPipeline {
    /**
     * @param {{
     *   channel: import("./Channel.js").Channel,
     *   packet_type: number,
     *   max_unacked?: number,
     *   max_received_history?: number,
     *   max_retries?: number,
     * }} options
     */
    constructor({ channel, packet_type, max_unacked, max_received_history, max_retries, }: {
        channel: import("./Channel.js").Channel;
        packet_type: number;
        max_unacked?: number;
        max_received_history?: number;
        max_retries?: number;
    });
    /** @type {import("./Channel.js").Channel} */
    channel: import("./Channel.js").Channel;
    /** @type {number} @readonly */
    readonly packet_type: number;
    /** @type {number} @readonly */
    readonly max_unacked: number;
    /** @type {number} @readonly */
    readonly max_received_history: number;
    /**
     * Maximum retransmissions per logical command before it is dropped
     * and {@link onCommandAbandoned} fires. Bounded so a permanently-
     * black-holed peer can't pin retransmit traffic on the channel
     * forever. The default (16) tolerates roughly half a second of
     * sustained loss at typical channel cadences before giving up.
     * @type {number} @readonly
     */
    readonly max_retries: number;
    /**
     * Fired when a brand-new logical command arrives (not a duplicate).
     * Args: `(buf, payload_offset, payload_length)`. The buffer is
     * shared scratch; consumers must copy bytes if they need them to
     * outlive the handler.
     * @type {Signal}
     */
    onCommand: Signal;
    /**
     * Fired when a sent command has been retransmitted `max_retries`
     * times without an ack and is being given up on. Args:
     * `(logical_seq)`. Subscribers typically surface this as a "command
     * failed to deliver" event to the application, or treat it as a
     * hard signal to tear down the session.
     * @type {Signal}
     */
    onCommandAbandoned: Signal;
    /**
     * Send a logical command. Returns the assigned `logical_seq` (useful
     * for application-level diagnostics; the receiver dedups internally
     * regardless).
     *
     * @param {Uint8Array} payload
     * @param {number} length
     * @returns {number}
     */
    send(payload: Uint8Array, length: number): number;
    /**
     * Called by the orchestrator (typically {@link NetworkPeer}'s
     * dispatcher) when a packet of this pipeline's type arrives. `buf`
     * is positioned just past the packet-type byte.
     *
     * @param {BinaryBuffer} buf
     * @param {number} total_length    full transport-level payload length,
     *                                  including the consumed packet-type byte
     */
    handle_inbound(buf: BinaryBuffer, total_length: number): void;
    /**
     * Number of commands sent that haven't yet been acked. Useful for
     * backpressure / progress UI.
     * @returns {number}
     */
    unacked_count(): number;
    /**
     * Drop subscriptions and clear state. Required before discarding a
     * pipeline whose channel will outlive it.
     */
    dispose(): void;
    #private;
}
import Signal from "../../../core/events/signal/Signal.js";
import { BinaryBuffer } from "../../../core/binary/BinaryBuffer.js";
//# sourceMappingURL=ReliableCommandPipeline.d.ts.map