/**
 * Wire packet types. The first byte of every NetworkPeer-routed payload picks
 * the dispatch path. New types can be added without breaking the action stream
 * because old peers will just see an unknown type and drop the packet.
 */
export type NetworkPacketType = number;
export namespace NetworkPacketType {
    let ACTION_STREAM: number;
    let RECOVERY_REQUEST: number;
    let STATE_BURST: number;
    let AUTH_STATE: number;
    let FRAGMENT: number;
    let RELIABLE_COMMAND: number;
    let NACK_FRAGMENT: number;
    let TIME_DILATION: number;
    let INITIAL_SYNC: number;
    let RESUME_HELLO: number;
    let RESUME_ACCEPT: number;
    let RESUME_REJECT: number;
    let DISCONNECT: number;
}
/**
 * Reason codes for {@link NetworkPacketType.RESUME_REJECT }.
 */
export type ResumeRejectReason = number;
/**
 * Reason codes for {@link NetworkPacketType.RESUME_REJECT}.
 * @readonly @enum {number}
 */
export const ResumeRejectReason: Readonly<{
    UnknownPeer: 0;
    GraceExpired: 1;
    TokenMismatch: 2;
    PeerIdCollision: 3;
}>;
/**
 * Per-tick orchestrator that wires the action infrastructure to one or more
 * peers over a Transport.
 *
 * Holds a single world (`EntityComponentDataset`) plus the action machinery
 * (executor, replicator, action log). For each connected peer it owns a
 * `Channel` and a `seq → frame_end` map so that ack notifications advance the
 * `Baseline.last_acked(peer_id)` watermark.
 *
 * Use as both server (many connected peers) and client (one peer = the server).
 * The asymmetry is in *who* connects — the orchestrator itself is symmetric.
 *
 * Lifecycle:
 *   1. `connect_peer(peer_id, transport)` — wire a transport for a peer.
 *   2. Per tick:
 *      - `begin_tick(frame_number)` — open the action log for this frame.
 *      - User code runs game logic, calling `executor.execute(action)` for each
 *        replicated state mutation. Inbound actions from peers also flow into
 *        the executor automatically (via the channel.onPayload wiring).
 *      - `end_tick()` — close the frame and dispatch outgoing packets to every peer.
 *   3. `disconnect_peer(peer_id)` — release the channel + baseline state.
 *
 * @author Alex Goldring
 * @copyright Company Named Limited (c) 2025
 */
