@oasys/oecs 0.5.1 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/README.md +12 -4
- package/dist/dev_flag.d.ts.map +1 -1
- package/dist/extensions/editor/index.development.cjs +1 -0
- package/dist/extensions/editor/index.development.js +239 -0
- package/dist/extensions/reactive/index.development.cjs +1 -0
- package/dist/extensions/reactive/index.development.js +215 -0
- package/dist/extensions/solid/index.development.cjs +1 -0
- package/dist/extensions/solid/index.development.js +40 -0
- package/dist/index.cjs +1 -1
- package/dist/index.development.cjs +1 -0
- package/dist/index.development.js +8116 -0
- package/dist/index.js +1 -1
- package/dist/internal-BMDgWZbt.js +2485 -0
- package/dist/internal-LiTSB_tG.cjs +2 -0
- package/dist/internal.development.cjs +1 -0
- package/dist/internal.development.js +24 -0
- package/dist/interop-DqxleBo7.js +18 -0
- package/dist/interop-T1HZ-Dpa.cjs +1 -0
- package/dist/kernel-Cz2Kxlwl.js +240 -0
- package/dist/kernel-sw7ScKWu.cjs +1 -0
- package/dist/primitives.development.cjs +1 -0
- package/dist/primitives.development.js +45 -0
- package/dist/reactive/index.development.cjs +1 -0
- package/dist/reactive/index.development.js +18 -0
- package/dist/shallow-9S1pY_Iw.js +159 -0
- package/dist/shallow-C5YmTbtb.cjs +1 -0
- package/dist/shared.development.cjs +1 -0
- package/dist/shared.development.js +7 -0
- package/dist/version.d.cts +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +31 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./internal-LiTSB_tG.cjs"),T=require("./typed_arrays-D3NmwtCG.cjs"),W=require("./shared-BymrGTyR.cjs"),I=!0,Te=c=>i.validateAndCast(c,i.isNonNegativeInteger,"ComponentID must be a non-negative integer"),le=Object.freeze({});function De(c){const e=(t=>({def:e,values:t??le}));return Object.defineProperty(e,"id",{value:c,enumerable:!1}),e}function He(c,...e){return{def:c,values:e[0]??le}}function G(c){return typeof c=="function"?c:c.def}function P(c){return typeof c=="function"?le:c.values}class B extends Error{constructor(e){super(e),this.name="StoreRestoreError"}}function Ue(c){const e=c.view.getUint32(i.STORE_HEADER_OFFSETS.capacity,!0);return new Uint8Array(c.buffer,0,e)}function Ve(c,e=W.DEFAULT_SAB_ALLOCATOR){const t=new DataView(c.buffer,c.byteOffset,c.byteLength);if(c.byteLength<i.STORE_HEADER_BYTES)throw new B(`snapshot too small: ${c.byteLength} bytes (header alone needs ${i.STORE_HEADER_BYTES})`);const s=t.getUint32(i.STORE_HEADER_OFFSETS.magic,!0);if(s!==i.STORE_MAGIC)throw new B(`bad magic: 0x${s.toString(16).padStart(8,"0")} (expected 0x${i.STORE_MAGIC.toString(16).padStart(8,"0")})`);const r=t.getUint32(i.STORE_HEADER_OFFSETS.sim_abi_version,!0);if(r!==i.SIM_ABI_VERSION)throw new B(`incompatible sim_abi_version: snapshot=${r}, build=${i.SIM_ABI_VERSION}`);const n=e(c.byteLength);new Uint8Array(n).set(c);const o=new DataView(n),h=i.readStoreHeader(o);if(h.layoutDescriptorOff<0||h.layoutDescriptorOff>n.byteLength)throw new B(`layout_descriptor_off ${h.layoutDescriptorOff} is outside the snapshot (${n.byteLength} bytes)`);try{const a=i.readLayoutDescriptorRegion(o,h.layoutDescriptorOff,h.archetypeCount),l=i.buildArchetypeViews(n,a);return{buffer:n,view:o,header:h,archetypes:l}}catch(a){throw a instanceof RangeError?new B(`snapshot layout is corrupt or truncated: a descriptor offset or column extent reads past the ${n.byteLength}-byte buffer (${a.message})`):a}}const qe=c=>i.validateAndCast(c,i.isNonNegativeInteger,"EventID must be a non-negative integer");class We{fieldNames;columns;reader;_readerLen;constructor(e){this.fieldNames=e,this.columns=[];for(let r=0;r<e.length;r++)this.columns.push([]);const t={};for(let r=0;r<e.length;r++)t[e[r]]=this.columns[r];const s={length:0,...t};this._readerLen=s,this.reader=s}emit(e){const t=this.fieldNames,s=this.columns;for(let r=0;r<t.length;r++)if(!(t[r]in e))throw new i.ECSError(i.ECS_ERROR.FIELD_NOT_REGISTERED,`emit: event field "${t[r]}" missing from values`);for(let r=0;r<t.length;r++)s[r].push(e[t[r]]);this._readerLen.length++}emitSignal(){this._readerLen.length++}clear(){this._readerLen.length=0;const e=this.columns;for(let t=0;t<e.length;t++)e[t].length=0}}function Ye(c){return i.unsafeCast(Symbol(c))}function ze(c){return i.unsafeCast(Symbol(c))}class je{channels=[];dirtyChannels=[];count=0;keyMap=new Map;registerEvent(e){const t=qe(this.count++),s=new We(e);return this.channels.push(s),i.unsafeCast(t)}emitEvent(e,t){const s=e,r=this.channels[s],n=r.reader.length===0;r.emit(t),n&&this.dirtyChannels.push(s)}emitSignal(e){const t=e,s=this.channels[t],r=s.reader.length===0;s.emitSignal(),r&&this.dirtyChannels.push(t)}getEventReader(e){return this.channels[e].reader}clearEvents(){const e=this.dirtyChannels,t=this.channels;for(let s=0;s<e.length;s++)t[e[s]].clear();e.length=0}devBufferedEventCount(){const e=this.dirtyChannels,t=this.channels;let s=0;for(let r=0;r<e.length;r++)s+=t[e[r]].reader.length;return s}registerEventByKey(e,t){if(this.keyMap.has(e))throw new i.ECSError(i.ECS_ERROR.EVENT_ALREADY_REGISTERED,`event '${e.description??"<unnamed>"}' is already registered`,{event:e.description});const s=this.registerEvent(t);return this.keyMap.set(e,s),s}getEventDefByKey(e){const t=this.keyMap.get(e);if(t===void 0)throw new i.ECSError(i.ECS_ERROR.EVENT_NOT_REGISTERED,`event '${e.description??"<unnamed>"}' is not registered — call ecs.events.register(key, fields) at world setup`,{event:e.description});return t}hasEventKey(e){return this.keyMap.has(e)}}class Qe{map=new Map;register(e,t){if(this.map.has(e))throw new i.ECSError(i.ECS_ERROR.RESOURCE_ALREADY_REGISTERED,`resource '${e.description??"<unnamed>"}' is already registered — remove() it first if you meant to replace it`,{resource:e.description});this.map.set(e,t)}get(e){if(!this.map.has(e))throw new i.ECSError(i.ECS_ERROR.RESOURCE_NOT_REGISTERED,`resource read: '${e.description??"<unnamed>"}' is not registered — call ecs.resources.register(key, value) at world setup`,{resource:e.description});return this.map.get(e)}set(e,t){if(!this.map.has(e))throw new i.ECSError(i.ECS_ERROR.RESOURCE_NOT_REGISTERED,`resource write: '${e.description??"<unnamed>"}' is not registered — call ecs.resources.register(key, value) at world setup`,{resource:e.description});this.map.set(e,t)}remove(e){if(!this.map.has(e))throw new i.ECSError(i.ECS_ERROR.RESOURCE_NOT_REGISTERED,`resource remove: '${e.description??"<unnamed>"}' is not registered — call ecs.resources.register(key, value) at world setup`,{resource:e.description});this.map.delete(e)}has(e){return this.map.has(e)}}class j extends Error{capacity;requested;constructor(e,t){super(`BufferBackedColumn overflow: requested length ${t} exceeds capacity ${e}`),this.name="StoreColumnOverflowError",this.capacity=e,this.requested=t}}class pe{_buf;_capacity;_len=0;constructor(e){this._buf=e,this._capacity=e.length}refreshView(e){if(e.length<this._len)throw new j(e.length,this._len);this._buf=e,this._capacity=e.length}get length(){return this._len}get capacity(){return this._capacity}push(e){if(this._len>=this._capacity)throw new j(this._capacity,this._len+1);this._buf[this._len++]=e}pop(){return this._buf[--this._len]}get(e){return this._buf[e]}setAt(e,t){this._buf[e]=t}swapRemove(e){const t=this._buf[e];return this._buf[e]=this._buf[--this._len],t}clear(){this._len=0}setLength(e){if(e>this._capacity)throw new j(this._capacity,e);this._len=e}get buf(){return this._buf}view(){return this._buf.subarray(0,this._len)}[Symbol.iterator](){let e=0;const t=this._buf,s=this._len;return{next(){return e<s?{value:t[e++],done:!1}:{value:0,done:!0}}}}ensureCapacity(e){if(e>this._capacity)throw new j(this._capacity,e)}bulkAppend(e,t,s){this.ensureCapacity(this._len+s),this._buf.set(e.subarray(t,t+s),this._len),this._len+=s}bulkAppendZeroes(e){this.ensureCapacity(this._len+e),this._buf.fill(0,this._len,this._len+e),this._len+=e}bulkAppendValue(e,t){this.ensureCapacity(this._len+t),this._buf.fill(e,this._len,this._len+t),this._len+=t}}const _e=c=>i.validateAndCast(c,i.isNonNegativeInteger,"ArchetypeID must be a non-negative integer");class ue{id;mask;hasColumns;materializesRows;_entityIds;length=0;enabledCount=0;_flushSeenEpoch=-1;_flushPreLen=0;_flushPreEnabled=0;_iterDepth=0;edges=[];batchTransitionMaps=new Map;compositeAddEdges=null;_flatColumns=[];_storeArchetypeId=null;_colOffset=[];_fieldCount=[];_fieldIndex=[];_fieldNames=[];columnGroups=[];_columnIds=[];_changedTick=[];_mutGroupCache=[];_readGroupCache=[];growHandler=null;constructor(e,t,s,r=i.DEFAULT_COLUMN_CAPACITY,n){if(this.id=e,this.mask=t,this._entityIds=new T.GrowableUint32Array(r),s){let o=0;for(let h=0;h<s.length;h++){const a=s[h],l=a.componentId,u=new Array(a.fieldNames.length);if(this._colOffset[l]=o,this._fieldCount[l]=a.fieldNames.length,this._fieldIndex[l]=a.fieldIndex,this._fieldNames[l]=a.fieldNames,a.fieldNames.length>0&&!n)throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,`Archetype ${e}: layouts with fields require a columnFactory — use Archetype.fromColumnStore for SAB-backed columns, or pass a heap factory explicitly in tests`);for(let d=0;d<a.fieldNames.length;d++){const f=a.fieldTypes[d],p=n(a.componentId,d,f);u[d]=p,this._flatColumns[o++]=p}this.columnGroups[l]={layout:a,columns:u},this._columnIds.push(l),this._changedTick[l]=0}}this.hasColumns=this._columnIds.length>0,this.materializesRows=!t.isEmpty()}static fromColumnStore(e,t,s,r,n){const o=r.archetypes.get(n);if(!o)throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,`ColumnStore has no archetype ${n}`);const h=(l,u)=>{const d=o.columns.get(i.columnKey(l,u));if(!d)throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,`ColumnStore archetype ${n} has no column for (${l}, ${u})`);return new pe(d.view)},a=new ue(e,t,s,o.rowCapacity,h);return a._storeArchetypeId=n,a}get isBufferBacked(){return this._storeArchetypeId!==null}refreshViews(e){if(this._storeArchetypeId===null)throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,`Archetype ${this.id} is not SAB-backed`);const t=e.archetypes.get(this._storeArchetypeId);if(!t)throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,`new ColumnStore has no archetype ${this._storeArchetypeId}`);const s=t.columnsInOrder,r=this._flatColumns;for(let n=0;n<s.length;n++)if(!(r[n]instanceof pe))throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,`Archetype ${this.id} column at index ${n} is not SAB-backed (internal)`);for(let n=0;n<s.length;n++)r[n].refreshView(s[n].view)}get entityCount(){return ie?this.length:this.enabledCount}get totalCount(){return this.length}get disabledCount(){return this.length-this.enabledCount}get entityIds(){return this._entityIds.buf}swapRows(e,t){if(e===t)return;const s=this._entityIds.buf,r=s[e];s[e]=s[t],s[t]=r;const n=this._flatColumns;for(let o=0;o<n.length;o++){const h=n[o].buf,a=h[e];h[e]=h[t],h[t]=a}}_placeTail(e,t){const s=this.enabledCount;if(s===e)return this.enabledCount=e+1,e;if(t===void 0)throw Ke();if(this.swapRows(s,e),t!==void 0){const r=this._entityIds.buf;t[i.getEntityIndex(r[e])]=e}return this.enabledCount=s+1,s}_placeTailBulk(e,t){if(this.enabledCount!==e)throw Ee();return this.enabledCount+=t,e}disableRow(e,t){if(this._iterDepth>0)throw U("disable");const s=this.enabledCount-1;if(e!==s){this.swapRows(e,s);const r=this._entityIds.buf;t[i.getEntityIndex(r[e])]=e,t[i.getEntityIndex(r[s])]=s}this.enabledCount=s}enableRow(e,t){if(this._iterDepth>0)throw U("enable");const s=this.enabledCount;if(e!==s){this.swapRows(e,s);const r=this._entityIds.buf;t[i.getEntityIndex(r[e])]=e,t[i.getEntityIndex(r[s])]=s}this.enabledCount=s+1}removeRow(e,t){if(this._iterDepth>0)throw U("removeRow");if(this.enabledCount===this.length){const s=this._entityIds.buf,r=this.length-1;if(e!==r){if(s[e]=s[r],this.hasColumns){const n=this._flatColumns;for(let o=0;o<n.length;o++)n[o].swapRemove(e)}t[i.getEntityIndex(s[e])]=e}else if(this.hasColumns){const n=this._flatColumns;for(let o=0;o<n.length;o++)n[o].pop()}this._entityIds.pop(),this.length=r,this.enabledCount=r;return}this._removeRowPartitioned(e,t)}_removeRowPartitioned(e,t){const s=this._entityIds.buf,r=this.hasColumns,n=this.enabledCount,o=this.length-1;if(e>=n){if(e!==o){if(s[e]=s[o],r){const a=this._flatColumns;for(let l=0;l<a.length;l++)a[l].swapRemove(e)}t[i.getEntityIndex(s[e])]=e}else if(r){const a=this._flatColumns;for(let l=0;l<a.length;l++)a[l].pop()}this._entityIds.pop(),this.length--;return}const h=n-1;if(e!==h&&(this.swapRows(e,h),t[i.getEntityIndex(s[e])]=e),h!==o){if(s[h]=s[o],r){const a=this._flatColumns;for(let l=0;l<a.length;l++)a[l].swapRemove(h)}t[i.getEntityIndex(s[h])]=h}else if(r){const a=this._flatColumns;for(let l=0;l<a.length;l++)a[l].pop()}this._entityIds.pop(),this.length--,this.enabledCount=h}get entityList(){return this._entityIds.view()}hasComponent(e){return this.mask.has(e)}matches(e){return this.mask.contains(e)}getColumnRead(e,t){const s=e.id;if(i.accessCheck.checkRead(e),this._colOffset[s]===void 0)throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,`Component ${e} not in archetype ${this.id}`);const r=this._fieldIndex[s][t];if(r===void 0)throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,`Field "${t}" does not exist on component`);return this._flatColumns[this._colOffset[s]+r].buf}getColumnsRead(e,...t){return t.map(r=>this.getColumnRead(e,r))}getOptionalColumnRead(e,t){const s=e.id;i.accessCheck.checkRead(e),i.accessCheck.checkOptionalFetch(e);const r=this._colOffset[s];if(r===void 0)return;const n=this._fieldIndex[s][t];if(n===void 0)throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,`Field "${t}" does not exist on component`);return this._flatColumns[r+n].buf}getColumn(e,t,s){const r=e.id;if(i.accessCheck.checkWrite(e),this._colOffset[r]===void 0)throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,`Component ${e} not in archetype ${this.id}`);this._changedTick[r]=s;const n=this._fieldIndex[r][t];if(n===void 0)throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,`Field "${t}" does not exist on component`);return this._flatColumns[this._colOffset[r]+n].buf}columnGroupMut(e,t){const s=e.id;if(i.accessCheck.checkWrite(e),this._colOffset[s]===void 0)throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,`Component ${e} not in archetype ${this.id}`);this._changedTick[s]=t;const r=this._colOffset[s],n=this._fieldNames[s],o=this._flatColumns;let h=this._mutGroupCache[s];h===void 0&&(h={},this._mutGroupCache[s]=h);for(let a=0;a<n.length;a++)h[n[a]]=o[r+a].buf;return h}columnGroupRead(e){const t=e.id;if(i.accessCheck.checkRead(e),this._colOffset[t]===void 0)throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,`Component ${e} not in archetype ${this.id}`);const s=this._colOffset[t],r=this._fieldNames[t],n=this._flatColumns;let o=this._readGroupCache[t];o===void 0&&(o={},this._readGroupCache[t]=o);for(let h=0;h<r.length;h++)o[r[h]]=n[s+h].buf;return o}writeFields(e,t,s,r){const n=t,o=this._colOffset[n];if(o===void 0)return;this._changedTick[n]=r;const h=this._fieldNames[n],a=this._flatColumns;for(let l=0;l<h.length;l++)a[o+l].buf[e]=s[h[l]]??0}bulkWriteFields(e,t,s,r,n){const o=s,h=this._colOffset[o];if(h===void 0)return;this._changedTick[o]=n;const a=this._fieldNames[o],l=this._flatColumns,u=e+t;for(let d=0;d<a.length;d++)l[h+d].buf.fill(r[a[d]]??0,e,u)}writeFieldsPositional(e,t,s,r){const n=t,o=this._colOffset[n];if(o===void 0)return;this._changedTick[n]=r;const h=this._flatColumns;for(let a=0;a<s.length;a++)h[o+a].buf[e]=s[a]}readField(e,t,s){const r=t,n=this._colOffset[r];if(n===void 0)throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,`readField: component ${r} has no column in this archetype — the entity doesn't hold it`,{component:r,field:s});const o=this._fieldIndex[r][s];if(o===void 0)throw new i.ECSError(i.ECS_ERROR.FIELD_NOT_REGISTERED,`readField: component ${r} has no field "${s}" — check the schema passed to registerComponent`,{component:r,field:s});return this._flatColumns[n+o].buf[e]}copySharedFrom(e,t,s,r){const n=e._colOffset,o=e._fieldCount,h=e._flatColumns,a=this._flatColumns,l=this._columnIds;for(let u=0;u<l.length;u++){const d=l[u],f=n[d];if(f===void 0)continue;this._changedTick[d]=r;const p=this._colOffset[d],g=o[d];for(let E=0;E<g;E++)a[p+E].buf[s]=h[f+E].buf[t]}}addEntity(e,t){if(!this.materializesRows)throw M();const s=this._flatColumns;s.length>0&&this.length>=s[0].buf.length&&this.growHandler!==null&&this.growHandler(this,1);const r=this.length;this._entityIds.push(e);for(let n=0;n<s.length;n++)s[n].push(0);return this.length++,this._placeTail(r,t)}removeEntity(e){const t=this.length-1;let s=i.NO_SWAP;const r=this._flatColumns,n=this._entityIds.buf;if(e!==t){n[e]=n[t],s=i.getEntityIndex(n[e]);for(let o=0;o<r.length;o++)r[o].swapRemove(e)}else for(let o=0;o<r.length;o++)r[o].pop();return this._entityIds.pop(),this.length--,e<this.enabledCount&&this.enabledCount--,s}addEntityTag(e,t){if(!this.materializesRows)throw M();const s=this.length;return this._entityIds.push(e),this.length++,this._placeTail(s,t)}addEntities(e,t=e.length){if(t===0)return this.length;if(!this.materializesRows)throw M();const s=this._flatColumns;s.length>0&&this.length+t>s[0].buf.length&&this.growHandler!==null&&this.growHandler(this,t);const r=this.length;this._entityIds.bulkAppend(e,0,t);for(let n=0;n<s.length;n++)s[n].bulkAppendZeroes(t);return this.length+=t,this._placeTailBulk(r,t)}addEntitiesTag(e,t=e.length){if(t===0)return this.length;if(!this.materializesRows)throw M();const s=this.length;return this._entityIds.bulkAppend(e,0,t),this.length+=t,this._placeTailBulk(s,t)}ensureRowCapacity(e){const t=this._flatColumns;t.length>0&&this.length+e>t[0].buf.length&&this.growHandler!==null&&this.growHandler(this,e)}addEntityWithValues(e,t,s,r){if(!this.materializesRows)throw M();const n=this._flatColumns;n.length>0&&this.length>=n[0].buf.length&&this.growHandler!==null&&this.growHandler(this,1);const o=this.length;this._entityIds.push(e);for(let a=0;a<n.length;a++)n[a].push(t[a]);this.length++;const h=this._columnIds;for(let a=0;a<h.length;a++)this._changedTick[h[a]]=s;return this._placeTail(o,r)}addEntitiesWithValues(e,t,s,r){if(t===0)return this.length;if(!this.materializesRows)throw M();const n=this._flatColumns;n.length>0&&this.length+t>n[0].buf.length&&this.growHandler!==null&&this.growHandler(this,t);const o=this.length;this._entityIds.bulkAppend(e,0,t);for(let a=0;a<n.length;a++)n[a].bulkAppendValue(s[a],t);this.length+=t;const h=this._columnIds;for(let a=0;a<h.length;a++)this._changedTick[h[a]]=r;return this._placeTailBulk(o,t)}removeEntityTag(e){const t=this.length-1;let s=i.NO_SWAP;const r=this._entityIds.buf;return e!==t&&(r[e]=r[t],s=i.getEntityIndex(r[e])),this._entityIds.pop(),this.length--,e<this.enabledCount&&this.enabledCount--,s}moveEntityFrom(e,t,s,r,n,o){if(e._iterDepth>0)throw U("moveEntityFrom");const h=t>=e.enabledCount;if(!this.materializesRows){e.removeRow(t,o),A[0]=i.UNASSIGNED,A[1]=i.NO_SWAP;return}const a=this._flatColumns;a.length>0&&this.length>=a[0].buf.length&&this.growHandler!==null&&this.growHandler(this,1);const l=this.length;this._entityIds.push(s);const u=e._flatColumns;for(let p=0;p<a.length;p++){const g=r[p];a[p].push(g>=0?u[g].buf[t]:0)}const d=this._columnIds;for(let p=0;p<d.length;p++)this._changedTick[d[p]]=n;this.length++;const f=h?l:this._placeTail(l,o);e.removeRow(t,o),A[0]=f,A[1]=i.NO_SWAP}moveEntityFromTag(e,t,s,r){if(e._iterDepth>0)throw U("moveEntityFrom");const n=t>=e.enabledCount;if(!this.materializesRows){e.removeRow(t,r),A[0]=i.UNASSIGNED,A[1]=i.NO_SWAP;return}const o=this.length;this._entityIds.push(s),this.length++;const h=n?o:this._placeTail(o,r);e.removeRow(t,r),A[0]=h,A[1]=i.NO_SWAP}bulkMoveAllFrom(e,t,s){const r=e.length;if(r===0)return this.length;if(!this.materializesRows)throw M();const n=this._flatColumns;n.length>0&&this.length+r>n[0].buf.length&&this.growHandler!==null&&this.growHandler(this,r);const o=this.length,h=e._flatColumns;this._entityIds.bulkAppend(e._entityIds.buf,0,r);for(let l=0;l<n.length;l++){const u=t[l];u>=0?n[l].bulkAppend(h[u].buf,0,r):n[l].bulkAppendZeroes(r)}const a=this._columnIds;for(let l=0;l<a.length;l++)this._changedTick[a[l]]=s;if(this.length+=r,this.enabledCount!==o)throw Ee();return this.enabledCount=o+e.enabledCount,e.clearRows(),o}clearRows(){this.length=0,this.enabledCount=0,this._entityIds.clear();const e=this._flatColumns;for(let t=0;t<e.length;t++)e[t].clear()}restoreHostRows(e,t){const s=e.length;if(t<0||t>s)throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,`Archetype ${this.id}: restore enabledCount ${t} out of range [0, ${s}]`);this._entityIds.clear(),this._entityIds.ensureCapacity(s);for(let n=0;n<s;n++)this._entityIds.push(e[n]);const r=this._flatColumns;for(let n=0;n<r.length;n++)r[n].setLength(s);this.length=s,this.enabledCount=t}getEdge(e){return this.edges[e]}setEdge(e,t){this.edges[e]=t}getBatchTransitionMap(e){const t=this.batchTransitionMaps.get(e.id);if(t!==void 0)return t;const s=oe(this,e);return this.batchTransitionMaps.set(e.id,s),s}getCompositeAddEdge(e){return this.compositeAddEdges===null?void 0:this.compositeAddEdges.get(e)}cacheCompositeAddEdge(e,t,s){(this.compositeAddEdges??=new Map).set(e,{target:t,map:s})}}const A=[0,i.NO_SWAP];let ie=!1;function N(c){const e=ie;return ie=c,e}function M(){return new i.ECSError(i.ECS_ERROR.EMPTY_ARCHETYPE_MATERIALIZE,"the empty archetype must not materialise rows: a component-less entity is unplaced (entity_row === UNASSIGNED). A Store mutation path is missing its rowless-destination branch.")}function U(c){return new i.ECSError(i.ECS_ERROR.STRUCTURAL_DURING_ITERATION,`${c} hit an archetype a live query iteration is visiting — immediate structural mutation mid-walk relocates rows under the iterator (entities get skipped or visited twice). Collect ids during the walk and mutate after it; inside a system use the deferred ctx.commands.`)}function Ke(){return new i.ECSError(i.ECS_ERROR.PARTITION_APPEND_NEEDS_ENTITY_ROW,"appending into a disabled-bearing archetype requires the entity_row map (to repoint the displaced disabled row). A Store append path is missing its entity_row argument.")}function Ee(){return new i.ECSError(i.ECS_ERROR.PARTITION_BULK_INTO_DISABLED,"bulk append/move into a disabled-bearing archetype is unsupported — the caller must fall back to per-entity placement to keep the enabled prefix contiguous.")}function oe(c,e){const t=e._flatColumns,s=new Int16Array(t.length),r=e._columnIds,n=c._colOffset,o=e._colOffset,h=e._fieldCount;for(let a=0;a<r.length;a++){const l=r[a],u=o[l],d=h[l],f=n[l];if(f!==void 0)for(let p=0;p<d;p++)s[u+p]=f+p;else for(let p=0;p<d;p++)s[u+p]=-1}return s}const ke=c=>i.validateAndCast(c,i.isNonNegativeInteger,"SystemID must be a non-negative integer"),V=Object.freeze([]);function ge(c){return typeof c=="object"&&!Array.isArray(c)}function Xe(c){let e=V;c.spawns!==void 0&&c.spawns.length>0&&(e=c.spawns.map(s=>ge(s)?s.defs:s));let t=V;if(c.despawns!==void 0&&c.despawns.length>0){const s=[];for(const r of c.despawns)ge(r)?s.push(...r.defs):s.push(r);t=s}return{reads:c.reads,writes:c.writes,spawns:e,despawns:t,transitions:c.transitions??V,resourceReads:c.resourceReads??V,resourceWrites:c.resourceWrites??V,sparseReads:c.sparseReads,sparseWrites:c.sparseWrites,relationReads:c.relationReads,relationWrites:c.relationWrites}}function Ze(c){const e=c.queries;if(e===void 0||c.exclusive===!0)return;const t=new Set;for(const n of c.reads)t.add(n.id);for(const n of c.writes)t.add(n.id);const s=new Set;for(const n of e)for(const o of n)t.has(o.id)||s.add(o.id);if(s.size===0)return;const r=c.name!==void 0?`'${c.name}' `:"";throw new i.ECSError(i.ECS_ERROR.QUERY_ACCESS_UNDECLARED,`system ${r}declares queries over component id(s) [${[...s].join(", ")}] not in reads ∪ writes. A query term reads each listed component, so add the id(s) to 'reads' (or to 'writes' if the system also mutates them).`)}const he=Object.freeze({reads:Object.freeze([]),writes:Object.freeze([]),spawns:Object.freeze([]),despawns:Object.freeze([]),transitions:Object.freeze([]),resourceReads:Object.freeze([]),resourceWrites:Object.freeze([]),sparseReads:Object.freeze([]),sparseWrites:Object.freeze([]),relationReads:Object.freeze([]),relationWrites:Object.freeze([])}),Je=Symbol.dispose??Symbol.for("Symbol.dispose"),ee=(1<<20)-1;let et=0;function tt(c,e){const t={...he,...e,id:ke(et++),name:c,fn:st};return Object.freeze(t)}function st(){}function ye(c){const e=new Set;if(c)for(let t=0;t<c.length;t++)e.add(c[t].id);return e}function rt(c){const e=(o,h)=>o.cid-h.cid||o.id-h.id,t=new Map,s=new Map;for(const o of c)t.set(o,[]),s.set(o,0);for(const o of c)if(o.writes.size!==0)for(const h of c){if(o===h)continue;let a=!1;for(const l of o.writes)if(h.reads.has(l)){a=!0;break}a&&(t.get(o).push(h),s.set(h,s.get(h)+1))}const r=c.filter(o=>s.get(o)===0).sort(e),n=[];for(;r.length>0;){const o=r.shift();n.push(o);for(const h of t.get(o)){const a=s.get(h)-1;s.set(h,a),a===0&&(r.push(h),r.sort(e))}}if(n.length!==c.length){const o=new Set(n);for(const h of c.slice().sort(e))o.has(h)||n.push(h)}return n}class nt{constructor(e,t){this.store=e,this.ctx=t}entries=[];byCid=new Map;_topo=null;_addBuckets=new Map;_remBuckets=new Map;_disBuckets=new Map;_enaBuckets=new Map;_radixOut=[];_radixC0=new Int32Array(1024);_radixC1=new Int32Array(1024);_setDrainCache=new Map;get count(){return this.entries.length}descriptors(){const e=new Array(this.entries.length);for(let t=0;t<this.entries.length;t++)e[t]=this.entries[t].descriptor;return e}register(e,t){const s=e.id,r=t.granularity??"archetype",n=t.onSet!==void 0&&r==="entity",o=t.onSet!==void 0&&r!=="entity";if(t.onSet===void 0&&t.granularity!==void 0)throw new i.ECSError(i.ECS_ERROR.OBSERVER_INVALID_CONFIG,"observe(): `granularity` is meaningless without `onSet`");if(t.onAdd===void 0&&t.onRemove===void 0&&t.onDisable===void 0&&t.onEnable===void 0&&t.onSet===void 0)throw new i.ECSError(i.ECS_ERROR.OBSERVER_INVALID_CONFIG,"observe(): at least one of onAdd / onRemove / onDisable / onEnable / onSet is required");const h=t.access??{},a=tt(t.name??`observer(${i.componentDebugName(e)??s})`,h),l={id:a.id,cid:s,def:e,onAdd:t.onAdd,onRemove:t.onRemove,onDisable:t.onDisable,onEnable:t.onEnable,onSetEntity:n?t.onSet:void 0,onSetArch:o?t.onSet:void 0,descriptor:a,writes:ye(h.writes),reads:ye(h.reads),yieldExisting:t.yieldExisting??!1,lastSetTick:0,disposed:!1};this.entries.push(l);let u=this.byCid.get(s);u===void 0&&(u=[],this.byCid.set(s,u)),u.push(l),this._topo=null,this._reconfigureComponent(s),l.yieldExisting&&l.onAdd!==void 0&&this._yieldExisting(l);const d=()=>this._dispose(l);return{dispose:d,[Je]:d}}_dispose(e){if(e.disposed)return;e.disposed=!0;const t=this.entries.indexOf(e);t>=0&&this.entries.splice(t,1);const s=this.byCid.get(e.cid);if(s!==void 0){const r=s.indexOf(e);r>=0&&s.splice(r,1),s.length===0&&this.byCid.delete(e.cid)}this._topo=null,this._reconfigureComponent(e.cid)}_reconfigureComponent(e){const t=this.byCid.get(e);let s=!1,r=!1,n=!1,o=!1,h=!1;if(t!==void 0)for(let a=0;a<t.length;a++){const l=t[a];l.onAdd!==void 0&&(s=!0),l.onRemove!==void 0&&(r=!0),l.onDisable!==void 0&&(n=!0),l.onEnable!==void 0&&(o=!0),l.onSetEntity!==void 0&&(h=!0)}this.store._configureComponentObservation(e,s,r,n,o,h)}getTopo(){return this._topo===null&&(this._topo=rt(this.entries)),this._topo}dispatchStructural(e){this._bucket(e.addComp,e.addEid,e.addLen,this._addBuckets),this._bucket(e.remComp,e.remEid,e.remLen,this._remBuckets),this._bucket(e.disComp,e.disEid,e.disLen,this._disBuckets),this._bucket(e.enaComp,e.enaEid,e.enaLen,this._enaBuckets);const t=this.getTopo(),s=i.accessCheck.current();for(let r=0;r<t.length;r++){const n=t[r];if(!n.disposed){if(n.onRemove!==void 0){const o=this._remBuckets.get(n.cid);o!==void 0&&o.length>0&&this._fireEach(n,n.onRemove,o,"remove")}if(n.onAdd!==void 0){const o=this._addBuckets.get(n.cid);o!==void 0&&o.length>0&&this._fireEach(n,n.onAdd,o,"add")}if(n.onDisable!==void 0){const o=this._disBuckets.get(n.cid);o!==void 0&&o.length>0&&this._fireEach(n,n.onDisable,o,"disable")}if(n.onEnable!==void 0){const o=this._enaBuckets.get(n.cid);o!==void 0&&o.length>0&&this._fireEach(n,n.onEnable,o,"enable")}}}s!==null&&i.accessCheck.enter(s),this._clearBuckets(this._addBuckets),this._clearBuckets(this._remBuckets),this._clearBuckets(this._disBuckets),this._clearBuckets(this._enaBuckets)}_fireEach(e,t,s,r){K(s,this._radixOut,this._radixC0,this._radixC1),i.accessCheck.enter(e.descriptor);try{const n=I?this.store._trace:null;for(let o=0;o<s.length;o++)t(i.unsafeCast(s[o]),this.ctx),I&&n?.observerFired(r,e.cid,s[o],e.descriptor)}finally{i.accessCheck.leave()}}_bucket(e,t,s,r){for(let n=0;n<s;n++){const o=e[n];let h=r.get(o);h===void 0&&(h=[],r.set(o,h)),h.push(t[n])}}_clearBuckets(e){for(const t of e.values())t.length=0}dispatchSet(e){if(this.entries.length===0)return;const t=i.accessCheck.current(),s=this.getTopo(),r=this._setDrainCache;for(let n=0;n<s.length;n++){const o=s[n];o.onSetEntity!==void 0?this._dispatchSetEntity(o,r):o.onSetArch!==void 0&&this._dispatchSetArch(o,e)}for(const n of r.values())n.length=0;r.clear(),t!==null&&i.accessCheck.enter(t)}_dispatchSetEntity(e,t){let s=t.get(e.cid);if(s===void 0&&(s=this.store._takeDirty(e.cid),K(s,this._radixOut,this._radixC0,this._radixC1),t.set(e.cid,s)),s.length===0)return;const r=e.def,n=e.onSetEntity;i.accessCheck.enter(e.descriptor);try{for(let o=0;o<s.length;o++){const h=i.unsafeCast(s[o]);this.store.isAlive(h)&&this.store.hasComponent(h,r)&&!this.store.isDisabled(h)&&(n(h,this.ctx),I&&this.store._trace?.observerFired("set",e.cid,h,e.descriptor))}}finally{i.accessCheck.leave()}}_dispatchSetArch(e,t){const s=e.onSetArch,r=e.lastSetTick;i.accessCheck.enter(e.descriptor);try{this.store._forEachChangedArchetype(e.cid,r,n=>{s(n,this.ctx),I&&this.store._trace?.observerFired("set",e.cid,-1,e.descriptor)})}finally{i.accessCheck.leave()}e.lastSetTick=t+1}_yieldExisting(e){const t=e.onAdd,s=this.store._collectEntitiesWithComponent(e.cid);if(s.length===0)return;K(s,this._radixOut,this._radixC0,this._radixC1);const r=i.accessCheck.current();i.accessCheck.enter(e.descriptor);try{for(let n=0;n<s.length;n++)t(i.unsafeCast(s[n]),this.ctx)}finally{i.accessCheck.leave(),r!==null&&i.accessCheck.enter(r)}}}function K(c,e,t,s){const r=c.length;if(!(r<2)){e.length<r&&(e.length=r),t.fill(0),s.fill(0);for(let n=0;n<r;n++){const o=c[n]ⅇt[o&1023]++,s[o>>10&1023]++}for(let n=1;n<1024;n++)t[n]+=t[n-1],s[n]+=s[n-1];for(let n=r-1;n>=0;n--){const o=c[n];e[--t[o&ee&1023]]=o}for(let n=r-1;n>=0;n--){const o=e[n];c[--s[(o&ee)>>10&1023]]=o}}}class it{constructor(e){this.host=e}relations=[];_hasTargetCleanup=!1;_hierarchyRadixOut=[];_hierarchyRadixC0=new Int32Array(1024);_hierarchyRadixC1=new Int32Array(1024);get stores(){return this.relations}get count(){return this.relations.length}get hasTargetCleanup(){return this._hasTargetCleanup}registerRelation(e){const t=e?.multi===!0,s=e?.exclusive===!0;if(t&&s)throw new i.ECSError(i.ECS_ERROR.RELATION_MODE_INVALID,"register_relation: a relation cannot be both exclusive and multi-target");const r=!t,n=e?.onDeleteTarget??i.DEFAULT_ON_DELETE_TARGET,o=r?this.host.pushSparseStore([i.RELATION_TARGET_FIELD],["f64"]):this.host.pushSparseStore([],[]),h=this.relations.length;return this.relations.push(i.makeRelationStore(r,o,this.host.sparseStoreOf(o),n)),n!=="orphan"&&(this._hasTargetCleanup=!0),i.unsafeCast(h)}relationOf(e){const t=e,s=this.relations[t];if(s===void 0)throw new i.ECSError(i.ECS_ERROR.RELATION_NOT_REGISTERED,`relation ${t} is not registered`);return s}addRelation(e,t,s){const r=this.relationOf(t);if(!this.host.isAlive(e))throw i.entityNotAliveError("addRelation",e,"source");if(!this.host.isAlive(s))throw i.entityNotAliveError("addRelation",s,"target");r.link(e,s)}removeRelation(e,t,s){const r=this.relationOf(t);if(!this.host.isAlive(e))throw i.entityNotAliveError("removeRelation",e,"source");r.unlink(e,s)}targetOf(e,t){const s=this.relationOf(t);{if(!s.exclusive)throw new i.ECSError(i.ECS_ERROR.RELATION_MODE_MISMATCH,"targetOf: relation is multi-target — use targetsOf");if(!this.host.isAlive(e))throw i.entityNotAliveError("targetOf",e)}return s.singleTarget(i.getEntityIndex(e))}targetsOf(e,t){const s=this.relationOf(t);if(!this.host.isAlive(e))throw i.entityNotAliveError("targetsOf",e);return s.targetsOf(i.getEntityIndex(e))}sourcesOf(e,t){return this.relationOf(t).sourcesOf(e)}hasRelation(e,t){return this.host.hasSparse(e,this.relationOf(t).sparse)}pairsOf(e){const t=this.relationOf(e),s=[],r=this.host.entityGenerations();return t.forEachCanonicalPair(n=>i.createEntityId(n,r[n]),(n,o)=>s.push([n,o])),s}sourcesOfAny(e){const t=[],s=this.relations;for(let r=0;r<s.length;r++){const n=i.unsafeCast(r),o=s[r].sourcesOf(e);for(let h=0;h<o.length;h++)t.push([n,o[h]])}return t}relationBackingSparseId(e){return this.relationOf(e).sparse}forEachRelationTargetMatch(e,t,s,r,n,o,h,a){const l=this.relations;if(l.length===0)return;const u=new Set;for(let y=0;y<l.length;y++){const _=l[y].sourcesOf(e);for(let m=0;m<_.length;m++)u.add(_[m])}if(u.size===0)return;const d=Array.from(u).sort((y,_)=>y-_),f=this.host.sparseStores(),p=this.host.entityArchetype(),g=this.host.entityRow(),E=this.host.archetypes();for(let y=0;y<d.length;y++){const _=i.unsafeCast(d[y]),m=i.getEntityIndex(_),S=p[m];if(S===i.UNASSIGNED)continue;const v=E[S],R=v.mask;if(!R.contains(t)||s!==null&&R.overlaps(s)||r!==null&&!R.overlaps(r))continue;let C=!0;for(let w=0;w<n.length;w++)if(!f[n[w]].has(m)){C=!1;break}if(C){for(let w=0;w<o.length;w++)if(f[o[w]].has(m)){C=!1;break}if(C){if(!h){const w=g[m];if(w!==i.UNASSIGNED&&w>=v.enabledCount)continue}a(_)}}}}compactRelations(){const e=this.relations;if(e.length===0)return 0;const t=r=>this.host.isAlive(r);let s=0;for(let r=0;r<e.length;r++)s+=e[r].pruneDeadReverse(t);return s}ancestorsOf(e,t){const s=this.relationOf(t);{if(!s.exclusive)throw new i.ECSError(i.ECS_ERROR.RELATION_MODE_MISMATCH,"ancestorsOf: relation is multi-target — traversal needs an exclusive (parent) chain");if(!this.host.isAlive(e))throw i.entityNotAliveError("ancestorsOf",e)}const r=this.host.sparseStoreOf(s.sparse),n=[e],o=new Set([i.getEntityIndex(e)]);let h=e;for(;;){const a=r.getField(i.getEntityIndex(h),0);if(a===void 0)break;const l=i.unsafeCast(a);if(!this.host.isAlive(l)){n.push(l);break}const u=i.getEntityIndex(l);if(o.has(u))throw new i.ECSError(i.ECS_ERROR.RELATION_CYCLE,`ancestors_of: cycle in relation chain at entity index ${u}`);o.add(u),h=l,n.push(h)}return n}rootOf(e,t){const s=this.ancestorsOf(e,t);return s[s.length-1]}cascadeOf(e,t){const s=this.relationOf(t);{if(!s.exclusive)throw new i.ECSError(i.ECS_ERROR.RELATION_MODE_MISMATCH,"cascadeOf: relation is multi-target — traversal needs an exclusive (parent) chain");if(!this.host.isAlive(e))throw i.entityNotAliveError("cascadeOf",e)}const r=[e],n=new Set([i.getEntityIndex(e)]);for(let o=0;o<r.length;o++){const h=s.sourcesOf(r[o]);for(let a=0;a<h.length;a++){const l=h[a],u=i.getEntityIndex(l);if(n.has(u))throw new i.ECSError(i.ECS_ERROR.RELATION_CYCLE,`cascade_of: cycle in relation chain at entity index ${u}`);n.add(u),r.push(l)}}return r}purgeSource(e){const t=this.relations;for(let s=0;s<t.length;s++)t[s].purgeSource(e)}cleanupTarget(e,t){const s=this.relations;for(let r=0;r<s.length;r++){const n=s[r];if(n.onDeleteTarget==="orphan")continue;const o=n.sourcesOf(e);if(o.length!==0){if(n.onDeleteTarget==="delete"){for(let h=0;h<o.length;h++)t.push(o[h]);continue}for(let h=0;h<o.length;h++)n.unlink(o[h],e)}}}forEachHierarchyMatch(e,t,s,r,n,o,h,a,l,u){const d=this.relationOf(h);if(!d.exclusive)throw new i.ECSError(i.ECS_ERROR.RELATION_MODE_MISMATCH,"hierarchy(): relation is multi-target — depth ordering needs an exclusive (parent) chain");const f=[];if(this.host.forEachSparseMatch(e,t,s,r,n,o,_=>f.push(_),l),f.length===0)return;K(f,this._hierarchyRadixOut,this._hierarchyRadixC0,this._hierarchyRadixC1);const p=this.host.sparseStoreOf(d.sparse),g=new Map,E=new Set,y=[];for(let _=0;_<f.length;_++){const m=f[_],S=this._hierarchyDepthOf(i.getEntityIndex(m),p,g,E);if(S>a)continue;let v=y[S];v===void 0&&(v=[],y[S]=v),v.push(m)}for(let _=0;_<y.length;_++){const m=y[_];if(m!==void 0)for(let S=0;S<m.length;S++)u(m[S])}}_hierarchyDepthOf(e,t,s,r){const n=[];let o=e,h=0;for(;;){const l=s.get(o);if(l!==void 0){h=l;break}const u=t.getField(o,0);let d=-1;if(u!==void 0){const f=i.unsafeCast(u);this.host.isAlive(f)&&(d=i.getEntityIndex(f))}if(d===-1){s.set(o,0),h=0;break}if(r.has(d))throw new i.ECSError(i.ECS_ERROR.RELATION_CYCLE,`hierarchy(): cycle in relation chain at entity index ${d}`);n.push(o),r.add(o),o=d}let a=h;for(let l=n.length-1;l>=0;l--)a+=1,s.set(n[l],a),r.delete(n[l]);return s.get(e)}}class ot{_generations;_lengthView;_highWater=0;_freeIndices=[];_aliveCount=0;_capacity;lastIndex=0;constructor(e,t,s){this._capacity=e,this._generations=t,this._lengthView=s}replantViews(e,t){this._generations=e,this._lengthView=t}get generations(){return this._generations}get highWater(){return this._highWater}get aliveCount(){return this._aliveCount}get freeCount(){return this._freeIndices.length}alloc(){let e,t;if(this._freeIndices.length>0)e=this._freeIndices.pop(),t=this._generations[e];else{if(this._highWater>=this._capacity)throw new i.ECSError(i.ECS_ERROR.EID_MAX_INDEX_OVERFLOW,`entityIndexCapacity (${this._capacity}) exhausted; raise it in ECSOptions.memory or destroy unused entities`);e=this._highWater++,this._generations[e]=i.INITIAL_GENERATION,t=i.INITIAL_GENERATION,this._lengthView[0]=this._highWater}return this._aliveCount++,this.lastIndex=e,i.createEntityId(e,t)}ensureCapacity(e){const t=e-this._freeIndices.length;if(t>0&&this._highWater+t>this._capacity)throw new i.ECSError(i.ECS_ERROR.EID_MAX_INDEX_OVERFLOW,`entityIndexCapacity (${this._capacity}) cannot fit ${e} new entities (${this._freeIndices.length} free, high-water ${this._highWater}); raise it in ECSOptions.memory or destroy unused entities`)}recycle(e,t){const s=t+1;s<i.RETIRED_GENERATION?(this._generations[e]=s,this._freeIndices.push(e)):this._generations[e]=i.RETIRED_GENERATION,this._aliveCount--}isAliveIndex(e,t){return e<this._highWater&&this._generations[e]===t}publishLength(){this._lengthView[0]=this._highWater}snapshotFreeIndices(){return this._freeIndices.slice()}setHighWater(e){this._highWater=e}restoreHostState(e,t){this._freeIndices.length=0;for(let s=0;s<e.length;s++)this._freeIndices.push(e[s]);this._aliveCount=t}}const me=65536;class ht{destroyIds=[];addIds=[];addDefs=[];addValues=[];removeIds=[];removeDefs=[];toggleIds=[];toggleDisable=[];_flushing=!1;host;obsEvents;constructor(e,t){this.host=e,this.obsEvents=t}queueDestroy(e){this.destroyIds.push(e)}queueAdd(e,t,s){this.addIds.push(e),this.addDefs.push(t),this.addValues.push(s)}queueRemove(e,t){this.removeIds.push(e),this.removeDefs.push(t)}queueToggle(e,t){this.toggleIds.push(e),this.toggleDisable.push(t)}get destroyCount(){return this.destroyIds.length}get structuralCount(){return this.addIds.length+this.removeIds.length}get toggleCount(){return this.toggleIds.length}flushDestroyed(){this._flushing||this.host.applyDestroys()}flushStructural(){if(this.host.structuralObserverCount()===0&&this.host.toggleObserverCount()===0){this.addIds.length>0&&this.host.applyAdds(),this.removeIds.length>0&&this.host.applyRemoves(),this.toggleIds.length>0&&this.host.applyToggles();return}if(this._flushing)return;this._flushing=!0;const e=this.obsEvents,t=this.host.structuralObserverHook();try{let s=0;for(;this.addIds.length>0||this.removeIds.length>0||this.destroyIds.length>0||this.toggleIds.length>0;){if(++s>me)throw new i.ECSError(i.ECS_ERROR.OBSERVER_NON_CONVERGENT,`observer cascade did not converge after ${me} rounds — two observers likely enqueue each other's structural ops forever`);e.addLen=0,e.remLen=0,e.disLen=0,e.enaLen=0,this.addIds.length>0||this.removeIds.length>0?(this.addIds.length>0&&this.host.applyAdds(),this.removeIds.length>0&&this.host.applyRemoves()):this.destroyIds.length>0?this.host.applyDestroys():this.host.applyToggles(),t!==null&&(e.addLen>0||e.remLen>0||e.disLen>0||e.enaLen>0)&&t(e)}}finally{this._flushing=!1}}}function Ne(c,e){let t=c;const s=new Array(e.length);for(let r=0;r<e.length;r++){const n=e[r],o=new Array(n.columns.length);for(let h=0;h<n.columns.length;h++){const a=n.columns[h];t=i.alignUp(t,a.stride),o[h]={componentId:a.componentId,fieldId:a.fieldId,typeTag:a.typeTag,byteOff:t,stride:a.stride},t+=a.stride*n.rowCapacity}s[r]={archetypeId:n.archetypeId,componentMask:n.componentMask,rowCount:0,enabledCount:0,rowCapacity:n.rowCapacity,columns:o}}if(t>i.STORE_MAX_BYTE_OFFSET)throw new i.StoreLayoutOverflowError(t);return{descriptors:s,newTotal:t}}function xe(c,e){const t=c._allocator(e),s=t!==c.buffer?new DataView(t):c.view;return{grownBuffer:t,newView:s}}function at(c){const e={};for(let r=0;r<i.STORE_PREFIX_REGIONS.length;r++){const n=i.STORE_PREFIX_REGIONS[r],o=c.view.getUint32(i.STORE_HEADER_OFFSETS[n.headerOff],!0);o!==0&&n.readOptions(c.view,o,e)}const t=i.readHeaderRegionTable(c.view);t.length>0&&(e.regions=t.map(r=>({id:r.regionId,name:`region:${r.regionId}`,bytes:r.byteLength,init:()=>{}})));const s=c.view.getUint32(i.STORE_HEADER_OFFSETS.bindings_off,!0);if(s!==0){const r=c.view.getUint32(i.STORE_HEADER_OFFSETS.layout_descriptor_off,!0);e.bindingsRegionBytes=r-s}return i.isColumnStoreInternal(c)&&c._reservedDescriptorBytes>0&&(e.reservedDescriptorBytes=c._reservedDescriptorBytes),e}function ct(c){const e=new Map;for(let r=0;r<i.STORE_PREFIX_REGIONS.length;r++){const n=i.STORE_PREFIX_REGIONS[r],o=c.view.getUint32(i.STORE_HEADER_OFFSETS[n.headerOff],!0);if(o===0)continue;const h=n.regionBytes(c.view,o);e.set(n.headerOff,new Uint8Array(c.buffer,o,h).slice())}const t=new Map,s=i.readHeaderRegionTable(c.view);for(let r=0;r<s.length;r++){const n=s[r];t.set(n.regionId,new Uint8Array(c.buffer,n.byteOffset,n.byteLength).slice())}return{mechanism:e,consumer:t}}function lt(c,e){for(const[t,s]of e.mechanism){const r=c.view.getUint32(i.STORE_HEADER_OFFSETS[t],!0);new Uint8Array(c.buffer,r,s.byteLength).set(s)}for(const[t,s]of e.consumer){const r=i.findRegionOffset(c.view,t);if(r===0)continue;new Uint8Array(c.buffer,r,s.byteLength).set(s)}}function ut(c,e){const t=new Map;for(const[s,r]of c.archetypes){const n=e.get(s)??0;if(n===0)continue;const o=[];for(let h=0;h<r.columnsInOrder.length;h++){const a=r.columnsInOrder[h],l=n*a.stride,u=new Uint8Array(l);u.set(new Uint8Array(a.view.buffer,a.view.byteOffset,l)),o.push(u)}t.set(s,o)}return t}function dt(c,e){for(const[t,s]of e){const r=c.archetypes.get(t);if(r===void 0)throw new Error(`restore_column_snapshots: new store missing archetype ${t} (internal)`);const n=r.columnsInOrder;for(let o=0;o<s.length;o++){const h=n[o].view;new Uint8Array(h.buffer,h.byteOffset,s[o].byteLength).set(s[o])}}}function Me(c,e,t,s){const r=c.view.getUint32(i.STORE_HEADER_OFFSETS.view_stamp,!0),n=ut(c,t),o=ct(c),h=at(c),a=i.createColumnStore(e,s,h);dt(a,n),lt(a,o);const l=r+1>>>0;return a.view.setUint32(i.STORE_HEADER_OFFSETS.view_stamp,l,!0),{store:{...a,header:{...a.header,viewStamp:l}},oldViewStamp:r,newViewStamp:l}}function ft(c,e,t){const s=new Array(e.length);for(let _=0;_<e.length;_++){const m=e[_],S=c.archetypes.get(m.archetypeId);s[_]={archetypeId:m.archetypeId,componentMask:S.componentMask,rowCapacity:m.newRowCapacity,columns:S.columnsInOrder}}const{descriptors:r,newTotal:n}=Ne(c.buffer.byteLength,s),o=new Map;for(let _=0;_<r.length;_++)o.set(r[_].archetypeId,r[_]);const{grownBuffer:h,newView:a}=xe(c,n),l=new Uint8Array(h);for(let _=0;_<e.length;_++){const m=e[_],S=c.archetypes.get(m.archetypeId),v=o.get(m.archetypeId);for(let R=0;R<S.columnsInOrder.length;R++){const C=S.columnsInOrder[R],w=m.rowCount*C.stride;w>0&&l.copyWithin(v.columns[R].byteOff,C.byteOff,C.byteOff+w)}}let u=t;for(const[_,m]of c.archetypes){{const v=a.getUint32(u+i.ARCHETYPE_DESCRIPTOR_OFFSETS.archetype_id,!0);if(v!==_)throw new X(`descriptor cursor desync at byte ${u}: store holds archetype ${v}, expected ${_} (Map order diverged from on-store write order)`)}const S=o.get(_);S!==void 0&&i.writeArchetypeDescriptor(a,u,S),u+=i.archetypeDescriptorBytes(m.columnsInOrder.length)}const d=a.getUint32(i.STORE_HEADER_OFFSETS.view_stamp,!0),f=d+1>>>0;a.setUint32(i.STORE_HEADER_OFFSETS.view_stamp,f,!0),a.setUint32(i.STORE_HEADER_OFFSETS.capacity,n,!0);const p=i.buildArchetypeViews(h,[...o.values()]),g=new Map;for(const[_,m]of c.archetypes){const S=p.get(_);g.set(_,S??m)}const E={buffer:h,view:a,header:{...c.header,viewStamp:f,capacity:n},archetypes:g,_regionBytes:c._regionBytes,_allocator:c._allocator,_reservedDescriptorBytes:c._reservedDescriptorBytes},y=new Array(e.length);for(let _=0;_<e.length;_++)y[_]=e[_].archetypeId;return{store:E,oldViewStamp:d,newViewStamp:f,viewsPreserved:!0,grownArchetypeIds:y}}class X extends Error{constructor(e){super(e),this.name="StoreGrowError"}}function pt(c,e,t){const s=new Map;for(let u=0;u<e.archetypes.length;u++){const d=e.archetypes[u];s.set(d.archetypeId,d)}const r=[],n=[];for(const[u,d]of c.archetypes){const f=s.get(u),p=f?.newRowCapacity??d.rowCapacity;if(p<(f?.rowCount??0))throw new X(`archetype ${u}: new_row_capacity ${p} < row_count ${f?.rowCount}`);if(p<d.rowCapacity)throw new X(`archetype ${u}: shrinking from ${d.rowCapacity} to ${p} is not supported`);p>d.rowCapacity&&n.push({archetypeId:u,newRowCapacity:p,rowCount:f?.rowCount??0}),r.push({archetypeId:u,componentMask:d.componentMask,rowCapacity:p,columns:d.columnsInOrder})}const o=new Map;for(const[u,d]of c.archetypes){const p=s.get(u)?.rowCount??0;if(p>d.rowCapacity)throw new X(`archetype ${u}: row_count ${p} > old row_capacity ${d.rowCapacity}`);p>0&&o.set(u,p)}if(t?.isInPlace===!0&&i.isColumnStoreInternal(c)&&c._allocator===t&&n.length>0){const u=c.view.getUint32(i.STORE_HEADER_OFFSETS.layout_descriptor_off,!0);return ft(c,n,u)}const{store:h,oldViewStamp:a,newViewStamp:l}=Me(c,r,o,t);return{store:h,oldViewStamp:a,newViewStamp:l,viewsPreserved:!1,grownArchetypeIds:[]}}class $ extends Error{constructor(e){super(e),this.name="StoreExtendError"}}function _t(c,e,t){if(e.newArchetypes.length===0)throw new $("extend plan has no new archetypes; use grow_column_store for resizes");const s=new Set;for(let l=0;l<e.newArchetypes.length;l++){const u=e.newArchetypes[l].archetypeId;if(s.has(u))throw new $(`duplicate archetype_id ${u} in extend plan`);if(c.archetypes.has(u))throw new $(`archetype_id ${u} already exists in the SAB; use grow_column_store to resize it`);s.add(u)}const r=new Map;if(e.existing)for(let l=0;l<e.existing.length;l++){const u=e.existing[l];if(!c.archetypes.has(u.archetypeId))throw new $(`existing row_count names unknown archetype_id ${u.archetypeId}`);if(u.rowCount<0)throw new $(`archetype ${u.archetypeId}: row_count must be non-negative (got ${u.rowCount})`);if(u.rowCount>0){const d=c.archetypes.get(u.archetypeId);if(u.rowCount>d.rowCapacity)throw new $(`archetype ${u.archetypeId}: row_count ${u.rowCount} > old row_capacity ${d.rowCapacity}`)}r.set(u.archetypeId,u.rowCount)}if(t?.isInPlace===!0&&i.isColumnStoreInternal(c)&&c._allocator===t){const l=c.view.getUint32(i.STORE_HEADER_OFFSETS.layout_descriptor_off,!0);let u=0;for(const[,f]of c.archetypes)u+=i.archetypeDescriptorBytes(f.columnsInOrder.length);let d=0;for(let f=0;f<e.newArchetypes.length;f++)d+=i.archetypeDescriptorBytes(e.newArchetypes[f].columns.length);if(u+d<=c._regionBytes)return Et(c,e.newArchetypes,l,u)}const n=[];for(const[l,u]of c.archetypes)n.push({archetypeId:l,componentMask:u.componentMask,rowCapacity:u.rowCapacity,columns:u.columnsInOrder});for(let l=0;l<e.newArchetypes.length;l++)n.push(e.newArchetypes[l]);const{store:o,oldViewStamp:h,newViewStamp:a}=Me(c,n,r,t);return{store:o,oldViewStamp:h,newViewStamp:a,viewsPreserved:!1}}function Et(c,e,t,s){const r=new Array(e.length);for(let y=0;y<e.length;y++){const _=e[y];r[y]={archetypeId:_.archetypeId,componentMask:_.componentMask,rowCapacity:_.rowCapacity,columns:_.columns.map(m=>({componentId:m.componentId,fieldId:m.fieldId,typeTag:m.typeTag,stride:i.TYPE_TAG_STRIDE[m.typeTag]}))}}const{descriptors:n,newTotal:o}=Ne(c.buffer.byteLength,r),{grownBuffer:h,newView:a}=xe(c,o);let l=t+s;for(let y=0;y<n.length;y++)l=i.writeArchetypeDescriptor(a,l,n[y]);const u=a.getUint32(i.STORE_HEADER_OFFSETS.view_stamp,!0),d=c.archetypes.size+e.length;a.setUint32(i.STORE_HEADER_OFFSETS.archetype_count,d,!0),a.setUint32(i.STORE_HEADER_OFFSETS.capacity,o,!0);const f=u+1>>>0;a.setUint32(i.STORE_HEADER_OFFSETS.view_stamp,f,!0);const p=i.buildArchetypeViews(h,n),g=new Map;for(const[y,_]of c.archetypes)g.set(y,_);for(const[y,_]of p)g.set(y,_);return{store:{buffer:h,view:a,header:{...c.header,viewStamp:f,capacity:o,archetypeCount:d},archetypes:g,_regionBytes:c._regionBytes,_allocator:c._allocator,_reservedDescriptorBytes:c._reservedDescriptorBytes},oldViewStamp:u,newViewStamp:f,viewsPreserved:!0}}const ae=810766935,J=1;class O extends Error{constructor(e){super(e),this.name="ECSRestoreError"}}const H=4;function gt(c){const e=c.freeIndices.length,t=c.archetypeRows.length,s=H*(4+e+1+t*3),r=new Uint8Array(s),n=new DataView(r.buffer);let o=0;const h=a=>{n.setUint32(o,a,!0),o+=H};h(c.tick),h(c.entityHighWater),h(c.entityAliveCount),h(e);for(let a=0;a<e;a++)h(c.freeIndices[a]);h(t);for(let a=0;a<t;a++){const l=c.archetypeRows[a];h(l.archetypeId),h(l.length),h(l.enabledCount)}return r}function yt(c){const e=new DataView(c.buffer,c.byteOffset,c.byteLength),t=c.byteLength;let s=0;const r=p=>{if(s+p>t)throw new O(`host-state truncated: need ${p} more bytes at offset ${s}, have ${t-s}`)},n=()=>{r(H);const p=e.getUint32(s,!0);return s+=H,p},o=n(),h=n(),a=n(),l=n(),u=new Array(l);for(let p=0;p<l;p++)u[p]=n();const d=n(),f=new Array(d);for(let p=0;p<d;p++){const g=n(),E=n(),y=n();f[p]={archetypeId:g,length:E,enabledCount:y}}if(s!==t)throw new O(`host-state has ${t-s} trailing bytes after the last archetype (not a canonical encoding)`);return{tick:o,entityHighWater:h,entityAliveCount:a,freeIndices:u,archetypeRows:f}}function mt(c,e,t){const s=H*5,r=new Uint8Array(s+c.length+e.length+t.length),n=new DataView(r.buffer);return n.setUint32(0,ae,!0),n.setUint32(4,J,!0),n.setUint32(8,c.length,!0),n.setUint32(12,e.length,!0),n.setUint32(16,t.length,!0),r.set(c,s),r.set(e,s+c.length),r.set(t,s+c.length+e.length),r}function wt(c){const e=H*5;if(c.byteLength<e)throw new O(`world snapshot too small: ${c.byteLength} bytes (frame header needs ${e})`);const t=new DataView(c.buffer,c.byteOffset,c.byteLength),s=t.getUint32(0,!0);if(s!==ae)throw new O(`bad world-snapshot magic: 0x${s.toString(16).padStart(8,"0")} (expected 0x${ae.toString(16).padStart(8,"0")}). A bare dense (SAB) snapshot is not a combined world snapshot — pass the bytes from ECS.snapshot(), not snapshotColumnStore().`);const r=t.getUint32(4,!0);if(r!==J)throw new O(`incompatible world-snapshot version: snapshot=${r}, build=${J}`);const n=t.getUint32(8,!0),o=t.getUint32(12,!0),h=t.getUint32(16,!0);if(e+n+o+h!==c.byteLength)throw new O(`world-snapshot frame mismatch: header declares ${e}+${n}+${o}+${h}=${e+n+o+h} bytes, buffer is ${c.byteLength}`);const a=c.byteOffset,l=c.buffer;return{dense:new Uint8Array(l,a+e,n),sparse:new Uint8Array(l,a+e+n,o),host:new Uint8Array(l,a+e+n+o,h)}}function St(c,e,t){if(c.byteLength<i.STORE_HEADER_BYTES)throw new O(`dense section too small: ${c.byteLength} bytes (SAB header needs ${i.STORE_HEADER_BYTES})`);const s=new DataView(c.buffer,c.byteOffset,c.byteLength),r=s.getUint32(i.STORE_HEADER_OFFSETS.magic,!0);if(r!==i.STORE_MAGIC)throw new O(`dense section bad magic: 0x${r.toString(16).padStart(8,"0")} (expected SAB magic 0x${i.STORE_MAGIC.toString(16).padStart(8,"0")})`);const n=s.getUint32(i.STORE_HEADER_OFFSETS.sim_abi_version,!0);if(n!==i.SIM_ABI_VERSION)throw new O(`dense section incompatible sim_abi_version: snapshot=${n}, build=${i.SIM_ABI_VERSION}`);const o=i.readStoreHeader(s);if(o.layoutDescriptorOff<0||o.layoutDescriptorOff>c.byteLength)throw new O(`dense layoutDescriptorOff ${o.layoutDescriptorOff} is outside the section (${c.byteLength} bytes)`);const h=o.entityIndexOff;if(h<0||h+i.ENTITY_INDEX_HEADER_BYTES>c.byteLength)throw new O(`dense entityIndexOff ${h} is outside the section (${c.byteLength} bytes)`);const a=s.getUint32(h+i.ENTITY_INDEX_HEADER_OFFSETS.capacity,!0);if(a!==t)throw new O(`entity-index capacity mismatch: live=${t}, snapshot=${a}`);let l;try{l=i.readLayoutDescriptorRegion(s,o.layoutDescriptorOff,o.archetypeCount)}catch(u){throw u instanceof RangeError?new O(`dense section layout is corrupt or truncated: a descriptor reads past the ${c.byteLength}-byte section (${u.message})`):u}if(e.size!==l.length)throw new O(`archetype-set mismatch: the live world has ${e.size} SAB archetypes, the snapshot has ${l.length}. restoreInto requires an identical archetype set (prewarm the world so its archetype set is stable, per ADR on no-lazy archetypes).`);for(let u=0;u<l.length;u++){const d=l[u],f=e.get(d.archetypeId);if(f===void 0)throw new O(`archetype-set mismatch: snapshot archetype ${d.archetypeId} is absent from the live world`);if(!Rt(f.componentMask,d.componentMask))throw new O(`archetype ${d.archetypeId} component-mask mismatch between the live world and the snapshot (different component registration)`);const p=f.columnsInOrder,g=d.columns;if(p.length!==g.length)throw new O(`archetype ${d.archetypeId} column-count mismatch: live=${p.length}, snapshot=${g.length}`);for(let E=0;E<p.length;E++)if(p[E].componentId!==g[E].componentId||p[E].fieldId!==g[E].fieldId||p[E].typeTag!==g[E].typeTag)throw new O(`archetype ${d.archetypeId} column ${E} layout mismatch: live=(c${p[E].componentId},f${p[E].fieldId},t${p[E].typeTag}), snapshot=(c${g[E].componentId},f${g[E].fieldId},t${g[E].typeTag})`)}}function Rt(c,e){if(c.length!==e.length)return!1;for(let t=0;t<c.length;t++)if(c[t]!==e[t])return!1;return!0}class Ct{host;allocator;constructor(e,t){this.host=e,this.allocator=t}snapshotSparse(){const e=i.snapshotSparseStores(this.host.sparseStores()),t=i.snapshotRelations(this.host.relationStores()),s=new Uint8Array(8+e.length+t.length),r=new DataView(s.buffer);return r.setUint32(0,e.length,!0),r.setUint32(4,t.length,!0),s.set(e,8),s.set(t,8+e.length),s}restoreSparse(e){const t=new DataView(e.buffer,e.byteOffset,e.byteLength);if(e.byteLength<8)throw new i.SparseRestoreError(`sparse snapshot truncated: need 8 header bytes, have ${e.byteLength}`);const s=t.getUint32(0,!0),r=t.getUint32(4,!0);if(8+s+r!==e.byteLength)throw new i.SparseRestoreError(`sparse snapshot frame mismatch: header declares 8+${s}+${r}=${8+s+r} bytes, buffer is ${e.byteLength}`);i.restoreSparseStores(this.host.sparseStores(),e.subarray(8,8+s)),this.rebuildRelationIndices(e.subarray(8+s,8+s+r))}rebuildRelationIndices(e){const t=this.host.generations(),s=n=>i.createEntityId(n,t[n]),r=this.host.relationStores();i.restoreRelations(r,e,s);for(let n=0;n<r.length;n++)r[n].rebuildReverseFromForward(s)}snapshot(){this.host.publishRowCounts();const e=new Uint8Array(Ue(this.host.columnStore())),t=this.snapshotSparse(),s=gt(this.collectHostState());return mt(e,t,s)}collectHostState(){const e=[],t=this.host.archetypes();for(let s=0;s<t.length;s++){const r=t[s];r.isBufferBacked&&e.push({archetypeId:r.id,length:r.length,enabledCount:r.enabledCount})}return{tick:this.host.tick(),entityHighWater:this.allocator.highWater,entityAliveCount:this.allocator.aliveCount,freeIndices:this.allocator.snapshotFreeIndices(),archetypeRows:e}}restoreInto(e){const t=wt(e),s=yt(t.host);St(t.dense,this.host.columnStore().archetypes,this.host.entityIndexCapacity()),this.assertSparseSectionMatches(t.sparse);const r=Ve(t.dense,this.host.bufferAllocator());this.host.mountRestoredDense(r),this.host.reconstructHostRows(s),this.allocator.restoreHostState(s.freeIndices,s.entityAliveCount),this.host.setTick(s.tick),this.host.invalidateQueryCaches(),this.restoreSparse(t.sparse)}assertSparseSectionMatches(e){const t=new DataView(e.buffer,e.byteOffset,e.byteLength);if(e.byteLength<8)throw new i.SparseRestoreError(`sparse snapshot truncated: need 8 header bytes, have ${e.byteLength}`);const s=t.getUint32(0,!0),r=t.getUint32(4,!0);if(8+s+r!==e.byteLength)throw new i.SparseRestoreError(`sparse snapshot frame mismatch: header declares 8+${s}+${r}=${8+s+r} bytes, buffer is ${e.byteLength}`);i.validateSparseStores(this.host.sparseStores(),e.subarray(8,8+s))}}function Le(c,e,t){const s=c.get(e);s!==void 0?s.push(t):c.set(e,[t])}class vt{archetypes=[];componentIndex=[];archetypeMap=new Map;nextArchetypeId=0;host;constructor(e){this.host=e}get(e){if(e<0||e>=this.archetypes.length)throw new i.ECSError(i.ECS_ERROR.ARCHETYPE_NOT_FOUND,`Archetype with ID ${e} not found`);return this.archetypes[e]}getOrCreateFromMask(e){const t=e.hash(),s=this.lookup(e,t);if(s!==null)return s;const r=_e(this.nextArchetypeId++),n=this.buildLayouts(e);return this.host.extendStore([we(r,e,n,this.host.initialCapacity())]),this.install(r,e,n,t),r}createManyFromMasks(e){const t=new Array(e.length),s=[],r=[],n=[],o=[];for(let a=0;a<e.length;a++){const l=e[a],u=l.hash(),d=this.lookup(l,u);if(d!==null){t[a]=d;continue}let f=!1;for(let g=0;g<s.length;g++)if(r[g]===u&&s[g].equals(l)){t[a]=o[g],f=!0;break}if(f)continue;const p=_e(this.nextArchetypeId++);s.push(l),r.push(u),n.push(this.buildLayouts(l)),o.push(p),t[a]=p}if(s.length===0)return t;const h=new Array(s.length);for(let a=0;a<s.length;a++)h[a]=we(o[a],s[a],n[a],this.host.initialCapacity());this.host.extendStore(h);for(let a=0;a<s.length;a++)this.install(o[a],s[a],n[a],r[a]);return t}lookup(e,t){const s=this.archetypeMap.get(t);if(s===void 0)return null;for(let r=0;r<s.length;r++)if(this.archetypes[s[r]].mask.equals(e))return s[r];return null}buildLayouts(e){const t=[],s=this.host.componentMetas();return e.forEach(r=>{const n=r,o=s[n];o&&o.fieldNames.length>0&&t.push({componentId:n,fieldNames:o.fieldNames,fieldIndex:o.fieldIndex,fieldTypes:o.fieldTypes})}),t}install(e,t,s,r){const n=t.copy(),o=this.host.materialize(e,n,s);this.archetypes.push(o),Le(this.archetypeMap,r,e),t.forEach(h=>{const a=h;let l=this.componentIndex[a];if(l===void 0&&(l=[],this.componentIndex[a]=l),l.length>0&&e<=l[l.length-1])throw new i.ECSError(i.ECS_ERROR.COMPONENT_INDEX_INVARIANT,`component_index bucket for component ${a} received archetype ${e} out of ascending order (last = ${l[l.length-1]}). Buckets are duplicate-free and ascending by construction (see install / ADR-0015) — this means install ran twice for an id, or a second writer of component_index was introduced.`);l.push(e)}),this.host.fanIntoQueries(o)}resolveAdd(e,t){const s=this.get(e);if(s.mask.has(t))return e;const r=s.getEdge(t);if(r?.add!=null)return r.add;const n=this.getOrCreateFromMask(s.mask.copyWithSet(t));return this.cacheEdge(s,this.get(n),t),n}resolveRemove(e,t){const s=this.get(e);if(!s.mask.has(t))return e;const r=s.getEdge(t);if(r?.remove!=null)return r.remove;const n=this.getOrCreateFromMask(s.mask.copyWithClear(t));return this.cacheEdge(this.get(n),s,t),n}cacheEdge(e,t,s){const r=e.getEdge(s)??{add:null,remove:null,addMap:null,removeMap:null};r.add=t.id,r.addMap=oe(e,t),e.setEdge(s,r);const n=t.getEdge(s)??{add:null,remove:null,addMap:null,removeMap:null};n.remove=e.id,n.removeMap=oe(t,e),t.setEdge(s,n)}}function we(c,e,t,s){const r=[];for(let h=0;h<t.length;h++){const a=t[h],l=a.fieldTypes;for(let u=0;u<l.length;u++)r.push({componentId:a.componentId,fieldId:u,typeTag:i.TYPED_ARRAY_TAG_TO_TYPE_TAG[l[u]]})}const n=e._words,o=new Array(i.COMPONENT_MASK_WORDS);for(let h=0;h<i.COMPONENT_MASK_WORDS;h++)o[h]=(n[h]??0)>>>0;return{archetypeId:c,componentMask:o,rowCapacity:s,columns:r}}const Ot=[],Se=-1,te=new DataView(new ArrayBuffer(8)),Re=129,bt=7,se=-1;class At{entityAllocator;componentMetas=[];componentCount=0;sparseStores=[];sparseNames=[];relationService;events=new je;archGraph;registeredQueries=[];emptyArchetypeId;entityArchetype;entityRow;_deferred;_snapshots;_tick=0;_trace=null;_structuralObserverCount=0;_toggleObserverCount=0;_obsEvents={addComp:[],addEid:[],addLen:0,remComp:[],remEid:[],remLen:0,disComp:[],disEid:[],disLen:0,enaComp:[],enaEid:[],enaLen:0};_structuralObserverHook=null;setStructuralObserverHook(e){this._structuralObserverHook=e}_collectDestroyEid=0;_collectDestroyRemoveBit=e=>{if(!this.componentMetas[e].obsRem)return;const t=this._obsEvents;t.remComp[t.remLen]=e,t.remEid[t.remLen]=this._collectDestroyEid,t.remLen++};_collectToggleEid=0;_collectDisableBit=e=>{if(!this.componentMetas[e].obsDisable)return;const t=this._obsEvents;t.disComp[t.disLen]=e,t.disEid[t.disLen]=this._collectToggleEid,t.disLen++};_collectEnableBit=e=>{if(!this.componentMetas[e].obsEnable)return;const t=this._obsEvents;t.enaComp[t.enaLen]=e,t.enaEid[t.enaLen]=this._collectToggleEid,t.enaLen++};_toggleInitial=new Map;_anyDirtyTracked=!1;_dirtyTrackedCids=[];_dirtyLists=[];_dirtyMarks=[];_rowCountsDirty=!1;_queryDirtyEpoch=0;initialCapacity;_scratchTargetMask=new T.BitSet;_columnStore;_growHandler=(e,t)=>{const s=e.id,r=this._columnStore.archetypes.get(s);if(r===void 0)throw new i.ECSError(i.ECS_ERROR.ARCHETYPE_NOT_FOUND,`grow_handler invoked on archetype ${s} which has no SAB region`);const n=r.rowCapacity,o=e.length+t;let h=n>0?n:1;for(;h<o;)h=h*2;const a=[],l=this.archGraph.archetypes;for(let d=0;d<l.length;d++){const f=l[d],p=this._columnStore.archetypes.get(f.id);p!==void 0&&a.push({archetypeId:f.id,newRowCapacity:f.id===s?h:p.rowCapacity,rowCount:f.hasColumns?f.length:0})}let u;try{u=pt(this._columnStore,{archetypes:a},this._bufferAllocator)}catch(d){throw d instanceof W.StoreCapExceededError?this._capExceededError(d):d}if(this._columnStore=u.store,u.viewsPreserved){const d=u.grownArchetypeIds;for(let f=0;f<d.length;f++){const p=this.archGet(d[f]);p.isBufferBacked&&p.refreshViews(this._columnStore)}}else for(let d=0;d<l.length;d++)l[d].isBufferBacked&&l[d].refreshViews(this._columnStore);this._handleBufferResized()};_capExceededError(e){const t=this._capContext,s=this.entityAllocator.aliveCount,r=`SAB grow refused: requested ${e.requestedBytes} bytes exceeds `+(e.capBytes!==null?`the ${e.capBytes}-byte cap.`:"the backing's ceiling.");let n;if(t===void 0)n=` The ECS holds ${s} live entities (no sizing intent declared).`;else if(t.budgetEntities!==null){const o=(s/t.budgetEntities).toFixed(1);n=` Declared ${t.intentLabel}; the ECS holds ${s} live entities (${o}× the budget) — runaway entity creation upstream, or an under-declared budget. Raise the budget only if a ${s}-entity ECS is intended.`}else n=` Declared ${t.intentLabel}; the ECS holds ${s} live entities.`;return new i.ECSError(i.ECS_ERROR.STORE_CAP_EXCEEDED,r+n+` The cap is a hard ceiling with no grow-beyond fallback (#380) — diagnose growth before raising it. Caused by: ${e.message}`)}_bufferAllocator;_capContext;_onBufferResized;constructor(e){const t=typeof e=="number"?{initialCapacity:e}:e??{};if(this.initialCapacity=t.initialCapacity??i.DEFAULT_COLUMN_CAPACITY,this._bufferAllocator=t.bufferAllocator??W.growableSabAllocator(),this._bufferAllocator.isInPlace!==!0)throw new i.ECSError(i.ECS_ERROR.INVALID_MEMORY_OPTIONS,"Store requires an in-place SAB allocator (ADR-0008): the flush loops keep writing through hoisted entity-index views across grows, so a non-in-place allocator (e.g. DEFAULT_SAB_ALLOCATOR) corrupts the entity→row mapping. Use growable_sab_allocator / wasm_memory_allocator; non-in-place allocators are snapshot/test sizing utilities only.");this._capContext=t.capContext,this._onBufferResized=t.onBufferResized,this._entityIndexCapacity=t.entityIndexCapacity??i.ENTITY_INDEX_DEFAULT_CAPACITY,this._regions=t.regions,this._bindingsRegionBytes=t.bindingsRegionBytes??0,this._deterministic=t.deterministic??!1,this._deferred=new ht({applyAdds:()=>this._flushAdds(),applyRemoves:()=>this._flushRemoves(),applyDestroys:()=>this._drainDestroyed(),applyToggles:()=>this._flushToggles(),structuralObserverCount:()=>this._structuralObserverCount,toggleObserverCount:()=>this._toggleObserverCount,structuralObserverHook:()=>this._structuralObserverHook},this._obsEvents),this.relationService=new it({isAlive:r=>this.isAlive(r),hasSparse:(r,n)=>this.hasSparse(r,n),pushSparseStore:(r,n)=>this._pushSparseStore(r,n),sparseStoreOf:r=>this.sparseStoreOf(r),sparseStores:()=>this.sparseStores,entityGenerations:()=>this.entityAllocator.generations,entityArchetype:()=>this.entityArchetype,entityRow:()=>this.entityRow,archetypes:()=>this.archGraph.archetypes,forEachSparseMatch:(r,n,o,h,a,l,u,d)=>this._forEachSparseMatch(r,n,o,h,a,l,u,d)}),this._columnStore=i.createColumnStore([],this._bufferAllocator,{reservedDescriptorBytes:64*1024,entityIndexCapacity:this._entityIndexCapacity,eventRingCapacitySlots:i.EVENT_RING_DEFAULT_CAPACITY_SLOTS,commandRingCapacitySlots:i.COMMAND_RING_DEFAULT_CAPACITY_SLOTS,actionRingCapacitySlots:i.ACTION_RING_DEFAULT_CAPACITY_SLOTS,regions:this._regions,bindingsRegionBytes:this._bindingsRegionBytes});const s=i.buildEntityIndexViews(this._columnStore.buffer,this._columnStore.header.entityIndexOff,this._entityIndexCapacity);this.entityArchetype=s.archetypes,this.entityRow=s.rows,this.entityAllocator=new ot(this._entityIndexCapacity,s.generations,new Uint32Array(this._columnStore.buffer,this._columnStore.header.entityIndexOff+i.ENTITY_INDEX_HEADER_OFFSETS.length,1)),this._snapshots=new Ct({sparseStores:()=>this.sparseStores,relationStores:()=>this.relationService.stores,generations:()=>this.entityAllocator.generations,archetypes:()=>this.archGraph.archetypes,columnStore:()=>this._columnStore,bufferAllocator:()=>this._bufferAllocator,entityIndexCapacity:()=>this._entityIndexCapacity,tick:()=>this._tick,setTick:r=>{this._tick=r},publishRowCounts:()=>this.publishRowCountsToDescriptor(),mountRestoredDense:r=>this._mountRestoredDense(r),reconstructHostRows:r=>this._reconstructHostRows(r),invalidateQueryCaches:()=>{this._queryDirtyEpoch++,this._rowCountsDirty=!0}},this.entityAllocator),this.archGraph=new vt({componentMetas:()=>this.componentMetas,initialCapacity:()=>this.initialCapacity,extendStore:r=>this._archExtendStoreWithNewSpecs(r),materialize:(r,n,o)=>this._materializeArchetype(r,n,o),fanIntoQueries:r=>this._fanIntoQueries(r)}),this.emptyArchetypeId=this.archGetOrCreateFromMask(new T.BitSet)}_entityIndexCapacity;_regions;_bindingsRegionBytes;_deterministic;get deterministic(){return this._deterministic}_requireDeterministic(e){if(!this._deterministic)throw new i.ECSError(i.ECS_ERROR.DETERMINISM_DISABLED,`${e} requires determinism — construct the Store/ECS with { deterministic: true }. The canonical-ordering determinism surface (state_hash / snapshot_sparse / restore_sparse) is opt-in; see ADR-0020.`)}_rejectNonDeterministicFields(e,t,s){if(this._deterministic)for(let r=0;r<t.length;r++){const n=t[r];if(n==="f32"||n==="f64")throw new i.ECSError(i.ECS_ERROR.NON_DETERMINISTIC_COLUMN_TYPE,`Cannot register ${s} field "${e[r]}" as "${n}" on a { deterministic: true } world: floating-point columns round differently across V8 / Bun / Zig (1-ULP IEEE-754), breaking cross-host state_hash agreement (ADR-0020). Use an integer type (e.g. "i32") — represent fractional quantities as fixed-point (Q16.16). Note the array shorthand defaults to "f64", so pass an explicit integer type there.`,{field:e[r],type:n,kind:s})}}_refreshEntityIndexViews(){const e=this._columnStore.view.getUint32(i.STORE_HEADER_OFFSETS.entity_index_off,!0),t=i.buildEntityIndexViews(this._columnStore.buffer,e,this._entityIndexCapacity);this.entityArchetype=t.archetypes,this.entityRow=t.rows,this.entityAllocator.replantViews(t.generations,new Uint32Array(this._columnStore.buffer,e+i.ENTITY_INDEX_HEADER_OFFSETS.length,1))}_handleBufferResized(){this._refreshEntityIndexViews(),this.entityAllocator.publishLength(),this._onBufferResized?.()}get columnStore(){return this._columnStore}regionOffset(e){return i.findRegionOffset(this._columnStore.view,e)}regionHandle(e){const t=i.findRegionEntry(this._columnStore.view,e);return t===null?null:{buffer:this._columnStore.buffer,view:this._columnStore.view,offset:t.byteOffset,bytes:t.byteLength}}publishRowCountsToDescriptor(){if(!this._rowCountsDirty)return;const e=this._columnStore.view;let t=e.getUint32(i.STORE_HEADER_OFFSETS.layout_descriptor_off,!0);const s=this.archGraph.archetypes;for(let r=0;r<s.length;r++){const n=s[r];if(!n.isBufferBacked)continue;const o=e.getUint32(t+i.ARCHETYPE_DESCRIPTOR_OFFSETS.column_count,!0);{const h=e.getUint32(t+i.ARCHETYPE_DESCRIPTOR_OFFSETS.archetype_id,!0);if(h!==n.id)throw new Error(`descriptor order drift: archetypes[${r}].id=${n.id} but descriptor at +${t} reports archetype_id=${h}`)}e.setUint32(t+i.ARCHETYPE_DESCRIPTOR_OFFSETS.row_count,n.hasColumns?n.length:0,!0),e.setUint32(t+i.ARCHETYPE_DESCRIPTOR_OFFSETS.enabled_count,n.hasColumns?n.enabledCount:0,!0),t+=i.ARCHETYPE_DESCRIPTOR_HEADER_BYTES+o*i.COLUMN_DESCRIPTOR_BYTES}this._rowCountsDirty=!1}stateHash(){this._requireDeterministic("state_hash()");let e=i.FNV1A_OFFSET_BASIS;const t=this.archGraph.archetypes;for(let n=0;n<t.length;n++){const o=t[n],h=o.id,a=o.length;if(e=i.fnv1aStepWord(e,h),e=i.fnv1aStepWord(e,a),e=i.fnv1aStepWord(e,o.enabledCount),a===0)continue;const l=o._flatColumns;for(let u=0;u<l.length;u++){const d=l[u].buf,f=a*d.BYTES_PER_ELEMENT,p=new Uint8Array(d.buffer,d.byteOffset,f),g=f>>>2;let E=0;for(let _=0;_<g;_++){const m=(p[E]|p[E+1]<<8|p[E+2]<<16|p[E+3]<<24)>>>0;e=(e^m)>>>0,e=Math.imul(e,i.FNV1A_PRIME),E+=4}const y=f&3;if(y!==0){let _=p[E];y>1&&(_|=p[E+1]<<8),y>2&&(_|=p[E+2]<<16),e=(e^_>>>0)>>>0,e=Math.imul(e,i.FNV1A_PRIME)}}}const s=this.sparseStores;for(let n=0;n<s.length;n++){const o=s[n];e=i.fnv1aStepWord(e,n),e=i.fnv1aStepWord(e,o.size);const h=o.canonicalIndices();for(let a=0;a<h.length;a++){const l=h[a];e=i.fnv1aStepWord(e,l);const u=o.getRow(l);for(let d=0;d<u.length;d++)te.setFloat64(0,u[d],!0),e=i.fnv1aStepWord(e,te.getUint32(0,!0)),e=i.fnv1aStepWord(e,te.getUint32(4,!0))}}const r=this.relationService.stores;for(let n=0;n<r.length;n++){const o=r[n];o.exclusive||(e=i.fnv1aStepWord(e,n),o.forEachCanonicalTargetSet((h,a)=>{e=i.fnv1aStepWord(e,h),e=i.fnv1aStepWord(e,a.length);for(let l=0;l<a.length;l++)e=i.fnv1aStepWord(e,a[l])}))}return e>>>0}archGet(e){return this.archGraph.get(e)}entityIdAtRow(e,t){const s=this.archGet(e);if(t<0||t>=s.entityCount)throw new i.ECSError(i.ECS_ERROR.ARCHETYPE_NOT_FOUND,`entity_id_at_row: archetype ${e} has ${s.entityCount} rows, requested row ${t}`);return s.entityIds[t]}archGetOrCreateFromMask(e){return this.archGraph.getOrCreateFromMask(e)}archCreateManyFromMasks(e){return this.archGraph.createManyFromMasks(e)}_archExtendStoreWithNewSpecs(e){const t=[],s=this.archGraph.archetypes;for(let n=0;n<s.length;n++){const o=s[n],h=this._columnStore.archetypes.get(o.id);h!==void 0&&t.push({archetypeId:o.id,newRowCapacity:h.rowCapacity,rowCount:o.hasColumns?o.length:0})}let r;try{r=_t(this._columnStore,{newArchetypes:e,existing:t},this._bufferAllocator)}catch(n){throw n instanceof W.StoreCapExceededError?this._capExceededError(n):n}if(this._columnStore=r.store,!r.viewsPreserved)for(let n=0;n<s.length;n++)s[n].isBufferBacked&&s[n].refreshViews(this._columnStore);this._handleBufferResized()}_materializeArchetype(e,t,s){const r=ue.fromColumnStore(e,t,s,this._columnStore,e);return r.growHandler=this._growHandler,r}_fanIntoQueries(e){const t=this.registeredQueries;for(let s=0;s<t.length;s++){const r=t[s];e.matches(r.includeMask)&&(!r.excludeMask||!e.mask.overlaps(r.excludeMask))&&(!r.anyOfMask||e.mask.overlaps(r.anyOfMask))&&r.result.push(e)}}archResolveAdd(e,t){return this.archGraph.resolveAdd(e,t)}archResolveRemove(e,t){return this.archGraph.resolveRemove(e,t)}createEntity(){const e=this.entityAllocator.alloc(),t=this.entityAllocator.lastIndex;return this.entityArchetype[t]=this.emptyArchetypeId,this.entityRow[t]=i.UNASSIGNED,e}_allocEntity(){return this.entityAllocator.alloc()}_ensureEntityIndexCapacity(e){this.entityAllocator.ensureCapacity(e)}resolveTemplate(e){const t=new T.BitSet;for(let a=0;a<e.length;a++)t.set(e[a].def.id);const s=this.archGetOrCreateFromMask(t),r=this.archGet(s),n=new Array(r._flatColumns.length).fill(0),o=new Map,h=new Array(e.length);for(let a=0;a<e.length;a++){h[a]=e[a].def;const l=e[a].def.id,u=this.componentMetas[l];if(u===void 0)throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,`template: component ${l} is not registered`);const d=e[a].values??i.EMPTY_VALUES,f=r._colOffset[l];for(let p=0;p<u.fieldNames.length;p++){const g=u.fieldNames[p];n[f+p]=d[g]??0,o.set(g,o.has(g)?Se:f+p)}}return{archetypeId:s,flatValues:n,overrideIndex:o,defs:h}}_resolveOverrideColumn(e,t){const s=e.overrideIndex.get(t);if(s===void 0)throw new i.ECSError(i.ECS_ERROR.FIELD_NOT_REGISTERED,`template override: no field "${t}" in this template`);if(s===Se)throw new i.ECSError(i.ECS_ERROR.FIELD_NOT_REGISTERED,`template override: field "${t}" is ambiguous (owned by more than one component in this template); set it via the template defaults instead of a flat override`);return s}_applyOverrides(e,t,s,r){const n=e._flatColumns;for(const o in r){if(r[o]===void 0)continue;const h=this._resolveOverrideColumn(s,o);h>=0&&(n[h].buf[t]=r[o])}}_applyOverridesRange(e,t,s,r,n){const o=e._flatColumns;for(const h in n){if(n[h]===void 0)continue;const a=this._resolveOverrideColumn(r,h);a>=0&&o[a].buf.fill(n[h],t,t+s)}}spawn(e,t){const s=this.archGraph.archetypes[e.archetypeId];s.materializesRows&&s.ensureRowCapacity(1);const r=this._allocEntity(),n=this.entityAllocator.lastIndex;if(!s.materializesRows)return this.entityArchetype[n]=e.archetypeId,this.entityRow[n]=i.UNASSIGNED,r;const o=s.length,h=s.enabledCount,a=s.addEntityWithValues(r,e.flatValues,this._tick,this.entityRow);return t!==void 0&&this._applyOverrides(s,a,e,t),this.entityArchetype[n]=e.archetypeId,this.entityRow[n]=a,this._onArchGrow(s,o,h),r}spawnMany(e,t,s){if(t<=0)return[];const r=this.archGraph.archetypes[e.archetypeId];this._ensureEntityIndexCapacity(t),r.ensureRowCapacity(t);const n=new Array(t),o=new Uint32Array(t);for(let f=0;f<t;f++){const p=this._allocEntity();o[f]=p,n[f]=p}const h=this.entityArchetype,a=this.entityRow;if(!r.materializesRows){for(let f=0;f<t;f++){const p=i.getEntityIndex(n[f]);h[p]=e.archetypeId,a[p]=i.UNASSIGNED}return n}const l=r.length,u=r.enabledCount;if(r.disabledCount>0){for(let f=0;f<t;f++){const p=r.addEntityWithValues(n[f],e.flatValues,this._tick,a),g=i.getEntityIndex(n[f]);h[g]=e.archetypeId,a[g]=p,s!==void 0&&this._applyOverrides(r,p,e,s)}return this._onArchGrow(r,l,u),n}const d=r.addEntitiesWithValues(o,t,e.flatValues,this._tick);for(let f=0;f<t;f++){const p=i.getEntityIndex(n[f]);h[p]=e.archetypeId,a[p]=d+f}return s!==void 0&&this._applyOverridesRange(r,d,t,e,s),this._onArchGrow(r,l,u),n}destroyEntity(e){if(!this.isAlive(e))throw i.entityNotAliveError("destroyEntity",e);if(!this.relationService.hasTargetCleanup){this._destroyOne(e,null);return}const t=[e];for(let s=0;s<t.length;s++){const r=t[s];this.isAlive(r)&&this._destroyOne(r,t)}}_destroyOne(e,t){const s=i.getEntityIndex(e),r=this.entityRow[s];if(r!==i.UNASSIGNED){const n=this.archGet(this.entityArchetype[s]),o=n.length;n.removeRow(r,this.entityRow),this._onArchLenChange(n,o)}this.entityArchetype[s]=i.UNASSIGNED,this.entityRow[s]=i.UNASSIGNED,this.relationService.count>0&&(this.relationService.purgeSource(e),t!==null&&this.relationService.cleanupTarget(e,t)),this.sparseStores.length>0&&this._purgeSparse(s),this._anyDirtyTracked&&this._clearDirtyForIndex(s),this.entityAllocator.recycle(s,i.getEntityGeneration(e))}isAlive(e){if(e<0||e>i.MAX_ENTITY_ID)return!1;const t=i.getEntityGeneration(e);if(t===i.RETIRED_GENERATION)return!1;const s=i.getEntityIndex(e);return this.entityAllocator.isAliveIndex(s,t)}get entityCount(){return this.entityAllocator.aliveCount}_onArchLenChange(e,t){this._rowCountsDirty=!0,t===0!=(e.length===0)&&this._queryDirtyEpoch++}_onArchGrow(e,t,s){this._rowCountsDirty=!0,(t===0||s===0&&e.enabledCount!==0)&&this._queryDirtyEpoch++}_onArchEnabledChange(e,t){this._rowCountsDirty=!0,t===0!=(e.enabledCount===0)&&this._queryDirtyEpoch++}disableEntity(e){if(!this.isAlive(e))throw i.entityNotAliveError("disableEntity",e);const t=i.getEntityIndex(e),s=this.entityRow[t];if(s===i.UNASSIGNED)throw new i.ECSError(i.ECS_ERROR.ENTITY_NOT_ALIVE,"cannot disable a component-less entity: it occupies no archetype row; add a component first");const r=this.archGet(this.entityArchetype[t]);if(s>=r.enabledCount)return;const n=r.enabledCount;r.disableRow(s,this.entityRow),this._onArchEnabledChange(r,n)}enableEntity(e){if(!this.isAlive(e))throw i.entityNotAliveError("enableEntity",e);const t=i.getEntityIndex(e),s=this.entityRow[t];if(s===i.UNASSIGNED)return;const r=this.archGet(this.entityArchetype[t]);if(s<r.enabledCount)return;const n=r.enabledCount;r.enableRow(s,this.entityRow),this._onArchEnabledChange(r,n)}isDisabled(e){if(!this.isAlive(e))throw i.entityNotAliveError("isDisabled",e);const t=i.getEntityIndex(e),s=this.entityRow[t];if(s===i.UNASSIGNED)return!1;const r=this.archGet(this.entityArchetype[t]);return s>=r.enabledCount}_flushEpoch=0;_flushTouched=[];_settleFlushDirty(){const e=this._flushTouched;if(e.length===0)return;this._rowCountsDirty=!0;let t=!1;for(let s=0;s<e.length;s++){const r=e[s];(r._flushPreLen===0!=(r.length===0)||r._flushPreEnabled===0!=(r.enabledCount===0))&&(t=!0)}t&&this._queryDirtyEpoch++,e.length=0,this._flushEpoch++}destroyEntityDeferred(e){if(!this.isAlive(e))throw i.entityNotAliveError("destroyEntityDeferred",e);this._deferred.queueDestroy(e)}disableEntityDeferred(e){if(!this.isAlive(e))throw i.entityNotAliveError("disableEntityDeferred",e);this._deferred.queueToggle(e,!0)}enableEntityDeferred(e){if(!this.isAlive(e))throw i.entityNotAliveError("enableEntityDeferred",e);this._deferred.queueToggle(e,!1)}_flushToggles(){const e=this._deferred.toggleIds,t=this._deferred.toggleDisable,s=e.length;if(!(this._toggleObserverCount>0)){for(let o=0;o<s;o++){const h=e[o];this.isAlive(h)&&(t[o]?this.disableEntity(h):this.enableEntity(h))}e.length=0,t.length=0;return}const n=this._toggleInitial;for(let o=0;o<s;o++){const h=e[o];this.isAlive(h)&&(n.has(h)||n.set(h,this.isDisabled(h)))}for(let o=0;o<s;o++){const h=e[o];this.isAlive(h)&&(t[o]?this.disableEntity(h):this.enableEntity(h))}e.length=0,t.length=0;for(const[o,h]of n){if(!this.isAlive(o))continue;const a=this.isDisabled(o);h!==a&&this._collectToggle(o,a)}n.clear()}_collectToggle(e,t){const s=i.getEntityIndex(e);if(this.entityRow[s]===i.UNASSIGNED)return;const r=this.archGet(this.entityArchetype[s]);this._collectToggleEid=e,r.mask.forEach(t?this._collectDisableBit:this._collectEnableBit)}get pendingToggleCount(){return this._deferred.toggleCount}flushDestroyed(){this._deferred.flushDestroyed()}_drainDestroyed(){const e=this._deferred.destroyIds;if(e.length===0)return;const t=this.entityAllocator,s=this.entityArchetype,r=this.entityRow,n=t.generations,o=this.archGraph.archetypes,h=t.highWater;let a=!1,l=!1;const u=this.sparseStores.length>0,d=this.relationService.count>0,f=d&&this.relationService.hasTargetCleanup,p=this._anyDirtyTracked,g=this._structuralObserverCount>0;for(let E=0;E<e.length;E++){const y=e[E],_=y&i.INDEX_MASK,m=y>>i.INDEX_BITS;if(_>=h||n[_]!==m)continue;const S=r[_];if(S!==i.UNASSIGNED){const v=o[s[_]];g&&(this._collectDestroyEid=y,v.mask.forEach(this._collectDestroyRemoveBit)),v.removeRow(S,r),a=!0,v.length===0&&(l=!0)}d&&this.relationService.purgeSource(y),f&&this.relationService.cleanupTarget(y,e),u&&this._purgeSparse(_),p&&this._clearDirtyForIndex(_),s[_]=i.UNASSIGNED,r[_]=i.UNASSIGNED,t.recycle(_,m)}e.length=0,a&&(this._rowCountsDirty=!0,l&&this._queryDirtyEpoch++)}get pendingDestroyCount(){return this._deferred.destroyCount}addComponentDeferred(e,t,s){if(!this.isAlive(e))throw i.entityNotAliveError("addComponentDeferred",e,this.componentLabel(t.id));this._deferred.queueAdd(e,t,s??i.EMPTY_VALUES)}removeComponentDeferred(e,t){if(!this.isAlive(e))throw i.entityNotAliveError("removeComponentDeferred",e,this.componentLabel(t.id));this._deferred.queueRemove(e,t)}flushStructural(){this._deferred.flushStructural()}_flushAdds(){const e=this._deferred.addIds,t=this._deferred.addDefs,s=this._deferred.addValues,r=e.length,n=this.entityArchetype,o=this.entityRow,h=this.entityAllocator.generations,a=this.archGraph.archetypes,l=this.componentMetas,u=this.entityAllocator.highWater,d=this._tick,f=this._flushEpoch,p=this._flushTouched,g=this._structuralObserverCount>0,E=this._obsEvents;for(let y=0;y<r;y++){const _=e[y],m=_&i.INDEX_MASK,S=_>>i.INDEX_BITS;if(m>=u||h[m]!==S)continue;const v=n[m],R=t[y].id,C=a[v],w=l[R];if(C.mask.has(R)){w.fieldNames.length>0&&C.writeFields(o[m],R,s[y],d);continue}const k=this.archResolveAdd(v,R),b=a[k],F=o[m],fe=!b.hasColumns&&!C.hasColumns;F!==i.UNASSIGNED&&C._flushSeenEpoch!==f&&(C._flushSeenEpoch=f,C._flushPreLen=C.length,C._flushPreEnabled=C.enabledCount,p.push(C)),b._flushSeenEpoch!==f&&(b._flushSeenEpoch=f,b._flushPreLen=b.length,b._flushPreEnabled=b.enabledCount,p.push(b));let z;if(F!==i.UNASSIGNED){if(fe)b.moveEntityFromTag(C,F,_,o);else{const Pe=C.getEdge(R);b.moveEntityFrom(C,F,_,Pe.addMap,d,o)}z=A[0]}else z=fe?b.addEntityTag(_,o):b.addEntity(_,o);w.fieldNames.length>0&&b.writeFields(z,R,s[y],d),n[m]=k,o[m]=z,g&&w.obsAdd&&(E.addComp[E.addLen]=R,E.addEid[E.addLen]=_,E.addLen++)}e.length=0,t.length=0,s.length=0,this._settleFlushDirty()}_flushRemoves(){const e=this._deferred.removeIds,t=this._deferred.removeDefs,s=e.length,r=this.entityArchetype,n=this.entityRow,o=this.entityAllocator.generations,h=this.archGraph.archetypes,a=this.entityAllocator.highWater,l=this._tick,u=this._flushEpoch,d=this._flushTouched,f=this.componentMetas,p=this._structuralObserverCount>0,g=this._obsEvents;for(let E=0;E<s;E++){const y=e[E],_=y&i.INDEX_MASK,m=y>>i.INDEX_BITS;if(_>=a||o[_]!==m)continue;const S=r[_],v=t[E].id,R=h[S];if(!R.mask.has(v))continue;const C=this.archResolveRemove(S,v),w=h[C],k=n[_],b=!w.hasColumns&&!R.hasColumns;if(R._flushSeenEpoch!==u&&(R._flushSeenEpoch=u,R._flushPreLen=R.length,R._flushPreEnabled=R.enabledCount,d.push(R)),w._flushSeenEpoch!==u&&(w._flushSeenEpoch=u,w._flushPreLen=w.length,w._flushPreEnabled=w.enabledCount,d.push(w)),b)w.moveEntityFromTag(R,k,y,n);else{const F=R.getEdge(v);w.moveEntityFrom(R,k,y,F.removeMap,l,n)}r[_]=C,n[_]=A[0],p&&f[v].obsRem&&(g.remComp[g.remLen]=v,g.remEid[g.remLen]=y,g.remLen++)}e.length=0,t.length=0,this._settleFlushDirty()}get pendingStructuralCount(){return this._deferred.structuralCount}_configureComponentObservation(e,t,s,r,n,o){const h=this.componentMetas[e];if(h===void 0)throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,`observe(): component ${e} is not registered`);const a=h.obsAdd||h.obsRem;h.obsAdd=t,h.obsRem=s;const l=t||s;a&&!l?this._structuralObserverCount--:!a&&l&&this._structuralObserverCount++;const u=h.obsDisable||h.obsEnable;h.obsDisable=r,h.obsEnable=n;const d=r||n;if(u&&!d?this._toggleObserverCount--:!u&&d&&this._toggleObserverCount++,o&&!h.trackDirty)h.trackDirty=!0,this._dirtyLists[e]===void 0&&(this._dirtyLists[e]=[],this._dirtyMarks[e]=new Uint8Array(Math.max(1,this.entityAllocator.generations.length))),this._dirtyTrackedCids.push(e),this._anyDirtyTracked=!0;else if(!o&&h.trackDirty){h.trackDirty=!1;const f=this._dirtyTrackedCids.indexOf(e);f>=0&&this._dirtyTrackedCids.splice(f,1),this._anyDirtyTracked=this._dirtyTrackedCids.length>0;const p=this._dirtyLists[e],g=this._dirtyMarks[e];if(p!==void 0&&g!==void 0){for(let E=0;E<p.length;E++)g[p[E]&i.INDEX_MASK]=0;p.length=0}}}_noteSet(e,t){const s=e.id,r=this.componentMetas[s];if(r===void 0||!r.trackDirty)return;const n=t&i.INDEX_MASK;let o=this._dirtyMarks[s];n>=o.length&&(o=this._growDirtyMarks(s,n)),o[n]===0&&(o[n]=1,this._dirtyLists[s].push(t))}_growDirtyMarks(e,t){const s=this._dirtyMarks[e];let r=Math.max(1,s.length);for(;r<=t;)r*=2;const n=new Uint8Array(r);return n.set(s),this._dirtyMarks[e]=n,n}_takeDirty(e){const t=this._dirtyLists[e];if(t===void 0||t.length===0)return Ot;this._dirtyLists[e]=[];const s=this._dirtyMarks[e];for(let r=0;r<t.length;r++)s[t[r]&i.INDEX_MASK]=0;return t}_clearDirtyForIndex(e){const t=this._dirtyTrackedCids;for(let s=0;s<t.length;s++){const r=this._dirtyMarks[t[s]];r!==void 0&&e<r.length&&(r[e]=0)}}_forEachChangedArchetype(e,t,s){const r=this.archGraph.componentIndex[e];if(r===void 0)return;const n=this.archGraph.archetypes;for(let o=0;o<r.length;o++){const h=n[r[o]];h.length>0&&h._changedTick[e]>=t&&s(h)}}_collectEntitiesWithComponent(e){const t=[],s=this.archGraph.componentIndex[e];if(s===void 0)return t;const r=this.archGraph.archetypes;for(let n=0;n<s.length;n++){const o=r[s[n]],h=o.entityIds;for(let a=0;a<o.enabledCount;a++)t.push(i.unsafeCast(h[a]))}return t}registerComponent(e,t){if(this.componentCount>=i.STORE_DESCRIPTOR_COMPONENT_LIMIT)throw new i.ECSError(i.ECS_ERROR.COMPONENT_LIMIT_EXCEEDED,`Cannot register more than ${i.STORE_DESCRIPTOR_COMPONENT_LIMIT} components: the SAB archetype descriptor mask is ${i.STORE_DESCRIPTOR_COMPONENT_LIMIT} bits wide. Widen the descriptor mask (descriptor.ts + abi.zig, a SIM_ABI_VERSION bump) to raise it.`,{componentCount:this.componentCount,limit:i.STORE_DESCRIPTOR_COMPONENT_LIMIT});const s=Object.keys(e),r=new Array(s.length),n=Object.create(null);for(let a=0;a<s.length;a++)n[s[a]]=a,r[a]=e[s[a]];this._rejectNonDeterministicFields(s,r,"component");const o=Te(this.componentCount++);this.componentMetas.push({name:t,fieldNames:s,fieldIndex:n,fieldTypes:r,obsAdd:!1,obsRem:!1,obsDisable:!1,obsEnable:!1,trackDirty:!1});const h=De(o);return t!==void 0&&i.setComponentDebugName(h,t),h}componentLabel(e){const t=this.componentMetas[e]?.name;return t!==void 0?`'${t}' (component ${e})`:`component ${e}`}fieldIdOf(e,t){const s=e.id,r=this.componentMetas[s];if(r===void 0)throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,`field_id_of: component ${s} is not registered`);const n=r.fieldIndex[t];if(n===void 0)throw new i.ECSError(i.ECS_ERROR.FIELD_NOT_REGISTERED,`field_id_of: component ${s} has no field "${t}"`);return n}registerSparseComponent(e,t){const s=Object.keys(e),r=new Array(s.length);for(let n=0;n<s.length;n++)r[n]=e[s[n]];return this._rejectNonDeterministicFields(s,r,"sparse component"),this._pushSparseStore(s,r,t)}sparseLabel(e){const t=this.sparseNames[e];return t!==void 0?`'${t}' (sparse component ${e})`:`sparse component ${e}`}_pushSparseStore(e,t,s){const r=this.sparseStores.length;return this.sparseStores.push(new i.SparseComponentStore(e,t)),this.sparseNames.push(s),i.unsafeCast(r)}sparseStoreOf(e){const t=e,s=this.sparseStores[t];if(s===void 0)throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,`sparse component ${t} is not registered`);return s}addSparse(e,t,s){if(!this.isAlive(e))throw i.entityNotAliveError("addSparse",e,this.sparseLabel(t));this.sparseStoreOf(t).setRow(i.getEntityIndex(e),s??i.EMPTY_VALUES)}removeSparse(e,t){if(!this.isAlive(e))throw i.entityNotAliveError("removeSparse",e,this.sparseLabel(t));this.sparseStoreOf(t).remove(i.getEntityIndex(e))}hasSparse(e,t){return this.isAlive(e)?this.sparseStoreOf(t).has(i.getEntityIndex(e)):!1}getSparseField(e,t,s){if(!this.isAlive(e))throw i.entityNotAliveError("getSparseField",e,`${this.sparseLabel(t)}.${s}`);const r=this.sparseStoreOf(t),n=r.fieldIndex[s];if(n===void 0)throw new i.ECSError(i.ECS_ERROR.FIELD_NOT_REGISTERED,`sparse component has no field "${s}"`);const o=r.getField(i.getEntityIndex(e),n);if(o===void 0)throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,"entity does not hold this sparse component");return o}setSparseField(e,t,s,r){if(!this.isAlive(e))throw i.entityNotAliveError("setSparseField",e,`${this.sparseLabel(t)}.${s}`);const n=this.sparseStoreOf(t),o=n.fieldIndex[s];if(o===void 0)throw new i.ECSError(i.ECS_ERROR.FIELD_NOT_REGISTERED,`sparse component has no field "${s}"`);if(!n.setField(i.getEntityIndex(e),o,r))throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,"entity does not hold this sparse component")}_purgeSparse(e){const t=this.sparseStores;for(let s=0;s<t.length;s++)t[s].remove(e)}snapshotSparse(){return this._requireDeterministic("snapshot_sparse()"),this._snapshots.snapshotSparse()}restoreSparse(e){this._requireDeterministic("restore_sparse()"),this._snapshots.restoreSparse(e)}snapshot(){return this._requireDeterministic("snapshot()"),this._snapshots.snapshot()}restoreInto(e){this._requireDeterministic("restoreInto()"),this._snapshots.restoreInto(e)}_mountRestoredDense(e){this._columnStore=e;const t=this.archGraph.archetypes;for(let s=0;s<t.length;s++)t[s].isBufferBacked&&t[s].refreshViews(this._columnStore);this.entityAllocator.setHighWater(e.view.getUint32(e.header.entityIndexOff+i.ENTITY_INDEX_HEADER_OFFSETS.length,!0)),this._handleBufferResized()}_reconstructHostRows(e){const t=this.entityAllocator.highWater,s=this.entityArchetype,r=this.entityRow,n=this.entityAllocator.generations,o=new Map;for(let h=0;h<t;h++){const a=s[h];if(a===i.UNASSIGNED)continue;const l=r[h];if(l===i.UNASSIGNED)continue;let u=o.get(a);u===void 0&&(u=[],o.set(a,u)),u[l]=i.createEntityId(h,n[h])}for(let h=0;h<e.archetypeRows.length;h++){const a=e.archetypeRows[h],l=this.archGet(a.archetypeId),u=o.get(a.archetypeId)??[];{if(u.length!==a.length)throw new O(`archetype ${a.archetypeId} row-count mismatch on restore: scan found ${u.length} rows, host-state recorded ${a.length}`);for(let d=0;d<u.length;d++)if(u[d]===void 0)throw new O(`archetype ${a.archetypeId} has a hole at row ${d} after restore (entity-index region inconsistent)`)}l.restoreHostRows(u,a.enabledCount)}}registerRelation(e){return this.relationService.registerRelation(e)}get relationCount(){return this.relationService.count}addRelation(e,t,s){this.relationService.addRelation(e,t,s)}removeRelation(e,t,s){this.relationService.removeRelation(e,t,s)}targetOf(e,t){return this.relationService.targetOf(e,t)}targetsOf(e,t){return this.relationService.targetsOf(e,t)}sourcesOf(e,t){return this.relationService.sourcesOf(e,t)}hasRelation(e,t){return this.relationService.hasRelation(e,t)}pairsOf(e){return this.relationService.pairsOf(e)}sourcesOfAny(e){return this.relationService.sourcesOfAny(e)}relationBackingSparseId(e){return this.relationService.relationBackingSparseId(e)}_forEachRelationTargetMatch(e,t,s,r,n,o,h,a){this.relationService.forEachRelationTargetMatch(e,t,s,r,n,o,h,a)}compactRelations(){return this.relationService.compactRelations()}ancestorsOf(e,t){return this.relationService.ancestorsOf(e,t)}rootOf(e,t){return this.relationService.rootOf(e,t)}cascadeOf(e,t){return this.relationService.cascadeOf(e,t)}_forEachSparseMatch(e,t,s,r,n,o,h,a){const l=this.sparseStores;{for(let d=0;d<r.length;d++)if(l[r[d]]===void 0)throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,`sparse component ${r[d]} is not registered`);for(let d=0;d<n.length;d++)if(l[n[d]]===void 0)throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,`sparse component ${n[d]} is not registered`)}if(r.length>0){let d=l[r[0]];for(let _=1;_<r.length;_++){const m=l[r[_]];m.size<d.size&&(d=m)}const f=d.indices,p=this.entityAllocator.generations,g=this.entityArchetype,E=this.entityRow,y=this.archGraph.archetypes;for(let _=0;_<f.length;_++){const m=f[_];let S=!0;for(let w=0;w<r.length;w++){const k=l[r[w]];if(k!==d&&!k.has(m)){S=!1;break}}if(!S)continue;for(let w=0;w<n.length;w++)if(l[n[w]].has(m)){S=!1;break}if(!S)continue;const v=g[m];if(v===i.UNASSIGNED)continue;const R=y[v],C=R.mask;if(C.contains(e)&&!(t!==null&&C.overlaps(t))&&!(s!==null&&!C.overlaps(s))){if(!a){const w=E[m];if(w!==i.UNASSIGNED&&w>=R.enabledCount)continue}h(i.createEntityId(m,p[m]))}}return}const u=n.length>0;for(let d=0;d<o.length;d++){const f=o[d],p=f.entityIds,g=a?f.totalCount:f.enabledCount;for(let E=0;E<g;E++){const y=p[E];if(u){const _=i.getEntityIndex(y);let m=!1;for(let S=0;S<n.length;S++)if(l[n[S]].has(_)){m=!0;break}if(m)continue}h(y)}}}_forEachHierarchyMatch(e,t,s,r,n,o,h,a,l,u){this.relationService.forEachHierarchyMatch(e,t,s,r,n,o,h,a,l,u)}addComponent(e,t,s){if(!this.isAlive(e))throw i.entityNotAliveError("addComponent",e,this.componentLabel(t.id));const r=i.getEntityIndex(e),n=this.entityArchetype[r],o=this.archGet(n);if(o.hasComponent(t.id)){o.writeFields(this.entityRow[r],t.id,s,this._tick);return}const h=this.archResolveAdd(n,t.id),a=this.archGet(h),l=this.entityRow[r];let u;if(l!==i.UNASSIGNED){const d=o.length,f=a.length,p=a.enabledCount,g=o.getEdge(t.id);!a.hasColumns&&!o.hasColumns?a.moveEntityFromTag(o,l,e,this.entityRow):a.moveEntityFrom(o,l,e,g.addMap,this._tick,this.entityRow),u=A[0],this._onArchLenChange(o,d),this._onArchGrow(a,f,p)}else{const d=a.length,f=a.enabledCount;u=a.hasColumns?a.addEntity(e,this.entityRow):a.addEntityTag(e,this.entityRow),this._onArchGrow(a,d,f)}a.writeFields(u,t.id,s,this._tick),this.entityArchetype[r]=h,this.entityRow[r]=u}addComponents(e,t){if(!this.isAlive(e))throw i.entityNotAliveError("addComponents",e);const s=i.getEntityIndex(e),r=this.entityArchetype[s],n=this.archGet(r),o=t.length;let h=o;for(let f=0;f<o;f++){const p=t[f].def.id;if(p>=Re-1||o>bt){h=se;break}h=h*Re+(p+1)}if(h!==se){const f=n.getCompositeAddEdge(h);if(f!==void 0){this._addComponentsInto(e,s,n,this.archGet(f.target),f.target,f.map,t);return}}let a=null;for(let f=0;f<o;f++){const p=t[f].def.id;a!==null?a.set(p):n.mask.has(p)||(a=n.mask.copyInto(this._scratchTargetMask),a.set(p))}if(a===null){const f=this.entityRow[s];for(let p=0;p<o;p++)n.writeFields(f,t[p].def.id,t[p].values??i.EMPTY_VALUES,this._tick);return}const l=this.archGetOrCreateFromMask(a),u=this.archGet(l),d=n.getBatchTransitionMap(u);h!==se&&n.cacheCompositeAddEdge(h,l,d),this._addComponentsInto(e,s,n,u,l,d,t)}_addComponentsInto(e,t,s,r,n,o,h){const a=this.entityRow[t];let l;if(a!==i.UNASSIGNED){const u=s.length,d=r.length,f=r.enabledCount;r.moveEntityFrom(s,a,e,o,this._tick,this.entityRow),l=A[0],this._onArchLenChange(s,u),this._onArchGrow(r,d,f)}else{const u=r.length,d=r.enabledCount;l=r.addEntity(e,this.entityRow),this._onArchGrow(r,u,d)}for(let u=0;u<h.length;u++)r.writeFields(l,h[u].def.id,h[u].values??i.EMPTY_VALUES,this._tick);this.entityArchetype[t]=n,this.entityRow[t]=l}removeComponent(e,t){if(!this.isAlive(e))throw i.entityNotAliveError("removeComponent",e,this.componentLabel(t.id));const s=i.getEntityIndex(e),r=this.entityArchetype[s],n=this.archGet(r);if(!n.hasComponent(t.id))return;const o=this.archResolveRemove(r,t.id),h=this.archGet(o),a=this.entityRow[s],l=n.getEdge(t.id),u=!h.hasColumns&&!n.hasColumns,d=n.length,f=h.length,p=h.enabledCount;u?h.moveEntityFromTag(n,a,e,this.entityRow):h.moveEntityFrom(n,a,e,l.removeMap,this._tick,this.entityRow),this.entityArchetype[s]=o,this.entityRow[s]=A[0],this._onArchLenChange(n,d),this._onArchGrow(h,f,p)}removeComponents(e,t){if(!this.isAlive(e))throw i.entityNotAliveError("removeComponents",e);const s=i.getEntityIndex(e),r=this.entityArchetype[s],n=this.archGet(r);let o=null;for(let g=0;g<t.length;g++){const E=t[g].id;o!==null?o.clear(E):n.mask.has(E)&&(o=n.mask.copyInto(this._scratchTargetMask),o.clear(E))}if(o===null)return;const h=this.archGetOrCreateFromMask(o),a=this.archGet(h),l=this.entityRow[s],u=n.length,d=a.length,f=a.enabledCount,p=n.getBatchTransitionMap(a);a.moveEntityFrom(n,l,e,p,this._tick,this.entityRow),this.entityArchetype[s]=h,this.entityRow[s]=A[0],this._onArchLenChange(n,u),this._onArchGrow(a,d,f)}hasComponent(e,t){if(!this.isAlive(e))return!1;const s=i.getEntityIndex(e);return this.archGet(this.entityArchetype[s]).hasComponent(t.id)}batchAddComponent(e,t,s){const r=this.archGet(e);if(r.length===0)return;const n=t.id;if(r.mask.has(n))return;const o=this.archResolveAdd(r.id,n),h=this.archGet(o);if(r.disabledCount>0||h.disabledCount>0)throw new i.ECSError(i.ECS_ERROR.PARTITION_BULK_INTO_DISABLED,"batchAddComponent is unsupported on archetypes with disabled entities — enable them first or use per-entity addComponent");const a=r.getEdge(n),l=r.length,u=l,d=h.length,f=h.enabledCount,p=this.entityArchetype,g=this.entityRow,E=h.bulkMoveAllFrom(r,a.addMap,this._tick);for(let _=0;_<l;_++){const m=i.getEntityIndex(h.entityIds[E+_]);p[m]=o,g[m]=E+_}this.componentMetas[n].fieldNames.length>0&&s&&h.bulkWriteFields(E,l,n,s,this._tick),this._onArchLenChange(r,u),this._onArchGrow(h,d,f)}batchRemoveComponent(e,t){const s=this.archGet(e);if(s.length===0)return;const r=t.id;if(!s.mask.has(r))return;const n=this.archResolveRemove(s.id,r),o=this.archGet(n);if(s.disabledCount>0||o.disabledCount>0)throw new i.ECSError(i.ECS_ERROR.PARTITION_BULK_INTO_DISABLED,"batchRemoveComponent is unsupported on archetypes with disabled entities — enable them first or use per-entity removeComponent");const h=s.getEdge(r),a=s.length,l=a,u=this.entityArchetype,d=this.entityRow;if(!o.materializesRows){const E=s.entityIds;for(let y=0;y<a;y++){const _=i.getEntityIndex(E[y]);u[_]=n,d[_]=i.UNASSIGNED}s.clearRows(),this._onArchLenChange(s,l);return}const f=o.length,p=o.enabledCount,g=o.bulkMoveAllFrom(s,h.removeMap,this._tick);for(let E=0;E<a;E++){const y=i.getEntityIndex(o.entityIds[g+E]);u[y]=n,d[y]=g+E}this._onArchLenChange(s,l),this._onArchGrow(o,f,p)}getEntityArchetype(e){return this.archGet(this.entityArchetype[i.getEntityIndex(e)])}getEntityRow(e){return this.entityRow[i.getEntityIndex(e)]}getMatchingArchetypes(e,t,s){const r=e._words;let n=!1;for(let l=0;l<r.length;l++)if(r[l]!==0){n=!0;break}if(!n){const l=this.archGraph.archetypes,u=[];for(let d=0;d<l.length;d++){const f=l[d];(!t||!f.mask.overlaps(t))&&(!s||f.mask.overlaps(s))&&u.push(f)}return u}let o,h=!1;for(let l=0;l<r.length;l++){let u=r[l];if(u===0)continue;const d=l<<T.BITS_PER_WORD_SHIFT;for(;u!==0;){const f=u&-u>>>0,p=d+(T.BITS_PER_WORD_MASK-Math.clz32(f));u^=f;const g=this.archGraph.componentIndex[p];if(g===void 0||g.length===0){h=!0;break}(!o||g.length<o.length)&&(o=g)}if(h)break}if(h||!o)return[];const a=[];for(let l=0;l<o.length;l++){const u=this.archGet(o[l]);u.matches(e)&&(!t||!u.mask.overlaps(t))&&(!s||u.mask.overlaps(s))&&a.push(u)}return a}registerQuery(e,t,s){const r=this.getMatchingArchetypes(e,t,s);return this.registeredQueries.push({includeMask:e.copy(),excludeMask:t?t.copy():null,anyOfMask:s?s.copy():null,result:r,query:null}),r}updateQueryRef(e,t){const s=this.registeredQueries;for(let r=0;r<s.length;r++)if(s[r].result===e){s[r].query=t;return}}get archetypeCount(){return this.archGraph.archetypes.length}registerEvent(e){return this.events.registerEvent(e)}emitEvent(e,t){this.events.emitEvent(e,t)}emitSignal(e){this.events.emitSignal(e)}getEventReader(e){return this.events.getEventReader(e)}clearEvents(){this.events.clearEvents()}_devBufferedEventCount(){return this.events.devBufferedEventCount()}registerEventByKey(e,t){return this.events.registerEventByKey(e,t)}getEventDefByKey(e){return this.events.getEventDefByKey(e)}hasEventKey(e){return this.events.hasEventKey(e)}resources=new Qe;registerResource(e,t){this.resources.register(e,t)}getResource(e){return this.resources.get(e)}setResource(e,t){this.resources.set(e,t)}removeResource(e){this.resources.remove(e)}hasResource(e){return this.resources.has(e)}}class It{store;constructor(e){this.store=e}register(e){return this.store.registerRelation(e)}get count(){return this.store.relationCount}add(e,t,s){return this.store.addRelation(e,t,s),this}remove(e,t,s){return this.store.removeRelation(e,t,s),this}has(e,t){return this.store.hasRelation(e,t)}targetOf(e,t){return this.store.targetOf(e,t)}targetsOf(e,t){return this.store.targetsOf(e,t)}sourcesOf(e,t){return this.store.sourcesOf(e,t)}pairsOf(e){return this.store.pairsOf(e)}sourcesOfAny(e){return this.store.sourcesOfAny(e)}ancestorsOf(e,t){return this.store.ancestorsOf(e,t)}rootOf(e,t){return this.store.rootOf(e,t)}cascadeOf(e,t){return this.store.cascadeOf(e,t)}compact(){return this.store.compactRelations()}}class Tt{store;constructor(e){this.store=e}register(e,t){this.store.registerEventByKey(e,t)}registerSignal(e){this.store.registerEventByKey(e,[])}emit(e,t){i.dispatchTrace.isActive()&&i.dispatchTrace.recordEmit(e.description??"");const s=this.store.getEventDefByKey(e);t===void 0?this.store.emitSignal(s):this.store.emitEvent(s,t)}read(e){i.dispatchTrace.isActive()&&i.dispatchTrace.recordRead(e.description??"");const t=this.store.getEventDefByKey(e);return this.store.getEventReader(t)}}class Dt{store;constructor(e){this.store=e}register(e,t){i.dispatchTrace.isActive()&&i.dispatchTrace.recordResourceRegister(e.description??""),this.store.registerResource(e,t)}get(e){return i.accessCheck.checkResourceRead(e),i.dispatchTrace.isActive()&&i.dispatchTrace.recordResourceRead(e.description??""),i.unsafeCast(this.store.getResource(e))}set(e,t){i.accessCheck.checkResourceWrite(e),i.dispatchTrace.isActive()&&i.dispatchTrace.recordResourceWrite(e.description??""),this.store.setResource(e,t)}remove(e){i.accessCheck.checkResourceWrite(e),i.dispatchTrace.isActive()&&i.dispatchTrace.recordResourceRemove(e.description??""),this.store.removeResource(e)}has(e){return this.store.hasResource(e)}}class kt{store;constructor(e){this.store=e}get deterministic(){return this.store.deterministic}stateHash(){return this.store.stateHash()}capture(){return this.store.snapshot()}restore(e){this.store.restoreInto(e)}captureSparse(){return this.store.snapshotSparse()}restoreSparse(e){this.store.restoreSparse(e)}}const Ce=new WeakMap;function ce(c,e){let t=Ce.get(c);if(!t){t=Object.create(null);const{fieldNames:r}=c.layout;for(let n=0;n<r.length;n++){const o=c.columns[n];Object.defineProperty(t,r[n],{get(){return o.buf[this._row]},set(h){o.buf[this._row]=h},enumerable:!0,configurable:!1})}Ce.set(c,t)}const s=Object.create(t);return s._row=e,s}class Nt{dedup=new Map;andSingle=new Map;notSingle=new Map;anyOfSingle=new Map;changedSingle=new Map;optionalSingle=new Map;withSparseSingle=new Map;withoutSparseSingle=new Map;withRelationSingle=new Map;withoutRelationSingle=new Map;includeDisabledSingle=new Map;hierarchySingle=new Map;findDedup(e,t,s,r){const n=this.dedup.get(e);if(n)for(let o=0;o<n.length;o++){const h=n[o];if(!(!h.includeMask.equals(t)||!(s===null?h.excludeMask===null:h.excludeMask!==null&&h.excludeMask.equals(s))||!(r===null?h.anyOfMask===null:h.anyOfMask!==null&&h.anyOfMask.equals(r))))return h}}addDedup(e,t){Le(this.dedup,e,t)}}const ve=Object.freeze([]),xt=Object.freeze([]),Oe=Object.freeze([]),Z=Number.POSITIVE_INFINITY,re=65536;function q(c,e){if(c>=re||e>=re)throw new i.ECSError(i.ECS_ERROR.SPARSE_CACHE_KEY_OVERFLOW,`sparse query cache key would overflow: query_id=${c}, sparse_id=${e} (each must be < ${re})`);return(c<<16|e)>>>0}function Q(c,e){for(let t=0;t<c.length;t++)if(c[t]===e)return c;return[...c,e]}function Mt(c,e){for(let t=0;t<c.length;t++)if(c[t]===e)return c;return[...c,e]}function be(c,e){for(let t=0;t<c.length;t++)if(c[t]===e)return c;return[...c,e]}class Fe{_arch;_tick=0;mut(e){return this._arch.columnGroupMut(e,this._tick)}read(e){return this._arch.columnGroupRead(e)}}class D{_archetypes;_defs;_resolver;_include;_exclude;_anyOf;_nonEmptyArchetypes=[];_lastSeenEpoch=-1;_id;_sparseInclude;_sparseExclude;_optional;_includeDisabled;_relationIncludes;_relationExcludes;_hierarchy;constructor(e,t,s,r,n,o,h,a=ve,l=ve,u=xt,d=!1,f=Oe,p=Oe,g=null){this._archetypes=e,this._defs=t,this._resolver=s,this._include=r,this._exclude=n,this._anyOf=o,this._id=h,this._sparseInclude=a,this._sparseExclude=l,this._optional=u,this._includeDisabled=d,this._relationIncludes=f,this._relationExcludes=p,this._hierarchy=g}_assertDenseOnly(e){if(this._sparseInclude.length>0||this._sparseExclude.length>0||this._relationIncludes.length>0||this._relationExcludes.length>0||this._hierarchy!==null)throw new i.ECSError(i.ECS_ERROR.SPARSE_QUERY_DENSE_PATH,`Query.${e} ignores sparse / relation-wildcard / hierarchy terms (withSparse / withoutSparse / withRelation / withoutRelation / hierarchy) — it walks only the dense archetype list and would return the wrong result (a hierarchy term has no per-archetype span — its order spans archetypes). Iterate this query with forEachEntity instead.`)}_isDenseOnly(){return this._sparseInclude.length===0&&this._sparseExclude.length===0&&this._relationIncludes.length===0&&this._relationExcludes.length===0&&this._hierarchy===null}firstEntity(){if(this._isDenseOnly()){const t=this._nonEmpty();for(let s=0;s<t.length;s++)if((this._includeDisabled?t[s].totalCount:t[s].enabledCount)>0)return t[s].entityIds[0];return}let e;return this.forEachEntity(t=>{e===void 0&&(e=t)}),e}singleEntity(){{const e=this._isDenseOnly()?this.entityCount:this._countViaWalk();if(e!==1)throw new i.ECSError(i.ECS_ERROR.QUERY_NOT_SINGLETON,`Query.singleEntity: expected exactly 1 matching entity, found ${e}`,{count:e})}return this.firstEntity()}_countViaWalk(){let e=0;return this.forEachEntity(()=>{e++}),e}get archetypeCount(){return this._assertDenseOnly("archetypeCount"),this._archetypes.length}get entityCount(){this._assertDenseOnly("entityCount");const e=this._nonEmpty();let t=0;if(this._includeDisabled)for(let s=0;s<e.length;s++)t+=e[s].totalCount;else for(let s=0;s<e.length;s++)t+=e[s].enabledCount;return t}get archetypes(){return this._archetypes}_carryNondense(e){return this._optional.length===0&&this._sparseInclude.length===0&&this._sparseExclude.length===0&&!this._includeDisabled&&this._relationIncludes.length===0&&this._relationExcludes.length===0&&this._hierarchy===null?e:new D(e._archetypes,e._defs,this._resolver,e._include,e._exclude,e._anyOf,this._resolver._nextQueryId(),this._sparseInclude,this._sparseExclude,this._optional,this._includeDisabled,this._relationIncludes,this._relationExcludes,this._hierarchy)}and(...e){if(e.length===1){const s=e[0].id,r=(this._id<<16|s)>>>0,n=this._resolver._caches.andSingle.get(r);return n!==void 0?n:this._andMiss(e[0],s,r)}let t=this;for(let s=0;s<e.length;s++)t=t.and(e[s]);return t}_andMiss(e,t,s){const r=this._include.copy(),n=this._defs.slice();r.has(t)||(r.set(t),n.push(e));const o=this._carryNondense(this._resolver._resolveQuery(r,this._exclude,this._anyOf,n));return this._resolver._caches.andSingle.set(s,o),o}without(...e){if(e.length===1){const s=e[0].id,r=(this._id<<16|s)>>>0,n=this._resolver._caches.notSingle.get(r);return n!==void 0?n:this._notMiss(s,r)}let t=this;for(let s=0;s<e.length;s++)t=t.without(e[s]);return t}_notMiss(e,t){const s=this._exclude?this._exclude.copy():new T.BitSet;s.set(e);const r=this._carryNondense(this._resolver._resolveQuery(this._include,s,this._anyOf,this._defs));return this._resolver._caches.notSingle.set(t,r),r}withSparse(...e){if(e.length===1)return this._withSparseOne(e[0]);let t=this;for(let s=0;s<e.length;s++)t=t._withSparseOne(e[s]);return t}_withSparseOne(e){const t=q(this._id,e),s=this._resolver._caches.withSparseSingle,r=s.get(t);if(r!==void 0)return r;const n=this._deriveSparse(Q(this._sparseInclude,e),this._sparseExclude);return s.set(t,n),n}withoutSparse(...e){if(e.length===1)return this._withoutSparseOne(e[0]);let t=this;for(let s=0;s<e.length;s++)t=t._withoutSparseOne(e[s]);return t}_withoutSparseOne(e){const t=q(this._id,e),s=this._resolver._caches.withoutSparseSingle,r=s.get(t);if(r!==void 0)return r;const n=this._deriveSparse(this._sparseInclude,Q(this._sparseExclude,e));return s.set(t,n),n}_deriveSparse(e,t){return new D(this._archetypes,this._defs,this._resolver,this._include,this._exclude,this._anyOf,this._resolver._nextQueryId(),e,t,this._optional,this._includeDisabled,this._relationIncludes,this._relationExcludes,this._hierarchy)}withRelation(...e){if(e.length===1)return this._withRelationOne(e[0]);let t=this;for(let s=0;s<e.length;s++)t=t._withRelationOne(e[s]);return t}_withRelationOne(e){const t=q(this._id,e),s=this._resolver._caches.withRelationSingle,r=s.get(t);if(r!==void 0)return r;const n=this._resolver._relationBackingSparseId(e),o=this._deriveRelation(Q(this._sparseInclude,n),this._sparseExclude,be(this._relationIncludes,e),this._relationExcludes);return s.set(t,o),o}withoutRelation(...e){if(e.length===1)return this._withoutRelationOne(e[0]);let t=this;for(let s=0;s<e.length;s++)t=t._withoutRelationOne(e[s]);return t}_withoutRelationOne(e){const t=q(this._id,e),s=this._resolver._caches.withoutRelationSingle,r=s.get(t);if(r!==void 0)return r;const n=this._resolver._relationBackingSparseId(e),o=this._deriveRelation(this._sparseInclude,Q(this._sparseExclude,n),this._relationIncludes,be(this._relationExcludes,e));return s.set(t,o),o}_deriveRelation(e,t,s,r){return new D(this._archetypes,this._defs,this._resolver,this._include,this._exclude,this._anyOf,this._resolver._nextQueryId(),e,t,this._optional,this._includeDisabled,s,r,this._hierarchy)}hierarchy(e,t=Z){{if(this._hierarchy!==null)throw new i.ECSError(i.ECS_ERROR.HIERARCHY_ALREADY_SET,"hierarchy() is already set on this query — a query carries a single depth ordering");if(t!==Z&&(!Number.isInteger(t)||t<0))throw new i.ECSError(i.ECS_ERROR.HIERARCHY_INVALID_MAX_DEPTH,`hierarchy() max_depth must be HIERARCHY_UNBOUNDED or a non-negative integer, got ${t}`)}if(t===Z){const s=q(this._id,e),r=this._resolver._caches.hierarchySingle,n=r.get(s);if(n!==void 0)return n;const o=this._deriveHierarchy({relation:e,maxDepth:t});return r.set(s,o),o}return this._deriveHierarchy({relation:e,maxDepth:t})}_deriveHierarchy(e){return new D(this._archetypes,this._defs,this._resolver,this._include,this._exclude,this._anyOf,this._resolver._nextQueryId(),this._sparseInclude,this._sparseExclude,this._optional,this._includeDisabled,this._relationIncludes,this._relationExcludes,e)}_checkRelationAccess(){for(let e=0;e<this._relationIncludes.length;e++)i.accessCheck.checkRelationRead(this._relationIncludes[e]);for(let e=0;e<this._relationExcludes.length;e++)i.accessCheck.checkRelationRead(this._relationExcludes[e])}forEachRelatedTo(e,t){i.accessCheck.checkRelationReadAny(),this._checkRelationAccess(),this._resolver._forEachRelationTargetMatch(e,this._include,this._exclude,this._anyOf,this._sparseInclude,this._sparseExclude,this._includeDisabled,t)}optional(...e){if(e.length===1)return this._optionalOne(e[0].id);let t=this;for(let s=0;s<e.length;s++)t=t._optionalOne(e[s].id);return t}_optionalOne(e){const t=(this._id<<16|e)>>>0,s=this._resolver._caches.optionalSingle,r=s.get(t);if(r!==void 0)return r;const n=this._deriveOptional(Mt(this._optional,e));return s.set(t,n),n}_deriveOptional(e){return new D(this._archetypes,this._defs,this._resolver,this._include,this._exclude,this._anyOf,this._resolver._nextQueryId(),this._sparseInclude,this._sparseExclude,e,this._includeDisabled,this._relationIncludes,this._relationExcludes,this._hierarchy)}includeDisabled(){if(this._includeDisabled)return this;const e=this._resolver._caches.includeDisabledSingle,t=e.get(this._id);if(t!==void 0)return t;const s=new D(this._archetypes,this._defs,this._resolver,this._include,this._exclude,this._anyOf,this._resolver._nextQueryId(),this._sparseInclude,this._sparseExclude,this._optional,!0,this._relationIncludes,this._relationExcludes,this._hierarchy);return e.set(this._id,s),s}forEach(e){if(this._includeDisabled){this._forEachIncludeDisabled(e);return}{this._assertDenseOnly("forEach"),i.accessCheck.enterOptionalScope(this._optional);try{const t=this._nonEmpty();for(let s=0;s<t.length;s++){const r=t[s];r._iterDepth++;try{e(r)}finally{r._iterDepth--}}}finally{i.accessCheck.leaveOptionalScope()}return}}_forEachIncludeDisabled(e){const t=N(!0);try{this._forEachInner(e)}finally{N(t)}}eachChunk(e){if(this._includeDisabled){const t=N(!0);try{this._eachChunkInner(e)}finally{N(t)}return}this._eachChunkInner(e)}_eachChunkInner(e){const t=new Fe;t._tick=this._resolver._getCurrentTick();{this._assertDenseOnly("eachChunk"),i.accessCheck.enterOptionalScope(this._optional);try{const s=this._nonEmpty();for(let r=0;r<s.length;r++){const n=s[r];t._arch=n,n._iterDepth++;try{e(t,n.entityCount)}finally{n._iterDepth--}}}finally{i.accessCheck.leaveOptionalScope()}return}}forEachUntil(e){if(this._includeDisabled){const t=N(!0);try{return this._forEachUntilInner(e)}finally{N(t)}}return this._forEachUntilInner(e)}_forEachUntilInner(e){{this._assertDenseOnly("forEachUntil"),i.accessCheck.enterOptionalScope(this._optional);try{const s=this._nonEmpty();for(let r=0;r<s.length;r++){const n=s[r];n._iterDepth++;try{if(e(n))return!0}finally{n._iterDepth--}}return!1}finally{i.accessCheck.leaveOptionalScope()}}const t=this._nonEmpty();for(let s=0;s<t.length;s++)if(e(t[s]))return!0;return!1}_forEachInner(e){{this._assertDenseOnly("forEach"),i.accessCheck.enterOptionalScope(this._optional);try{const t=this._nonEmpty();for(let s=0;s<t.length;s++){const r=t[s];r._iterDepth++;try{e(r)}finally{r._iterDepth--}}}finally{i.accessCheck.leaveOptionalScope()}return}}forEachEntity(e){if(this._checkRelationAccess(),this._hierarchy!==null){i.accessCheck.checkRelationRead(this._hierarchy.relation),this._resolver._forEachHierarchyMatch(this._include,this._exclude,this._anyOf,this._sparseInclude,this._sparseExclude,this._nonEmpty(),this._hierarchy.relation,this._hierarchy.maxDepth,this._includeDisabled,e);return}this._resolver._forEachSparseMatch(this._include,this._exclude,this._anyOf,this._sparseInclude,this._sparseExclude,this._nonEmpty(),e,this._includeDisabled)}_nonEmpty(){const e=this._resolver._getQueryDirtyEpoch();return this._lastSeenEpoch!==e&&this._rebuildNonEmpty(e),this._nonEmptyArchetypes}_rebuildNonEmpty(e){const t=this._archetypes,s=[];if(this._includeDisabled)for(let r=0;r<t.length;r++)t[r].totalCount>0&&s.push(t[r]);else for(let r=0;r<t.length;r++)t[r].enabledCount>0&&s.push(t[r]);this._nonEmptyArchetypes=s,this._lastSeenEpoch=e}anyOf(...e){if(e.length===1){const s=e[0].id,r=(this._id<<16|s)>>>0,n=this._resolver._caches.anyOfSingle.get(r);return n!==void 0?n:this._anyOfMiss(s,r)}let t=this;for(let s=0;s<e.length;s++)t=t.anyOf(e[s]);return t}_anyOfMiss(e,t){const s=this._anyOf?this._anyOf.copy():new T.BitSet;s.set(e);const r=this._carryNondense(this._resolver._resolveQuery(this._include,this._exclude,s,this._defs));return this._resolver._caches.anyOfSingle.set(t,r),r}changed(...e){if(e.length===1){const s=e[0].id,r=(this._id<<16|s)>>>0,n=this._resolver._caches.changedSingle.get(r);return n!==void 0?n:this._changedMiss(s,r)}const t=new Array(e.length);for(let s=0;s<e.length;s++)t[s]=e[s].id;return new x(this,t)}_changedMiss(e,t){const s=new x(this,[e]);return this._resolver._caches.changedSingle.set(t,s),s}_ctxLastRunTick(){return this._resolver._getLastRunTick()}}class $e{constructor(e){this._resolver=e}with(...e){const t=new T.BitSet;for(let s=0;s<e.length;s++)t.set(e[s].id);return this._resolver._resolveQuery(t,null,null,e)}}class Be{constructor(e){this.store=e}spawn(...e){const t=this.store.createEntity();this.store._trace?.commandQueued("spawn",t,null);for(let s=0;s<e.length;s++){const r=G(e[s]);i.accessCheck.checkAdd(r),this.store.addComponentDeferred(t,r,P(e[s])),this.store._trace?.commandQueued("add",t,r.id)}return t}add(e,...t){if(t.length===2&&typeof t[0]=="function"&&t[1]!==null&&typeof t[1]=="object"&&typeof t[1].def!="function"){const s=t[0];return i.accessCheck.checkAdd(s),this.store.addComponentDeferred(e,s,t[1]),this.store._trace?.commandQueued("add",e,s.id),this}for(let s=0;s<t.length;s++){const r=t[s],n=G(r);i.accessCheck.checkAdd(n),this.store.addComponentDeferred(e,n,P(r)),this.store._trace?.commandQueued("add",e,n.id)}return this}remove(e,t){return i.accessCheck.checkRemove(t),this.store.removeComponentDeferred(e,t),this.store._trace?.commandQueued("remove",e,t.id),this}despawn(e){i.accessCheck.checkDestroy();const t=e;return this.store.destroyEntityDeferred(t),this.store._trace?.commandQueued("despawn",t,null),this}disable(e){return this.store.disableEntityDeferred(e),this.store._trace?.commandQueued("disable",e,null),this}enable(e){return this.store.enableEntityDeferred(e),this.store._trace?.commandQueued("enable",e,null),this}}class Ge{constructor(e){this.store=e,this.commands=new Be(e)}lastRunTick=0;commands;get ecsTick(){return this.store._tick}get _trace(){return this.store._trace}isAlive(e){return this.store.isAlive(e)}hasComponent(e,t){return this.store.hasComponent(e,t)}getField(e,t,s){if(i.accessCheck.checkRead(t),!this.store.isAlive(e))throw i.entityNotAliveError("ctx.getField",e,i.componentLabel(t));const r=this.store.getEntityArchetype(e),n=this.store.getEntityRow(e);return r.readField(n,t.id,s)}tryGetField(e,t,s){if(i.accessCheck.checkRead(t),!this.store.hasComponent(e,t))return;const r=this.store.getEntityArchetype(e),n=this.store.getEntityRow(e);return r.readField(n,t.id,s)}setField(e,t,s,r){if(!this.store.isAlive(e))throw i.entityNotAliveError("ctx.setField",e,i.componentLabel(t));const n=this.store.getEntityArchetype(e),o=this.store.getEntityRow(e),h=n.getColumn(t,s,this.store._tick);h[o]=r,this.store._anyDirtyTracked&&this.store._noteSet(t,e)}updateField(e,t,s,r){if(i.accessCheck.checkRead(t),!this.store.isAlive(e))throw i.entityNotAliveError("ctx.updateField",e,i.componentLabel(t));const n=this.store.getEntityArchetype(e),o=this.store.getEntityRow(e),h=r(n.readField(o,t.id,s)),a=n.getColumn(t,s,this.store._tick);return a[o]=h,this.store._anyDirtyTracked&&this.store._noteSet(t,e),h}markChanged(e,t){this.store._anyDirtyTracked&&this.store._noteSet(t,e)}ref(e,t){if(i.accessCheck.checkWrite(e),!this.store.isAlive(t))throw i.entityNotAliveError("ctx.ref",t,i.componentLabel(e));const s=this.store.getEntityArchetype(t),r=this.store.getEntityRow(t);if(s.columnGroups[e.id]===void 0)throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,`ctx.ref: ${i.componentLabel(e)} has no columns in this archetype — the entity doesn't hold it, or it is a tag (no fields to ref)`,{component:e.id,entity:t});return s._changedTick[e.id]=this.store._tick,ce(s.columnGroups[e.id],r)}refRead(e,t){if(i.accessCheck.checkRead(e),!this.store.isAlive(t))throw i.entityNotAliveError("ctx.refRead",t,i.componentLabel(e));const s=this.store.getEntityArchetype(t),r=this.store.getEntityRow(t);if(s.columnGroups[e.id]===void 0)throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,`ctx.refRead: ${i.componentLabel(e)} has no columns in this archetype — the entity doesn't hold it, or it is a tag (no fields to ref)`,{component:e.id,entity:t});return ce(s.columnGroups[e.id],r)}isDisabled(e){return this.store.isDisabled(e)}addSparse(e,t,...s){return i.accessCheck.checkSparseWrite(t),this.store.addSparse(e,t,s[0]),this}removeSparse(e,t){return i.accessCheck.checkSparseWrite(t),this.store.removeSparse(e,t),this}hasSparse(e,t){return this.store.hasSparse(e,t)}getSparseField(e,t,s){return i.accessCheck.checkSparseRead(t),this.store.getSparseField(e,t,s)}setSparseField(e,t,s,r){i.accessCheck.checkSparseWrite(t),this.store.setSparseField(e,t,s,r)}addRelation(e,t,s){return i.accessCheck.checkRelationWrite(t),this.store.addRelation(e,t,s),this}removeRelation(e,t,s){return i.accessCheck.checkRelationWrite(t),this.store.removeRelation(e,t,s),this}targetOf(e,t){return i.accessCheck.checkRelationRead(t),this.store.targetOf(e,t)}targetsOf(e,t){return i.accessCheck.checkRelationRead(t),this.store.targetsOf(e,t)}sourcesOf(e,t){return i.accessCheck.checkRelationRead(t),this.store.sourcesOf(e,t)}hasRelation(e,t){return this.store.hasRelation(e,t)}flush(){this.store.flushStructural(),this.store.flushDestroyed(),this.store.publishRowCountsToDescriptor()}emit(e,t){i.dispatchTrace.isActive()&&i.dispatchTrace.recordEmit(e.description??""),this.store._trace?.eventEmitted(e.description??"");const s=this.store.getEventDefByKey(e);t===void 0?this.store.emitSignal(s):this.store.emitEvent(s,t)}read(e){i.dispatchTrace.isActive()&&i.dispatchTrace.recordRead(e.description??"");const t=this.store.getEventDefByKey(e),s=this.store.getEventReader(t);return this.store._trace?.eventRead(e.description??"",s.length),s}getResource(e){return i.accessCheck.checkResourceRead(e),i.dispatchTrace.isActive()&&i.dispatchTrace.recordResourceRead(e.description??""),i.unsafeCast(this.store.getResource(e))}setResource(e,t){i.accessCheck.checkResourceWrite(e),i.dispatchTrace.isActive()&&i.dispatchTrace.recordResourceWrite(e.description??""),this.store.setResource(e,t)}removeResource(e){i.accessCheck.checkResourceWrite(e),i.dispatchTrace.isActive()&&i.dispatchTrace.recordResourceRemove(e.description??""),this.store.removeResource(e)}hasResource(e){return this.store.hasResource(e)}}class x{_query;_changedIds;constructor(e,t){this._query=e,this._changedIds=t;for(let s=0;s<t.length;s++)if(!e._include.has(t[s]))throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,`changed() component ${t[s]} is not in query's include mask`)}and(...e){return new x(this._query.and(...e),this._changedIds)}without(...e){return new x(this._query.without(...e),this._changedIds)}anyOf(...e){return new x(this._query.anyOf(...e),this._changedIds)}optional(...e){return new x(this._query.optional(...e),this._changedIds)}forEach(e){if(this._query._includeDisabled){this._forEachIncludeDisabled(e);return}const t=this._query._ctxLastRunTick(),s=this._query._nonEmpty(),r=this._changedIds;{i.accessCheck.enterOptionalScope(this._query._optional);try{for(let n=0;n<s.length;n++){const o=s[n];for(let h=0;h<r.length;h++)if(o._changedTick[r[h]]>=t){o._iterDepth++;try{e(o)}finally{o._iterDepth--}break}}}finally{i.accessCheck.leaveOptionalScope()}return}}_forEachIncludeDisabled(e){const t=N(!0);try{this._forEachInner(e)}finally{N(t)}}_forEachInner(e){const t=this._query._ctxLastRunTick(),s=this._query._nonEmpty(),r=this._changedIds;{i.accessCheck.enterOptionalScope(this._query._optional);try{for(let n=0;n<s.length;n++){const o=s[n];for(let h=0;h<r.length;h++)if(o._changedTick[r[h]]>=t){o._iterDepth++;try{e(o)}finally{o._iterDepth--}break}}}finally{i.accessCheck.leaveOptionalScope()}return}}}const Ae=new Set(["fixedTimestep","maxFixedSteps","onWarn","memory","regions","bindingsRegionBytes","deterministic"]);function Ie(c){if(!(c>0)||!Number.isFinite(c))throw new i.ECSError(i.ECS_ERROR.INVALID_FIXED_TIMESTEP,`fixedTimestep must be a finite number > 0, got ${c}`);return c}function Lt(c){if(!Number.isInteger(c)||c<1)throw new i.ECSError(i.ECS_ERROR.INVALID_MAX_FIXED_STEPS,`maxFixedSteps must be an integer >= 1, got ${c}`);return c}class Ft{store;schedule;ctx;_observers;relations;events;resources;snapshots;systems=new Set;nextSystemId=0;_tick=0;_updating=!1;_fixedTimestep;_accumulator=0;_maxFixedSteps;scratchMask=new T.BitSet;_nextQueryIdCounter=0;_caches=new Nt;_layoutSubscribers=[];_backend=null;_memory;get memoryPlan(){return this._memory}get wasmMemory(){return this._memory.wasmMemory}constructor(e){const t=Object.prototype.hasOwnProperty;if(e!==void 0&&(t.call(e,"initial_capacity")||t.call(e,"buffer_allocator")))throw new i.ECSError(i.ECS_ERROR.INVALID_MEMORY_OPTIONS,"ECSOptions.initial_capacity / buffer_allocator were replaced by ECSOptions.memory: initial_capacity → memory.columnCapacity (or memory.budget); buffer_allocator → memory.wasm (WASM-backed) or memory.allocator (custom in-place).");if(e!==void 0)for(const r of Object.keys(e))Ae.has(r)||(e.onWarn??console.warn)(`ECSOptions: unknown option '${r}' ignored — known options: ${[...Ae].join(", ")}`);const s=i.resolveECSMemory(e?.memory);this._memory=s,this.store=new At({initialCapacity:s.columnCapacity,bufferAllocator:s.allocator,entityIndexCapacity:s.entityIndexCapacity,capContext:{capBytes:s.capBytes,intentLabel:s.intentLabel,budgetEntities:s.budgetEntities},onBufferResized:()=>{const r=this._layoutSubscribers;for(let n=0;n<r.length;n++)r[n].setLayout(0)},regions:e?.regions,bindingsRegionBytes:e?.bindingsRegionBytes,deterministic:e?.deterministic}),this.schedule=new i.Schedule(e?.onWarn),this.relations=new It(this.store),this.events=new Tt(this.store),this.resources=new Dt(this.store),this.snapshots=new kt(this.store),this.ctx=new Ge(this.store),this._observers=new nt(this.store,this.ctx),this.store.setStructuralObserverHook(r=>this._observers.dispatchStructural(r)),this._fixedTimestep=Ie(e?.fixedTimestep??i.DEFAULT_FIXED_TIMESTEP),this._maxFixedSteps=Lt(e?.maxFixedSteps??i.DEFAULT_MAX_FIXED_STEPS)}regionHandles(...e){const t=new Array(e.length);let s=null;for(let r=0;r<e.length;r++){const n=this.store.regionHandle(e[r]);n===null?(s??=[]).push(e[r]):t[r]=n}if(s!==null)throw new i.ECSError(i.ECS_ERROR.REGION_NOT_DECLARED,`region_handles: region id(s) [${s.join(", ")}] not declared — pass them via ECSOptions.regions`);return t}onStoreLayoutPublished(e){return this._layoutSubscribers.push(e),e.setLayout(0),()=>{const t=this._layoutSubscribers.indexOf(e);t>=0&&this._layoutSubscribers.splice(t,1)}}attachBackend(e){if(this._backend!==null)throw new i.ECSError(i.ECS_ERROR.BACKEND_ALREADY_ATTACHED,"A ComputeBackend is already attached; detach it before attaching another (one backend per ECS).");this._backend=e,this.schedule.setBackend(e);const t=this.onStoreLayoutPublished(e);return()=>{t(),this._backend===e&&(this._backend=null,this.schedule.setBackend(null))}}get fixedTimestep(){return this._fixedTimestep}set fixedTimestep(e){this._fixedTimestep=Ie(e)}get fixedAlpha(){return this._accumulator/this._fixedTimestep}setTrace(e){this.store._trace=e}registerComponent(e,t,s){if(Array.isArray(e)){const n=typeof t=="string"?t:"f64",o=Object.create(null);for(const h of e)o[h]=n;return this.store.registerComponent(o,s?.name)}const r=typeof t=="object"?t:s;return this.store.registerComponent(e,r?.name)}registerSparseComponent(e,t,s){if(Array.isArray(e)){const n=typeof t=="string"?t:"f64",o=Object.create(null);for(const h of e)o[h]=n;return this.store.registerSparseComponent(o,s?.name)}const r=typeof t=="object"?t:s;return this.store.registerSparseComponent(e,r?.name)}spawn(e,t){return this._assertHostMutationOutsideSystem("spawn","ctx.commands.spawn (deferred to the phase flush)"),e===void 0?this.store.createEntity():this.store.spawn(e,t)}spawnBundle(...e){this._assertHostMutationOutsideSystem("spawnBundle","ctx.commands.spawn (deferred to the phase flush)");const t=this.store.createEntity();for(let s=0;s<e.length;s++){const r=e[s],n=G(r);i.accessCheck.checkAdd(n),this.store.addComponent(t,n,P(r))}return t}spawnMany(e,t,s){return this._assertHostMutationOutsideSystem("spawnMany","ctx.commands.spawn (deferred to the phase flush)"),this.store.spawnMany(e,t,s)}_assertHostMutationOutsideSystem(e,t){if(this._updating&&i.accessCheck.current()!==null){const s=i.accessCheck.current(),r=s.name??`system_${s.id}`;throw new i.ECSError(i.ECS_ERROR.ACCESS_UNDECLARED,`ecs.${e} called from inside system '${r}' — host ${e} is immediate and unsafe mid-iteration (and invisible to observers); use ${t} instead`,{op:e})}}despawn(e){return this._assertHostMutationOutsideSystem("despawn","ctx.commands.despawn (deferred to the phase flush)"),this.store.destroyEntity(e),this}disable(e){return this._assertHostMutationOutsideSystem("disable","ctx.commands.disable (deferred to the phase flush)"),this.store.disableEntity(e),this}enable(e){return this._assertHostMutationOutsideSystem("enable","ctx.commands.enable (deferred to the phase flush)"),this.store.enableEntity(e),this}addComponent(e,t,s){const r=G(t);return this._assertHostMutationOutsideSystem("addComponent","ctx.commands.add (deferred to the phase flush)"),i.accessCheck.checkAdd(r),this.store.addComponent(e,r,s??P(t)),this}addComponents(e,...t){const s=[];for(let r=0;r<t.length;r++){const n=t[r];s.push({def:G(n),values:P(n)})}{this._assertHostMutationOutsideSystem("addComponents","ctx.commands.add (deferred to the phase flush)");for(let r=0;r<s.length;r++)i.accessCheck.checkAdd(s[r].def)}return this.store.addComponents(e,s),this}removeComponent(e,t){return this._assertHostMutationOutsideSystem("removeComponent","ctx.commands.remove (deferred to the phase flush)"),i.accessCheck.checkRemove(t),this.store.removeComponent(e,t),this}removeComponents(e,...t){{this._assertHostMutationOutsideSystem("removeComponents","ctx.commands.remove (deferred to the phase flush)");for(let s=0;s<t.length;s++)i.accessCheck.checkRemove(t[s])}return this.store.removeComponents(e,t),this}batchAddComponent(e,t,s){return this._assertHostMutationOutsideSystem("batchAddComponent","ctx.commands.add per entity, or the batch after update() returns"),i.accessCheck.checkAdd(t),this.store.batchAddComponent(e,t,s),this}batchRemoveComponent(e,t){return this._assertHostMutationOutsideSystem("batchRemoveComponent","ctx.commands.remove per entity, or the batch after update() returns"),i.accessCheck.checkRemove(t),this.store.batchRemoveComponent(e,t),this}getField(e,t,s){if(i.accessCheck.checkRead(t),!this.store.isAlive(e))throw i.entityNotAliveError("getField",e,i.componentLabel(t));const r=this.store.getEntityArchetype(e),n=this.store.getEntityRow(e);return r.readField(n,t.id,s)}refRead(e,t){if(i.accessCheck.checkRead(e),!this.store.isAlive(t))throw i.entityNotAliveError("refRead",t,i.componentLabel(e));const s=this.store.getEntityArchetype(t),r=this.store.getEntityRow(t);if(s.columnGroups[e.id]===void 0)throw new i.ECSError(i.ECS_ERROR.COMPONENT_NOT_REGISTERED,`refRead: ${i.componentLabel(e)} has no columns in this archetype — the entity doesn't hold it, or it is a tag (no fields to ref)`,{component:e.id,entity:t});return ce(s.columnGroups[e.id],r)}tryGetField(e,t,s){if(i.accessCheck.checkRead(t),!this.store.hasComponent(e,t))return;const r=this.store.getEntityArchetype(e),n=this.store.getEntityRow(e);return r.readField(n,t.id,s)}setField(e,t,s,r){if(!this.store.isAlive(e))throw i.entityNotAliveError("setField",e,i.componentLabel(t));const n=this.store.getEntityArchetype(e),o=this.store.getEntityRow(e),h=n.getColumn(t,s,this.store._tick);h[o]=r,this.store._anyDirtyTracked&&this.store._noteSet(t,e)}updateField(e,t,s,r){const n=r(this.getField(e,t,s));return this.setField(e,t,s,n),n}query(...e){const t=this.scratchMask;t._words.fill(0);for(let s=0;s<e.length;s++)t.set(e[s].id);return this._resolveQuery(t.copy(),null,null,e)}_nextQueryId(){return this._nextQueryIdCounter++}_resolveQuery(e,t,s,r){const n=e.hash(),o=t?t.hash():0,h=s?s.hash():0,a=n^Math.imul(o,i.HASH_GOLDEN_RATIO)^Math.imul(h,i.HASH_SECONDARY_PRIME)|0,l=this._caches.findDedup(a,e,t,s);if(l!==void 0)return l.query;const u=this.store.registerQuery(e,t??void 0,s??void 0),d=new D(u,r,this,e.copy(),t?.copy()??null,s?.copy()??null,this._nextQueryIdCounter++);return this.store.updateQueryRef(u,d),this._caches.addDedup(a,{includeMask:e.copy(),excludeMask:t?.copy()??null,anyOfMask:s?.copy()??null,query:d}),d}registerSystem(e,t){let s;if(typeof e=="function")if(t!==void 0){const o=t(new $e(this)),h=this.ctx,a=e;s={...he,fn:(l,u)=>a(o,h,u)}}else{if(e.length>=3)throw new i.ECSError(i.ECS_ERROR.SYSTEM_FN_ARITY,`registerSystem was passed a ${e.length}-parameter function with no query builder. A bare system function is (ctx, dt); a query system is (q, ctx, dt) and needs the query builder as the second argument: registerSystem((q, ctx, dt) => …, (qb) => qb.with(…)). Without it, q would receive the SystemContext and dt would be undefined.`);s={...he,fn:e}}else s=e;if(Ze(s),s.fn===void 0&&s.backendHandle===void 0)throw new i.ECSError(i.ECS_ERROR.SYSTEM_FN_ARITY,`registerSystem: config${s.name?` '${s.name}'`:""} has neither 'fn' nor 'backendHandle' — provide a system body, or a backend handle for backend execution`);const r=ke(this.nextSystemId++),n=Object.freeze({...s,...Xe(s),id:r});return this.systems.add(n),n}removeSystem(e){return this.schedule.removeSystem(e),e.onRemoved?.(),this.systems.delete(e),this}get systemCount(){return this.systems.size}startup(){this.prewarmArchetypes(),this._updating=!0;try{for(const e of this.systems.values())if(e.onAdded!==void 0){I&&i.accessCheck.enter(e);try{e.onAdded(this.ctx)}finally{I&&i.accessCheck.leave()}}this.schedule.runStartup(this.ctx,this._tick)}finally{this._updating=!1}this.store.clearEvents()}prewarmArchetypes(){const e=$t([...this.systems,...this._observers.descriptors()]);e.length!==0&&this.store.archCreateManyFromMasks(e)}update(e){const t=i.accessCheck.current();try{if(I&&(this._updating=!0),this.store._tick=this._tick,I&&this.store._trace?.tickBegin(this._tick,e),this.store.publishRowCountsToDescriptor(),this.schedule.hasFixedSystems()){this._accumulator+=e;const r=this._maxFixedSteps*this._fixedTimestep;for(this._accumulator>r&&(this._accumulator=r);this._accumulator>=this._fixedTimestep;)this.schedule.runFixedUpdate(this.ctx,this._fixedTimestep,this._tick),this._accumulator-=this._fixedTimestep}this.schedule.runUpdate(this.ctx,e,this._tick);const s=I?this.store._devBufferedEventCount():0;if(this._observers.dispatchSet(this._tick),I&&this.store._devBufferedEventCount()!==s)throw new i.ECSError(i.ECS_ERROR.OBSERVER_ONSET_EMIT,"onSet observer emitted an event; onSet runs at the tick tail and its emissions would be dropped at clear_events. Emit from a system instead.");this.store.clearEvents(),I&&this.store._trace?.tickEnd(this._tick),this._tick++}finally{this._updating=!1,t!==null&&i.accessCheck.enter(t)}}dispose(){for(const e of this.systems.values())e.dispose?.(),e.onRemoved?.();this.systems.clear(),this.schedule.clear()}template(...e){const t=[];for(let s=0;s<e.length;s++){const r=e[s];t.push({def:G(r),values:P(r)})}return this.store.resolveTemplate(t)}regionOffset(e){return this.store.regionOffset(e)}regionHandle(e){return this.store.regionHandle(e)}fieldId(e,t){return this.store.fieldIdOf(e,t)}entityIdAtRow(e,t){return this.store.entityIdAtRow(e,t)}get columnStore(){return this.store.columnStore}get archetypeCount(){return this.store.archetypeCount}registerTag(){return this.store.registerComponent({})}registerSparseTag(){return this.store.registerSparseComponent({})}isAlive(e){return this.store.isAlive(e)}get entityCount(){return this.store.entityCount}hasComponent(e,t){return this.store.hasComponent(e,t)}isDisabled(e){return this.store.isDisabled(e)}addSparse(e,t,s){return this.store.addSparse(e,t,s),this}removeSparse(e,t){return this.store.removeSparse(e,t),this}hasSparse(e,t){return this.store.hasSparse(e,t)}getSparseField(e,t,s){return this.store.getSparseField(e,t,s)}setSparseField(e,t,s,r){this.store.setSparseField(e,t,s,r)}_getLastRunTick(){return this.ctx.lastRunTick}_getCurrentTick(){return this.store._tick}_getQueryDirtyEpoch(){return this.store._queryDirtyEpoch}_forEachSparseMatch(e,t,s,r,n,o,h,a){this.store._forEachSparseMatch(e,t,s,r,n,o,h,a)}_relationBackingSparseId(e){return this.store.relationBackingSparseId(e)}_forEachRelationTargetMatch(e,t,s,r,n,o,h,a){this.store._forEachRelationTargetMatch(e,t,s,r,n,o,h,a)}_forEachHierarchyMatch(e,t,s,r,n,o,h,a,l,u){this.store._forEachHierarchyMatch(e,t,s,r,n,o,h,a,l,u)}addSystems(e,...t){return this.schedule.addSystems(e,...t),this}configureSet(e,t){return this.schedule.configureSet(e,t),this}observe(e,t){return this._observers.register(e,t)}publishArchetypeRowCounts(){this.store.publishRowCountsToDescriptor()}flush(){this.ctx.flush()}}function $t(c){const e=new Map,t=[],s=h=>{const a=h.hash(),l=e.get(a);if(l!==void 0){for(let u=0;u<l.length;u++)if(l[u].equals(h))return;l.push(h)}else e.set(a,[h]);t.push(h)},r=h=>{const a=new T.BitSet;for(let l=0;l<h.length;l++)a.set(h[l].id);return a},n=[];for(const h of c){const a=h.transitions;for(let l=0;l<a.length;l++){const u=a[l];n.push({whenHas:r(u.whenHas),add:u.add,remove:u.remove})}}for(const h of c){const a=h.spawns;for(let l=0;l<a.length;l++)s(r(a[l]))}for(;t.length>0;){const h=t.pop();for(let a=0;a<n.length;a++){const l=n[a];if(!h.contains(l.whenHas))continue;const u=h.copy();if(l.add!==void 0)for(let d=0;d<l.add.length;d++)u.set(l.add[d].id);if(l.remove!==void 0)for(let d=0;d<l.remove.length;d++)u.clear(l.remove[d].id);s(u)}}const o=[];for(const h of e.values())for(let a=0;a<h.length;a++)o.push(h[a]);return o}function Bt(c,e){return typeof e=="object"&&e!==null&&console.warn(`runIfResourceEq('${c.description??"?"}'): 'expected' is an object — comparison is by reference identity (===), so the gate only fires when the resource is set to this exact instance. Prefer a primitive phase value.`),{name:`runIfResourceEq(${c.description??"?"})`,resourceReads:[c],evaluate:t=>t.getResource(c)===e}}function Gt(c,e=0){if(!Number.isInteger(c)||c<1)throw new i.ECSError(i.ECS_ERROR.INVALID_RUN_CONDITION,`runEveryNTicks: n must be a positive integer, got ${c}`);if(!Number.isInteger(e))throw new i.ECSError(i.ECS_ERROR.INVALID_RUN_CONDITION,`runEveryNTicks: offset must be an integer, got ${e}`);const t=(e%c+c)%c;return{name:`runEveryNTicks(${c}${t!==0?`, +${t}`:""})`,evaluate:s=>(s.ecsTick-t)%c===0}}function Pt(c){return{name:"runIfAnyMatch",reads:c._defs,evaluate:()=>c.entityCount>0}}function de(c){const e=[],t=[];for(const s of c)s.reads&&e.push(...s.reads),s.resourceReads&&t.push(...s.resourceReads);return{...e.length>0?{reads:e}:{},...t.length>0?{resourceReads:t}:{}}}function Ht(c){return{name:`not(${c.name})`,...de([c]),evaluate:e=>!c.evaluate(e)}}function Ut(...c){return{name:`allOf(${c.map(e=>e.name).join(", ")})`,...de(c),evaluate:e=>c.every(t=>t.evaluate(e))}}function Vt(...c){return{name:`anyOf(${c.map(e=>e.name).join(", ")})`,...de(c),evaluate:e=>c.some(t=>t.evaluate(e))}}function qt(c){return c.kind==="spawn"&&c.onSpawned!==void 0?{kind:"spawn",components:c.components}:c}class Wt{seed;_startup=[];_ticks=[];sink=this._startup;constructor(e=0){this.seed=e}openTick(e,t){const s=this._ticks[this._ticks.length-1];if(s!==void 0&&s.tick===e){this.sink=s.commands;return}const r=[];this._ticks.push({tick:e,dt:t,commands:r}),this.sink=r}record=e=>{this.sink.push(qt(e))};log(){return{seed:this.seed,startup:this._startup,ticks:this._ticks}}snapshotLog(){return{seed:this.seed,startup:this._startup.map(e=>({...e})),ticks:this._ticks.map(e=>({...e,commands:e.commands.map(t=>({...t}))}))}}}const Y="__component_def";function Yt(c){return JSON.stringify(c,(e,t)=>{if(typeof t=="function"&&"id"in t)return{[Y]:t.id};if(t!==null&&typeof t=="object"&&Y in t)throw new i.ECSError(i.ECS_ERROR.COMMAND_LOG_TAG_COLLISION,`Cannot serialize the command log: a value object owns a field named "${Y}", the reserved tag the serializer uses for component defs. Rename that component field so the log can round-trip losslessly.`);return t})}function zt(c){return JSON.parse(c,(e,t)=>t!==null&&typeof t=="object"&&Y in t?De(Te(t[Y])):t)}function jt(c,e,t,s){for(const o of t.startup)e.push(o);c.startup();const r=s?.hash??c.snapshots.deterministic,n=[];for(const o of t.ticks){for(const h of o.commands)e.push(h);c.update(o.dt),r&&n.push(c.snapshots.stateHash())}return{startupCommands:t.startup.length,ticks:t.ticks.length,stateHashes:n}}function ne(c){return c.name??`system#${c.id}`}class Qt{_frames=[];_current=null;tickBegin(e,t){const s={tick:e,dt:t,events:[]};this._current=s,this._frames.push(s)}tickEnd(e){this._current=null}systemStart(e,t){this._current?.events.push({kind:"system_start",system:ne(e),phase:t})}systemEnd(e){this._current?.events.push({kind:"system_end",system:ne(e)})}commandQueued(e,t,s){this._current?.events.push({kind:"command_queued",op:e,entity:t,component:s})}flushBegin(e){this._current?.events.push({kind:"flush_begin",phase:e})}flushEnd(e){this._current?.events.push({kind:"flush_end",phase:e})}phaseBoundary(e){}observerFired(e,t,s,r){this._current?.events.push({kind:"observer_fired",op:e,component:t,entity:s,observer:ne(r)})}eventEmitted(e){this._current?.events.push({kind:"event_emitted",key:e})}eventRead(e,t){this._current?.events.push({kind:"event_read",key:e,count:t})}frames(){return this._frames}reset(){this._frames.length=0,this._current=null}}function L(c,e){if(!(e>=0)||!Number.isFinite(e))throw new i.ECSError(i.ECS_ERROR.INVALID_FRAME_STEP,`${c} must be a finite number >= 0, got ${e}`);return e}function Kt(c){if(!Number.isInteger(c)||c<0)throw new i.ECSError(i.ECS_ERROR.INVALID_FRAME_STEP,`frame count must be an integer >= 0, got ${c}`);return c}class Xt{ecs;requestFrame;cancelFrame;frameHandle=null;lastTimestampMs=null;running=!1;_fixedDt;_maxDt;constructor(e,t={}){this.ecs=e,this._fixedDt=L("fixedDt",t.fixedDt??1/60),this._maxDt=L("maxDt",t.maxDt??.25);const s=globalThis;this.requestFrame=t.requestFrame??s.requestAnimationFrame?.bind(globalThis),this.cancelFrame=t.cancelFrame??s.cancelAnimationFrame?.bind(globalThis),t.autoStart===!0&&this.play()}get fixedDt(){return this._fixedDt}set fixedDt(e){this._fixedDt=L("fixedDt",e)}get maxDt(){return this._maxDt}set maxDt(e){this._maxDt=L("maxDt",e)}get isRunning(){return this.running}step(e=this._fixedDt){this.ecs.update(L("dt",e))}stepFrames(e,t=this._fixedDt){Kt(e);const s=L("dt",t);for(let r=0;r<e;r++)this.ecs.update(s)}play(){if(!this.running){if(this.requestFrame===void 0)throw new i.ECSError(i.ECS_ERROR.INVALID_FRAME_STEP,"FrameStepper.play() requires requestAnimationFrame or a requestFrame option");this.running=!0,this.lastTimestampMs=null,this.scheduleNextFrame()}}pause(){this.running=!1,this.lastTimestampMs=null,this.frameHandle!==null&&this.cancelFrame!==void 0&&this.cancelFrame(this.frameHandle),this.frameHandle=null}toggle(){this.running?this.pause():this.play()}dispose(){this.pause()}scheduleNextFrame(){this.frameHandle=this.requestFrame?.(this.onFrame)??null}onFrame=e=>{if(!this.running)return;const t=this.lastTimestampMs===null?this._fixedDt:(e-this.lastTimestampMs)/1e3;this.lastTimestampMs=e,this.ecs.update(Math.min(L("dt",t),this._maxDt)),this.running&&this.scheduleNextFrame()}}function Zt(c,e){return c.relations.register({exclusive:!0,onDeleteTarget:e?.onDeleteTarget??"clear"})}function Jt(c,e){return c.relations.register({exclusive:!0,onDeleteTarget:e?.onDeleteTarget??"delete"})}function es(c){return i.unsafeCast(Symbol(c))}const ts="0.5.2";exports.ANY_RELATION=i.ANY_RELATION;exports.ECSError=i.ECSError;exports.ECS_ERROR=i.ECS_ERROR;exports.HostCommandQueue=i.HostCommandQueue;exports.SCHEDULE=i.SCHEDULE;exports.SparseRestoreError=i.SparseRestoreError;exports.applyHostCommand=i.applyHostCommand;exports.getEntityIndex=i.getEntityIndex;exports.installHostCommandSeam=i.installHostCommandSeam;exports.isEcsError=i.isEcsError;exports.spawnEntry=i.spawnEntry;exports.systemSet=i.systemSet;exports.uninstallHostCommandSeam=i.uninstallHostCommandSeam;exports.SabUnavailableError=W.SabUnavailableError;exports.ChangedQuery=x;exports.ChunkColumns=Fe;exports.Commands=Be;exports.ECS=Ft;exports.ECSRestoreError=O;exports.ECS_SNAPSHOT_VERSION=J;exports.FrameStepper=Xt;exports.FrameTraceRecorder=Qt;exports.HIERARCHY_UNBOUNDED=Z;exports.HostCommandRecorder=Wt;exports.Query=D;exports.QueryBuilder=$e;exports.StoreRestoreError=B;exports.SystemContext=Ge;exports.VERSION=ts;exports.allOf=Ut;exports.anyOf=Vt;exports.bundle=He;exports.deserializeCommandLog=zt;exports.eventKey=Ye;exports.not=Ht;exports.registerChildOf=Jt;exports.registerIsA=Zt;exports.replayCommandLog=jt;exports.resourceKey=es;exports.runEveryNTicks=Gt;exports.runIfAnyMatch=Pt;exports.runIfResourceEq=Bt;exports.serializeCommandLog=Yt;exports.signalKey=ze;
|