/**
 * Spatial Hash Grid
 *
 * Uniform-grid spatial hash for broadphase collision detection and
 * proximity queries. Pure data structure, no ECS dependencies.
 */
export interface SpatialEntry {
    entityId: number;
    x: number;
    y: number;
    halfW: number;
    halfH: number;
    /** Generation stamp used by query functions to dedup multi-cell hits without a Set. Internal. */
    _lastSeenGen: number;
    /** Rebuild generation when this entry was last inserted. Internal. */
    _aliveGen: number;
}
/**
 * A cell bucket — entries plus the alive-gen at which the bucket was last
 * filled. Buckets are reset lazily on the next insert in a new generation
 * (see `insertEntity`); queries skip buckets whose `_gen` is stale.
 *
 * Internal — exposed only through `SpatialHashGrid.cells`.
 */
interface CellBucket extends Array<SpatialEntry> {
    _gen: number;
}
export interface SpatialHashGrid {
    cellSize: number;
    invCellSize: number;
    cells: Map<number, CellBucket>;
    /**
     * Dense, indexed by entityId. Holes are `undefined`. Entries from previous
     * rebuilds remain in place for in-place reuse (zero allocation in steady
     * state); liveness is determined by `entry._aliveGen === grid._aliveGen`.
     * Internal — read live entries via `getEntry` / `liveEntryCount` helpers.
     *
     * High-water-mark grows with max entityId ever inserted; despawned ids
     * leave their slot occupied by a stale entry. Acceptable when the entity
     * manager recycles ids or peak count is bounded.
     */
    entries: (SpatialEntry | undefined)[];
    /** Monotonic counter bumped by each `clearGrid` call. Internal. */
    _aliveGen: number;
    /** Monotonic counter bumped on each query; entries record their last-seen gen for O(1) dedup. Internal. */
    _queryGen: number;
}
/**
 * Hash a cell coordinate pair to a single integer key.
 * Uses large-prime XOR to distribute values.
 */
export declare function hashCell(cx: number, cy: number): number;
/**
 * Create a new empty spatial hash grid.
 */
export declare function createGrid(cellSize: number): SpatialHashGrid;
/**
 * Prepare the grid for a rebuild.
 *
 * O(1): bumps the alive-generation counter so entries inserted prior to this
 * call are implicitly stale. `getLiveEntry` / `liveEntryCount` filter
 * entries by the current gen; queries skip buckets whose own `_gen` lags
 * behind the alive gen; `insertEntity` resets a bucket's `length` lazily
 * the first time it is touched in a new generation.
 *
 * Existing `SpatialEntry` objects and `CellBucket` arrays remain in place
 * for reuse, so steady-state rebuilds allocate zero entries and zero
 * buckets, regardless of how many cells have ever been touched.
 */
export declare function clearGrid(grid: SpatialHashGrid): void;
/**
 * Insert an entity into all overlapping cells of the grid.
 */
export declare function insertEntity(grid: SpatialHashGrid, entityId: number, x: number, y: number, halfW: number, halfH: number): void;
/**
 * Collect entity IDs from all cells overlapping the given rectangle.
 *
 * Appends to `result` (caller clears/truncates first if reusing). Multi-cell
 * entries are deduplicated via a per-grid generation stamp on each
 * `SpatialEntry`.
 *
 * When `minId` is provided, only entries with `entityId > minId` are added —
 * used for symmetric broadphase pair generation.
 */
export declare function gridQueryRect(grid: SpatialHashGrid, minX: number, minY: number, maxX: number, maxY: number, result: number[], minId?: number): void;
/**
 * Collect entity IDs within a circle. AABB-to-point distance filter against
 * the cells overlapping the circle's bounding rect. Appends to `result`.
 */
export declare function gridQueryRadius(grid: SpatialHashGrid, cx: number, cy: number, radius: number, result: number[]): void;
/**
 * Get the current-generation entry for an entityId, or `undefined` if the
 * entity isn't in the index for this rebuild. Stale entries from previous
 * rebuilds remain in `entries` for in-place reuse but are filtered here.
 */
export declare function getLiveEntry(grid: SpatialHashGrid, entityId: number): SpatialEntry | undefined;
/**
 * Count entries inserted in the current rebuild generation. Linear scan —
 * intended for tests and diagnostics, not hot paths.
 */
export declare function liveEntryCount(grid: SpatialHashGrid): number;
export interface SpatialIndex {
    readonly grid: SpatialHashGrid;
    queryRect(minX: number, minY: number, maxX: number, maxY: number): number[];
    queryRectInto(minX: number, minY: number, maxX: number, maxY: number, result: number[], minId?: number): void;
    queryRadius(cx: number, cy: number, radius: number): number[];
    queryRadiusInto(cx: number, cy: number, radius: number, result: number[]): void;
    getEntry(entityId: number): SpatialEntry | undefined;
}
export {};
