import type { EntityGeneration, EntityHandle, EntityIndex as EntityIndexBrand, HandleLayout } from './codec.js'; import { EntityIndex } from './index-allocator.js'; import { ARCHETYPE_NONE, EntityRecord } from './record.js'; import { EntityRef } from './ref.js'; import type { AccessorResolver } from './ref.js'; export interface EntityStoreConfig { readonly layout: HandleLayout; readonly maxEntities: number; readonly shared: boolean; } export interface HandleStats { readonly aliveCount: number; readonly minted: number; readonly capacity: number; /** Monotonic lifetime spawn total (worker reservations included); aliveCount === spawned - despawned. */ readonly spawned: number; /** Monotonic lifetime despawn total (unused-reservation releases included). */ readonly despawned: number; readonly wrapTimeFormula: string; } /** * ROLLBACK-ONLY: the live prefix of the five identity/record regions plus the four allocator * cursors — the state that makes a rollback restore HANDLE-STABLE (every entity keeps its original * handle, every stored `eid` still resolves). The arrays are owned and sized by the caller * (@ecsia/rollback); only `[0, denseLen)` of each is meaningful. */ export interface EntityIdentityImage { sparse: Uint32Array; dense: Uint32Array; generation: Uint32Array; recordArchetypeId: Uint32Array; recordArchetypeRow: Uint32Array; aliveCount: number; denseLen: number; spawned: number; despawned: number; } export declare class EntityStore { #private; readonly layout: HandleLayout; constructor(config: EntityStoreConfig); setLifecycle(hooks: { onSpawn(handle: EntityHandle): void; onDespawn(handle: EntityHandle): void; }): void; spawn(): EntityHandle; despawn(handle: EntityHandle): void; isAlive(handle: EntityHandle): boolean; entity(handle: EntityHandle, opts?: { lenient?: boolean; }): EntityRef; encodeHandle(index: number, generation: number): EntityHandle; decodeHandle(handle: EntityHandle): { index: EntityIndexBrand; generation: EntityGeneration; }; /** Install the read/write accessor resolver onto the pooled ref (world wiring). */ setAccessorResolver(resolver: AccessorResolver): void; get index(): EntityIndex; get records(): EntityRecord; /** * The two entity-record region backings (archetypeId, archetypeRow), for the worker bootstrap * manifest. A worker resolves an entity's (archetypeId, row) from these shared * regions — reading ARCHETYPE TABLES ONLY, never the bitmask. Backings are SAB when * threaded + isolation present; otherwise plain AB (the worker path then has nothing to share). */ sharedRecordRegions(): { archetypeId: ArrayBufferLike; archetypeRow: ArrayBufferLike; }; /** * ROLLBACK-ONLY (@ecsia/rollback capture): copy the live prefix of the five identity/record regions * + the allocator cursors into `img`, whose arrays the caller has sized to at least `index.denseLen`. * Never aliases a region view — a fallback grow can re-create it. Serial-phase only. */ captureIdentity(img: EntityIdentityImage): void; /** * ROLLBACK-ONLY (@ecsia/rollback restore): write the captured identity/record prefix back IN PLACE * and rewind the allocator cursors. Slots at/above the captured `denseLen` are left untouched — * nothing reads them once the cursors are rewound. Serial-phase only. */ restoreIdentity(img: EntityIdentityImage): void; /** The full (generational) handle occupying `index` — the query engine's index→handle resolver. */ handleOfIndex(index: number): EntityHandle; /** index → its (archetypeId, row) location — the query engine's resolveLocation seam. */ locationOfIndex(index: number): { archetypeId: number; row: number; }; handleStats(): HandleStats; } export { ARCHETYPE_NONE }; //# sourceMappingURL=store.d.ts.map