export class NetworkPeer {
    /**
     * @param {{
     *   world: EntityComponentDataset,
     *   binary_registry: BinarySerializationRegistry,
     *   replicated_components: Function[],
     *   action_classes: Function[],
     *   scope_filter?: { is_entity_in_scope(peer_id: number, network_id: number): boolean },
     *   frame_capacity?: number,
     *   initial_buffer_size?: number,
     *   mutation_ledger?: MutationLedger|null,
     *   changed_set_capacity?: number,
     * }} options
     */
    constructor({ world, binary_registry, replicated_components, action_classes, scope_filter, frame_capacity, initial_buffer_size, mutation_ledger, changed_set_capacity, }: {
        world: EntityComponentDataset;
        binary_registry: BinarySerializationRegistry;
        replicated_components: Function[];
        action_classes: Function[];
        scope_filter?: {
            is_entity_in_scope(peer_id: number, network_id: number): boolean;
        };
        frame_capacity?: number;
        initial_buffer_size?: number;
        mutation_ledger?: MutationLedger | null;
        changed_set_capacity?: number;
    });
    /** @type {EntityComponentDataset} */
    world: EntityComponentDataset;
    /** @type {ReplicatedComponentRegistry} */
    component_registry: ReplicatedComponentRegistry;
    /** @type {SimActionRegistry} */
    action_registry: SimActionRegistry;
    /** @type {ReplicationSlotTable} */
    slot_table: ReplicationSlotTable;
    /** @type {ActionLog} */
    action_log: ActionLog;
    /**
     * Optional per-tick mutation tracker. When a `MutationLedger` is supplied,
     * this peer records each tick's affected network IDs into a fresh
     * `ChangedEntitySet`, then compacts the set into the ledger at `end_tick`.
     * Server-side peers should provide a ledger so they can answer recovery
     * queries. Receive-only client peers don't need one.
     *
     * @type {MutationLedger|null}
     */
    mutation_ledger: MutationLedger | null;
    /** @type {SimActionExecutor} */
    executor: SimActionExecutor;
    /** @type {Replicator} */
    replicator: Replicator;
    /** @type {Baseline} */
    baseline: Baseline;
    /**
     * Fired when an inbound packet is a `RECOVERY_REQUEST` (peer is asking
     * which entities mutated in a tick range so it can request their state).
     * Args: `(peer_id, start_tick, end_tick)`. Subscriber typically responds
     * via {@link send_state_burst_for_range}.
     * @type {Signal}
     */
    onRecoveryRequest: Signal;
    /**
     * Fired when an inbound packet is a `STATE_BURST` carrying current state
     * for a list of entities (response to a recovery request, or push).
     * Args: `(peer_id, buffer, length)` where `buffer` is positioned just
     * past the packet-type prefix and `length` is the byte count of the
     * burst payload (not counting the prefix). Apply via
     * {@link snapshotter_apply_to_existing}.
     * @type {Signal}
     */
    onStateBurst: Signal;
    /**
     * Fired when an inbound packet is an `AUTH_STATE` (server's authoritative
     * state for one entity, tagged with the frame the state represents).
     * Args: `(peer_id, frame_number, network_id, buffer)` where `buffer` is
     * positioned at the start of the entity's state payload. The handler
     * is responsible for deserializing the bytes and triggering whatever
     * reconciliation policy the application wants (snap, rewind+replay).
     * @type {Signal}
     */
    onAuthState: Signal;
    /**
     * Fires on TIME_DILATION packet arrival.
     * Args: `(peer_id, buffer_depth)` — signed int16.
     * @type {Signal}
     */
    onTimeDilationFeedback: Signal;
    /**
     * Fires on INITIAL_SYNC packet arrival.
     * Args: `(peer_id, session_token, frame_number, buffer, payload_end)`.
     * `session_token` is a `Uint8Array(16)` (UUID v1 raw bytes); the
     * buffer is positioned at the start of the Snapshotter payload.
     * @type {Signal}
     */
    onInitialSync: Signal;
    /**
     * Fires on RESUME_HELLO arrival (host-only path in practice).
     * Args: `(peer_id, local_peer_id, last_acked_frame, session_token)`.
     * Subscriber decides whether to accept (call
     * {@link send_resume_accept}) or reject (call
     * {@link send_resume_reject}).
     * @type {Signal}
     */
    onResumeHello: Signal;
    /**
     * Fires on RESUME_ACCEPT arrival (client-only in practice).
     * Args: `(peer_id)`.
     * @type {Signal}
     */
    onResumeAccept: Signal;
    /**
     * Fires on RESUME_REJECT arrival (client-only in practice).
     * Args: `(peer_id, reason_code)` — see {@link ResumeRejectReason}.
     * @type {Signal}
     */
    onResumeReject: Signal;
    /**
     * Fires on DISCONNECT arrival.
     * Args: `(peer_id, reason_label)` — `reason_label` is a string,
     * opaque to the engine.
     * @type {Signal}
     */
    onDisconnectPacket: Signal;
    /**
     * Fired when a reliable command arrives from a peer (delivered via
     * {@link ReliableCommandPipeline}, dedup'd against retransmits).
     *
     * Args: `(peer_id, buffer, payload_offset, payload_length)`. The
     * buffer is the per-peer scratch and may be reused after the handler
     * returns; consumers must copy the payload bytes if they need them
     * to outlive the call.
     *
     * Used for chat, level transitions, lobby/room state — application-
     * level messages that need at-least-once delivery semantics rather
     * than the action stream's best-effort.
     * @type {Signal}
     */
    onReliableCommand: Signal;
    /**
     * Wire `transport` to the peer identified by `peer_id`. Creates a Channel
     * over the transport and connects ack/payload notifications to the local
     * Baseline / Replicator.
     *
     * @param {number} peer_id
     * @param {{ send(bytes: Uint8Array, length: number): void, onReceive: any }} transport
     */
    connect_peer(peer_id: number, transport: {
        send(bytes: Uint8Array, length: number): void;
        onReceive: any;
    }): void;
    /**
     * Unwire and forget a peer.
     * @param {number} peer_id
     */
    disconnect_peer(peer_id: number): void;
    /**
     * Whether `peer_id` is currently connected.
     * @param {number} peer_id
     * @returns {boolean}
     */
    is_connected(peer_id: number): boolean;
    /**
     * Direct access to a peer's channel (for sending acks-only packets, raw payloads, etc.).
     * @param {number} peer_id
     * @returns {Channel|undefined}
     */
    channel_for(peer_id: number): Channel | undefined;
    /**
     * Open the action log for `frame_number`. Call before running game logic
     * for the tick. The user's code (or the engine's `EntityManager.simulate`)
     * runs between `begin_tick` and `end_tick`, calling `executor.execute()`
     * for each replicated state mutation.
     *
     * @param {number} frame_number
     */
    begin_tick(frame_number: number): void;
    /**
     * Close the current tick and send pending action records to every peer.
     * For each peer, packs frames `[Baseline.last_acked(peer) + 1, current_frame]`
     * and sends via the channel; records the seq→frame_end mapping so the next
     * ack from that peer advances the baseline.
     *
     * If a {@link MutationLedger} was supplied at construction, this tick's
     * accumulated changed-entity set is also compacted into the ledger.
     */
    end_tick(): void;
    /**
     * Pack and dispatch the outbound action stream for `current_frame` to
     * every connected peer. Second half of {@link end_tick} — exposed
     * separately so orchestrators that manage action_log frames directly
     * (e.g. {@link ServerAuthoritativeServer}'s rollback flow, which
     * begin_frame/end_frames many frames per tick) can drive the
     * outbound dispatch without going through begin_tick/end_tick.
     *
     * Assumes the action_log frame for `current_frame` is already CLOSED
     * by the caller. Records the tick's accumulated mutations into the
     * MutationLedger (if configured), then packs frames
     * `[last_acked+1, current_frame]` for each peer via
     * `Replicator.pack_for_peer`. Empty packs (no in-scope actions) are
     * not sent. Clears the per-tick changed-entity set after recording.
     *
     * @param {number} current_frame
     */
    flush_outbound(current_frame: number): void;
    /**
     * Send a recovery request to `peer_id`: "tell me the current state of every
     * entity that mutated between `start_tick` and `end_tick`." The peer's
     * server-side handler ({@link onRecoveryRequest}) is expected to respond by
     * calling {@link send_state_burst_for_range}.
     *
     * Best-effort delivery via the same UDP-style channel — if the request is
     * lost, the client is expected to retry.
     *
     * @param {number} peer_id
     * @param {number} start_tick
     * @param {number} end_tick
     */
    send_recovery_request(peer_id: number, start_tick: number, end_tick: number): void;
    /**
     * Server-side recovery response. Looks up which entities mutated in
     * `[start_tick, end_tick]` via the local `MutationLedger` (must be present),
     * then sends the current state of those entities to `peer_id` via a
     * `STATE_BURST` packet. Receiver applies via `snapshotter_apply_to_existing`.
     *
     * If no entities are in the range (or the range is older than the ledger
     * retains), nothing is sent. The requester should treat absence of response
     * after a timeout as "needs full re-init."
     *
     * @param {number} peer_id
     * @param {number} start_tick
     * @param {number} end_tick
     */
    send_state_burst_for_range(peer_id: number, start_tick: number, end_tick: number): void;
    /**
     * Send the authoritative state of one entity to `peer_id`, tagged with
     * the frame the state represents. Used by client-side prediction: the
     * server emits this every tick (or every N ticks) for client-owned
     * entities; the client compares to its predicted state at the same frame
     * and reconciles via rewind+replay if they differ.
     *
     * The payload is whatever `write_fn(buffer)` writes — typically a
     * `BinaryClassSerializationAdapter.serialize(buffer, component)` call.
     * The receiver's `onAuthState` handler reads the same bytes via the
     * matching deserializer.
     *
     * @param {number} peer_id
     * @param {number} frame_number sender's frame the state corresponds to
     * @param {number} network_id which entity this state is for
     * @param {function(BinaryBuffer): void} write_fn writes the entity's state bytes
     */
    send_auth_state(peer_id: number, frame_number: number, network_id: number, write_fn: (arg0: BinaryBuffer) => void): void;
    /**
     * Send an INITIAL_SYNC packet. `write_fn` receives the send-buffer
     * positioned just past the `(packet_type, session_token, frame_number)`
     * header and writes the Snapshotter payload. Fragments transparently.
     *
     * @param {number} peer_id
     * @param {Uint8Array} session_token 16-byte UUID v1 identifying this peer-session
     * @param {number} frame_number server sim frame this snapshot represents
     * @param {function(BinaryBuffer): void} write_fn
     */
    send_initial_sync(peer_id: number, session_token: Uint8Array, frame_number: number, write_fn: (arg0: BinaryBuffer) => void): void;
    /**
     * Send a RESUME_HELLO packet to the server. Client-only direction.
     *
     * @param {number} peer_id remote peer (the server)
     * @param {number} local_peer_id the client's own peer id
     * @param {number} last_acked_frame the client's view of last-acked frame
     * @param {Uint8Array} session_token 16-byte token from a prior INITIAL_SYNC
     */
    send_resume_hello(peer_id: number, local_peer_id: number, last_acked_frame: number, session_token: Uint8Array): void;
    /**
     * Send a RESUME_ACCEPT packet. Host-only direction.
     * @param {number} peer_id
     */
    send_resume_accept(peer_id: number): void;
    /**
     * Send a RESUME_REJECT packet. Host-only direction.
     * @param {number} peer_id
     * @param {number} reason_code one of {@link ResumeRejectReason}
     */
    send_resume_reject(peer_id: number, reason_code: number): void;
    /**
     * Send a DISCONNECT packet. Either direction. `reason_label` is an
     * opaque string (255 byte cap after UTF-8 encoding).
     *
     * @param {number} peer_id
     * @param {string} [reason_label]
     */
    send_disconnect(peer_id: number, reason_label?: string): void;
    /**
     * Send a TIME_DILATION feedback packet. `buffer_depth` is clamped
     * to the int16 range — saturating is fine since the controller
     * doesn't need sub-int16 precision.
     *
     * @param {number} peer_id
     * @param {number} buffer_depth signed integer; clamped to int16
     */
    send_time_dilation_feedback(peer_id: number, buffer_depth: number): void;
    /**
     * Send a reliable command to a connected peer. Delivered at-least-once
     * with sender-side retransmit on Channel-detected loss and receiver-
     * side dedup by logical seq. Use for messages where the action-stream
     * model (best-effort, per-frame back-fill) isn't suitable — chat,
     * lobby/room state, level transitions.
     *
     * Returns the logical seq the pipeline assigned (diagnostic only; the
     * receiver dedups internally regardless).
     *
     * @param {number} peer_id
     * @param {Uint8Array} payload
     * @param {number} length
     * @returns {number} logical seq
     */
    send_reliable_command(peer_id: number, payload: Uint8Array, length: number): number;
    #private;
}
import { ReplicatedComponentRegistry } from "../sim/ReplicatedComponentRegistry.js";
import { SimActionRegistry } from "../sim/SimActionRegistry.js";
import { ReplicationSlotTable } from "../state/ReplicationSlotTable.js";
import { ActionLog } from "../sim/ActionLog.js";
import { MutationLedger } from "../state/MutationLedger.js";
import { SimActionExecutor } from "../sim/SimActionExecutor.js";
import { Replicator } from "../replication/Replicator.js";
import { Baseline } from "../state/Baseline.js";
import Signal from "../../../core/events/signal/Signal.js";
import { Channel } from "../transport/Channel.js";
import { BinaryBuffer } from "../../../core/binary/BinaryBuffer.js";
//# sourceMappingURL=NetworkPeer.d.ts.map