@lastolivegames/becsy
Advanced tools
Comparing version 0.4.1 to 0.5.0
@@ -132,4 +132,4 @@ interface LogPointer { | ||
} | ||
interface SystemType { | ||
new (): System; | ||
interface SystemType<S extends System> { | ||
new (): S; | ||
} | ||
@@ -142,7 +142,10 @@ declare abstract class System { | ||
delta: number; | ||
// TODO: support schedule builder | ||
get name(): string; | ||
query(buildCallback: (q: QueryBuilder) => void): Query; | ||
attach<S extends System>(systemType: SystemType<S>): S; | ||
createEntity(...initialComponents: (ComponentType<any> | any)[]): Entity; | ||
accessRecentlyDeletedData(toggle?: boolean): void; | ||
abstract execute(): void; | ||
initialize(): void | Promise<void>; // eslint-disable-line @typescript-eslint/no-empty-function | ||
execute(): void; // eslint-disable-line @typescript-eslint/no-empty-function | ||
} | ||
@@ -162,2 +165,4 @@ declare class SystemBox { | ||
constructor(system: System, dispatcher: Dispatcher); | ||
replaceAttachmentPlaceholders(): void; | ||
initialize(): Promise<void>; | ||
execute(time: number, delta: number): void; | ||
@@ -169,3 +174,2 @@ private runQueries; | ||
restart(): void; | ||
suspend(): void; | ||
} | ||
@@ -231,3 +235,3 @@ declare class ComponentStats { | ||
// https://stackoverflow.com/questions/67467302/type-for-an-interleaved-array-of-classes-and-values | ||
type DefsArray = (ComponentType<any> | SystemType | any | DefsArray)[]; | ||
type DefsArray = (ComponentType<any> | SystemType<System> | any | DefsArray)[]; | ||
interface WorldOptions { | ||
@@ -245,3 +249,2 @@ defs: DefsArray; | ||
stop: DefsArray; | ||
suspend: DefsArray; | ||
restart: DefsArray; | ||
@@ -254,3 +257,3 @@ } | ||
private readonly systems; | ||
private readonly systemsByClass; | ||
readonly systemsByClass: Map<SystemType<System>, SystemBox>; | ||
private lastTime; | ||
@@ -270,3 +273,4 @@ executing: boolean; | ||
private splitDefs; | ||
execute(time?: number, delta?: number, systems?: SystemBox[]): void; | ||
initialize(): Promise<void>; | ||
execute(time?: number, delta?: number, systems?: SystemBox[]): Promise<void>; | ||
executeFunction(fn: (system: System) => void): void; | ||
@@ -366,2 +370,3 @@ private processEndOfFrame; | ||
static weakObject: Type<any>; | ||
// TODO: add autoremove/autodelete when nulled out | ||
static ref: Type<Entity | undefined>; | ||
@@ -393,3 +398,6 @@ static backrefs: (type?: ComponentType<any>, fieldName?: string, trackDeletedBackrefs?: boolean) => Type<Entity[]>; | ||
} | ||
interface ComponentType<C> { | ||
interface Component { | ||
__invalid?: boolean; | ||
} | ||
interface ComponentType<C extends Component> { | ||
new (): C; | ||
@@ -416,4 +424,4 @@ schema?: Schema; | ||
readonly elastic: boolean; | ||
readonly readonlyInstance: C; | ||
readonly writableInstance: C; | ||
readonlyInstance: C; | ||
writableInstance: C; | ||
readonly shapeOffset: number; | ||
@@ -430,6 +438,7 @@ readonly shapeMask: number; | ||
private readonly __dispatcher; | ||
constructor(options: WorldOptions); | ||
static create(options: WorldOptions): Promise<World>; | ||
private constructor(); | ||
build(callback: (system: System) => void): void; | ||
createEntity(...initialComponents: (ComponentType<any> | any)[]): void; | ||
execute(time?: number, delta?: number): void; | ||
execute(time?: number, delta?: number): Promise<void>; | ||
control(options: ControlOptions): void; | ||
@@ -442,7 +451,7 @@ get stats(): Stats; | ||
} | ||
declare function prop<JSType>(practicalOptions: PropOptions<JSType> | Type<any> | (() => Type<any>)): (target: any, name: string) => void; | ||
declare function field<JSType>(practicalOptions: PropOptions<JSType> | Type<any> | (() => Type<any>)): (target: any, name: string) => void; | ||
declare const componentTypes: ComponentType<any>[]; | ||
declare function component(constructor: ComponentType<any>): void; | ||
declare function component(options: ComponentOptions): (constructor: ComponentType<any>) => void; | ||
export { World, Type, Entity, System, SystemType, componentTypes, component, prop, Query, ComponentType }; | ||
export { World, Type, Entity, System, SystemType, componentTypes, component, field, Query, ComponentType }; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -132,4 +132,4 @@ interface LogPointer { | ||
} | ||
interface SystemType { | ||
new (): System; | ||
interface SystemType<S extends System> { | ||
new (): S; | ||
} | ||
@@ -142,7 +142,10 @@ declare abstract class System { | ||
delta: number; | ||
// TODO: support schedule builder | ||
get name(): string; | ||
query(buildCallback: (q: QueryBuilder) => void): Query; | ||
attach<S extends System>(systemType: SystemType<S>): S; | ||
createEntity(...initialComponents: (ComponentType<any> | any)[]): Entity; | ||
accessRecentlyDeletedData(toggle?: boolean): void; | ||
abstract execute(): void; | ||
initialize(): void | Promise<void>; // eslint-disable-line @typescript-eslint/no-empty-function | ||
execute(): void; // eslint-disable-line @typescript-eslint/no-empty-function | ||
} | ||
@@ -162,2 +165,4 @@ declare class SystemBox { | ||
constructor(system: System, dispatcher: Dispatcher); | ||
replaceAttachmentPlaceholders(): void; | ||
initialize(): Promise<void>; | ||
execute(time: number, delta: number): void; | ||
@@ -169,3 +174,2 @@ private runQueries; | ||
restart(): void; | ||
suspend(): void; | ||
} | ||
@@ -231,3 +235,3 @@ declare class ComponentStats { | ||
// https://stackoverflow.com/questions/67467302/type-for-an-interleaved-array-of-classes-and-values | ||
type DefsArray = (ComponentType<any> | SystemType | any | DefsArray)[]; | ||
type DefsArray = (ComponentType<any> | SystemType<System> | any | DefsArray)[]; | ||
interface WorldOptions { | ||
@@ -245,3 +249,2 @@ defs: DefsArray; | ||
stop: DefsArray; | ||
suspend: DefsArray; | ||
restart: DefsArray; | ||
@@ -254,3 +257,3 @@ } | ||
private readonly systems; | ||
private readonly systemsByClass; | ||
readonly systemsByClass: Map<SystemType<System>, SystemBox>; | ||
private lastTime; | ||
@@ -270,3 +273,4 @@ executing: boolean; | ||
private splitDefs; | ||
execute(time?: number, delta?: number, systems?: SystemBox[]): void; | ||
initialize(): Promise<void>; | ||
execute(time?: number, delta?: number, systems?: SystemBox[]): Promise<void>; | ||
executeFunction(fn: (system: System) => void): void; | ||
@@ -366,2 +370,3 @@ private processEndOfFrame; | ||
static weakObject: Type<any>; | ||
// TODO: add autoremove/autodelete when nulled out | ||
static ref: Type<Entity | undefined>; | ||
@@ -393,3 +398,6 @@ static backrefs: (type?: ComponentType<any>, fieldName?: string, trackDeletedBackrefs?: boolean) => Type<Entity[]>; | ||
} | ||
interface ComponentType<C> { | ||
interface Component { | ||
__invalid?: boolean; | ||
} | ||
interface ComponentType<C extends Component> { | ||
new (): C; | ||
@@ -416,4 +424,4 @@ schema?: Schema; | ||
readonly elastic: boolean; | ||
readonly readonlyInstance: C; | ||
readonly writableInstance: C; | ||
readonlyInstance: C; | ||
writableInstance: C; | ||
readonly shapeOffset: number; | ||
@@ -430,6 +438,7 @@ readonly shapeMask: number; | ||
private readonly __dispatcher; | ||
constructor(options: WorldOptions); | ||
static create(options: WorldOptions): Promise<World>; | ||
private constructor(); | ||
build(callback: (system: System) => void): void; | ||
createEntity(...initialComponents: (ComponentType<any> | any)[]): void; | ||
execute(time?: number, delta?: number): void; | ||
execute(time?: number, delta?: number): Promise<void>; | ||
control(options: ControlOptions): void; | ||
@@ -442,7 +451,7 @@ get stats(): Stats; | ||
} | ||
declare function prop<JSType>(practicalOptions: PropOptions<JSType> | Type<any> | (() => Type<any>)): (target: any, name: string) => void; | ||
declare function field<JSType>(practicalOptions: PropOptions<JSType> | Type<any> | (() => Type<any>)): (target: any, name: string) => void; | ||
declare const componentTypes: ComponentType<any>[]; | ||
declare function component(constructor: ComponentType<any>): void; | ||
declare function component(options: ComponentOptions): (constructor: ComponentType<any>) => void; | ||
export { World, Type, Entity, System, SystemType, componentTypes, component, prop, Query, ComponentType }; | ||
export { World, Type, Entity, System, SystemType, componentTypes, component, field, Query, ComponentType }; | ||
//# sourceMappingURL=index.min.d.ts.map |
@@ -1,2 +0,2 @@ | ||
class e{size;bytes;constructor(e){this.size=e,this.bytes=new Uint32Array(Math.ceil(e/32))}get(e){if(e<0||e>=this.size)throw new Error(`Bit index out of bounds: ${e}`);return 0!=(this.bytes[e>>>5]&1<<(31&e))}set(e){if(e<0||e>=this.size)throw new Error(`Bit index out of bounds: ${e}`);this.bytes[e>>>5]|=1<<(31&e)}unset(e){if(e<0||e>=this.size)throw new Error(`Bit index out of bounds: ${e}`);this.bytes[e>>>5]&=~(1<<(31&e))}clear(){this.bytes.fill(0)}}const t=[];class s{maxEntries;configParamName;localProcessingAllowed;data;corral;constructor(e,t,s=!1){this.maxEntries=e,this.configParamName=t,this.localProcessingAllowed=s;const r=new SharedArrayBuffer((e+2)*Uint32Array.BYTES_PER_ELEMENT);this.data=new Uint32Array(r);const i=new SharedArrayBuffer((e+2)*Uint32Array.BYTES_PER_ELEMENT);this.corral=new Uint32Array(i)}push(e){const t=this.corral[0];t>=this.maxEntries&&this.throwCapacityExceeded(),t&&this.corral[t]===e||(this.corral[t+2]=e,this.corral[0]+=1)}commit(e){if(!e&&this.localProcessingAllowed)throw new Error("Cannot use blind commit when log local processing is allowed");const t=this.corral[0];if(!t)return!0;let s=this.data[0];if(e&&(e.generation!==this.data[1]||e.index!==s||e.corralGeneration!==this.corral[1]||e.corralIndex!==this.corral[0]))return!1;const r=Math.min(t,this.maxEntries-s);for(this.data.set(this.corral.subarray(2,r+2),s+2),r<t&&this.data.set(this.corral.subarray(r+2,t+2),2),s+=t;s>=this.maxEntries;)s-=this.maxEntries,this.data[1]+=1;return this.data[0]=s,this.corral[0]=0,this.corral[1]+=1,e&&(e.index=s,e.generation=this.data[1]),!0}createPointer(e){return e?(e.index=this.data[0],e.generation=this.data[1],e.corralIndex=this.corral[0],e.corralGeneration=this.corral[1],e):{index:this.data[0],generation:this.data[1],corralIndex:this.corral[0],corralGeneration:this.corral[1]}}hasUpdatesSince(e){return this.checkPointer(e),!(e.index===this.data[0]&&e.generation===this.data[1]&&(e.corralGeneration===this.corral[1]?e.corralIndex===this.corral[0]:0===this.corral[0]))}processSince(e,s){this.checkPointers(e,s);let r=t;const i=s?.index??this.data[0],n=s?.generation??this.data[1];if(e.generation===n)if(e.index<i)r=[this.data,e.index+2,i+2,!1],e.index=i;else{const t=this.corral[0],s=this.corral[1];(e.corralGeneration===s?e.corralIndex<t:t)&&(r=[this.corral,e.corralIndex+2,t+2,!0],e.corralIndex=t,e.corralGeneration=s)}else r=[this.data,e.index+2,this.data.length,!1],e.index=0,e.generation=n;return r}processAndCommitSince(e){const s=this.processSince(e);return s[0]?s:this.commit(e)?t:this.processSince(e)}countSince(e,t){if(this.checkPointers(e,t),this.corral[0])throw new Error("Internal error, should commit log before counting");const s=e.index,r=t?.index??this.data[0],i=t?.generation??this.data[1];return e.index=r,e.generation=i,s===r&&e.generation===i?0:s<r?r-s:this.maxEntries-(s-r)}checkPointers(e,t){if(this.checkPointer(e),t&&(this.checkPointer(t),e.index>t.index&&e.generation>=t.generation))throw new RangeError("Internal error, start pointer exceeds end pointer")}checkPointer(e){const t=this.data[0];let s=e.generation;if(e.index===t?s+1<this.data[1]&&this.throwCapacityExceeded():(e.index>t&&(s+=1),s!==this.data[1]&&this.throwCapacityExceeded()),e.corralGeneration>this.corral[1])throw new Error("Internal error, pointer corral generation older than corral");if(e.corralGeneration===this.corral[1]&&e.corralIndex>this.corral[0])throw new Error("Internal error, pointer past end of log corral area")}throwCapacityExceeded(){throw new Error(`Log capacity exceeded, please raise ${this.configParamName} above ${this.maxEntries}`)}}class r{maxItems;configParamName;data;constructor(e,t){this.maxItems=e,this.configParamName=t,this.data=new Uint32Array(new SharedArrayBuffer((e+1)*Uint32Array.BYTES_PER_ELEMENT))}get length(){return this.data[0]}take(){const e=this.data[0]--;if(e<=0)throw new RangeError(`Pool capacity exceeded, please raise ${this.configParamName} above ${this.maxItems}`);return this.data[e]}refill(e){if(!e.length)return;const t=this.length,s=t+e.length;if(s>this.maxItems)throw new Error("Internal error, refill exceeded pool capacity");this.data.set(e,t+1),this.data[0]=s}fillWithDescendingIntegers(e){const t=this.length;for(let s=this.data.length-1;s>t;s--)this.data[s]=e++;this.data[0]=this.data.length-1}}const i=new TextEncoder,n=new TextDecoder;function a(e){throw new Error(`Component is not writable; use entity.write(${e.type.name}) to acquire a writable version`)}class o{defaultValue;constructor(e){this.defaultValue=e}static boolean;static uint8;static int8;static uint16;static int16;static uint32;static int32;static float32;static float64;static staticString;static dynamicString;static object;static weakObject;static ref;static backrefs}class h extends o{NumberArray;constructor(e){super(0),this.NumberArray=e}defineElastic(e,t){let s,r;t.updateBuffer=()=>{const i=e.capacity*this.NumberArray.BYTES_PER_ELEMENT,n=t.buffer?.byteLength!==i;(n||t.buffer!==s)&&(s=n?new SharedArrayBuffer(i):t.buffer,r=new this.NumberArray(s),n&&t.buffer&&r.set(new this.NumberArray(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>r[e.index],set(t){r[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>r[e.index],set(t){a(e)}})}defineFixed(e,t){const s=e.capacity*this.NumberArray.BYTES_PER_ELEMENT,r=new SharedArrayBuffer(s),i=new this.NumberArray(r);t.buffer=r,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>i[e.index],set(t){i[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>i[e.index],set(t){a(e)}})}}class c extends o{choices;choicesIndex=new Map;TypedArray;constructor(e){if(super(e[0]),this.choices=e,!e?.length)throw new Error("No choices specified for Type.staticString");e.length<256?this.TypedArray=Uint8Array:e.length<65536?this.TypedArray=Uint16Array:this.TypedArray=Uint32Array;for(let t=0;t<e.length;t++)this.choicesIndex.set(e[t],t)}defineElastic(e,t){let s,r;const i=this.choices,n=this.choicesIndex;t.updateBuffer=()=>{const i=e.capacity*this.TypedArray.BYTES_PER_ELEMENT,n=t.buffer?.byteLength!==i;(n||t.buffer!==s)&&(s=n?new SharedArrayBuffer(i):t.buffer,r=new this.TypedArray(s),n&&t.buffer&&r.set(new this.TypedArray(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=r[e.index],s=i[t];if(void 0===s)throw new Error(`Invalid static string index: ${t}`);return s},set(t){const s=n.get(t);if(void 0===s)throw new Error(`Static string not in set: "${t}"`);r[e.index]=s}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=r[e.index],s=i[t];if(void 0===s)throw new Error(`Invalid static string index: ${t}`);return s},set(t){a(e)}})}defineFixed(e,t){const s=this.choices,r=this.choicesIndex,i=e.capacity*this.TypedArray.BYTES_PER_ELEMENT,n=new SharedArrayBuffer(i),o=new this.TypedArray(n);t.buffer=n,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=o[e.index],r=s[t];if(void 0===r)throw new Error(`Invalid static string index: ${t}`);return r},set(t){const s=r.get(t);if(void 0===s)throw new Error(`Static string not in set: "${t}"`);o[e.index]=s}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=o[e.index],r=s[t];if(void 0===r)throw new Error(`Invalid static string index: ${t}`);return r},set(t){a(e)}})}}class d extends o{maxUtf8Length;lengthsStride;bytesStride;constructor(e){super(""),this.maxUtf8Length=e+e%2,this.lengthsStride=e/2+1,this.bytesStride=this.maxUtf8Length+2}defineElastic(e,t){let s,r,o;const h=this.maxUtf8Length,c=this.lengthsStride,d=this.bytesStride;t.updateBuffer=()=>{const i=e.capacity*(this.maxUtf8Length+Uint16Array.BYTES_PER_ELEMENT),n=t.buffer?.byteLength!==i;(n||t.buffer!==s)&&(s=n?new SharedArrayBuffer(i):t.buffer,r=new Uint16Array(s),o=new Uint8Array(s),n&&t.buffer&&o.set(new Uint8Array(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=r[e.index*c];return n.decode(new Uint8Array(o.buffer,e.index*d+2,t))},set(t){const s=i.encode(t);if(s.byteLength>h)throw new Error(`Dynamic string length > ${h} after encoding: ${t}`);r[e.index*c]=s.byteLength,o.set(s,e.index*d+2)}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=r[e.index*c];return n.decode(new Uint8Array(o.buffer,e.index*d+2,t))},set(t){a(e)}})}defineFixed(e,t){const s=this.maxUtf8Length,r=this.lengthsStride,o=this.bytesStride,h=e.capacity*(this.maxUtf8Length+Uint16Array.BYTES_PER_ELEMENT),c=new SharedArrayBuffer(h),d=new Uint16Array(c),l=new Uint8Array(c);t.buffer=c,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=d[e.index*r];return n.decode(new Uint8Array(l.buffer,e.index*o+2,t))},set(t){const n=i.encode(t);if(n.byteLength>s)throw new Error(`Dynamic string length > ${s} after encoding: ${t}`);d[e.index*r]=n.byteLength,l.set(n,e.index*o+2)}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=d[e.index*r];return n.decode(new Uint8Array(l.buffer,e.index*o+2,t))},set(t){a(e)}})}}const l=[];class f extends o{type;fieldName;trackDeletedBackrefs;constructor(e,t,s){super(l),this.type=e,this.fieldName=t,this.trackDeletedBackrefs=s}defineElastic(e,t){const s=this.fieldName?this.type?.__binding.fields.find((e=>e.name===this.fieldName)):void 0;if(this.fieldName&&!s)throw new Error(`Backrefs field ${e.type.name}.${t.name} refers to an unknown field ${this.type.name}.${this.fieldName}`);if(s&&s.type!==o.ref)throw new Error(`Backrefs field ${e.type.name}.${t.name} refers to a field ${this.type.name}.${this.fieldName} that is not a ref`);if(this.fieldName&&!this.type)throw new Error(`Backrefs selector has field but no component in ${e.type.name}.${t.name}`);if(this.type&&!this.fieldName&&!this.type.__binding.refFields.length)throw new Error(`Backrefs field ${e.type.name}.${t.name} refers to component ${this.type.name} that has no ref fields`);const r=this.trackDeletedBackrefs,i=e.dispatcher.indexer;i.registerSelector();const n=i.registerSelector(e.type,this.type,s?.seq,this.trackDeletedBackrefs),a={enumerable:!0,configurable:!0,get(){if(!r&&e.dispatcher.registry.includeRecentlyDeleted)throw new Error(`Backrefs field ${e.type.name}.${t.name} not configured to track recently deleted refs`);return i.getBackrefs(e.entityId,n)},set(e){if(e!==l)throw new Error("Backrefs properties are computed automatically, you cannot set them")}};Object.defineProperty(e.writableInstance,t.name,a),Object.defineProperty(e.readonlyInstance,t.name,a)}defineFixed(e,t){this.defineElastic(e,t)}}o.boolean=new class extends o{constructor(){super(!1)}defineElastic(e,t){let s,r;t.updateBuffer=()=>{const i=t.buffer?.byteLength!==e.capacity;(i||t.buffer!==s)&&(s=i?new SharedArrayBuffer(e.capacity):t.buffer,r=new Uint8Array(s),i&&t.buffer&&r.set(new Uint8Array(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>Boolean(r[e.index]),set(t){r[e.index]=t?1:0}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>Boolean(r[e.index]),set(t){a(e)}})}defineFixed(e,t){const s=new SharedArrayBuffer(e.capacity),r=new Uint8Array(s);t.buffer=s,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>Boolean(r[e.index]),set(t){r[e.index]=t?1:0}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>Boolean(r[e.index]),set(t){a(e)}})}},o.uint8=new h(Uint8Array),o.int8=new h(Int8Array),o.uint16=new h(Uint16Array),o.int16=new h(Int16Array),o.uint32=new h(Uint32Array),o.int32=new h(Int32Array),o.float32=new h(Float32Array),o.float64=new h(Float64Array),o.staticString=e=>new c(e),o.dynamicString=e=>new d(e),o.ref=new class extends o{constructor(){super(void 0)}defineElastic(e,t){let s,r;const i=e.dispatcher.indexer,n=e.dispatcher.registry,o=n.pool;i.registerSelector(),t.updateBuffer=()=>{const i=e.capacity*Int32Array.BYTES_PER_ELEMENT,n=t.buffer?.byteLength!==i;if(n||t.buffer!==s){if(s=n?new SharedArrayBuffer(i):t.buffer,r=new Int32Array(s),n&&t.buffer){const e=new Int32Array(t.buffer);r.set(e),r.fill(-1,e.length)}else r.fill(-1);t.buffer=s}},t.updateBuffer(),t.clearRef=(s,n,a)=>{if(a)throw new Error("Ref fields have no internal index");if(0!=(2147483648&r[e.index])!==s)throw new Error("Wrong ref stale state");const o=4194303&r[e.index],h=void 0!==n;h&&o!==n||(s?h&&(r[e.index]=-1):r[e.index]|=2147483648,i.trackRefChange(e.entityId,e.type,t.seq,void 0,o,-1,s))},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=r[e.index];if(!(-1===t||2147483648&t&&!n.includeRecentlyDeleted))return o.borrowTemporarily(4194303&t)},set(s){if(s&&!n.hasShape(s.__id,n.Alive,!1))throw new Error("Referencing a deleted entity is not allowed");const a=r[e.index],o=s?.__id??-1;a!==o&&(r[e.index]=o,i.trackRefChange(e.entityId,e.type,t.seq,void 0,a,o,!0))}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=r[e.index];if(!(-1===t||2147483648&t&&!n.includeRecentlyDeleted))return o.borrowTemporarily(4194303&t)},set(t){a(e)}})}defineFixed(e,t){const s=e.capacity*Int32Array.BYTES_PER_ELEMENT,r=new SharedArrayBuffer(s),i=new Int32Array(r);i.fill(-1),t.buffer=r;const n=e.dispatcher.indexer,o=e.dispatcher.registry,h=o.pool;n.registerSelector(),t.clearRef=(s,r,a)=>{if(a)throw new Error("Ref fields have no internal index");if(0!=(2147483648&i[e.index])!==s)throw new Error("Wrong ref stale state");const o=4194303&i[e.index],h=void 0!==r;h&&o!==r||(s?h&&(i[e.index]=-1):i[e.index]|=2147483648,n.trackRefChange(e.entityId,e.type,t.seq,void 0,o,-1,s))},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=i[e.index];if(!(-1===t||2147483648&t&&!o.includeRecentlyDeleted))return h.borrowTemporarily(4194303&t)},set(s){if(s&&!o.hasShape(s.__id,o.Alive,!1))throw new Error("Referencing a deleted entity is not allowed");const r=i[e.index],a=s?.__id??-1;r!==a&&(i[e.index]=a,n.trackRefChange(e.entityId,e.type,t.seq,void 0,r,a,!0))}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=i[e.index];if(!(-1===t||2147483648&t&&!o.includeRecentlyDeleted))return h.borrowTemporarily(4194303&t)},set(t){a(e)}})}},o.backrefs=(e,t,s=!1)=>new f(e,t,s),o.object=new class extends o{constructor(){super(void 0)}defineElastic(e,t){const s=[];t.localBuffer=s,t.updateBuffer=()=>{},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>s[e.index],set(t){s[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>s[e.index],set(t){a(e)}})}defineFixed(e,t){const s=new Array(e.capacity);t.localBuffer=s,t.updateBuffer=()=>{},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>s[e.index],set(t){s[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>s[e.index],set(t){a(e)}})}},o.weakObject=new class extends o{finalizers;constructor(){super(void 0)}defineElastic(e,t){const s=[];t.localBuffer=s,t.updateBuffer=()=>{};const r=this.initFinalizers(e);Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=s[e.index];return null==t?t:t.deref()},set(i){if(null!=i){const s=new WeakRef(i);r?.register(i,{type:e.type,field:t,weakRef:s,id:e.entityId,index:e.index}),i=s}s[e.index]=i}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=s[e.index];return null==t?t:t.deref()},set(t){a(e)}})}defineFixed(e,t){const s=new Array(e.capacity);t.localBuffer=s,t.updateBuffer=()=>{};const r=this.initFinalizers(e);Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=s[e.index];return null==t?t:t.deref()},set(i){if(null!=i){const s=new WeakRef(i);r?.register(i,{type:e.type,field:t,weakRef:s,id:e.entityId,index:e.index}),i=s}s[e.index]=i}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=s[e.index];return null==t?t:t.deref()},set(t){a(e)}})}initFinalizers(e){if(!e.trackedWrites)return;if(this.finalizers)return this.finalizers;const t=e.dispatcher;return t.writeLog&&"undefined"!=typeof FinalizationRegistry?(this.finalizers=new FinalizationRegistry((({type:e,field:s,weakRef:r,id:i,index:n})=>{s.localBuffer?.[n]===r&&t.registry.trackWrite(i,e)})),this.finalizers):void 0}};class u{type;fields;dispatcher;capacity;storage;elastic;readonlyInstance;writableInstance;shapeOffset;shapeMask;refFields;trackedWrites=!1;internallyIndexed=!1;entityId=0;index=0;constructor(e,t,s,r,i,n){this.type=e,this.fields=t,this.dispatcher=s,this.capacity=r,this.storage=i,this.elastic=n,this.readonlyInstance=new e,this.writableInstance=new e,this.shapeOffset=e.id>>5,this.shapeMask=1<<(31&e.id),this.refFields=t.filter((e=>e.type===o.ref))}}function g(e){if(!e.__binding)throw new Error(`Component ${e.name} not defined; add to world defs`)}class p{maxEntities;binding;fields;index;spares;constructor(e,t,s){this.maxEntities=e,this.binding=t,this.fields=s,this.growSpares(),this.growCapacity()}acquireIndex(e){let t=this.index[e];if(-1===t){if(this.spares[3]>0)t=this.spares[4+--this.spares[3]];else{if(this.spares[1]===this.spares[2]){if(!this.binding.elastic)throw new Error(`Storage exhausted for component ${this.binding.type.name}; raise its capacity above ${this.binding.capacity}`);this.binding.capacity=Math.min(this.maxEntities,2*this.binding.capacity),this.growCapacity()}t=this.spares[1]++}this.index[e]=t}return t}releaseIndex(e){if(-1===this.index[e])throw new Error(`Internal error, index for entity ${e} not allocated`);this.spares[3]===this.spares.length-4&&this.growSpares(),this.spares[4+this.spares[3]++]=this.index[e],this.index[e]=-1}growCapacity(){this.binding.dispatcher.stats.for(this.binding.type).capacity=this.binding.capacity;const e=this.ArrayType,t=e.BYTES_PER_ELEMENT!==this.spares?.[0];if(!this.index||t){const t=new e(new SharedArrayBuffer(this.maxEntities*e.BYTES_PER_ELEMENT));this.index?t.set(this.index):t.fill(-1),this.index=t}if(this.spares&&t){const t=new e(new SharedArrayBuffer(this.spares.length*e.BYTES_PER_ELEMENT));t.set(this.spares),t[0]=e.BYTES_PER_ELEMENT,this.spares=t}if(this.spares[2]=this.binding.capacity,this.binding.elastic)for(const e of this.fields)e.updateBuffer()}growSpares(){const e=this.ArrayType,t=this.spares?Math.min(this.maxEntities,2*(this.spares.length-4)):8,s=new e(new SharedArrayBuffer((4+t)*e.BYTES_PER_ELEMENT));this.spares?s.set(this.spares):(s[0]=e.BYTES_PER_ELEMENT,s[2]=this.binding.capacity),this.spares=s}get ArrayType(){const e=this.binding.capacity;return e<=127?Int8Array:e<=32767?Int16Array:Int32Array}}function m(e,t,s){const r=function(e){const t=e.schema,s=[];if(t){let r=0;for(const e in t){let i=t[e];(i instanceof o||"function"==typeof i)&&(i={type:i}),"function"==typeof i.type&&(i.type=i.type()),"default"in i||(i.default=i.type.defaultValue),s.push({name:e,seq:r++,type:i.type,default:i.default})}if(r>128)throw new Error(`Component ${e.name} declares too many fields`)}return s}(t),i=r.length?t.options?.storage??s.defaultComponentStorage:"sparse",n="sparse"===i?s.maxEntities:Math.min(s.maxEntities,t.options?.capacity??0),a=t.options?.initialCapacity??8;if(void 0!==t.options?.capacity){if("sparse"===i)throw new Error(`Component type ${t.name} cannot combine custom capacity with sparse storage`);if(t.options.capacity<=0)throw new Error(`Component type ${t.name} capacity option must be great than zero: got ${n}`);if(void 0!==t.options.initialCapacity)throw new Error(`Component type ${t.name} cannot have both capacity and initialCapacity options`)}if(("undefined"==typeof process||"test"!==process.env.NODE_ENV)&&t.__bind)throw new Error(`Component type ${t.name} is already in use in another world`);t.id=e;const h=new u(t,r,s,n||a,i,!n);t.__binding=h}function y(e){const t=e.__binding;for(const e of t.fields)t.elastic?e.type.defineElastic(t,e):e.type.defineFixed(t,e);switch(t.storage){case"sparse":t.dispatcher.stats.for(e).capacity=t.capacity,e.__bind=(e,s)=>(t.entityId=e,t.index=e,s?t.writableInstance:t.readonlyInstance),e.__allocate=e=>(t.entityId=e,t.index=e,t.writableInstance);break;case"packed":{const s=new p(t.dispatcher.maxEntities,t,t.fields);e.__bind=(r,i)=>{if(t.entityId=r,t.index=s.index[r],-1===t.index)throw new Error(`Attempt to bind unacquired entity ${r} to ${e.name}`);return i?t.writableInstance:t.readonlyInstance},e.__allocate=e=>(t.entityId=e,t.index=s.acquireIndex(e),t.writableInstance),e.__free=e=>{s.releaseIndex(e)};break}case"compact":throw new Error("Not yet implemented");default:throw new Error(`Invalid storage type "${t.storage}`)}}class w{__registry;__id;constructor(e){this.__registry=e}add(e,t){if(this.__checkMask(e,!0),!this.__registry.hasShape(this.__id,this.__registry.Alive,!1))throw new Error("Entity has been deleted");if(this.__registry.hasShape(this.__id,e,!1))throw new Error(`Entity already has a ${e.name} component`);return this.__registry.setShape(this.__id,e),this.__registry.dispatcher.stats.for(e).numEntities+=1,function(e,t,s){if(g(e),void 0!==s)for(const t in s)if(!e.schema?.[t])throw new Error(`Property ${t} not defined for component ${e.name}`);const r=e.__allocate(t);for(const t of e.__binding.fields)r[t.name]=s?.[t.name]??t.default}(e,this.__id,t),this}addAll(...e){for(let t=0;t<e.length;t++){const s=e[t];if("function"!=typeof s)throw new Error(`Bad arguments to bulk add: expected component type, got: ${s}`);let r=e[t+1];"function"==typeof r?r=void 0:t++,this.add(s,r)}return this}remove(e){this.__checkHas(e,!1),this.__checkMask(e,!0),this.__registry.clearShape(this.__id,e)}removeAll(...e){for(const t of e)this.remove(t)}has(e){return this.__checkMask(e,!1),this.__registry.hasShape(this.__id,e,!0)}read(e){return this.__checkMask(e,!1),this.__checkHas(e,!0),e.__bind(this.__id,!1)}write(e){return this.__checkMask(e,!0),this.__checkHas(e,!0),e.__binding.trackedWrites&&this.__registry.trackWrite(this.__id,e),e.__bind(this.__id,!0)}delete(){const e=this.__registry.Alive;for(const t of this.__registry.types)this.__registry.hasShape(this.__id,t,!1)&&(t!==e&&this.__checkMask(t,!0),this.__registry.clearShape(this.__id,t));this.__registry.queueDeletion(this.__id),this.__registry.dispatcher.indexer.clearAllRefs(this.__id,!1)}__checkMask(e,t){_(e,this.__registry.executingSystem,t)}__checkHas(e,t){if(!this.__registry.hasShape(this.__id,e,t))throw new Error(`Entity doesn't have a ${e.name} component`)}}function _(e,t,s){g(e);const r=s?t?.rwMasks.write:t?.rwMasks.read;if(!(!r||0!=((r[e.__binding.shapeOffset]??0)&e.__binding.shapeMask)))throw new Error(`System didn't mark component ${e.name} as ${s?"writable":"readable"}`)}function E(e,t){g(t);const s=t.__binding.shapeOffset;s>=e.length&&(e.length=s+1,e.fill(0,e.length,s)),e[s]|=t.__binding.shapeMask}class b{pool;entities=[];constructor(e){this.pool=e}add(e){this.entities.push(this.pool.borrowTemporarily(e))}clear(){this.entities.length&&this.entities.splice(0,1/0)}}class x{pool;entities=[];lookupTable;constructor(e,t){this.pool=e,this.lookupTable=new Int32Array(t),this.lookupTable.fill(-1)}add(e){const t=this.entities.push(this.pool.borrow(e))-1;this.lookupTable[e]=t}remove(e){const t=this.lookupTable[e];if(t<0)throw new Error("Internal error, entity not in list");this.pool.return(e),this.lookupTable[e]=-1;const s=this.entities.pop();t<this.entities.length&&(this.entities[t]=s,this.lookupTable[s.__id]=t)}has(e){return this.lookupTable[e]>=0}clear(){for(const e of this.entities)this.pool.return(e.__id);this.entities=[],this.lookupTable.fill(-1)}}var k;!function(e){e[e.all=1]="all",e[e.added=2]="added",e[e.removed=4]="removed",e[e.changed=8]="changed",e[e.addedOrChanged=16]="addedOrChanged",e[e.changedOrRemoved=32]="changedOrRemoved",e[e.addedChangedOrRemoved=64]="addedChangedOrRemoved"}(k||(k={}));const R=k.added|k.removed|k.changed|k.addedOrChanged|k.changedOrRemoved|k.addedChangedOrRemoved,S=k.changed|k.addedOrChanged|k.changedOrRemoved|k.addedChangedOrRemoved;class P{query;system;results={};flavors=0;withMask;withoutMask;trackMask;hasTransientResults;hasChangedResults;currentEntities;changedEntities;constructor(e,t){this.query=e,this.system=t,e.__results=this.results,e.__systemName=t.name}complete(){const t=this.system.dispatcher;if(this.hasTransientResults=Boolean(this.flavors&R),this.hasChangedResults=Boolean(this.flavors&S),this.hasChangedResults&&!this.trackMask)throw new Error("Query for changed entities must track at least one component");this.flavors&k.all?this.results.all=new x(t.registry.pool,t.maxEntities):this.currentEntities=new e(t.maxEntities),this.hasTransientResults&&this.allocateTransientResultLists(),this.flavors&&this.system.shapeQueries.push(this),this.hasChangedResults&&(this.changedEntities=new e(t.maxEntities),this.system.writeQueries.push(this))}allocateTransientResultLists(){this.flavors&k.added&&this.allocateResult("added"),this.flavors&k.removed&&this.allocateResult("removed"),this.flavors&k.changed&&this.allocateResult("changed"),this.flavors&k.addedOrChanged&&this.allocateResult("addedOrChanged"),this.flavors&k.changedOrRemoved&&this.allocateResult("changedOrRemoved"),this.flavors&k.addedChangedOrRemoved&&this.allocateResult("addedChangedOrRemoved")}allocateResult(e){const t=this.system.dispatcher;this.results[e]=new b(t.registry.pool)}clearTransientResults(){this.hasTransientResults&&(this.results.added?.clear(),this.results.removed?.clear(),this.results.changed?.clear(),this.results.addedOrChanged?.clear(),this.results.changedOrRemoved?.clear(),this.results.addedChangedOrRemoved?.clear(),this.changedEntities?.clear())}clearAllResults(){this.clearTransientResults(),this.results.all?.clear()}handleShapeUpdate(e){const t=this.system.dispatcher.registry,s=this.results.all?.has(e)??this.currentEntities.get(e),r=t.matchShape(e,this.withMask,this.withoutMask);r&&!s?(this.currentEntities?.set(e),this.results.all?.add(e),this.results.added?.add(e),this.results.addedOrChanged?.add(e),this.results.addedChangedOrRemoved?.add(e)):!r&&s&&(this.currentEntities?.unset(e),this.results.all?.remove(e),this.results.removed?.add(e),this.results.changedOrRemoved?.add(e),this.results.addedChangedOrRemoved?.add(e))}handleWrite(e,t,s){!this.changedEntities.get(e)&&(this.trackMask[t]??0)&s&&(this.changedEntities.set(e),this.results.changed?.add(e),this.results.addedOrChanged?.add(e),this.results.changedOrRemoved?.add(e),this.results.addedChangedOrRemoved?.add(e))}}class v{__callback;__userQuery;__query;__system;__lastTypes;constructor(e,t){this.__callback=e,this.__userQuery=t}__build(e){try{this.__system=e,this.__query=new P(this.__userQuery,e),this.__callback(this),this.__query.complete()}catch(t){throw t.message=`Failed to build query in system ${e.name}: ${t.message}`,t}}get and(){return this}get but(){return this}get also(){return this}get all(){return this.__query.flavors|=k.all,this}get added(){return this.__query.flavors|=k.added,this}get removed(){return this.__query.flavors|=k.removed,this}get changed(){return this.__query.flavors|=k.changed,this}get addedOrChanged(){return this.__query.flavors|=k.addedOrChanged,this}get changedOrRemoved(){return this.__query.flavors|=k.changedOrRemoved,this}get addedChangedOrRemoved(){return this.__query.flavors|=k.addedChangedOrRemoved,this}with(...e){return this.set(this.__system.rwMasks.read,e),this.set("withMask"),this}without(...e){return this.set(this.__system.rwMasks.read,e),this.set("withoutMask",e),this}using(...e){return this.set(this.__system.rwMasks.read,e),this}get track(){this.set("trackMask");for(const e of this.__lastTypes)e.__binding.trackedWrites=!0;return this}get read(){return this}get write(){return this.set(this.__system.rwMasks.write),this}set(e,t,s){if(e){if(t||(t=this.__lastTypes),!t)throw new Error("No component type to apply query modifier to");if(this.__lastTypes=t,"string"==typeof e){if(s&&this.__query[e])throw new Error(`Only one ${s} allowed`);this.__query[e]||(this.__query[e]=[]),e=this.__query[e]}else if(s&&e.some((e=>0!==e)))throw new Error(`Only one ${s} allowed`);for(const s of t)E(e,s)}}}class L{__results;__systemName;get all(){return this.__checkList("all"),this.__results.all.entities}get added(){return this.__checkList("added"),this.__results.added.entities}get removed(){return this.__checkList("removed"),this.__results.removed.entities}get changed(){return this.__checkList("changed"),this.__results.changed.entities}get addedOrChanged(){return this.__checkList("addedOrChanged"),this.__results.addedOrChanged.entities}get changedOrRemoved(){return this.__checkList("changedOrRemoved"),this.__results.changedOrRemoved.entities}get addedChangedOrRemoved(){return this.__checkList("addedChangedOrRemoved"),this.__results.addedChangedOrRemoved.entities}__checkList(e){if(!this.__results[e])throw new Error(`Query '${e}' not configured, please add .${e} to your query definition in system ${this.__systemName}`)}}var I,C;!function(e){e[e.RUNNING=0]="RUNNING",e[e.SUSPENDED=1]="SUSPENDED",e[e.STOPPED=2]="STOPPED"}(I||(I={}));class T{static __system=!0;__queryBuilders=[];__dispatcher;time;delta;get name(){return this.constructor.name}query(e){const t=new L,s=new v(e,t);if(!this.__queryBuilders)throw new Error(`Attempt to create a new query after world initialized in system ${this.name}`);return this.__queryBuilders.push(s),t}createEntity(...e){return this.__dispatcher.createEntity(e)}accessRecentlyDeletedData(e=!0){this.__dispatcher.registry.includeRecentlyDeleted=e}}class A{system;dispatcher;rwMasks={read:[],write:[]};shapeQueries=[];writeQueries=[];hasWriteQueries;processedEntities;shapeLogPointer;writeLogPointer;state=I.RUNNING;get name(){return this.system.name}constructor(t,s){this.system=t,this.dispatcher=s,t.__dispatcher=s,this.shapeLogPointer=s.shapeLog.createPointer(),this.writeLogPointer=s.writeLog?.createPointer(),this.processedEntities=new e(s.maxEntities);for(const e of t.__queryBuilders)e.__build(this);t.__queryBuilders=null,this.hasWriteQueries=!!this.writeQueries.length}execute(e,t){this.state===I.RUNNING&&(this.system.time=e,this.system.delta=t,this.runQueries(),this.system.execute())}runQueries(){const e=this.dispatcher.shapeLog.hasUpdatesSince(this.shapeLogPointer),t=this.hasWriteQueries&&this.dispatcher.writeLog.hasUpdatesSince(this.writeLogPointer);if(e||t){this.processedEntities.clear();for(const e of this.shapeQueries)e.clearTransientResults();e&&this.__updateShapeQueries(),t&&this.__updateWriteQueries()}}__updateShapeQueries(){const e=this.dispatcher.shapeLog;let t,s,r;for(;[t,s,r]=e.processSince(this.shapeLogPointer),t;)for(let e=s;e<r;e++){const s=t[e];if(!this.processedEntities.get(s)){this.processedEntities.set(s);for(const e of this.shapeQueries)e.handleShapeUpdate(s)}}}__updateWriteQueries(){const e=this.dispatcher.writeLog;let t,s,r;for(;[t,s,r]=e.processSince(this.writeLogPointer),t;)for(let e=s;e<r;e++){const s=t[e],r=4194303&s;if(!this.processedEntities.get(r)){const e=s>>>22;for(const t of this.writeQueries)t.handleWrite(r,e>>5,1<<(31&e))}}}stop(){if(this.state!==I.STOPPED){this.state=I.STOPPED;for(const e of this.shapeQueries)e.clearAllResults()}}restart(){if(this.state===I.STOPPED){const e=this.dispatcher.registry,t=e.Alive;for(let s=0;s<this.dispatcher.maxEntities;s++)if(e.hasShape(s,t,!1))for(const e of this.shapeQueries)e.handleShapeUpdate(s);for(const e of this.shapeQueries)e.clearTransientResults();this.dispatcher.shapeLog.createPointer(this.shapeLogPointer),this.dispatcher.writeLog?.createPointer(this.writeLogPointer)}this.state=I.RUNNING}suspend(){this.state===I.STOPPED&&this.restart(),this.state=I.SUSPENDED}}class O{registry;borrowed;borrowCounts;spares=[];temporarilyBorrowedIds=[];constructor(e,t){this.registry=e,this.borrowed=Array.from({length:t}),this.borrowCounts=new Int32Array(t)}borrow(e){this.borrowCounts[e]+=1;let t=this.borrowed[e];return t||(t=this.borrowed[e]=this.spares.pop()??new w(this.registry),t.__id=e),t}borrowTemporarily(e){const t=this.borrow(e);return this.temporarilyBorrowedIds.push(e),t}returnTemporaryBorrows(){for(const e of this.temporarilyBorrowedIds)this.return(e);this.temporarilyBorrowedIds.splice(0,1/0)}return(e){if(!this.borrowCounts[e])throw new Error("Internal error, returning entity with no borrows");--this.borrowCounts[e]<=0&&(this.spares.push(this.borrowed[e]),this.borrowed[e]=void 0)}}class B{types;dispatcher;stride;shapes;staleShapes;entityIdPool;pool;executingSystem;includeRecentlyDeleted=!1;deletionLog;prevDeletionPointer;oldDeletionPointer;removalLog;prevRemovalPointer;oldRemovalPointer;Alive=class{};constructor(e,t,i,n,a){this.types=n,this.dispatcher=a,this.stride=Math.ceil(n.length/32);const o=e*this.stride*4;this.shapes=new Uint32Array(new SharedArrayBuffer(o)),this.staleShapes=new Uint32Array(new SharedArrayBuffer(o)),this.entityIdPool=new r(e,"maxEntities"),this.entityIdPool.fillWithDescendingIntegers(0),this.pool=new O(this,e),this.deletionLog=new s(t,"maxLimboEntities"),this.prevDeletionPointer=this.deletionLog.createPointer(),this.oldDeletionPointer=this.deletionLog.createPointer(),this.removalLog=new s(i,"maxLimboComponents"),this.prevRemovalPointer=this.removalLog.createPointer(),this.oldRemovalPointer=this.removalLog.createPointer()}initializeComponentTypes(){this.types.unshift(this.Alive);let e=0;for(const t of this.types)m(e++,t,this.dispatcher);for(const e of this.types)y(e);{const e=this.types[0].__binding;if(0!==e.shapeOffset||1!==e.shapeMask)throw new Error("Alive component was not assigned first available shape mask")}}createEntity(e){const t=this.entityIdPool.take(),s=t*this.stride;this.shapes[s]=1,this.stride>1&&this.shapes.fill(0,s+1,s+this.stride);const r=this.pool.borrowTemporarily(t);return e&&r.addAll(...e),this.dispatcher.stats.numEntities+=1,r}queueDeletion(e){this.deletionLog.push(e)}flush(){this.includeRecentlyDeleted=!1,this.pool.returnTemporaryBorrows(),this.deletionLog.commit(),this.removalLog.commit()}processEndOfFrame(){this.processDeletionLog(),this.processRemovalLog()}processDeletionLog(){this.deletionLog.commit();let e,t,s,r=0;for(;[e,t,s]=this.deletionLog.processSince(this.oldDeletionPointer,this.prevDeletionPointer),e;){for(let r=t;r<s;r++)this.dispatcher.indexer.clearAllRefs(e[r],!0);const i=e.subarray(t,s);this.entityIdPool.refill(i),r+=i.length}this.dispatcher.stats.numEntities-=r,this.dispatcher.stats.maxLimboEntities=r,this.deletionLog.createPointer(this.prevDeletionPointer)}processRemovalLog(){this.removalLog.commit();let e,t,s,r=0;for(;[e,t,s]=this.removalLog.processSince(this.oldRemovalPointer,this.prevRemovalPointer),e;){for(let r=t;r<s;r++){const t=e[r],s=4194303&t,i=t>>>22,n=this.types[i],a=s*this.stride+n.__binding.shapeOffset,o=n.__binding.shapeMask;0==(this.shapes[a]&o)&&(this.staleShapes[a]&=~o,this.clearRefs(s,n,!0),n.__free?.(s))}r+=s-t}this.dispatcher.stats.maxLimboComponents=r,this.removalLog.createPointer(this.prevRemovalPointer)}hasShape(e,t,s){const r=e*this.stride+t.__binding.shapeOffset,i=t.__binding.shapeMask;return 0!=(this.shapes[r]&i)||!(!s||!this.includeRecentlyDeleted||0==(this.staleShapes[r]&i))}setShape(e,t){const s=e*this.stride+t.__binding.shapeOffset,r=t.__binding.shapeMask;this.shapes[s]|=r,this.staleShapes[s]|=r,this.dispatcher.shapeLog.push(e)}clearShape(e,t){const s=this.clearRefs(e,t,!1);(t.__free||s)&&this.removalLog.push(e|t.id<<22),this.shapes[e*this.stride+t.__binding.shapeOffset]&=~t.__binding.shapeMask,this.dispatcher.shapeLog.push(e),this.dispatcher.stats.for(t).numEntities-=1}trackWrite(e,t){this.dispatcher.writeLog.push(e|t.id<<22)}clearRefs(e,t,s){const r=!!t.__binding.refFields.length;if(r){t.__bind(e,!0);for(const e of t.__binding.refFields)e.clearRef(s)}return r}matchShape(e,t,s){const r=e*this.stride;if(t)for(let e=0;e<t.length;e++){const s=t[e];if((this.shapes[r+e]&s)!==s)return!1}if(s)for(let e=0;e<s.length;e++){const t=s[e];if(0!=(this.shapes[r+e]&t))return!1}return!0}}class N{_numEntities=0;maxEntities=0;capacity=0;get numEntities(){return this._numEntities}set numEntities(e){this._numEntities=e,e>this.maxEntities&&(this.maxEntities=e)}toString(){return`${this.numEntities.toLocaleString()} of ${this.maxEntities.toLocaleString()} peak (capacity ${this.capacity.toLocaleString()})`}}class F{frames=0;_numEntities=0;maxEntities=0;_maxLimboEntities=0;_maxLimboComponents=0;_maxRefChangesPerFrame=0;_maxShapeChangesPerFrame=0;_maxWritesPerFrame=0;components=Object.create(null);get numEntities(){return this._numEntities}set numEntities(e){this._numEntities=e,e>this.maxEntities&&(this.maxEntities=e)}get maxLimboEntities(){return this._maxLimboEntities}set maxLimboEntities(e){e>this._maxLimboEntities&&(this._maxLimboEntities=e)}get maxLimboComponents(){return this._maxLimboComponents}set maxLimboComponents(e){e>this._maxLimboComponents&&(this._maxLimboComponents=e)}get maxRefChangesPerFrame(){return this._maxRefChangesPerFrame}set maxRefChangesPerFrame(e){e>this._maxRefChangesPerFrame&&(this._maxRefChangesPerFrame=e)}get maxShapeChangesPerFrame(){return this._maxShapeChangesPerFrame}set maxShapeChangesPerFrame(e){e>this._maxShapeChangesPerFrame&&(this._maxShapeChangesPerFrame=e)}get maxWritesPerFrame(){return this._maxWritesPerFrame}set maxWritesPerFrame(e){e>this._maxWritesPerFrame&&(this._maxWritesPerFrame=e)}for(e){return this.components[e.name]=this.components[e.name]??new N}toString(){return`World stats:\n frames: ${this.frames.toLocaleString()}\n entities: ${this.numEntities.toLocaleString()} of ${this.maxEntities.toLocaleString()} max (${this.maxLimboEntities.toLocaleString()} limbo max)\n refs: ${this.maxRefChangesPerFrame.toLocaleString()} ref changes/frame max\n logs: ${this.maxShapeChangesPerFrame.toLocaleString()} shape changes/frame max, ${this.maxWritesPerFrame.toLocaleString()} writes/frame max`}}!function(e){e[e.REFERENCE=0]="REFERENCE",e[e.UNREFERENCE=1073741824]="UNREFERENCE",e[e.RELEASE=2147483648]="RELEASE"}(C||(C={}));const $=C.REFERENCE|C.UNREFERENCE|C.RELEASE;class M{targetEntityId;selector;dispatcher;entities=[];tags;entityIndex;clearing=!1;registry;constructor(e,t,s){this.targetEntityId=e,this.selector=t,this.dispatcher=s;const r=t.sourceType?.__binding;t.matchType&&(t.matchSeq||1===r.refFields.length)&&!r.internallyIndexed||(this.tags=[]),this.registry=s.registry}clearAllRefs(e){if(!this.tags)throw new Error("Unreferencing an untagged tracker");this.clearing=!0;for(let t=0;t<this.entities.length;t++){const s=this.entities[t].__id,r=this.tags[t];if("number"==typeof r)this.clearRef(s,r,e);else for(const t of r)this.clearRef(s,t,e)}this.entities=[],this.tags=[],this.entityIndex=void 0,this.clearing=!1}clearRef(e,t,s){const r=511&t,i=t>>>9&127,n=t>>>16,a=this.registry.types[r];_(a,this.registry.executingSystem,!0),a.__bind(e,!0),a.__binding.fields[i].clearRef(s,this.targetEntityId,n)}trackReference(e,t,s,r,i){if(this.clearing)throw new Error("Cannot track a new reference while clearing tracker");i&&this.checkWriteMask();let n=this.getEntityIndex(e);void 0===n&&(n=this.addEntity(e,i)),this.addTag(n,this.makeTag(t,s,r))}trackUnreference(e,t,s,r,i){if(this.clearing)return;i&&this.checkWriteMask();const n=this.getEntityIndex(e);if(void 0===n)throw new Error("Entity backref not tracked");this.removeTag(n,this.makeTag(t,s,r))&&this.removeEntity(n,e,i)}getEntityIndex(e){if(this.entityIndex)return this.entityIndex[e];const t=this.entities.findIndex((t=>t.__id===e));return t>=0?t:void 0}indexEntities(){if(this.entityIndex)throw new Error("Entities already indexed");this.entityIndex=new Array(this.dispatcher.maxEntities);for(let e=0;e<this.entities.length;e++)this.entityIndex[this.entities[e].__id]=e}addTag(e,t){if(!this.tags)return;const s=this.tags[e];if(void 0===s)this.tags[e]=t;else if("number"==typeof s){if(s===t)throw new Error("Ref already tracked");this.tags[e]=[s,t]}else if(Array.isArray(s)){if(s.includes(t))throw new Error("Ref already tracked");if(s.length>=1e3){(this.tags[e]=new Set(s)).add(t)}else s.push(t)}else{if(s.has(t))throw new Error("Ref already tracked");s.add(t)}}removeTag(e,t){if(!this.tags)return!0;const s=this.tags[e];if(void 0===s)throw new Error("Ref not tracked");if("number"==typeof s){if(s!==t)throw new Error("Ref not tracked");return delete this.tags[e],!0}if(Array.isArray(s)){const e=s.indexOf(t);if(-1===e)throw new Error("Ref not tracked");return s.splice(e,1),!this.tags.length}return s.delete(t),!s.size}makeTag(e,t,s){return e|t<<9|(void 0===s?0:s<<16)}addEntity(e,t){const s=this.entities.length;return this.entities.push(this.registry.pool.borrow(e)),this.entityIndex?this.entityIndex[e]=s:s>100&&this.indexEntities(),t&&this.trackBackrefsChange(),s}removeEntity(e,t,s){this.registry.pool.return(t);const r=this.entities.pop();this.entityIndex&&delete this.entityIndex[e],this.entities.length>e&&(this.entities[e]=r,this.entityIndex&&(this.entityIndex[r.__id]=e)),s&&this.trackBackrefsChange()}trackBackrefsChange(){for(const e of this.selector.targetTypes)e.__binding.trackedWrites&&this.registry.trackWrite(this.targetEntityId,e)}checkWriteMask(){const e=this.registry.executingSystem;for(const t of this.selector.targetTypes)_(t,e,!0)}}class U{dispatcher;maxRefChangesPerFrame;refLog;refLogPointer;refLogStatsPointer;selectorIdsBySourceKey=new Map;selectors=[];trackers=new Map;registry;constructor(e,t){this.dispatcher=e,this.maxRefChangesPerFrame=t,this.registry=e.registry}processEndOfFrame(){this.flush(),this.dispatcher.stats.maxRefChangesPerFrame=this.refLog?.countSince(this.refLogStatsPointer)??0}registerSelector(e,t,r,i=!1){e&&g(e),t&&g(t),this.refLog||(this.refLog=new s(this.maxRefChangesPerFrame,"maxRefChangesPerFrame",!0),this.refLogPointer=this.refLog.createPointer(),this.refLogStatsPointer=this.refLog.createPointer());const n=t?void 0===r?-2-t.id:t.id|r<<9:-1;let a=this.selectorIdsBySourceKey.get(n);if(void 0===a){this.selectors.length||(i=!0);const s={id:this.selectors.length,targetTypes:e?[e]:[],sourceType:t,matchType:!!t,matchSeq:void 0!==r,sourceTypeId:t?.id,sourceSeq:r,trackStale:i};if(this.selectors.push(s),a=s.id,this.selectorIdsBySourceKey.set(n,a),a>512)throw new Error("Too many distinct backrefs selectors")}else{const t=this.selectors[a];t.trackStale=t.trackStale||i,e&&t.targetTypes.push(e)}return a}getBackrefs(e,t=0){const s=this.selectors[t];return this.getOrCreateTracker(s,e,this.registry.includeRecentlyDeleted).entities}trackRefChange(e,t,s,r,i,n,a){if(!this.refLog)throw new Error("Trying to trackRefChange without a refLog");if(i===n)throw new Error("No-op call to trackRefChange");-1!==i&&this.pushRefLogEntry(e,t,s,r,i,a?C.RELEASE:C.UNREFERENCE),-1!==n&&this.pushRefLogEntry(e,t,s,r,n,C.REFERENCE)}clearAllRefs(e,t){this.selectors.length&&this.getTracker(this.selectors[0],e,t)?.clearAllRefs(t)}pushRefLogEntry(e,t,s,r,i,n){const a=void 0!==r;if(a!==t.__binding.internallyIndexed)throw new Error("Inconsistent internally indexed flag");this.refLog.push(e|t.id<<22),this.refLog.push(i|s<<22|n|(a?2**29:0)),a&&this.refLog.push(r),this.processEntry(e,t.id,s,r,i,n,!0)}getOrCreateTracker(e,t,s){let r,i=this.getTracker(e,t,s);if(i)return i;if(s&&!e.trackStale)throw new Error("Selector not configured for stale tracking");return i=new M(t,e,this.dispatcher),this.trackers.set(t|e.id<<22,i),e.trackStale&&(r=new M(t,e,this.dispatcher),this.trackers.set(t|e.id<<22|2**31,r)),s?r:i}getTracker(e,t,s){return this.trackers.get(t|e.id<<22|(s?2**31:0))}flush(){if(this.refLog)for(;;){const[e,t,s,r]=this.refLog.processAndCommitSince(this.refLogPointer);if(!e)break;if(!r)for(let r=t;r<s;r+=2){const t=e[r],s=e[r+1],i=4194303&t,n=t>>>22,a=4194303&s,o=s>>>22&127,h=(s&$)>>>30,c=0!=(s&2**29),d=c?e[r+2]:void 0;c&&(r+=1),this.processEntry(i,n,o,d,a,h,!1)}}}processEntry(e,t,s,r,i,n,a){for(let o=0;o<this.selectors.length;o++){const h=this.selectors[o];if(!(h.matchType&&h.sourceTypeId!==t||h.matchSeq&&h.sourceSeq!==s)){if(n===C.REFERENCE||n===C.UNREFERENCE){const o=this.getOrCreateTracker(h,i,!1);n===C.REFERENCE?o.trackReference(e,t,s,r,a):o.trackUnreference(e,t,s,r,a)}if(h.trackStale&&(n===C.REFERENCE||n===C.RELEASE)){const o=this.getOrCreateTracker(h,i,!0);n===C.REFERENCE?o.trackReference(e,t,s,r,a):o.trackUnreference(e,t,s,r,a)}}}}}const D="undefined"!=typeof window&&void 0!==window.performance?performance.now.bind(performance):Date.now.bind(Date);class q extends T{__callback;execute(){this.__callback(this)}}class W{maxEntities;defaultComponentStorage;registry;systems;systemsByClass=new Map;lastTime=D()/1e3;executing;shapeLog;writeLog;shapeLogFramePointer;writeLogFramePointer;stats;indexer;userCallbackSystem;callbackSystem;deferredControls=new Map;constructor({defs:e,maxEntities:t=1e4,maxLimboEntities:r=Math.ceil(t/5),maxLimboComponents:i=Math.ceil(t/5),maxShapeChangesPerFrame:n=2*t,maxWritesPerFrame:a=4*t,maxRefChangesPerFrame:o=t,defaultComponentStorage:h="sparse"}){if(t>4194304)throw new Error("maxEntities too high, the limit is 4194304");const{componentTypes:c,systemTypes:d}=this.splitDefs(e);if(c.length>512)throw new Error("Too many component types, the limit is 512");this.stats=new F,this.maxEntities=t,this.defaultComponentStorage=h,this.shapeLog=new s(n,"maxShapeChangesPerFrame"),this.shapeLogFramePointer=this.shapeLog.createPointer(),this.registry=new B(t,r,i,c.flat(1/0),this),this.indexer=new U(this,o),this.registry.initializeComponentTypes(),this.systems=this.normalizeAndInitSystems(d),this.systems.some((e=>e.hasWriteQueries))&&(this.writeLog=new s(a,"maxWritesPerFrame"),this.writeLogFramePointer=this.writeLog.createPointer()),this.userCallbackSystem=new q,this.callbackSystem=new A(this.userCallbackSystem,this),this.callbackSystem.rwMasks.read=void 0,this.callbackSystem.rwMasks.write=void 0}normalizeAndInitSystems(e){const t=[],s=e.flat(1/0);for(let e=0;e<s.length;e++){const r=s[e],i=new r,n=s[e+1];n&&"function"!=typeof n&&(Object.assign(i,n),e++);const a=new A(i,this);t.push(a),this.systemsByClass.set(r,a)}return t}splitDefs(e){const t=[],s=[];let r=!1;for(const i of e.flat(1/0))if("function"==typeof i)r=i.__system,(r?s:t).push(i);else{if(!r)throw new Error("Unexpected value in world defs: "+i);s.push(i),r=!1}return{componentTypes:t,systemTypes:s}}execute(e,t,s){if(this.executing)throw new Error("Recursive system execution not allowed");this.executing=!0,void 0===e&&(e=D()/1e3),void 0===t&&(t=e-this.lastTime),this.lastTime=e;for(const r of s??this.systems)this.registry.executingSystem=r,r.execute(e,t),this.flush();this.registry.executingSystem=void 0,this.executing=!1,this.processEndOfFrame()}executeFunction(e){if(this.executing)throw new Error("Ad hoc function execution not allowed while world is executing");this.executing=!0,this.registry.executingSystem=this.callbackSystem,this.userCallbackSystem.__callback=e,this.callbackSystem.execute(0,0),this.flush(),this.registry.executingSystem=void 0,this.executing=!1,this.processEndOfFrame()}processEndOfFrame(){this.registry.processEndOfFrame(),this.indexer.processEndOfFrame(),this.gatherFrameStats(),this.processDeferredControls()}gatherFrameStats(){this.stats.frames+=1,this.stats.maxShapeChangesPerFrame=this.shapeLog.countSince(this.shapeLogFramePointer),this.stats.maxWritesPerFrame=this.writeLog?.countSince(this.writeLogFramePointer)??0}flush(){this.registry.flush(),this.indexer.flush(),this.shapeLog.commit(),this.writeLog?.commit()}createEntity(e){const t=this.registry.createEntity(e);return this.executing||this.flush(),t}control(e){this.checkControlOverlap(e),this.deferRequestedRunState(e.stop,I.STOPPED),this.deferRequestedRunState(e.suspend,I.SUSPENDED),this.deferRequestedRunState(e.restart,I.RUNNING),this.executing||this.processDeferredControls()}deferRequestedRunState(e,t){for(const s of e.flat(1/0)){if(!s.__system)continue;const e=this.systemsByClass.get(s);if(!e)throw new Error(`System ${s.name} not defined for this world`);this.deferredControls.set(e,t)}}checkControlOverlap(e){const t=new Set,s=new Set;for(const s of e.stop.flat(1/0))s.__system&&t.add(s);for(const r of e.suspend.flat(1/0))if(r.__system){if(t.has(r))throw new Error(`Request to both stop and suspend system ${r.name}`);s.add(r)}for(const r of e.restart.flat(1/0))if(r.__system){if(t.has(r))throw new Error(`Request to both stop and restart system ${r.name}`);if(s.has(r))throw new Error(`Request to both suspend and restart system ${r.name}`)}}processDeferredControls(){if(this.deferredControls.size){for(const[e,t]of this.deferredControls.entries())switch(t){case I.STOPPED:e.stop();break;case I.SUSPENDED:e.suspend();break;case I.RUNNING:e.restart()}this.deferredControls.clear()}}}class j{__dispatcher;constructor(e){this.__dispatcher=new W(e)}build(e){this.__dispatcher.executeFunction(e)}createEntity(...e){this.__dispatcher.createEntity(e)}execute(e,t){this.__dispatcher.execute(e,t)}control(e){this.__dispatcher.control(e)}get stats(){return this.__dispatcher.stats}}function Q(e){return function(t,s){t.constructor.schema||(t.constructor.schema={});const r="type"in e?e:{type:e};t.constructor.schema[s]=r}}const z=[];function Y(e){if("function"!=typeof e)return t=>{t.options=e,z.push(t)};z.push(e)}export{w as Entity,L as Query,T as System,o as Type,j as World,Y as component,z as componentTypes,Q as prop}; | ||
class e{size;bytes;constructor(e){this.size=e,this.bytes=new Uint32Array(Math.ceil(e/32))}get(e){if(e<0||e>=this.size)throw new Error(`Bit index out of bounds: ${e}`);return 0!=(this.bytes[e>>>5]&1<<(31&e))}set(e){if(e<0||e>=this.size)throw new Error(`Bit index out of bounds: ${e}`);this.bytes[e>>>5]|=1<<(31&e)}unset(e){if(e<0||e>=this.size)throw new Error(`Bit index out of bounds: ${e}`);this.bytes[e>>>5]&=~(1<<(31&e))}clear(){this.bytes.fill(0)}}const t=[];class s{maxEntries;configParamName;localProcessingAllowed;data;corral;constructor(e,t,s=!1){this.maxEntries=e,this.configParamName=t,this.localProcessingAllowed=s;const i=new SharedArrayBuffer((e+2)*Uint32Array.BYTES_PER_ELEMENT);this.data=new Uint32Array(i);const r=new SharedArrayBuffer((e+2)*Uint32Array.BYTES_PER_ELEMENT);this.corral=new Uint32Array(r)}push(e){const t=this.corral[0];t>=this.maxEntries&&this.throwCapacityExceeded(),t&&this.corral[t]===e||(this.corral[t+2]=e,this.corral[0]+=1)}commit(e){if(!e&&this.localProcessingAllowed)throw new Error("Cannot use blind commit when log local processing is allowed");const t=this.corral[0];if(!t)return!0;let s=this.data[0];if(e&&(e.generation!==this.data[1]||e.index!==s||e.corralGeneration!==this.corral[1]||e.corralIndex!==this.corral[0]))return!1;const i=Math.min(t,this.maxEntries-s);for(this.data.set(this.corral.subarray(2,i+2),s+2),i<t&&this.data.set(this.corral.subarray(i+2,t+2),2),s+=t;s>=this.maxEntries;)s-=this.maxEntries,this.data[1]+=1;return this.data[0]=s,this.corral[0]=0,this.corral[1]+=1,e&&(e.index=s,e.generation=this.data[1]),!0}createPointer(e){return e?(e.index=this.data[0],e.generation=this.data[1],e.corralIndex=this.corral[0],e.corralGeneration=this.corral[1],e):{index:this.data[0],generation:this.data[1],corralIndex:this.corral[0],corralGeneration:this.corral[1]}}hasUpdatesSince(e){return this.checkPointer(e),!(e.index===this.data[0]&&e.generation===this.data[1]&&(e.corralGeneration===this.corral[1]?e.corralIndex===this.corral[0]:0===this.corral[0]))}processSince(e,s){this.checkPointers(e,s);let i=t;const r=s?.index??this.data[0],n=s?.generation??this.data[1];if(e.generation===n)if(e.index<r)i=[this.data,e.index+2,r+2,!1],e.index=r;else{const t=this.corral[0],s=this.corral[1];(e.corralGeneration===s?e.corralIndex<t:t)&&(i=[this.corral,e.corralIndex+2,t+2,!0],e.corralIndex=t,e.corralGeneration=s)}else i=[this.data,e.index+2,this.data.length,!1],e.index=0,e.generation=n;return i}processAndCommitSince(e){const s=this.processSince(e);return s[0]?s:this.commit(e)?t:this.processSince(e)}countSince(e,t){if(this.checkPointers(e,t),this.corral[0])throw new Error("Internal error, should commit log before counting");const s=e.index,i=t?.index??this.data[0],r=t?.generation??this.data[1];return e.index=i,e.generation=r,s===i&&e.generation===r?0:s<i?i-s:this.maxEntries-(s-i)}checkPointers(e,t){if(this.checkPointer(e),t&&(this.checkPointer(t),e.index>t.index&&e.generation>=t.generation))throw new RangeError("Internal error, start pointer exceeds end pointer")}checkPointer(e){const t=this.data[0];let s=e.generation;if(e.index===t?s+1<this.data[1]&&this.throwCapacityExceeded():(e.index>t&&(s+=1),s!==this.data[1]&&this.throwCapacityExceeded()),e.corralGeneration>this.corral[1])throw new Error("Internal error, pointer corral generation older than corral");if(e.corralGeneration===this.corral[1]&&e.corralIndex>this.corral[0])throw new Error("Internal error, pointer past end of log corral area")}throwCapacityExceeded(){throw new Error(`Log capacity exceeded, please raise ${this.configParamName} above ${this.maxEntries}`)}}class i{maxItems;configParamName;data;constructor(e,t){this.maxItems=e,this.configParamName=t,this.data=new Uint32Array(new SharedArrayBuffer((e+1)*Uint32Array.BYTES_PER_ELEMENT))}get length(){return this.data[0]}take(){const e=this.data[0]--;if(e<=0)throw new RangeError(`Pool capacity exceeded, please raise ${this.configParamName} above ${this.maxItems}`);return this.data[e]}refill(e){if(!e.length)return;const t=this.length,s=t+e.length;if(s>this.maxItems)throw new Error("Internal error, refill exceeded pool capacity");this.data.set(e,t+1),this.data[0]=s}fillWithDescendingIntegers(e){const t=this.length;for(let s=this.data.length-1;s>t;s--)this.data[s]=e++;this.data[0]=this.data.length-1}}const r=new TextEncoder,n=new TextDecoder;function a(e){throw new Error(`Component is not writable; use entity.write(${e.type.name}) to acquire a writable version`)}function o(e,t){if(e.__invalid)throw new Error(`Component instance for ${t.type.name} is no longer valid, as you already bound it to another entity`)}class h{defaultValue;constructor(e){this.defaultValue=e}static boolean;static uint8;static int8;static uint16;static int16;static uint32;static int32;static float32;static float64;static staticString;static dynamicString;static object;static weakObject;static ref;static backrefs}class c extends h{NumberArray;constructor(e){super(0),this.NumberArray=e}defineElastic(e,t){let s,i;t.updateBuffer=()=>{const r=e.capacity*this.NumberArray.BYTES_PER_ELEMENT,n=t.buffer?.byteLength!==r;(n||t.buffer!==s)&&(s=n?new SharedArrayBuffer(r):t.buffer,i=new this.NumberArray(s),n&&t.buffer&&i.set(new this.NumberArray(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){return o(this,e),i[e.index]},set(t){o(this,e),i[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){return o(this,e),i[e.index]},set(t){a(e)}})}defineFixed(e,t){const s=e.capacity*this.NumberArray.BYTES_PER_ELEMENT,i=new SharedArrayBuffer(s),r=new this.NumberArray(i);t.buffer=i,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){return o(this,e),r[e.index]},set(t){o(this,e),r[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){return o(this,e),r[e.index]},set(t){a(e)}})}}class d extends h{choices;choicesIndex=new Map;TypedArray;constructor(e){if(super(e[0]),this.choices=e,!e?.length)throw new Error("No choices specified for Type.staticString");e.length<256?this.TypedArray=Uint8Array:e.length<65536?this.TypedArray=Uint16Array:this.TypedArray=Uint32Array;for(let t=0;t<e.length;t++)this.choicesIndex.set(e[t],t)}defineElastic(e,t){let s,i;const r=this.choices,n=this.choicesIndex;t.updateBuffer=()=>{const r=e.capacity*this.TypedArray.BYTES_PER_ELEMENT,n=t.buffer?.byteLength!==r;(n||t.buffer!==s)&&(s=n?new SharedArrayBuffer(r):t.buffer,i=new this.TypedArray(s),n&&t.buffer&&i.set(new this.TypedArray(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){o(this,e);const t=i[e.index],s=r[t];if(void 0===s)throw new Error(`Invalid static string index: ${t}`);return s},set(t){o(this,e);const s=n.get(t);if(void 0===s)throw new Error(`Static string not in set: "${t}"`);i[e.index]=s}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){o(this,e);const t=i[e.index],s=r[t];if(void 0===s)throw new Error(`Invalid static string index: ${t}`);return s},set(t){a(e)}})}defineFixed(e,t){const s=this.choices,i=this.choicesIndex,r=e.capacity*this.TypedArray.BYTES_PER_ELEMENT,n=new SharedArrayBuffer(r),h=new this.TypedArray(n);t.buffer=n,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){o(this,e);const t=h[e.index],i=s[t];if(void 0===i)throw new Error(`Invalid static string index: ${t}`);return i},set(t){o(this,e);const s=i.get(t);if(void 0===s)throw new Error(`Static string not in set: "${t}"`);h[e.index]=s}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){o(this,e);const t=h[e.index],i=s[t];if(void 0===i)throw new Error(`Invalid static string index: ${t}`);return i},set(t){a(e)}})}}class l extends h{maxUtf8Length;lengthsStride;bytesStride;constructor(e){super(""),this.maxUtf8Length=e+e%2,this.lengthsStride=e/2+1,this.bytesStride=this.maxUtf8Length+2}defineElastic(e,t){let s,i,h;const c=this.maxUtf8Length,d=this.lengthsStride,l=this.bytesStride;t.updateBuffer=()=>{const r=e.capacity*(this.maxUtf8Length+Uint16Array.BYTES_PER_ELEMENT),n=t.buffer?.byteLength!==r;(n||t.buffer!==s)&&(s=n?new SharedArrayBuffer(r):t.buffer,i=new Uint16Array(s),h=new Uint8Array(s),n&&t.buffer&&h.set(new Uint8Array(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){o(this,e);const t=i[e.index*d];return n.decode(new Uint8Array(h.buffer,e.index*l+2,t))},set(t){o(this,e);const s=r.encode(t);if(s.byteLength>c)throw new Error(`Dynamic string length > ${c} after encoding: ${t}`);i[e.index*d]=s.byteLength,h.set(s,e.index*l+2)}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){o(this,e);const t=i[e.index*d];return n.decode(new Uint8Array(h.buffer,e.index*l+2,t))},set(t){a(e)}})}defineFixed(e,t){const s=this.maxUtf8Length,i=this.lengthsStride,h=this.bytesStride,c=e.capacity*(this.maxUtf8Length+Uint16Array.BYTES_PER_ELEMENT),d=new SharedArrayBuffer(c),l=new Uint16Array(d),f=new Uint8Array(d);t.buffer=d,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){o(this,e);const t=l[e.index*i];return n.decode(new Uint8Array(f.buffer,e.index*h+2,t))},set(t){o(this,e);const n=r.encode(t);if(n.byteLength>s)throw new Error(`Dynamic string length > ${s} after encoding: ${t}`);l[e.index*i]=n.byteLength,f.set(n,e.index*h+2)}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){o(this,e);const t=l[e.index*i];return n.decode(new Uint8Array(f.buffer,e.index*h+2,t))},set(t){a(e)}})}}const f=[];class u extends h{type;fieldName;trackDeletedBackrefs;constructor(e,t,s){super(f),this.type=e,this.fieldName=t,this.trackDeletedBackrefs=s}defineElastic(e,t){const s=this.fieldName?this.type?.__binding.fields.find((e=>e.name===this.fieldName)):void 0;if(this.fieldName&&!s)throw new Error(`Backrefs field ${e.type.name}.${t.name} refers to an unknown field ${this.type.name}.${this.fieldName}`);if(s&&s.type!==h.ref)throw new Error(`Backrefs field ${e.type.name}.${t.name} refers to a field ${this.type.name}.${this.fieldName} that is not a ref`);if(this.fieldName&&!this.type)throw new Error(`Backrefs selector has field but no component in ${e.type.name}.${t.name}`);if(this.type&&!this.fieldName&&!this.type.__binding.refFields.length)throw new Error(`Backrefs field ${e.type.name}.${t.name} refers to component ${this.type.name} that has no ref fields`);const i=this.trackDeletedBackrefs,r=e.dispatcher.indexer;r.registerSelector();const n=r.registerSelector(e.type,this.type,s?.seq,this.trackDeletedBackrefs),a={enumerable:!0,configurable:!0,get(){if(o(this,e),!i&&e.dispatcher.registry.includeRecentlyDeleted)throw new Error(`Backrefs field ${e.type.name}.${t.name} not configured to track recently deleted refs`);return r.getBackrefs(e.entityId,n)},set(t){if(o(this,e),t!==f)throw new Error("Backrefs properties are computed automatically, you cannot set them")}};Object.defineProperty(e.writableInstance,t.name,a),Object.defineProperty(e.readonlyInstance,t.name,a)}defineFixed(e,t){this.defineElastic(e,t)}}h.boolean=new class extends h{constructor(){super(!1)}defineElastic(e,t){let s,i;t.updateBuffer=()=>{const r=t.buffer?.byteLength!==e.capacity;(r||t.buffer!==s)&&(s=r?new SharedArrayBuffer(e.capacity):t.buffer,i=new Uint8Array(s),r&&t.buffer&&i.set(new Uint8Array(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){return o(this,e),Boolean(i[e.index])},set(t){o(this,e),i[e.index]=t?1:0}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){return o(this,e),Boolean(i[e.index])},set(t){a(e)}})}defineFixed(e,t){const s=new SharedArrayBuffer(e.capacity),i=new Uint8Array(s);t.buffer=s,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){return o(this,e),Boolean(i[e.index])},set(t){o(this,e),i[e.index]=t?1:0}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){return o(this,e),Boolean(i[e.index])},set(t){a(e)}})}},h.uint8=new c(Uint8Array),h.int8=new c(Int8Array),h.uint16=new c(Uint16Array),h.int16=new c(Int16Array),h.uint32=new c(Uint32Array),h.int32=new c(Int32Array),h.float32=new c(Float32Array),h.float64=new c(Float64Array),h.staticString=e=>new d(e),h.dynamicString=e=>new l(e),h.ref=new class extends h{constructor(){super(void 0)}defineElastic(e,t){let s,i;const r=e.dispatcher.indexer,n=e.dispatcher.registry,h=n.pool;r.registerSelector(),t.updateBuffer=()=>{const r=e.capacity*Int32Array.BYTES_PER_ELEMENT,n=t.buffer?.byteLength!==r;if(n||t.buffer!==s){if(s=n?new SharedArrayBuffer(r):t.buffer,i=new Int32Array(s),n&&t.buffer){const e=new Int32Array(t.buffer);i.set(e),i.fill(-1,e.length)}else i.fill(-1);t.buffer=s}},t.updateBuffer(),t.clearRef=(s,n,a)=>{if(a)throw new Error("Ref fields have no internal index");if(0!=(2147483648&i[e.index])!==s)throw new Error("Wrong ref stale state");const o=4194303&i[e.index],h=void 0!==n;h&&o!==n||(s?h&&(i[e.index]=-1):i[e.index]|=2147483648,r.trackRefChange(e.entityId,e.type,t.seq,void 0,o,-1,s))},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){o(this,e);const t=i[e.index];if(!(-1===t||2147483648&t&&!n.includeRecentlyDeleted))return h.borrowTemporarily(4194303&t)},set(s){if(o(this,e),s&&!n.hasShape(s.__id,n.Alive,!1))throw new Error("Referencing a deleted entity is not allowed");const a=i[e.index],h=s?.__id??-1;a!==h&&(i[e.index]=h,r.trackRefChange(e.entityId,e.type,t.seq,void 0,a,h,!0))}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){o(this,e);const t=i[e.index];if(!(-1===t||2147483648&t&&!n.includeRecentlyDeleted))return h.borrowTemporarily(4194303&t)},set(t){a(e)}})}defineFixed(e,t){const s=e.capacity*Int32Array.BYTES_PER_ELEMENT,i=new SharedArrayBuffer(s),r=new Int32Array(i);r.fill(-1),t.buffer=i;const n=e.dispatcher.indexer,h=e.dispatcher.registry,c=h.pool;n.registerSelector(),t.clearRef=(s,i,a)=>{if(a)throw new Error("Ref fields have no internal index");if(0!=(2147483648&r[e.index])!==s)throw new Error("Wrong ref stale state");const o=4194303&r[e.index],h=void 0!==i;h&&o!==i||(s?h&&(r[e.index]=-1):r[e.index]|=2147483648,n.trackRefChange(e.entityId,e.type,t.seq,void 0,o,-1,s))},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){o(this,e);const t=r[e.index];if(!(-1===t||2147483648&t&&!h.includeRecentlyDeleted))return c.borrowTemporarily(4194303&t)},set(s){if(o(this,e),s&&!h.hasShape(s.__id,h.Alive,!1))throw new Error("Referencing a deleted entity is not allowed");const i=r[e.index],a=s?.__id??-1;i!==a&&(r[e.index]=a,n.trackRefChange(e.entityId,e.type,t.seq,void 0,i,a,!0))}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){o(this,e);const t=r[e.index];if(!(-1===t||2147483648&t&&!h.includeRecentlyDeleted))return c.borrowTemporarily(4194303&t)},set(t){a(e)}})}},h.backrefs=(e,t,s=!1)=>new u(e,t,s),h.object=new class extends h{constructor(){super(void 0)}defineElastic(e,t){const s=[];t.localBuffer=s,t.updateBuffer=()=>{},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){return o(this,e),s[e.index]},set(t){o(this,e),s[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){return o(this,e),s[e.index]},set(t){a(e)}})}defineFixed(e,t){const s=new Array(e.capacity);t.localBuffer=s,t.updateBuffer=()=>{},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){return o(this,e),s[e.index]},set(t){o(this,e),s[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){return o(this,e),s[e.index]},set(t){a(e)}})}},h.weakObject=new class extends h{finalizers;constructor(){super(void 0)}defineElastic(e,t){const s=[];t.localBuffer=s,t.updateBuffer=()=>{};const i=this.initFinalizers(e);Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){o(this,e);const t=s[e.index];return null==t?t:t.deref()},set(r){if(o(this,e),null!=r){const s=new WeakRef(r);i?.register(r,{type:e.type,field:t,weakRef:s,id:e.entityId,index:e.index}),r=s}s[e.index]=r}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){o(this,e);const t=s[e.index];return null==t?t:t.deref()},set(t){a(e)}})}defineFixed(e,t){const s=new Array(e.capacity);t.localBuffer=s,t.updateBuffer=()=>{};const i=this.initFinalizers(e);Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){o(this,e);const t=s[e.index];return null==t?t:t.deref()},set(r){if(o(this,e),null!=r){const s=new WeakRef(r);i?.register(r,{type:e.type,field:t,weakRef:s,id:e.entityId,index:e.index}),r=s}s[e.index]=r}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){o(this,e);const t=s[e.index];return null==t?t:t.deref()},set(t){a(e)}})}initFinalizers(e){if(!e.trackedWrites)return;if(this.finalizers)return this.finalizers;const t=e.dispatcher;return t.writeLog&&"undefined"!=typeof FinalizationRegistry?(this.finalizers=new FinalizationRegistry((({type:e,field:s,weakRef:i,id:r,index:n})=>{s.localBuffer?.[n]===i&&t.registry.trackWrite(r,e)})),this.finalizers):void 0}};class g{type;fields;dispatcher;capacity;storage;elastic;readonlyInstance;writableInstance;shapeOffset;shapeMask;refFields;trackedWrites=!1;internallyIndexed=!1;entityId=0;index=0;constructor(e,t,s,i,r,n){this.type=e,this.fields=t,this.dispatcher=s,this.capacity=i,this.storage=r,this.elastic=n,this.readonlyInstance=new e,this.writableInstance=new e,this.shapeOffset=e.id>>5,this.shapeMask=1<<(31&e.id),this.refFields=t.filter((e=>e.type===h.ref))}}function p(e){if(!e.__binding)throw new Error(`Component ${e.name} not defined; add to world defs`)}class m{maxEntities;binding;fields;index;spares;constructor(e,t,s){this.maxEntities=e,this.binding=t,this.fields=s,this.growSpares(),this.growCapacity()}acquireIndex(e){let t=this.index[e];if(-1===t){if(this.spares[3]>0)t=this.spares[4+--this.spares[3]];else{if(this.spares[1]===this.spares[2]){if(!this.binding.elastic)throw new Error(`Storage exhausted for component ${this.binding.type.name}; raise its capacity above ${this.binding.capacity}`);this.binding.capacity=Math.min(this.maxEntities,2*this.binding.capacity),this.growCapacity()}t=this.spares[1]++}this.index[e]=t}return t}releaseIndex(e){if(-1===this.index[e])throw new Error(`Internal error, index for entity ${e} not allocated`);this.spares[3]===this.spares.length-4&&this.growSpares(),this.spares[4+this.spares[3]++]=this.index[e],this.index[e]=-1}growCapacity(){this.binding.dispatcher.stats.for(this.binding.type).capacity=this.binding.capacity;const e=this.ArrayType,t=e.BYTES_PER_ELEMENT!==this.spares?.[0];if(!this.index||t){const t=new e(new SharedArrayBuffer(this.maxEntities*e.BYTES_PER_ELEMENT));this.index?t.set(this.index):t.fill(-1),this.index=t}if(this.spares&&t){const t=new e(new SharedArrayBuffer(this.spares.length*e.BYTES_PER_ELEMENT));t.set(this.spares),t[0]=e.BYTES_PER_ELEMENT,this.spares=t}if(this.spares[2]=this.binding.capacity,this.binding.elastic)for(const e of this.fields)e.updateBuffer()}growSpares(){const e=this.ArrayType,t=this.spares?Math.min(this.maxEntities,2*(this.spares.length-4)):8,s=new e(new SharedArrayBuffer((4+t)*e.BYTES_PER_ELEMENT));this.spares?s.set(this.spares):(s[0]=e.BYTES_PER_ELEMENT,s[2]=this.binding.capacity),this.spares=s}get ArrayType(){const e=this.binding.capacity;return e<=127?Int8Array:e<=32767?Int16Array:Int32Array}}function y(e,t,s){const i=function(e){const t=e.schema,s=[];if(t){let i=0;for(const e in t){let r=t[e];(r instanceof h||"function"==typeof r)&&(r={type:r}),"function"==typeof r.type&&(r.type=r.type()),"default"in r||(r.default=r.type.defaultValue),s.push({name:e,seq:i++,type:r.type,default:r.default})}if(i>128)throw new Error(`Component ${e.name} declares too many fields`)}return s}(t),r=i.length?t.options?.storage??s.defaultComponentStorage:"sparse",n="sparse"===r?s.maxEntities:Math.min(s.maxEntities,t.options?.capacity??0),a=t.options?.initialCapacity??8;if(void 0!==t.options?.capacity){if("sparse"===r)throw new Error(`Component type ${t.name} cannot combine custom capacity with sparse storage`);if(t.options.capacity<=0)throw new Error(`Component type ${t.name} capacity option must be great than zero: got ${n}`);if(void 0!==t.options.initialCapacity)throw new Error(`Component type ${t.name} cannot have both capacity and initialCapacity options`)}if(("undefined"==typeof process||"test"!==process.env.NODE_ENV)&&t.__bind)throw new Error(`Component type ${t.name} is already in use in another world`);t.id=e;const o=new g(t,i,s,n||a,r,!n);t.__binding=o}function w(e){const t=e.__binding;for(const e of t.fields)t.elastic?e.type.defineElastic(t,e):e.type.defineFixed(t,e);let s,i;function r(e){e?(t.writableInstance.__invalid=!0,t.writableInstance=Object.create(i)):(t.readonlyInstance.__invalid=!0,t.readonlyInstance=Object.create(s))}switch(s=t.readonlyInstance,i=t.writableInstance,t.readonlyInstance=Object.create(s),t.readonlyInstance.__invalid=!0,t.writableInstance=Object.create(i),t.writableInstance.__invalid=!0,t.storage){case"sparse":t.dispatcher.stats.for(e).capacity=t.capacity,e.__bind=(e,s)=>(t.entityId=e,t.index=e,r(s),s?t.writableInstance:t.readonlyInstance),e.__allocate=e=>(t.entityId=e,t.index=e,r(!0),t.writableInstance);break;case"packed":{const s=new m(t.dispatcher.maxEntities,t,t.fields);e.__bind=(i,n)=>{if(t.entityId=i,t.index=s.index[i],-1===t.index)throw new Error(`Attempt to bind unacquired entity ${i} to ${e.name}`);return r(n),n?t.writableInstance:t.readonlyInstance},e.__allocate=e=>(t.entityId=e,t.index=s.acquireIndex(e),r(!0),t.writableInstance),e.__free=e=>{s.releaseIndex(e)};break}case"compact":throw new Error("Not yet implemented");default:throw new Error(`Invalid storage type "${t.storage}`)}}class _{__registry;__id;constructor(e){this.__registry=e}add(e,t){if(this.__checkMask(e,!0),!this.__registry.hasShape(this.__id,this.__registry.Alive,!1))throw new Error("Entity has been deleted");if(this.__registry.hasShape(this.__id,e,!1))throw new Error(`Entity already has a ${e.name} component`);return this.__registry.setShape(this.__id,e),this.__registry.dispatcher.stats.for(e).numEntities+=1,function(e,t,s){if(p(e),void 0!==s)for(const t in s)if(!e.schema?.[t])throw new Error(`Property ${t} not defined for component ${e.name}`);const i=e.__allocate(t);for(const t of e.__binding.fields)i[t.name]=s?.[t.name]??t.default}(e,this.__id,t),this}addAll(...e){for(let t=0;t<e.length;t++){const s=e[t];if("function"!=typeof s)throw new Error(`Bad arguments to bulk add: expected component type, got: ${s}`);let i=e[t+1];"function"==typeof i?i=void 0:t++,this.add(s,i)}return this}remove(e){this.__checkHas(e,!1),this.__checkMask(e,!0),this.__registry.clearShape(this.__id,e)}removeAll(...e){for(const t of e)this.remove(t)}has(e){return this.__checkMask(e,!1),this.__registry.hasShape(this.__id,e,!0)}read(e){return this.__checkMask(e,!1),this.__checkHas(e,!0),e.__bind(this.__id,!1)}write(e){return this.__checkMask(e,!0),this.__checkHas(e,!0),e.__binding.trackedWrites&&this.__registry.trackWrite(this.__id,e),e.__bind(this.__id,!0)}delete(){const e=this.__registry.Alive;for(const t of this.__registry.types)this.__registry.hasShape(this.__id,t,!1)&&(t!==e&&this.__checkMask(t,!0),this.__registry.clearShape(this.__id,t));this.__registry.queueDeletion(this.__id),this.__registry.dispatcher.indexer.clearAllRefs(this.__id,!1)}__checkMask(e,t){E(e,this.__registry.executingSystem,t)}__checkHas(e,t){if(!this.__registry.hasShape(this.__id,e,t))throw new Error(`Entity doesn't have a ${e.name} component`)}}function E(e,t,s){p(e);const i=s?t?.rwMasks.write:t?.rwMasks.read;if(!(!i||0!=((i[e.__binding.shapeOffset]??0)&e.__binding.shapeMask)))throw new Error(`System didn't mark component ${e.name} as ${s?"writable":"readable"}`)}function b(e,t){p(t);const s=t.__binding.shapeOffset;s>=e.length&&(e.length=s+1,e.fill(0,e.length,s)),e[s]|=t.__binding.shapeMask}class x{pool;entities=[];constructor(e){this.pool=e}add(e){this.entities.push(this.pool.borrowTemporarily(e))}clear(){this.entities.length&&this.entities.splice(0,1/0)}}class k{pool;entities=[];lookupTable;constructor(e,t){this.pool=e,this.lookupTable=new Int32Array(t),this.lookupTable.fill(-1)}add(e){const t=this.entities.push(this.pool.borrow(e))-1;this.lookupTable[e]=t}remove(e){const t=this.lookupTable[e];if(t<0)throw new Error("Internal error, entity not in list");this.pool.return(e),this.lookupTable[e]=-1;const s=this.entities.pop();t<this.entities.length&&(this.entities[t]=s,this.lookupTable[s.__id]=t)}has(e){return this.lookupTable[e]>=0}clear(){for(const e of this.entities)this.pool.return(e.__id);this.entities=[],this.lookupTable.fill(-1)}}var R;!function(e){e[e.all=1]="all",e[e.added=2]="added",e[e.removed=4]="removed",e[e.changed=8]="changed",e[e.addedOrChanged=16]="addedOrChanged",e[e.changedOrRemoved=32]="changedOrRemoved",e[e.addedChangedOrRemoved=64]="addedChangedOrRemoved"}(R||(R={}));const S=R.added|R.removed|R.changed|R.addedOrChanged|R.changedOrRemoved|R.addedChangedOrRemoved,P=R.changed|R.addedOrChanged|R.changedOrRemoved|R.addedChangedOrRemoved;class v{query;system;results={};flavors=0;withMask;withoutMask;trackMask;hasTransientResults;hasChangedResults;currentEntities;changedEntities;constructor(e,t){this.query=e,this.system=t,e.__results=this.results,e.__systemName=t.name}complete(){const t=this.system.dispatcher;if(this.hasTransientResults=Boolean(this.flavors&S),this.hasChangedResults=Boolean(this.flavors&P),this.hasChangedResults&&!this.trackMask)throw new Error("Query for changed entities must track at least one component");this.flavors&R.all?this.results.all=new k(t.registry.pool,t.maxEntities):this.currentEntities=new e(t.maxEntities),this.hasTransientResults&&this.allocateTransientResultLists(),this.flavors&&this.system.shapeQueries.push(this),this.hasChangedResults&&(this.changedEntities=new e(t.maxEntities),this.system.writeQueries.push(this))}allocateTransientResultLists(){this.flavors&R.added&&this.allocateResult("added"),this.flavors&R.removed&&this.allocateResult("removed"),this.flavors&R.changed&&this.allocateResult("changed"),this.flavors&R.addedOrChanged&&this.allocateResult("addedOrChanged"),this.flavors&R.changedOrRemoved&&this.allocateResult("changedOrRemoved"),this.flavors&R.addedChangedOrRemoved&&this.allocateResult("addedChangedOrRemoved")}allocateResult(e){const t=this.system.dispatcher;this.results[e]=new x(t.registry.pool)}clearTransientResults(){this.hasTransientResults&&(this.results.added?.clear(),this.results.removed?.clear(),this.results.changed?.clear(),this.results.addedOrChanged?.clear(),this.results.changedOrRemoved?.clear(),this.results.addedChangedOrRemoved?.clear(),this.changedEntities?.clear())}clearAllResults(){this.clearTransientResults(),this.results.all?.clear()}handleShapeUpdate(e){const t=this.system.dispatcher.registry,s=this.results.all?.has(e)??this.currentEntities.get(e),i=t.matchShape(e,this.withMask,this.withoutMask);i&&!s?(this.currentEntities?.set(e),this.results.all?.add(e),this.results.added?.add(e),this.results.addedOrChanged?.add(e),this.results.addedChangedOrRemoved?.add(e)):!i&&s&&(this.currentEntities?.unset(e),this.results.all?.remove(e),this.results.removed?.add(e),this.results.changedOrRemoved?.add(e),this.results.addedChangedOrRemoved?.add(e))}handleWrite(e,t,s){!this.changedEntities.get(e)&&(this.trackMask[t]??0)&s&&(this.changedEntities.set(e),this.results.changed?.add(e),this.results.addedOrChanged?.add(e),this.results.changedOrRemoved?.add(e),this.results.addedChangedOrRemoved?.add(e))}}class L{__callback;__userQuery;__query;__system;__lastTypes;constructor(e,t){this.__callback=e,this.__userQuery=t}__build(e){try{this.__system=e,this.__query=new v(this.__userQuery,e),this.__callback(this),this.__query.complete()}catch(t){throw t.message=`Failed to build query in system ${e.name}: ${t.message}`,t}}get and(){return this}get but(){return this}get also(){return this}get all(){return this.__query.flavors|=R.all,this}get added(){return this.__query.flavors|=R.added,this}get removed(){return this.__query.flavors|=R.removed,this}get changed(){return this.__query.flavors|=R.changed,this}get addedOrChanged(){return this.__query.flavors|=R.addedOrChanged,this}get changedOrRemoved(){return this.__query.flavors|=R.changedOrRemoved,this}get addedChangedOrRemoved(){return this.__query.flavors|=R.addedChangedOrRemoved,this}with(...e){return this.set(this.__system.rwMasks.read,e),this.set("withMask"),this}without(...e){return this.set(this.__system.rwMasks.read,e),this.set("withoutMask",e),this}using(...e){return this.set(this.__system.rwMasks.read,e),this}get track(){this.set("trackMask");for(const e of this.__lastTypes)e.__binding.trackedWrites=!0;return this}get read(){return this}get write(){return this.set(this.__system.rwMasks.write),this}set(e,t,s){if(e){if(t||(t=this.__lastTypes),!t)throw new Error("No component type to apply query modifier to");if(this.__lastTypes=t,"string"==typeof e){if(s&&this.__query[e])throw new Error(`Only one ${s} allowed`);this.__query[e]||(this.__query[e]=[]),e=this.__query[e]}else if(s&&e.some((e=>0!==e)))throw new Error(`Only one ${s} allowed`);for(const s of t)b(e,s)}}}class I{__results;__systemName;get all(){return this.__checkList("all"),this.__results.all.entities}get added(){return this.__checkList("added"),this.__results.added.entities}get removed(){return this.__checkList("removed"),this.__results.removed.entities}get changed(){return this.__checkList("changed"),this.__results.changed.entities}get addedOrChanged(){return this.__checkList("addedOrChanged"),this.__results.addedOrChanged.entities}get changedOrRemoved(){return this.__checkList("changedOrRemoved"),this.__results.changedOrRemoved.entities}get addedChangedOrRemoved(){return this.__checkList("addedChangedOrRemoved"),this.__results.addedChangedOrRemoved.entities}__checkList(e){if(!this.__results[e])throw new Error(`Query '${e}' not configured, please add .${e} to your query definition in system ${this.__systemName}`)}}var C,A;!function(e){e[e.RUNNING=0]="RUNNING",e[e.STOPPED=1]="STOPPED"}(C||(C={}));class T{type;constructor(e){this.type=e}}class O{static __system=!0;__queryBuilders=[];__dispatcher;time;delta;get name(){return this.constructor.name}query(e){const t=new I,s=new L(e,t);if(!this.__queryBuilders)throw new Error(`Attempt to create a new query after world initialized in system ${this.name}`);return this.__queryBuilders.push(s),t}attach(e){return new T(e)}createEntity(...e){return this.__dispatcher.createEntity(e)}accessRecentlyDeletedData(e=!0){this.__dispatcher.registry.includeRecentlyDeleted=e}initialize(){}execute(){}}class B{system;dispatcher;rwMasks={read:[],write:[]};shapeQueries=[];writeQueries=[];hasWriteQueries;processedEntities;shapeLogPointer;writeLogPointer;state=C.RUNNING;get name(){return this.system.name}constructor(t,s){this.system=t,this.dispatcher=s,t.__dispatcher=s,this.shapeLogPointer=s.shapeLog.createPointer(),this.writeLogPointer=s.writeLog?.createPointer(),this.processedEntities=new e(s.maxEntities);for(const e of t.__queryBuilders)e.__build(this);t.__queryBuilders=null,this.hasWriteQueries=!!this.writeQueries.length}replaceAttachmentPlaceholders(){for(const e in this.system)if(this.system[e]instanceof T){const t=this.system[e].type,s=this.dispatcher.systemsByClass.get(t);if(!s)throw new Error(`Attached system ${t.name} not defined in this world`);this.system[e]=s}}async initialize(){await Promise.resolve(this.system.initialize())}execute(e,t){this.state===C.RUNNING&&(this.system.time=e,this.system.delta=t,this.runQueries(),this.system.execute())}runQueries(){const e=this.dispatcher.shapeLog.hasUpdatesSince(this.shapeLogPointer),t=this.hasWriteQueries&&this.dispatcher.writeLog.hasUpdatesSince(this.writeLogPointer);if(e||t){this.processedEntities.clear();for(const e of this.shapeQueries)e.clearTransientResults();e&&this.__updateShapeQueries(),t&&this.__updateWriteQueries()}}__updateShapeQueries(){const e=this.dispatcher.shapeLog;let t,s,i;for(;[t,s,i]=e.processSince(this.shapeLogPointer),t;)for(let e=s;e<i;e++){const s=t[e];if(!this.processedEntities.get(s)){this.processedEntities.set(s);for(const e of this.shapeQueries)e.handleShapeUpdate(s)}}}__updateWriteQueries(){const e=this.dispatcher.writeLog;let t,s,i;for(;[t,s,i]=e.processSince(this.writeLogPointer),t;)for(let e=s;e<i;e++){const s=t[e],i=4194303&s;if(!this.processedEntities.get(i)){const e=s>>>22;for(const t of this.writeQueries)t.handleWrite(i,e>>5,1<<(31&e))}}}stop(){if(this.state!==C.STOPPED){this.state=C.STOPPED;for(const e of this.shapeQueries)e.clearAllResults()}}restart(){if(this.state===C.STOPPED){const e=this.dispatcher.registry,t=e.Alive;for(let s=0;s<this.dispatcher.maxEntities;s++)if(e.hasShape(s,t,!1))for(const e of this.shapeQueries)e.handleShapeUpdate(s);for(const e of this.shapeQueries)e.clearTransientResults();this.dispatcher.shapeLog.createPointer(this.shapeLogPointer),this.dispatcher.writeLog?.createPointer(this.writeLogPointer)}this.state=C.RUNNING}}class N{registry;borrowed;borrowCounts;spares=[];temporarilyBorrowedIds=[];constructor(e,t){this.registry=e,this.borrowed=Array.from({length:t}),this.borrowCounts=new Int32Array(t)}borrow(e){this.borrowCounts[e]+=1;let t=this.borrowed[e];return t||(t=this.borrowed[e]=this.spares.pop()??new _(this.registry),t.__id=e),t}borrowTemporarily(e){const t=this.borrow(e);return this.temporarilyBorrowedIds.push(e),t}returnTemporaryBorrows(){for(const e of this.temporarilyBorrowedIds)this.return(e);this.temporarilyBorrowedIds.splice(0,1/0)}return(e){if(!this.borrowCounts[e])throw new Error("Internal error, returning entity with no borrows");--this.borrowCounts[e]<=0&&(this.spares.push(this.borrowed[e]),this.borrowed[e]=void 0)}}class F{types;dispatcher;stride;shapes;staleShapes;entityIdPool;pool;executingSystem;includeRecentlyDeleted=!1;deletionLog;prevDeletionPointer;oldDeletionPointer;removalLog;prevRemovalPointer;oldRemovalPointer;Alive=class{};constructor(e,t,r,n,a){this.types=n,this.dispatcher=a,this.stride=Math.ceil(n.length/32);const o=e*this.stride*4;this.shapes=new Uint32Array(new SharedArrayBuffer(o)),this.staleShapes=new Uint32Array(new SharedArrayBuffer(o)),this.entityIdPool=new i(e,"maxEntities"),this.entityIdPool.fillWithDescendingIntegers(0),this.pool=new N(this,e),this.deletionLog=new s(t,"maxLimboEntities"),this.prevDeletionPointer=this.deletionLog.createPointer(),this.oldDeletionPointer=this.deletionLog.createPointer(),this.removalLog=new s(r,"maxLimboComponents"),this.prevRemovalPointer=this.removalLog.createPointer(),this.oldRemovalPointer=this.removalLog.createPointer()}initializeComponentTypes(){this.types.unshift(this.Alive);let e=0;for(const t of this.types)y(e++,t,this.dispatcher);for(const e of this.types)w(e);{const e=this.types[0].__binding;if(0!==e.shapeOffset||1!==e.shapeMask)throw new Error("Alive component was not assigned first available shape mask")}}createEntity(e){const t=this.entityIdPool.take(),s=t*this.stride;this.shapes[s]=1,this.stride>1&&this.shapes.fill(0,s+1,s+this.stride);const i=this.pool.borrowTemporarily(t);return e&&i.addAll(...e),this.dispatcher.stats.numEntities+=1,i}queueDeletion(e){this.deletionLog.push(e)}flush(){this.includeRecentlyDeleted=!1,this.pool.returnTemporaryBorrows(),this.deletionLog.commit(),this.removalLog.commit()}processEndOfFrame(){this.processDeletionLog(),this.processRemovalLog()}processDeletionLog(){this.deletionLog.commit();let e,t,s,i=0;for(;[e,t,s]=this.deletionLog.processSince(this.oldDeletionPointer,this.prevDeletionPointer),e;){for(let i=t;i<s;i++)this.dispatcher.indexer.clearAllRefs(e[i],!0);const r=e.subarray(t,s);this.entityIdPool.refill(r),i+=r.length}this.dispatcher.stats.numEntities-=i,this.dispatcher.stats.maxLimboEntities=i,this.deletionLog.createPointer(this.prevDeletionPointer)}processRemovalLog(){this.removalLog.commit();let e,t,s,i=0;for(;[e,t,s]=this.removalLog.processSince(this.oldRemovalPointer,this.prevRemovalPointer),e;){for(let i=t;i<s;i++){const t=e[i],s=4194303&t,r=t>>>22,n=this.types[r],a=s*this.stride+n.__binding.shapeOffset,o=n.__binding.shapeMask;0==(this.shapes[a]&o)&&(this.staleShapes[a]&=~o,this.clearRefs(s,n,!0),n.__free?.(s))}i+=s-t}this.dispatcher.stats.maxLimboComponents=i,this.removalLog.createPointer(this.prevRemovalPointer)}hasShape(e,t,s){const i=e*this.stride+t.__binding.shapeOffset,r=t.__binding.shapeMask;return 0!=(this.shapes[i]&r)||!(!s||!this.includeRecentlyDeleted||0==(this.staleShapes[i]&r))}setShape(e,t){const s=e*this.stride+t.__binding.shapeOffset,i=t.__binding.shapeMask;this.shapes[s]|=i,this.staleShapes[s]|=i,this.dispatcher.shapeLog.push(e)}clearShape(e,t){const s=this.clearRefs(e,t,!1);(t.__free||s)&&this.removalLog.push(e|t.id<<22),this.shapes[e*this.stride+t.__binding.shapeOffset]&=~t.__binding.shapeMask,this.dispatcher.shapeLog.push(e),this.dispatcher.stats.for(t).numEntities-=1}trackWrite(e,t){this.dispatcher.writeLog.push(e|t.id<<22)}clearRefs(e,t,s){const i=!!t.__binding.refFields.length;if(i){t.__bind(e,!0);for(const e of t.__binding.refFields)e.clearRef(s)}return i}matchShape(e,t,s){const i=e*this.stride;if(t)for(let e=0;e<t.length;e++){const s=t[e];if((this.shapes[i+e]&s)!==s)return!1}if(s)for(let e=0;e<s.length;e++){const t=s[e];if(0!=(this.shapes[i+e]&t))return!1}return!0}}class ${_numEntities=0;maxEntities=0;capacity=0;get numEntities(){return this._numEntities}set numEntities(e){this._numEntities=e,e>this.maxEntities&&(this.maxEntities=e)}toString(){return`${this.numEntities.toLocaleString()} of ${this.maxEntities.toLocaleString()} peak (capacity ${this.capacity.toLocaleString()})`}}class M{frames=0;_numEntities=0;maxEntities=0;_maxLimboEntities=0;_maxLimboComponents=0;_maxRefChangesPerFrame=0;_maxShapeChangesPerFrame=0;_maxWritesPerFrame=0;components=Object.create(null);get numEntities(){return this._numEntities}set numEntities(e){this._numEntities=e,e>this.maxEntities&&(this.maxEntities=e)}get maxLimboEntities(){return this._maxLimboEntities}set maxLimboEntities(e){e>this._maxLimboEntities&&(this._maxLimboEntities=e)}get maxLimboComponents(){return this._maxLimboComponents}set maxLimboComponents(e){e>this._maxLimboComponents&&(this._maxLimboComponents=e)}get maxRefChangesPerFrame(){return this._maxRefChangesPerFrame}set maxRefChangesPerFrame(e){e>this._maxRefChangesPerFrame&&(this._maxRefChangesPerFrame=e)}get maxShapeChangesPerFrame(){return this._maxShapeChangesPerFrame}set maxShapeChangesPerFrame(e){e>this._maxShapeChangesPerFrame&&(this._maxShapeChangesPerFrame=e)}get maxWritesPerFrame(){return this._maxWritesPerFrame}set maxWritesPerFrame(e){e>this._maxWritesPerFrame&&(this._maxWritesPerFrame=e)}for(e){return this.components[e.name]=this.components[e.name]??new $}toString(){return`World stats:\n frames: ${this.frames.toLocaleString()}\n entities: ${this.numEntities.toLocaleString()} of ${this.maxEntities.toLocaleString()} max (${this.maxLimboEntities.toLocaleString()} limbo max)\n refs: ${this.maxRefChangesPerFrame.toLocaleString()} ref changes/frame max\n logs: ${this.maxShapeChangesPerFrame.toLocaleString()} shape changes/frame max, ${this.maxWritesPerFrame.toLocaleString()} writes/frame max`}}!function(e){e[e.REFERENCE=0]="REFERENCE",e[e.UNREFERENCE=1073741824]="UNREFERENCE",e[e.RELEASE=2147483648]="RELEASE"}(A||(A={}));const U=A.REFERENCE|A.UNREFERENCE|A.RELEASE;class D{targetEntityId;selector;dispatcher;entities=[];tags;entityIndex;clearing=!1;registry;constructor(e,t,s){this.targetEntityId=e,this.selector=t,this.dispatcher=s;const i=t.sourceType?.__binding;t.matchType&&(t.matchSeq||1===i.refFields.length)&&!i.internallyIndexed||(this.tags=[]),this.registry=s.registry}clearAllRefs(e){if(!this.tags)throw new Error("Unreferencing an untagged tracker");this.clearing=!0;for(let t=0;t<this.entities.length;t++){const s=this.entities[t].__id,i=this.tags[t];if("number"==typeof i)this.clearRef(s,i,e);else for(const t of i)this.clearRef(s,t,e)}this.entities=[],this.tags=[],this.entityIndex=void 0,this.clearing=!1}clearRef(e,t,s){const i=511&t,r=t>>>9&127,n=t>>>16,a=this.registry.types[i];E(a,this.registry.executingSystem,!0),a.__bind(e,!0),a.__binding.fields[r].clearRef(s,this.targetEntityId,n)}trackReference(e,t,s,i,r){if(this.clearing)throw new Error("Cannot track a new reference while clearing tracker");r&&this.checkWriteMask();let n=this.getEntityIndex(e);void 0===n&&(n=this.addEntity(e,r)),this.addTag(n,this.makeTag(t,s,i))}trackUnreference(e,t,s,i,r){if(this.clearing)return;r&&this.checkWriteMask();const n=this.getEntityIndex(e);if(void 0===n)throw new Error("Entity backref not tracked");this.removeTag(n,this.makeTag(t,s,i))&&this.removeEntity(n,e,r)}getEntityIndex(e){if(this.entityIndex)return this.entityIndex[e];const t=this.entities.findIndex((t=>t.__id===e));return t>=0?t:void 0}indexEntities(){if(this.entityIndex)throw new Error("Entities already indexed");this.entityIndex=new Array(this.dispatcher.maxEntities);for(let e=0;e<this.entities.length;e++)this.entityIndex[this.entities[e].__id]=e}addTag(e,t){if(!this.tags)return;const s=this.tags[e];if(void 0===s)this.tags[e]=t;else if("number"==typeof s){if(s===t)throw new Error("Ref already tracked");this.tags[e]=[s,t]}else if(Array.isArray(s)){if(s.includes(t))throw new Error("Ref already tracked");if(s.length>=1e3){(this.tags[e]=new Set(s)).add(t)}else s.push(t)}else{if(s.has(t))throw new Error("Ref already tracked");s.add(t)}}removeTag(e,t){if(!this.tags)return!0;const s=this.tags[e];if(void 0===s)throw new Error("Ref not tracked");if("number"==typeof s){if(s!==t)throw new Error("Ref not tracked");return delete this.tags[e],!0}if(Array.isArray(s)){const e=s.indexOf(t);if(-1===e)throw new Error("Ref not tracked");return s.splice(e,1),!this.tags.length}return s.delete(t),!s.size}makeTag(e,t,s){return e|t<<9|(void 0===s?0:s<<16)}addEntity(e,t){const s=this.entities.length;return this.entities.push(this.registry.pool.borrow(e)),this.entityIndex?this.entityIndex[e]=s:s>100&&this.indexEntities(),t&&this.trackBackrefsChange(),s}removeEntity(e,t,s){this.registry.pool.return(t);const i=this.entities.pop();this.entityIndex&&delete this.entityIndex[e],this.entities.length>e&&(this.entities[e]=i,this.entityIndex&&(this.entityIndex[i.__id]=e)),s&&this.trackBackrefsChange()}trackBackrefsChange(){for(const e of this.selector.targetTypes)e.__binding.trackedWrites&&this.registry.trackWrite(this.targetEntityId,e)}checkWriteMask(){const e=this.registry.executingSystem;for(const t of this.selector.targetTypes)E(t,e,!0)}}class q{dispatcher;maxRefChangesPerFrame;refLog;refLogPointer;refLogStatsPointer;selectorIdsBySourceKey=new Map;selectors=[];trackers=new Map;registry;constructor(e,t){this.dispatcher=e,this.maxRefChangesPerFrame=t,this.registry=e.registry}processEndOfFrame(){this.flush(),this.dispatcher.stats.maxRefChangesPerFrame=this.refLog?.countSince(this.refLogStatsPointer)??0}registerSelector(e,t,i,r=!1){e&&p(e),t&&p(t),this.refLog||(this.refLog=new s(this.maxRefChangesPerFrame,"maxRefChangesPerFrame",!0),this.refLogPointer=this.refLog.createPointer(),this.refLogStatsPointer=this.refLog.createPointer());const n=t?void 0===i?-2-t.id:t.id|i<<9:-1;let a=this.selectorIdsBySourceKey.get(n);if(void 0===a){this.selectors.length||(r=!0);const s={id:this.selectors.length,targetTypes:e?[e]:[],sourceType:t,matchType:!!t,matchSeq:void 0!==i,sourceTypeId:t?.id,sourceSeq:i,trackStale:r};if(this.selectors.push(s),a=s.id,this.selectorIdsBySourceKey.set(n,a),a>512)throw new Error("Too many distinct backrefs selectors")}else{const t=this.selectors[a];t.trackStale=t.trackStale||r,e&&t.targetTypes.push(e)}return a}getBackrefs(e,t=0){const s=this.selectors[t];return this.getOrCreateTracker(s,e,this.registry.includeRecentlyDeleted).entities}trackRefChange(e,t,s,i,r,n,a){if(!this.refLog)throw new Error("Trying to trackRefChange without a refLog");if(r===n)throw new Error("No-op call to trackRefChange");-1!==r&&this.pushRefLogEntry(e,t,s,i,r,a?A.RELEASE:A.UNREFERENCE),-1!==n&&this.pushRefLogEntry(e,t,s,i,n,A.REFERENCE)}clearAllRefs(e,t){this.selectors.length&&this.getTracker(this.selectors[0],e,t)?.clearAllRefs(t)}pushRefLogEntry(e,t,s,i,r,n){const a=void 0!==i;if(a!==t.__binding.internallyIndexed)throw new Error("Inconsistent internally indexed flag");this.refLog.push(e|t.id<<22),this.refLog.push(r|s<<22|n|(a?2**29:0)),a&&this.refLog.push(i),this.processEntry(e,t.id,s,i,r,n,!0)}getOrCreateTracker(e,t,s){let i,r=this.getTracker(e,t,s);if(r)return r;if(s&&!e.trackStale)throw new Error("Selector not configured for stale tracking");return r=new D(t,e,this.dispatcher),this.trackers.set(t|e.id<<22,r),e.trackStale&&(i=new D(t,e,this.dispatcher),this.trackers.set(t|e.id<<22|2**31,i)),s?i:r}getTracker(e,t,s){return this.trackers.get(t|e.id<<22|(s?2**31:0))}flush(){if(this.refLog)for(;;){const[e,t,s,i]=this.refLog.processAndCommitSince(this.refLogPointer);if(!e)break;if(!i)for(let i=t;i<s;i+=2){const t=e[i],s=e[i+1],r=4194303&t,n=t>>>22,a=4194303&s,o=s>>>22&127,h=(s&U)>>>30,c=0!=(s&2**29),d=c?e[i+2]:void 0;c&&(i+=1),this.processEntry(r,n,o,d,a,h,!1)}}}processEntry(e,t,s,i,r,n,a){for(let o=0;o<this.selectors.length;o++){const h=this.selectors[o];if(!(h.matchType&&h.sourceTypeId!==t||h.matchSeq&&h.sourceSeq!==s)){if(n===A.REFERENCE||n===A.UNREFERENCE){const o=this.getOrCreateTracker(h,r,!1);n===A.REFERENCE?o.trackReference(e,t,s,i,a):o.trackUnreference(e,t,s,i,a)}if(h.trackStale&&(n===A.REFERENCE||n===A.RELEASE)){const o=this.getOrCreateTracker(h,r,!0);n===A.REFERENCE?o.trackReference(e,t,s,i,a):o.trackUnreference(e,t,s,i,a)}}}}}const j="undefined"!=typeof window&&void 0!==window.performance?performance.now.bind(performance):Date.now.bind(Date);class W extends O{__callback;execute(){this.__callback(this)}}class z{maxEntities;defaultComponentStorage;registry;systems;systemsByClass=new Map;lastTime=j()/1e3;executing;shapeLog;writeLog;shapeLogFramePointer;writeLogFramePointer;stats;indexer;userCallbackSystem;callbackSystem;deferredControls=new Map;constructor({defs:e,maxEntities:t=1e4,maxLimboEntities:i=Math.ceil(t/5),maxLimboComponents:r=Math.ceil(t/5),maxShapeChangesPerFrame:n=2*t,maxWritesPerFrame:a=4*t,maxRefChangesPerFrame:o=t,defaultComponentStorage:h="sparse"}){if(t>4194304)throw new Error("maxEntities too high, the limit is 4194304");const{componentTypes:c,systemTypes:d}=this.splitDefs(e);if(c.length>512)throw new Error("Too many component types, the limit is 512");this.stats=new M,this.maxEntities=t,this.defaultComponentStorage=h,this.shapeLog=new s(n,"maxShapeChangesPerFrame"),this.shapeLogFramePointer=this.shapeLog.createPointer(),this.registry=new F(t,i,r,c.flat(1/0),this),this.indexer=new q(this,o),this.registry.initializeComponentTypes(),this.systems=this.normalizeAndInitSystems(d),this.systems.some((e=>e.hasWriteQueries))&&(this.writeLog=new s(a,"maxWritesPerFrame"),this.writeLogFramePointer=this.writeLog.createPointer()),this.userCallbackSystem=new W,this.callbackSystem=new B(this.userCallbackSystem,this),this.callbackSystem.rwMasks.read=void 0,this.callbackSystem.rwMasks.write=void 0}normalizeAndInitSystems(e){const t=[],s=e.flat(1/0);for(let e=0;e<s.length;e++){const i=s[e],r=new i,n=s[e+1];n&&"function"!=typeof n&&(Object.assign(r,n),e++);const a=new B(r,this);t.push(a),this.systemsByClass.set(i,a)}for(const e of t)e.replaceAttachmentPlaceholders();return t}splitDefs(e){const t=[],s=[];let i=!1;for(const r of e.flat(1/0))if("function"==typeof r)i=r.__system,(i?s:t).push(r);else{if(!i)throw new Error("Unexpected value in world defs: "+r);s.push(r),i=!1}return{componentTypes:t,systemTypes:s}}async initialize(){await Promise.all(this.systems.map((e=>e.initialize())))}async execute(e,t,s){if(this.executing)throw new Error("Recursive system execution not allowed");this.executing=!0,void 0===e&&(e=j()/1e3),void 0===t&&(t=e-this.lastTime),this.lastTime=e;for(const i of s??this.systems)this.registry.executingSystem=i,i.execute(e,t),this.flush();this.registry.executingSystem=void 0,this.executing=!1,this.processEndOfFrame()}executeFunction(e){if(this.executing)throw new Error("Ad hoc function execution not allowed while world is executing");this.executing=!0,this.registry.executingSystem=this.callbackSystem,this.userCallbackSystem.__callback=e,this.callbackSystem.execute(0,0),this.flush(),this.registry.executingSystem=void 0,this.executing=!1,this.processEndOfFrame()}processEndOfFrame(){this.registry.processEndOfFrame(),this.indexer.processEndOfFrame(),this.gatherFrameStats(),this.processDeferredControls()}gatherFrameStats(){this.stats.frames+=1,this.stats.maxShapeChangesPerFrame=this.shapeLog.countSince(this.shapeLogFramePointer),this.stats.maxWritesPerFrame=this.writeLog?.countSince(this.writeLogFramePointer)??0}flush(){this.registry.flush(),this.indexer.flush(),this.shapeLog.commit(),this.writeLog?.commit()}createEntity(e){const t=this.registry.createEntity(e);return this.executing||this.flush(),t}control(e){this.checkControlOverlap(e),this.deferRequestedRunState(e.stop,C.STOPPED),this.deferRequestedRunState(e.restart,C.RUNNING),this.executing||this.processDeferredControls()}deferRequestedRunState(e,t){for(const s of e.flat(1/0)){if(!s.__system)continue;const e=this.systemsByClass.get(s);if(!e)throw new Error(`System ${s.name} not defined for this world`);this.deferredControls.set(e,t)}}checkControlOverlap(e){const t=new Set;for(const s of e.stop.flat(1/0))s.__system&&t.add(s);for(const s of e.restart.flat(1/0))if(s.__system&&t.has(s))throw new Error(`Request to both stop and restart system ${s.name}`)}processDeferredControls(){if(this.deferredControls.size){for(const[e,t]of this.deferredControls.entries())switch(t){case C.STOPPED:e.stop();break;case C.RUNNING:e.restart()}this.deferredControls.clear()}}}const Q={};class Y{__dispatcher;static async create(e){const t=new Y(e,Q);return await t.__dispatcher.initialize(),t}constructor(e,t){if(t!==Q)throw new Error("Don't call World constructor directly; use World.create instead");this.__dispatcher=new z(e)}build(e){this.__dispatcher.executeFunction(e)}createEntity(...e){this.__dispatcher.createEntity(e)}execute(e,t){return this.__dispatcher.execute(e,t)}control(e){this.__dispatcher.control(e)}get stats(){return this.__dispatcher.stats}}function G(e){return function(t,s){t.constructor.schema||(t.constructor.schema={});const i="type"in e?e:{type:e};t.constructor.schema[s]=i}}const H=[];function V(e){if("function"!=typeof e)return t=>{t.options=e,H.push(t)};H.push(e)}export{_ as Entity,I as Query,O as System,h as Type,Y as World,V as component,H as componentTypes,G as field}; | ||
//# sourceMappingURL=index.min.js.map |
@@ -132,4 +132,4 @@ interface LogPointer { | ||
} | ||
interface SystemType { | ||
new (): System; | ||
interface SystemType<S extends System> { | ||
new (): S; | ||
} | ||
@@ -142,7 +142,10 @@ declare abstract class System { | ||
delta: number; | ||
// TODO: support schedule builder | ||
get name(): string; | ||
query(buildCallback: (q: QueryBuilder) => void): Query; | ||
attach<S extends System>(systemType: SystemType<S>): S; | ||
createEntity(...initialComponents: (ComponentType<any> | any)[]): Entity; | ||
accessRecentlyDeletedData(toggle?: boolean): void; | ||
abstract execute(): void; | ||
initialize(): void | Promise<void>; // eslint-disable-line @typescript-eslint/no-empty-function | ||
execute(): void; // eslint-disable-line @typescript-eslint/no-empty-function | ||
} | ||
@@ -162,2 +165,4 @@ declare class SystemBox { | ||
constructor(system: System, dispatcher: Dispatcher); | ||
replaceAttachmentPlaceholders(): void; | ||
initialize(): Promise<void>; | ||
execute(time: number, delta: number): void; | ||
@@ -169,3 +174,2 @@ private runQueries; | ||
restart(): void; | ||
suspend(): void; | ||
} | ||
@@ -231,3 +235,3 @@ declare class ComponentStats { | ||
// https://stackoverflow.com/questions/67467302/type-for-an-interleaved-array-of-classes-and-values | ||
type DefsArray = (ComponentType<any> | SystemType | any | DefsArray)[]; | ||
type DefsArray = (ComponentType<any> | SystemType<System> | any | DefsArray)[]; | ||
interface WorldOptions { | ||
@@ -245,3 +249,2 @@ defs: DefsArray; | ||
stop: DefsArray; | ||
suspend: DefsArray; | ||
restart: DefsArray; | ||
@@ -254,3 +257,3 @@ } | ||
private readonly systems; | ||
private readonly systemsByClass; | ||
readonly systemsByClass: Map<SystemType<System>, SystemBox>; | ||
private lastTime; | ||
@@ -270,3 +273,4 @@ executing: boolean; | ||
private splitDefs; | ||
execute(time?: number, delta?: number, systems?: SystemBox[]): void; | ||
initialize(): Promise<void>; | ||
execute(time?: number, delta?: number, systems?: SystemBox[]): Promise<void>; | ||
executeFunction(fn: (system: System) => void): void; | ||
@@ -366,2 +370,3 @@ private processEndOfFrame; | ||
static weakObject: Type<any>; | ||
// TODO: add autoremove/autodelete when nulled out | ||
static ref: Type<Entity | undefined>; | ||
@@ -393,3 +398,6 @@ static backrefs: (type?: ComponentType<any>, fieldName?: string, trackDeletedBackrefs?: boolean) => Type<Entity[]>; | ||
} | ||
interface ComponentType<C> { | ||
interface Component { | ||
__invalid?: boolean; | ||
} | ||
interface ComponentType<C extends Component> { | ||
new (): C; | ||
@@ -416,4 +424,4 @@ schema?: Schema; | ||
readonly elastic: boolean; | ||
readonly readonlyInstance: C; | ||
readonly writableInstance: C; | ||
readonlyInstance: C; | ||
writableInstance: C; | ||
readonly shapeOffset: number; | ||
@@ -430,6 +438,7 @@ readonly shapeMask: number; | ||
private readonly __dispatcher; | ||
constructor(options: WorldOptions); | ||
static create(options: WorldOptions): Promise<World>; | ||
private constructor(); | ||
build(callback: (system: System) => void): void; | ||
createEntity(...initialComponents: (ComponentType<any> | any)[]): void; | ||
execute(time?: number, delta?: number): void; | ||
execute(time?: number, delta?: number): Promise<void>; | ||
control(options: ControlOptions): void; | ||
@@ -442,7 +451,7 @@ get stats(): Stats; | ||
} | ||
declare function prop<JSType>(practicalOptions: PropOptions<JSType> | Type<any> | (() => Type<any>)): (target: any, name: string) => void; | ||
declare function field<JSType>(practicalOptions: PropOptions<JSType> | Type<any> | (() => Type<any>)): (target: any, name: string) => void; | ||
declare const componentTypes: ComponentType<any>[]; | ||
declare function component(constructor: ComponentType<any>): void; | ||
declare function component(options: ComponentOptions): (constructor: ComponentType<any>) => void; | ||
export { World, Type, Entity, System, SystemType, componentTypes, component, prop, Query, ComponentType }; | ||
export { World, Type, Entity, System, SystemType, componentTypes, component, field, Query, ComponentType }; | ||
//# sourceMappingURL=index.umd.d.ts.map |
@@ -132,4 +132,4 @@ interface LogPointer { | ||
} | ||
interface SystemType { | ||
new (): System; | ||
interface SystemType<S extends System> { | ||
new (): S; | ||
} | ||
@@ -142,7 +142,10 @@ declare abstract class System { | ||
delta: number; | ||
// TODO: support schedule builder | ||
get name(): string; | ||
query(buildCallback: (q: QueryBuilder) => void): Query; | ||
attach<S extends System>(systemType: SystemType<S>): S; | ||
createEntity(...initialComponents: (ComponentType<any> | any)[]): Entity; | ||
accessRecentlyDeletedData(toggle?: boolean): void; | ||
abstract execute(): void; | ||
initialize(): void | Promise<void>; // eslint-disable-line @typescript-eslint/no-empty-function | ||
execute(): void; // eslint-disable-line @typescript-eslint/no-empty-function | ||
} | ||
@@ -162,2 +165,4 @@ declare class SystemBox { | ||
constructor(system: System, dispatcher: Dispatcher); | ||
replaceAttachmentPlaceholders(): void; | ||
initialize(): Promise<void>; | ||
execute(time: number, delta: number): void; | ||
@@ -169,3 +174,2 @@ private runQueries; | ||
restart(): void; | ||
suspend(): void; | ||
} | ||
@@ -231,3 +235,3 @@ declare class ComponentStats { | ||
// https://stackoverflow.com/questions/67467302/type-for-an-interleaved-array-of-classes-and-values | ||
type DefsArray = (ComponentType<any> | SystemType | any | DefsArray)[]; | ||
type DefsArray = (ComponentType<any> | SystemType<System> | any | DefsArray)[]; | ||
interface WorldOptions { | ||
@@ -245,3 +249,2 @@ defs: DefsArray; | ||
stop: DefsArray; | ||
suspend: DefsArray; | ||
restart: DefsArray; | ||
@@ -254,3 +257,3 @@ } | ||
private readonly systems; | ||
private readonly systemsByClass; | ||
readonly systemsByClass: Map<SystemType<System>, SystemBox>; | ||
private lastTime; | ||
@@ -270,3 +273,4 @@ executing: boolean; | ||
private splitDefs; | ||
execute(time?: number, delta?: number, systems?: SystemBox[]): void; | ||
initialize(): Promise<void>; | ||
execute(time?: number, delta?: number, systems?: SystemBox[]): Promise<void>; | ||
executeFunction(fn: (system: System) => void): void; | ||
@@ -366,2 +370,3 @@ private processEndOfFrame; | ||
static weakObject: Type<any>; | ||
// TODO: add autoremove/autodelete when nulled out | ||
static ref: Type<Entity | undefined>; | ||
@@ -393,3 +398,6 @@ static backrefs: (type?: ComponentType<any>, fieldName?: string, trackDeletedBackrefs?: boolean) => Type<Entity[]>; | ||
} | ||
interface ComponentType<C> { | ||
interface Component { | ||
__invalid?: boolean; | ||
} | ||
interface ComponentType<C extends Component> { | ||
new (): C; | ||
@@ -416,4 +424,4 @@ schema?: Schema; | ||
readonly elastic: boolean; | ||
readonly readonlyInstance: C; | ||
readonly writableInstance: C; | ||
readonlyInstance: C; | ||
writableInstance: C; | ||
readonly shapeOffset: number; | ||
@@ -430,6 +438,7 @@ readonly shapeMask: number; | ||
private readonly __dispatcher; | ||
constructor(options: WorldOptions); | ||
static create(options: WorldOptions): Promise<World>; | ||
private constructor(); | ||
build(callback: (system: System) => void): void; | ||
createEntity(...initialComponents: (ComponentType<any> | any)[]): void; | ||
execute(time?: number, delta?: number): void; | ||
execute(time?: number, delta?: number): Promise<void>; | ||
control(options: ControlOptions): void; | ||
@@ -442,7 +451,7 @@ get stats(): Stats; | ||
} | ||
declare function prop<JSType>(practicalOptions: PropOptions<JSType> | Type<any> | (() => Type<any>)): (target: any, name: string) => void; | ||
declare function field<JSType>(practicalOptions: PropOptions<JSType> | Type<any> | (() => Type<any>)): (target: any, name: string) => void; | ||
declare const componentTypes: ComponentType<any>[]; | ||
declare function component(constructor: ComponentType<any>): void; | ||
declare function component(options: ComponentOptions): (constructor: ComponentType<any>) => void; | ||
export { World, Type, Entity, System, SystemType, componentTypes, component, prop, Query, ComponentType }; | ||
export { World, Type, Entity, System, SystemType, componentTypes, component, field, Query, ComponentType }; | ||
//# sourceMappingURL=index.umd.min.d.ts.map |
@@ -1,2 +0,2 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).becsy={})}(this,(function(e){"use strict";const t=22,s=4194304,r=4194303,i=512;class n{size;bytes;constructor(e){this.size=e,this.bytes=new Uint32Array(Math.ceil(e/32))}get(e){if(e<0||e>=this.size)throw new Error(`Bit index out of bounds: ${e}`);return 0!=(this.bytes[e>>>5]&1<<(31&e))}set(e){if(e<0||e>=this.size)throw new Error(`Bit index out of bounds: ${e}`);this.bytes[e>>>5]|=1<<(31&e)}unset(e){if(e<0||e>=this.size)throw new Error(`Bit index out of bounds: ${e}`);this.bytes[e>>>5]&=~(1<<(31&e))}clear(){this.bytes.fill(0)}}const a=[];class o{maxEntries;configParamName;localProcessingAllowed;data;corral;constructor(e,t,s=!1){this.maxEntries=e,this.configParamName=t,this.localProcessingAllowed=s;const r=new SharedArrayBuffer((e+2)*Uint32Array.BYTES_PER_ELEMENT);this.data=new Uint32Array(r);const i=new SharedArrayBuffer((e+2)*Uint32Array.BYTES_PER_ELEMENT);this.corral=new Uint32Array(i)}push(e){const t=this.corral[0];t>=this.maxEntries&&this.throwCapacityExceeded(),t&&this.corral[t]===e||(this.corral[t+2]=e,this.corral[0]+=1)}commit(e){if(!e&&this.localProcessingAllowed)throw new Error("Cannot use blind commit when log local processing is allowed");const t=this.corral[0];if(!t)return!0;let s=this.data[0];if(e&&(e.generation!==this.data[1]||e.index!==s||e.corralGeneration!==this.corral[1]||e.corralIndex!==this.corral[0]))return!1;const r=Math.min(t,this.maxEntries-s);for(this.data.set(this.corral.subarray(2,r+2),s+2),r<t&&this.data.set(this.corral.subarray(r+2,t+2),2),s+=t;s>=this.maxEntries;)s-=this.maxEntries,this.data[1]+=1;return this.data[0]=s,this.corral[0]=0,this.corral[1]+=1,e&&(e.index=s,e.generation=this.data[1]),!0}createPointer(e){return e?(e.index=this.data[0],e.generation=this.data[1],e.corralIndex=this.corral[0],e.corralGeneration=this.corral[1],e):{index:this.data[0],generation:this.data[1],corralIndex:this.corral[0],corralGeneration:this.corral[1]}}hasUpdatesSince(e){return this.checkPointer(e),!(e.index===this.data[0]&&e.generation===this.data[1]&&(e.corralGeneration===this.corral[1]?e.corralIndex===this.corral[0]:0===this.corral[0]))}processSince(e,t){this.checkPointers(e,t);let s=a;const r=t?.index??this.data[0],i=t?.generation??this.data[1];if(e.generation===i)if(e.index<r)s=[this.data,e.index+2,r+2,!1],e.index=r;else{const t=this.corral[0],r=this.corral[1];(e.corralGeneration===r?e.corralIndex<t:t)&&(s=[this.corral,e.corralIndex+2,t+2,!0],e.corralIndex=t,e.corralGeneration=r)}else s=[this.data,e.index+2,this.data.length,!1],e.index=0,e.generation=i;return s}processAndCommitSince(e){const t=this.processSince(e);return t[0]?t:this.commit(e)?a:this.processSince(e)}countSince(e,t){if(this.checkPointers(e,t),this.corral[0])throw new Error("Internal error, should commit log before counting");const s=e.index,r=t?.index??this.data[0],i=t?.generation??this.data[1];return e.index=r,e.generation=i,s===r&&e.generation===i?0:s<r?r-s:this.maxEntries-(s-r)}checkPointers(e,t){if(this.checkPointer(e),t&&(this.checkPointer(t),e.index>t.index&&e.generation>=t.generation))throw new RangeError("Internal error, start pointer exceeds end pointer")}checkPointer(e){const t=this.data[0];let s=e.generation;if(e.index===t?s+1<this.data[1]&&this.throwCapacityExceeded():(e.index>t&&(s+=1),s!==this.data[1]&&this.throwCapacityExceeded()),e.corralGeneration>this.corral[1])throw new Error("Internal error, pointer corral generation older than corral");if(e.corralGeneration===this.corral[1]&&e.corralIndex>this.corral[0])throw new Error("Internal error, pointer past end of log corral area")}throwCapacityExceeded(){throw new Error(`Log capacity exceeded, please raise ${this.configParamName} above ${this.maxEntries}`)}}class h{maxItems;configParamName;data;constructor(e,t){this.maxItems=e,this.configParamName=t,this.data=new Uint32Array(new SharedArrayBuffer((e+1)*Uint32Array.BYTES_PER_ELEMENT))}get length(){return this.data[0]}take(){const e=this.data[0]--;if(e<=0)throw new RangeError(`Pool capacity exceeded, please raise ${this.configParamName} above ${this.maxItems}`);return this.data[e]}refill(e){if(!e.length)return;const t=this.length,s=t+e.length;if(s>this.maxItems)throw new Error("Internal error, refill exceeded pool capacity");this.data.set(e,t+1),this.data[0]=s}fillWithDescendingIntegers(e){const t=this.length;for(let s=this.data.length-1;s>t;s--)this.data[s]=e++;this.data[0]=this.data.length-1}}const c=new TextEncoder,d=new TextDecoder;function l(e){throw new Error(`Component is not writable; use entity.write(${e.type.name}) to acquire a writable version`)}class f{defaultValue;constructor(e){this.defaultValue=e}static boolean;static uint8;static int8;static uint16;static int16;static uint32;static int32;static float32;static float64;static staticString;static dynamicString;static object;static weakObject;static ref;static backrefs}class u extends f{NumberArray;constructor(e){super(0),this.NumberArray=e}defineElastic(e,t){let s,r;t.updateBuffer=()=>{const i=e.capacity*this.NumberArray.BYTES_PER_ELEMENT,n=t.buffer?.byteLength!==i;(n||t.buffer!==s)&&(s=n?new SharedArrayBuffer(i):t.buffer,r=new this.NumberArray(s),n&&t.buffer&&r.set(new this.NumberArray(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>r[e.index],set(t){r[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>r[e.index],set(t){l(e)}})}defineFixed(e,t){const s=e.capacity*this.NumberArray.BYTES_PER_ELEMENT,r=new SharedArrayBuffer(s),i=new this.NumberArray(r);t.buffer=r,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>i[e.index],set(t){i[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>i[e.index],set(t){l(e)}})}}class p extends f{choices;choicesIndex=new Map;TypedArray;constructor(e){if(super(e[0]),this.choices=e,!e?.length)throw new Error("No choices specified for Type.staticString");e.length<256?this.TypedArray=Uint8Array:e.length<65536?this.TypedArray=Uint16Array:this.TypedArray=Uint32Array;for(let t=0;t<e.length;t++)this.choicesIndex.set(e[t],t)}defineElastic(e,t){let s,r;const i=this.choices,n=this.choicesIndex;t.updateBuffer=()=>{const i=e.capacity*this.TypedArray.BYTES_PER_ELEMENT,n=t.buffer?.byteLength!==i;(n||t.buffer!==s)&&(s=n?new SharedArrayBuffer(i):t.buffer,r=new this.TypedArray(s),n&&t.buffer&&r.set(new this.TypedArray(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=r[e.index],s=i[t];if(void 0===s)throw new Error(`Invalid static string index: ${t}`);return s},set(t){const s=n.get(t);if(void 0===s)throw new Error(`Static string not in set: "${t}"`);r[e.index]=s}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=r[e.index],s=i[t];if(void 0===s)throw new Error(`Invalid static string index: ${t}`);return s},set(t){l(e)}})}defineFixed(e,t){const s=this.choices,r=this.choicesIndex,i=e.capacity*this.TypedArray.BYTES_PER_ELEMENT,n=new SharedArrayBuffer(i),a=new this.TypedArray(n);t.buffer=n,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=a[e.index],r=s[t];if(void 0===r)throw new Error(`Invalid static string index: ${t}`);return r},set(t){const s=r.get(t);if(void 0===s)throw new Error(`Static string not in set: "${t}"`);a[e.index]=s}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=a[e.index],r=s[t];if(void 0===r)throw new Error(`Invalid static string index: ${t}`);return r},set(t){l(e)}})}}class g extends f{maxUtf8Length;lengthsStride;bytesStride;constructor(e){super(""),this.maxUtf8Length=e+e%2,this.lengthsStride=e/2+1,this.bytesStride=this.maxUtf8Length+2}defineElastic(e,t){let s,r,i;const n=this.maxUtf8Length,a=this.lengthsStride,o=this.bytesStride;t.updateBuffer=()=>{const n=e.capacity*(this.maxUtf8Length+Uint16Array.BYTES_PER_ELEMENT),a=t.buffer?.byteLength!==n;(a||t.buffer!==s)&&(s=a?new SharedArrayBuffer(n):t.buffer,r=new Uint16Array(s),i=new Uint8Array(s),a&&t.buffer&&i.set(new Uint8Array(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=r[e.index*a];return d.decode(new Uint8Array(i.buffer,e.index*o+2,t))},set(t){const s=c.encode(t);if(s.byteLength>n)throw new Error(`Dynamic string length > ${n} after encoding: ${t}`);r[e.index*a]=s.byteLength,i.set(s,e.index*o+2)}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=r[e.index*a];return d.decode(new Uint8Array(i.buffer,e.index*o+2,t))},set(t){l(e)}})}defineFixed(e,t){const s=this.maxUtf8Length,r=this.lengthsStride,i=this.bytesStride,n=e.capacity*(this.maxUtf8Length+Uint16Array.BYTES_PER_ELEMENT),a=new SharedArrayBuffer(n),o=new Uint16Array(a),h=new Uint8Array(a);t.buffer=a,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=o[e.index*r];return d.decode(new Uint8Array(h.buffer,e.index*i+2,t))},set(t){const n=c.encode(t);if(n.byteLength>s)throw new Error(`Dynamic string length > ${s} after encoding: ${t}`);o[e.index*r]=n.byteLength,h.set(n,e.index*i+2)}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=o[e.index*r];return d.decode(new Uint8Array(h.buffer,e.index*i+2,t))},set(t){l(e)}})}}const m=2**31;const y=[];class w extends f{type;fieldName;trackDeletedBackrefs;constructor(e,t,s){super(y),this.type=e,this.fieldName=t,this.trackDeletedBackrefs=s}defineElastic(e,t){const s=this.fieldName?this.type?.__binding.fields.find((e=>e.name===this.fieldName)):void 0;if(this.fieldName&&!s)throw new Error(`Backrefs field ${e.type.name}.${t.name} refers to an unknown field ${this.type.name}.${this.fieldName}`);if(s&&s.type!==f.ref)throw new Error(`Backrefs field ${e.type.name}.${t.name} refers to a field ${this.type.name}.${this.fieldName} that is not a ref`);if(this.fieldName&&!this.type)throw new Error(`Backrefs selector has field but no component in ${e.type.name}.${t.name}`);if(this.type&&!this.fieldName&&!this.type.__binding.refFields.length)throw new Error(`Backrefs field ${e.type.name}.${t.name} refers to component ${this.type.name} that has no ref fields`);const r=this.trackDeletedBackrefs,i=e.dispatcher.indexer;i.registerSelector();const n=i.registerSelector(e.type,this.type,s?.seq,this.trackDeletedBackrefs),a={enumerable:!0,configurable:!0,get(){if(!r&&e.dispatcher.registry.includeRecentlyDeleted)throw new Error(`Backrefs field ${e.type.name}.${t.name} not configured to track recently deleted refs`);return i.getBackrefs(e.entityId,n)},set(e){if(e!==y)throw new Error("Backrefs properties are computed automatically, you cannot set them")}};Object.defineProperty(e.writableInstance,t.name,a),Object.defineProperty(e.readonlyInstance,t.name,a)}defineFixed(e,t){this.defineElastic(e,t)}}f.boolean=new class extends f{constructor(){super(!1)}defineElastic(e,t){let s,r;t.updateBuffer=()=>{const i=t.buffer?.byteLength!==e.capacity;(i||t.buffer!==s)&&(s=i?new SharedArrayBuffer(e.capacity):t.buffer,r=new Uint8Array(s),i&&t.buffer&&r.set(new Uint8Array(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>Boolean(r[e.index]),set(t){r[e.index]=t?1:0}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>Boolean(r[e.index]),set(t){l(e)}})}defineFixed(e,t){const s=new SharedArrayBuffer(e.capacity),r=new Uint8Array(s);t.buffer=s,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>Boolean(r[e.index]),set(t){r[e.index]=t?1:0}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>Boolean(r[e.index]),set(t){l(e)}})}},f.uint8=new u(Uint8Array),f.int8=new u(Int8Array),f.uint16=new u(Uint16Array),f.int16=new u(Int16Array),f.uint32=new u(Uint32Array),f.int32=new u(Int32Array),f.float32=new u(Float32Array),f.float64=new u(Float64Array),f.staticString=e=>new p(e),f.dynamicString=e=>new g(e),f.ref=new class extends f{constructor(){super(void 0)}defineElastic(e,t){let s,i;const n=e.dispatcher.indexer,a=e.dispatcher.registry,o=a.pool;n.registerSelector(),t.updateBuffer=()=>{const r=e.capacity*Int32Array.BYTES_PER_ELEMENT,n=t.buffer?.byteLength!==r;if(n||t.buffer!==s){if(s=n?new SharedArrayBuffer(r):t.buffer,i=new Int32Array(s),n&&t.buffer){const e=new Int32Array(t.buffer);i.set(e),i.fill(-1,e.length)}else i.fill(-1);t.buffer=s}},t.updateBuffer(),t.clearRef=(s,a,o)=>{if(o)throw new Error("Ref fields have no internal index");if(0!=(i[e.index]&m)!==s)throw new Error("Wrong ref stale state");const h=i[e.index]&r,c=void 0!==a;c&&h!==a||(s?c&&(i[e.index]=-1):i[e.index]|=m,n.trackRefChange(e.entityId,e.type,t.seq,void 0,h,-1,s))},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=i[e.index];if(!(-1===t||t&m&&!a.includeRecentlyDeleted))return o.borrowTemporarily(t&r)},set(s){if(s&&!a.hasShape(s.__id,a.Alive,!1))throw new Error("Referencing a deleted entity is not allowed");const r=i[e.index],o=s?.__id??-1;r!==o&&(i[e.index]=o,n.trackRefChange(e.entityId,e.type,t.seq,void 0,r,o,!0))}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=i[e.index];if(!(-1===t||t&m&&!a.includeRecentlyDeleted))return o.borrowTemporarily(t&r)},set(t){l(e)}})}defineFixed(e,t){const s=e.capacity*Int32Array.BYTES_PER_ELEMENT,i=new SharedArrayBuffer(s),n=new Int32Array(i);n.fill(-1),t.buffer=i;const a=e.dispatcher.indexer,o=e.dispatcher.registry,h=o.pool;a.registerSelector(),t.clearRef=(s,i,o)=>{if(o)throw new Error("Ref fields have no internal index");if(0!=(n[e.index]&m)!==s)throw new Error("Wrong ref stale state");const h=n[e.index]&r,c=void 0!==i;c&&h!==i||(s?c&&(n[e.index]=-1):n[e.index]|=m,a.trackRefChange(e.entityId,e.type,t.seq,void 0,h,-1,s))},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=n[e.index];if(!(-1===t||t&m&&!o.includeRecentlyDeleted))return h.borrowTemporarily(t&r)},set(s){if(s&&!o.hasShape(s.__id,o.Alive,!1))throw new Error("Referencing a deleted entity is not allowed");const r=n[e.index],i=s?.__id??-1;r!==i&&(n[e.index]=i,a.trackRefChange(e.entityId,e.type,t.seq,void 0,r,i,!0))}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=n[e.index];if(!(-1===t||t&m&&!o.includeRecentlyDeleted))return h.borrowTemporarily(t&r)},set(t){l(e)}})}},f.backrefs=(e,t,s=!1)=>new w(e,t,s),f.object=new class extends f{constructor(){super(void 0)}defineElastic(e,t){const s=[];t.localBuffer=s,t.updateBuffer=()=>{},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>s[e.index],set(t){s[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>s[e.index],set(t){l(e)}})}defineFixed(e,t){const s=new Array(e.capacity);t.localBuffer=s,t.updateBuffer=()=>{},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>s[e.index],set(t){s[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>s[e.index],set(t){l(e)}})}},f.weakObject=new class extends f{finalizers;constructor(){super(void 0)}defineElastic(e,t){const s=[];t.localBuffer=s,t.updateBuffer=()=>{};const r=this.initFinalizers(e);Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=s[e.index];return null==t?t:t.deref()},set(i){if(null!=i){const s=new WeakRef(i);r?.register(i,{type:e.type,field:t,weakRef:s,id:e.entityId,index:e.index}),i=s}s[e.index]=i}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=s[e.index];return null==t?t:t.deref()},set(t){l(e)}})}defineFixed(e,t){const s=new Array(e.capacity);t.localBuffer=s,t.updateBuffer=()=>{};const r=this.initFinalizers(e);Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=s[e.index];return null==t?t:t.deref()},set(i){if(null!=i){const s=new WeakRef(i);r?.register(i,{type:e.type,field:t,weakRef:s,id:e.entityId,index:e.index}),i=s}s[e.index]=i}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=s[e.index];return null==t?t:t.deref()},set(t){l(e)}})}initFinalizers(e){if(!e.trackedWrites)return;if(this.finalizers)return this.finalizers;const t=e.dispatcher;return t.writeLog&&"undefined"!=typeof FinalizationRegistry?(this.finalizers=new FinalizationRegistry((({type:e,field:s,weakRef:r,id:i,index:n})=>{s.localBuffer?.[n]===r&&t.registry.trackWrite(i,e)})),this.finalizers):void 0}};class _{type;fields;dispatcher;capacity;storage;elastic;readonlyInstance;writableInstance;shapeOffset;shapeMask;refFields;trackedWrites=!1;internallyIndexed=!1;entityId=0;index=0;constructor(e,t,s,r,i,n){this.type=e,this.fields=t,this.dispatcher=s,this.capacity=r,this.storage=i,this.elastic=n,this.readonlyInstance=new e,this.writableInstance=new e,this.shapeOffset=e.id>>5,this.shapeMask=1<<(31&e.id),this.refFields=t.filter((e=>e.type===f.ref))}}function E(e){if(!e.__binding)throw new Error(`Component ${e.name} not defined; add to world defs`)}class b{maxEntities;binding;fields;index;spares;constructor(e,t,s){this.maxEntities=e,this.binding=t,this.fields=s,this.growSpares(),this.growCapacity()}acquireIndex(e){let t=this.index[e];if(-1===t){if(this.spares[3]>0)t=this.spares[4+--this.spares[3]];else{if(this.spares[1]===this.spares[2]){if(!this.binding.elastic)throw new Error(`Storage exhausted for component ${this.binding.type.name}; raise its capacity above ${this.binding.capacity}`);this.binding.capacity=Math.min(this.maxEntities,2*this.binding.capacity),this.growCapacity()}t=this.spares[1]++}this.index[e]=t}return t}releaseIndex(e){if(-1===this.index[e])throw new Error(`Internal error, index for entity ${e} not allocated`);this.spares[3]===this.spares.length-4&&this.growSpares(),this.spares[4+this.spares[3]++]=this.index[e],this.index[e]=-1}growCapacity(){this.binding.dispatcher.stats.for(this.binding.type).capacity=this.binding.capacity;const e=this.ArrayType,t=e.BYTES_PER_ELEMENT!==this.spares?.[0];if(!this.index||t){const t=new e(new SharedArrayBuffer(this.maxEntities*e.BYTES_PER_ELEMENT));this.index?t.set(this.index):t.fill(-1),this.index=t}if(this.spares&&t){const t=new e(new SharedArrayBuffer(this.spares.length*e.BYTES_PER_ELEMENT));t.set(this.spares),t[0]=e.BYTES_PER_ELEMENT,this.spares=t}if(this.spares[2]=this.binding.capacity,this.binding.elastic)for(const e of this.fields)e.updateBuffer()}growSpares(){const e=this.ArrayType,t=this.spares?Math.min(this.maxEntities,2*(this.spares.length-4)):8,s=new e(new SharedArrayBuffer((4+t)*e.BYTES_PER_ELEMENT));this.spares?s.set(this.spares):(s[0]=e.BYTES_PER_ELEMENT,s[2]=this.binding.capacity),this.spares=s}get ArrayType(){const e=this.binding.capacity;return e<=127?Int8Array:e<=32767?Int16Array:Int32Array}}function x(e,t,s){const r=function(e){const t=e.schema,s=[];if(t){let r=0;for(const e in t){let i=t[e];(i instanceof f||"function"==typeof i)&&(i={type:i}),"function"==typeof i.type&&(i.type=i.type()),"default"in i||(i.default=i.type.defaultValue),s.push({name:e,seq:r++,type:i.type,default:i.default})}if(r>128)throw new Error(`Component ${e.name} declares too many fields`)}return s}(t),i=r.length?t.options?.storage??s.defaultComponentStorage:"sparse",n="sparse"===i?s.maxEntities:Math.min(s.maxEntities,t.options?.capacity??0),a=t.options?.initialCapacity??8;if(void 0!==t.options?.capacity){if("sparse"===i)throw new Error(`Component type ${t.name} cannot combine custom capacity with sparse storage`);if(t.options.capacity<=0)throw new Error(`Component type ${t.name} capacity option must be great than zero: got ${n}`);if(void 0!==t.options.initialCapacity)throw new Error(`Component type ${t.name} cannot have both capacity and initialCapacity options`)}if(("undefined"==typeof process||"test"!==process.env.NODE_ENV)&&t.__bind)throw new Error(`Component type ${t.name} is already in use in another world`);t.id=e;const o=new _(t,r,s,n||a,i,!n);t.__binding=o}function k(e){const t=e.__binding;for(const e of t.fields)t.elastic?e.type.defineElastic(t,e):e.type.defineFixed(t,e);switch(t.storage){case"sparse":t.dispatcher.stats.for(e).capacity=t.capacity,e.__bind=(e,s)=>(t.entityId=e,t.index=e,s?t.writableInstance:t.readonlyInstance),e.__allocate=e=>(t.entityId=e,t.index=e,t.writableInstance);break;case"packed":{const s=new b(t.dispatcher.maxEntities,t,t.fields);e.__bind=(r,i)=>{if(t.entityId=r,t.index=s.index[r],-1===t.index)throw new Error(`Attempt to bind unacquired entity ${r} to ${e.name}`);return i?t.writableInstance:t.readonlyInstance},e.__allocate=e=>(t.entityId=e,t.index=s.acquireIndex(e),t.writableInstance),e.__free=e=>{s.releaseIndex(e)};break}case"compact":throw new Error("Not yet implemented");default:throw new Error(`Invalid storage type "${t.storage}`)}}class S{__registry;__id;constructor(e){this.__registry=e}add(e,t){if(this.__checkMask(e,!0),!this.__registry.hasShape(this.__id,this.__registry.Alive,!1))throw new Error("Entity has been deleted");if(this.__registry.hasShape(this.__id,e,!1))throw new Error(`Entity already has a ${e.name} component`);return this.__registry.setShape(this.__id,e),this.__registry.dispatcher.stats.for(e).numEntities+=1,function(e,t,s){if(E(e),void 0!==s)for(const t in s)if(!e.schema?.[t])throw new Error(`Property ${t} not defined for component ${e.name}`);const r=e.__allocate(t);for(const t of e.__binding.fields)r[t.name]=s?.[t.name]??t.default}(e,this.__id,t),this}addAll(...e){for(let t=0;t<e.length;t++){const s=e[t];if("function"!=typeof s)throw new Error(`Bad arguments to bulk add: expected component type, got: ${s}`);let r=e[t+1];"function"==typeof r?r=void 0:t++,this.add(s,r)}return this}remove(e){this.__checkHas(e,!1),this.__checkMask(e,!0),this.__registry.clearShape(this.__id,e)}removeAll(...e){for(const t of e)this.remove(t)}has(e){return this.__checkMask(e,!1),this.__registry.hasShape(this.__id,e,!0)}read(e){return this.__checkMask(e,!1),this.__checkHas(e,!0),e.__bind(this.__id,!1)}write(e){return this.__checkMask(e,!0),this.__checkHas(e,!0),e.__binding.trackedWrites&&this.__registry.trackWrite(this.__id,e),e.__bind(this.__id,!0)}delete(){const e=this.__registry.Alive;for(const t of this.__registry.types)this.__registry.hasShape(this.__id,t,!1)&&(t!==e&&this.__checkMask(t,!0),this.__registry.clearShape(this.__id,t));this.__registry.queueDeletion(this.__id),this.__registry.dispatcher.indexer.clearAllRefs(this.__id,!1)}__checkMask(e,t){R(e,this.__registry.executingSystem,t)}__checkHas(e,t){if(!this.__registry.hasShape(this.__id,e,t))throw new Error(`Entity doesn't have a ${e.name} component`)}}function R(e,t,s){E(e);const r=s?t?.rwMasks.write:t?.rwMasks.read;if(!(!r||0!=((r[e.__binding.shapeOffset]??0)&e.__binding.shapeMask)))throw new Error(`System didn't mark component ${e.name} as ${s?"writable":"readable"}`)}function P(e,t){E(t);const s=t.__binding.shapeOffset;s>=e.length&&(e.length=s+1,e.fill(0,e.length,s)),e[s]|=t.__binding.shapeMask}class v{pool;entities=[];constructor(e){this.pool=e}add(e){this.entities.push(this.pool.borrowTemporarily(e))}clear(){this.entities.length&&this.entities.splice(0,1/0)}}class L{pool;entities=[];lookupTable;constructor(e,t){this.pool=e,this.lookupTable=new Int32Array(t),this.lookupTable.fill(-1)}add(e){const t=this.entities.push(this.pool.borrow(e))-1;this.lookupTable[e]=t}remove(e){const t=this.lookupTable[e];if(t<0)throw new Error("Internal error, entity not in list");this.pool.return(e),this.lookupTable[e]=-1;const s=this.entities.pop();t<this.entities.length&&(this.entities[t]=s,this.lookupTable[s.__id]=t)}has(e){return this.lookupTable[e]>=0}clear(){for(const e of this.entities)this.pool.return(e.__id);this.entities=[],this.lookupTable.fill(-1)}}var I;!function(e){e[e.all=1]="all",e[e.added=2]="added",e[e.removed=4]="removed",e[e.changed=8]="changed",e[e.addedOrChanged=16]="addedOrChanged",e[e.changedOrRemoved=32]="changedOrRemoved",e[e.addedChangedOrRemoved=64]="addedChangedOrRemoved"}(I||(I={}));const C=I.added|I.removed|I.changed|I.addedOrChanged|I.changedOrRemoved|I.addedChangedOrRemoved,T=I.changed|I.addedOrChanged|I.changedOrRemoved|I.addedChangedOrRemoved;class A{query;system;results={};flavors=0;withMask;withoutMask;trackMask;hasTransientResults;hasChangedResults;currentEntities;changedEntities;constructor(e,t){this.query=e,this.system=t,e.__results=this.results,e.__systemName=t.name}complete(){const e=this.system.dispatcher;if(this.hasTransientResults=Boolean(this.flavors&C),this.hasChangedResults=Boolean(this.flavors&T),this.hasChangedResults&&!this.trackMask)throw new Error("Query for changed entities must track at least one component");this.flavors&I.all?this.results.all=new L(e.registry.pool,e.maxEntities):this.currentEntities=new n(e.maxEntities),this.hasTransientResults&&this.allocateTransientResultLists(),this.flavors&&this.system.shapeQueries.push(this),this.hasChangedResults&&(this.changedEntities=new n(e.maxEntities),this.system.writeQueries.push(this))}allocateTransientResultLists(){this.flavors&I.added&&this.allocateResult("added"),this.flavors&I.removed&&this.allocateResult("removed"),this.flavors&I.changed&&this.allocateResult("changed"),this.flavors&I.addedOrChanged&&this.allocateResult("addedOrChanged"),this.flavors&I.changedOrRemoved&&this.allocateResult("changedOrRemoved"),this.flavors&I.addedChangedOrRemoved&&this.allocateResult("addedChangedOrRemoved")}allocateResult(e){const t=this.system.dispatcher;this.results[e]=new v(t.registry.pool)}clearTransientResults(){this.hasTransientResults&&(this.results.added?.clear(),this.results.removed?.clear(),this.results.changed?.clear(),this.results.addedOrChanged?.clear(),this.results.changedOrRemoved?.clear(),this.results.addedChangedOrRemoved?.clear(),this.changedEntities?.clear())}clearAllResults(){this.clearTransientResults(),this.results.all?.clear()}handleShapeUpdate(e){const t=this.system.dispatcher.registry,s=this.results.all?.has(e)??this.currentEntities.get(e),r=t.matchShape(e,this.withMask,this.withoutMask);r&&!s?(this.currentEntities?.set(e),this.results.all?.add(e),this.results.added?.add(e),this.results.addedOrChanged?.add(e),this.results.addedChangedOrRemoved?.add(e)):!r&&s&&(this.currentEntities?.unset(e),this.results.all?.remove(e),this.results.removed?.add(e),this.results.changedOrRemoved?.add(e),this.results.addedChangedOrRemoved?.add(e))}handleWrite(e,t,s){!this.changedEntities.get(e)&&(this.trackMask[t]??0)&s&&(this.changedEntities.set(e),this.results.changed?.add(e),this.results.addedOrChanged?.add(e),this.results.changedOrRemoved?.add(e),this.results.addedChangedOrRemoved?.add(e))}}class O{__callback;__userQuery;__query;__system;__lastTypes;constructor(e,t){this.__callback=e,this.__userQuery=t}__build(e){try{this.__system=e,this.__query=new A(this.__userQuery,e),this.__callback(this),this.__query.complete()}catch(t){throw t.message=`Failed to build query in system ${e.name}: ${t.message}`,t}}get and(){return this}get but(){return this}get also(){return this}get all(){return this.__query.flavors|=I.all,this}get added(){return this.__query.flavors|=I.added,this}get removed(){return this.__query.flavors|=I.removed,this}get changed(){return this.__query.flavors|=I.changed,this}get addedOrChanged(){return this.__query.flavors|=I.addedOrChanged,this}get changedOrRemoved(){return this.__query.flavors|=I.changedOrRemoved,this}get addedChangedOrRemoved(){return this.__query.flavors|=I.addedChangedOrRemoved,this}with(...e){return this.set(this.__system.rwMasks.read,e),this.set("withMask"),this}without(...e){return this.set(this.__system.rwMasks.read,e),this.set("withoutMask",e),this}using(...e){return this.set(this.__system.rwMasks.read,e),this}get track(){this.set("trackMask");for(const e of this.__lastTypes)e.__binding.trackedWrites=!0;return this}get read(){return this}get write(){return this.set(this.__system.rwMasks.write),this}set(e,t,s){if(e){if(t||(t=this.__lastTypes),!t)throw new Error("No component type to apply query modifier to");if(this.__lastTypes=t,"string"==typeof e){if(s&&this.__query[e])throw new Error(`Only one ${s} allowed`);this.__query[e]||(this.__query[e]=[]),e=this.__query[e]}else if(s&&e.some((e=>0!==e)))throw new Error(`Only one ${s} allowed`);for(const s of t)P(e,s)}}}class B{__results;__systemName;get all(){return this.__checkList("all"),this.__results.all.entities}get added(){return this.__checkList("added"),this.__results.added.entities}get removed(){return this.__checkList("removed"),this.__results.removed.entities}get changed(){return this.__checkList("changed"),this.__results.changed.entities}get addedOrChanged(){return this.__checkList("addedOrChanged"),this.__results.addedOrChanged.entities}get changedOrRemoved(){return this.__checkList("changedOrRemoved"),this.__results.changedOrRemoved.entities}get addedChangedOrRemoved(){return this.__checkList("addedChangedOrRemoved"),this.__results.addedChangedOrRemoved.entities}__checkList(e){if(!this.__results[e])throw new Error(`Query '${e}' not configured, please add .${e} to your query definition in system ${this.__systemName}`)}}var N,F;!function(e){e[e.RUNNING=0]="RUNNING",e[e.SUSPENDED=1]="SUSPENDED",e[e.STOPPED=2]="STOPPED"}(N||(N={}));class ${static __system=!0;__queryBuilders=[];__dispatcher;time;delta;get name(){return this.constructor.name}query(e){const t=new B,s=new O(e,t);if(!this.__queryBuilders)throw new Error(`Attempt to create a new query after world initialized in system ${this.name}`);return this.__queryBuilders.push(s),t}createEntity(...e){return this.__dispatcher.createEntity(e)}accessRecentlyDeletedData(e=!0){this.__dispatcher.registry.includeRecentlyDeleted=e}}class M{system;dispatcher;rwMasks={read:[],write:[]};shapeQueries=[];writeQueries=[];hasWriteQueries;processedEntities;shapeLogPointer;writeLogPointer;state=N.RUNNING;get name(){return this.system.name}constructor(e,t){this.system=e,this.dispatcher=t,e.__dispatcher=t,this.shapeLogPointer=t.shapeLog.createPointer(),this.writeLogPointer=t.writeLog?.createPointer(),this.processedEntities=new n(t.maxEntities);for(const t of e.__queryBuilders)t.__build(this);e.__queryBuilders=null,this.hasWriteQueries=!!this.writeQueries.length}execute(e,t){this.state===N.RUNNING&&(this.system.time=e,this.system.delta=t,this.runQueries(),this.system.execute())}runQueries(){const e=this.dispatcher.shapeLog.hasUpdatesSince(this.shapeLogPointer),t=this.hasWriteQueries&&this.dispatcher.writeLog.hasUpdatesSince(this.writeLogPointer);if(e||t){this.processedEntities.clear();for(const e of this.shapeQueries)e.clearTransientResults();e&&this.__updateShapeQueries(),t&&this.__updateWriteQueries()}}__updateShapeQueries(){const e=this.dispatcher.shapeLog;let t,s,r;for(;[t,s,r]=e.processSince(this.shapeLogPointer),t;)for(let e=s;e<r;e++){const s=t[e];if(!this.processedEntities.get(s)){this.processedEntities.set(s);for(const e of this.shapeQueries)e.handleShapeUpdate(s)}}}__updateWriteQueries(){const e=this.dispatcher.writeLog;let s,i,n;for(;[s,i,n]=e.processSince(this.writeLogPointer),s;)for(let e=i;e<n;e++){const i=s[e],n=i&r;if(!this.processedEntities.get(n)){const e=i>>>t;for(const t of this.writeQueries)t.handleWrite(n,e>>5,1<<(31&e))}}}stop(){if(this.state!==N.STOPPED){this.state=N.STOPPED;for(const e of this.shapeQueries)e.clearAllResults()}}restart(){if(this.state===N.STOPPED){const e=this.dispatcher.registry,t=e.Alive;for(let s=0;s<this.dispatcher.maxEntities;s++)if(e.hasShape(s,t,!1))for(const e of this.shapeQueries)e.handleShapeUpdate(s);for(const e of this.shapeQueries)e.clearTransientResults();this.dispatcher.shapeLog.createPointer(this.shapeLogPointer),this.dispatcher.writeLog?.createPointer(this.writeLogPointer)}this.state=N.RUNNING}suspend(){this.state===N.STOPPED&&this.restart(),this.state=N.SUSPENDED}}class U{registry;borrowed;borrowCounts;spares=[];temporarilyBorrowedIds=[];constructor(e,t){this.registry=e,this.borrowed=Array.from({length:t}),this.borrowCounts=new Int32Array(t)}borrow(e){this.borrowCounts[e]+=1;let t=this.borrowed[e];return t||(t=this.borrowed[e]=this.spares.pop()??new S(this.registry),t.__id=e),t}borrowTemporarily(e){const t=this.borrow(e);return this.temporarilyBorrowedIds.push(e),t}returnTemporaryBorrows(){for(const e of this.temporarilyBorrowedIds)this.return(e);this.temporarilyBorrowedIds.splice(0,1/0)}return(e){if(!this.borrowCounts[e])throw new Error("Internal error, returning entity with no borrows");--this.borrowCounts[e]<=0&&(this.spares.push(this.borrowed[e]),this.borrowed[e]=void 0)}}class D{types;dispatcher;stride;shapes;staleShapes;entityIdPool;pool;executingSystem;includeRecentlyDeleted=!1;deletionLog;prevDeletionPointer;oldDeletionPointer;removalLog;prevRemovalPointer;oldRemovalPointer;Alive=class{};constructor(e,t,s,r,i){this.types=r,this.dispatcher=i,this.stride=Math.ceil(r.length/32);const n=e*this.stride*4;this.shapes=new Uint32Array(new SharedArrayBuffer(n)),this.staleShapes=new Uint32Array(new SharedArrayBuffer(n)),this.entityIdPool=new h(e,"maxEntities"),this.entityIdPool.fillWithDescendingIntegers(0),this.pool=new U(this,e),this.deletionLog=new o(t,"maxLimboEntities"),this.prevDeletionPointer=this.deletionLog.createPointer(),this.oldDeletionPointer=this.deletionLog.createPointer(),this.removalLog=new o(s,"maxLimboComponents"),this.prevRemovalPointer=this.removalLog.createPointer(),this.oldRemovalPointer=this.removalLog.createPointer()}initializeComponentTypes(){this.types.unshift(this.Alive);let e=0;for(const t of this.types)x(e++,t,this.dispatcher);for(const e of this.types)k(e);{const e=this.types[0].__binding;if(0!==e.shapeOffset||1!==e.shapeMask)throw new Error("Alive component was not assigned first available shape mask")}}createEntity(e){const t=this.entityIdPool.take(),s=t*this.stride;this.shapes[s]=1,this.stride>1&&this.shapes.fill(0,s+1,s+this.stride);const r=this.pool.borrowTemporarily(t);return e&&r.addAll(...e),this.dispatcher.stats.numEntities+=1,r}queueDeletion(e){this.deletionLog.push(e)}flush(){this.includeRecentlyDeleted=!1,this.pool.returnTemporaryBorrows(),this.deletionLog.commit(),this.removalLog.commit()}processEndOfFrame(){this.processDeletionLog(),this.processRemovalLog()}processDeletionLog(){this.deletionLog.commit();let e,t,s,r=0;for(;[e,t,s]=this.deletionLog.processSince(this.oldDeletionPointer,this.prevDeletionPointer),e;){for(let r=t;r<s;r++)this.dispatcher.indexer.clearAllRefs(e[r],!0);const i=e.subarray(t,s);this.entityIdPool.refill(i),r+=i.length}this.dispatcher.stats.numEntities-=r,this.dispatcher.stats.maxLimboEntities=r,this.deletionLog.createPointer(this.prevDeletionPointer)}processRemovalLog(){this.removalLog.commit();let e,s,i,n=0;for(;[e,s,i]=this.removalLog.processSince(this.oldRemovalPointer,this.prevRemovalPointer),e;){for(let n=s;n<i;n++){const s=e[n],i=s&r,a=s>>>t,o=this.types[a],h=i*this.stride+o.__binding.shapeOffset,c=o.__binding.shapeMask;0==(this.shapes[h]&c)&&(this.staleShapes[h]&=~c,this.clearRefs(i,o,!0),o.__free?.(i))}n+=i-s}this.dispatcher.stats.maxLimboComponents=n,this.removalLog.createPointer(this.prevRemovalPointer)}hasShape(e,t,s){const r=e*this.stride+t.__binding.shapeOffset,i=t.__binding.shapeMask;return 0!=(this.shapes[r]&i)||!(!s||!this.includeRecentlyDeleted||0==(this.staleShapes[r]&i))}setShape(e,t){const s=e*this.stride+t.__binding.shapeOffset,r=t.__binding.shapeMask;this.shapes[s]|=r,this.staleShapes[s]|=r,this.dispatcher.shapeLog.push(e)}clearShape(e,s){const r=this.clearRefs(e,s,!1);(s.__free||r)&&this.removalLog.push(e|s.id<<t),this.shapes[e*this.stride+s.__binding.shapeOffset]&=~s.__binding.shapeMask,this.dispatcher.shapeLog.push(e),this.dispatcher.stats.for(s).numEntities-=1}trackWrite(e,s){this.dispatcher.writeLog.push(e|s.id<<t)}clearRefs(e,t,s){const r=!!t.__binding.refFields.length;if(r){t.__bind(e,!0);for(const e of t.__binding.refFields)e.clearRef(s)}return r}matchShape(e,t,s){const r=e*this.stride;if(t)for(let e=0;e<t.length;e++){const s=t[e];if((this.shapes[r+e]&s)!==s)return!1}if(s)for(let e=0;e<s.length;e++){const t=s[e];if(0!=(this.shapes[r+e]&t))return!1}return!0}}class q{_numEntities=0;maxEntities=0;capacity=0;get numEntities(){return this._numEntities}set numEntities(e){this._numEntities=e,e>this.maxEntities&&(this.maxEntities=e)}toString(){return`${this.numEntities.toLocaleString()} of ${this.maxEntities.toLocaleString()} peak (capacity ${this.capacity.toLocaleString()})`}}class j{frames=0;_numEntities=0;maxEntities=0;_maxLimboEntities=0;_maxLimboComponents=0;_maxRefChangesPerFrame=0;_maxShapeChangesPerFrame=0;_maxWritesPerFrame=0;components=Object.create(null);get numEntities(){return this._numEntities}set numEntities(e){this._numEntities=e,e>this.maxEntities&&(this.maxEntities=e)}get maxLimboEntities(){return this._maxLimboEntities}set maxLimboEntities(e){e>this._maxLimboEntities&&(this._maxLimboEntities=e)}get maxLimboComponents(){return this._maxLimboComponents}set maxLimboComponents(e){e>this._maxLimboComponents&&(this._maxLimboComponents=e)}get maxRefChangesPerFrame(){return this._maxRefChangesPerFrame}set maxRefChangesPerFrame(e){e>this._maxRefChangesPerFrame&&(this._maxRefChangesPerFrame=e)}get maxShapeChangesPerFrame(){return this._maxShapeChangesPerFrame}set maxShapeChangesPerFrame(e){e>this._maxShapeChangesPerFrame&&(this._maxShapeChangesPerFrame=e)}get maxWritesPerFrame(){return this._maxWritesPerFrame}set maxWritesPerFrame(e){e>this._maxWritesPerFrame&&(this._maxWritesPerFrame=e)}for(e){return this.components[e.name]=this.components[e.name]??new q}toString(){return`World stats:\n frames: ${this.frames.toLocaleString()}\n entities: ${this.numEntities.toLocaleString()} of ${this.maxEntities.toLocaleString()} max (${this.maxLimboEntities.toLocaleString()} limbo max)\n refs: ${this.maxRefChangesPerFrame.toLocaleString()} ref changes/frame max\n logs: ${this.maxShapeChangesPerFrame.toLocaleString()} shape changes/frame max, ${this.maxWritesPerFrame.toLocaleString()} writes/frame max`}}!function(e){e[e.REFERENCE=0]="REFERENCE",e[e.UNREFERENCE=1073741824]="UNREFERENCE",e[e.RELEASE=2147483648]="RELEASE"}(F||(F={}));const W=F.REFERENCE|F.UNREFERENCE|F.RELEASE;class Q{targetEntityId;selector;dispatcher;entities=[];tags;entityIndex;clearing=!1;registry;constructor(e,t,s){this.targetEntityId=e,this.selector=t,this.dispatcher=s;const r=t.sourceType?.__binding;t.matchType&&(t.matchSeq||1===r.refFields.length)&&!r.internallyIndexed||(this.tags=[]),this.registry=s.registry}clearAllRefs(e){if(!this.tags)throw new Error("Unreferencing an untagged tracker");this.clearing=!0;for(let t=0;t<this.entities.length;t++){const s=this.entities[t].__id,r=this.tags[t];if("number"==typeof r)this.clearRef(s,r,e);else for(const t of r)this.clearRef(s,t,e)}this.entities=[],this.tags=[],this.entityIndex=void 0,this.clearing=!1}clearRef(e,t,s){const r=511&t,i=t>>>9&127,n=t>>>16,a=this.registry.types[r];R(a,this.registry.executingSystem,!0),a.__bind(e,!0),a.__binding.fields[i].clearRef(s,this.targetEntityId,n)}trackReference(e,t,s,r,i){if(this.clearing)throw new Error("Cannot track a new reference while clearing tracker");i&&this.checkWriteMask();let n=this.getEntityIndex(e);void 0===n&&(n=this.addEntity(e,i)),this.addTag(n,this.makeTag(t,s,r))}trackUnreference(e,t,s,r,i){if(this.clearing)return;i&&this.checkWriteMask();const n=this.getEntityIndex(e);if(void 0===n)throw new Error("Entity backref not tracked");this.removeTag(n,this.makeTag(t,s,r))&&this.removeEntity(n,e,i)}getEntityIndex(e){if(this.entityIndex)return this.entityIndex[e];const t=this.entities.findIndex((t=>t.__id===e));return t>=0?t:void 0}indexEntities(){if(this.entityIndex)throw new Error("Entities already indexed");this.entityIndex=new Array(this.dispatcher.maxEntities);for(let e=0;e<this.entities.length;e++)this.entityIndex[this.entities[e].__id]=e}addTag(e,t){if(!this.tags)return;const s=this.tags[e];if(void 0===s)this.tags[e]=t;else if("number"==typeof s){if(s===t)throw new Error("Ref already tracked");this.tags[e]=[s,t]}else if(Array.isArray(s)){if(s.includes(t))throw new Error("Ref already tracked");if(s.length>=1e3){(this.tags[e]=new Set(s)).add(t)}else s.push(t)}else{if(s.has(t))throw new Error("Ref already tracked");s.add(t)}}removeTag(e,t){if(!this.tags)return!0;const s=this.tags[e];if(void 0===s)throw new Error("Ref not tracked");if("number"==typeof s){if(s!==t)throw new Error("Ref not tracked");return delete this.tags[e],!0}if(Array.isArray(s)){const e=s.indexOf(t);if(-1===e)throw new Error("Ref not tracked");return s.splice(e,1),!this.tags.length}return s.delete(t),!s.size}makeTag(e,t,s){return e|t<<9|(void 0===s?0:s<<16)}addEntity(e,t){const s=this.entities.length;return this.entities.push(this.registry.pool.borrow(e)),this.entityIndex?this.entityIndex[e]=s:s>100&&this.indexEntities(),t&&this.trackBackrefsChange(),s}removeEntity(e,t,s){this.registry.pool.return(t);const r=this.entities.pop();this.entityIndex&&delete this.entityIndex[e],this.entities.length>e&&(this.entities[e]=r,this.entityIndex&&(this.entityIndex[r.__id]=e)),s&&this.trackBackrefsChange()}trackBackrefsChange(){for(const e of this.selector.targetTypes)e.__binding.trackedWrites&&this.registry.trackWrite(this.targetEntityId,e)}checkWriteMask(){const e=this.registry.executingSystem;for(const t of this.selector.targetTypes)R(t,e,!0)}}class z{dispatcher;maxRefChangesPerFrame;refLog;refLogPointer;refLogStatsPointer;selectorIdsBySourceKey=new Map;selectors=[];trackers=new Map;registry;constructor(e,t){this.dispatcher=e,this.maxRefChangesPerFrame=t,this.registry=e.registry}processEndOfFrame(){this.flush(),this.dispatcher.stats.maxRefChangesPerFrame=this.refLog?.countSince(this.refLogStatsPointer)??0}registerSelector(e,t,s,r=!1){e&&E(e),t&&E(t),this.refLog||(this.refLog=new o(this.maxRefChangesPerFrame,"maxRefChangesPerFrame",!0),this.refLogPointer=this.refLog.createPointer(),this.refLogStatsPointer=this.refLog.createPointer());const n=t?void 0===s?-2-t.id:t.id|s<<9:-1;let a=this.selectorIdsBySourceKey.get(n);if(void 0===a){this.selectors.length||(r=!0);const o={id:this.selectors.length,targetTypes:e?[e]:[],sourceType:t,matchType:!!t,matchSeq:void 0!==s,sourceTypeId:t?.id,sourceSeq:s,trackStale:r};if(this.selectors.push(o),a=o.id,this.selectorIdsBySourceKey.set(n,a),a>i)throw new Error("Too many distinct backrefs selectors")}else{const t=this.selectors[a];t.trackStale=t.trackStale||r,e&&t.targetTypes.push(e)}return a}getBackrefs(e,t=0){const s=this.selectors[t];return this.getOrCreateTracker(s,e,this.registry.includeRecentlyDeleted).entities}trackRefChange(e,t,s,r,i,n,a){if(!this.refLog)throw new Error("Trying to trackRefChange without a refLog");if(i===n)throw new Error("No-op call to trackRefChange");-1!==i&&this.pushRefLogEntry(e,t,s,r,i,a?F.RELEASE:F.UNREFERENCE),-1!==n&&this.pushRefLogEntry(e,t,s,r,n,F.REFERENCE)}clearAllRefs(e,t){this.selectors.length&&this.getTracker(this.selectors[0],e,t)?.clearAllRefs(t)}pushRefLogEntry(e,s,r,i,n,a){const o=void 0!==i;if(o!==s.__binding.internallyIndexed)throw new Error("Inconsistent internally indexed flag");this.refLog.push(e|s.id<<t),this.refLog.push(n|r<<t|a|(o?2**29:0)),o&&this.refLog.push(i),this.processEntry(e,s.id,r,i,n,a,!0)}getOrCreateTracker(e,s,r){let i,n=this.getTracker(e,s,r);if(n)return n;if(r&&!e.trackStale)throw new Error("Selector not configured for stale tracking");return n=new Q(s,e,this.dispatcher),this.trackers.set(s|e.id<<t,n),e.trackStale&&(i=new Q(s,e,this.dispatcher),this.trackers.set(s|e.id<<t|2**31,i)),r?i:n}getTracker(e,s,r){return this.trackers.get(s|e.id<<t|(r?2**31:0))}flush(){if(this.refLog)for(;;){const[e,s,i,n]=this.refLog.processAndCommitSince(this.refLogPointer);if(!e)break;if(!n)for(let n=s;n<i;n+=2){const s=e[n],i=e[n+1],a=s&r,o=s>>>t,h=i&r,c=i>>>t&127,d=(i&W)>>>30,l=0!=(i&2**29),f=l?e[n+2]:void 0;l&&(n+=1),this.processEntry(a,o,c,f,h,d,!1)}}}processEntry(e,t,s,r,i,n,a){for(let o=0;o<this.selectors.length;o++){const h=this.selectors[o];if(!(h.matchType&&h.sourceTypeId!==t||h.matchSeq&&h.sourceSeq!==s)){if(n===F.REFERENCE||n===F.UNREFERENCE){const o=this.getOrCreateTracker(h,i,!1);n===F.REFERENCE?o.trackReference(e,t,s,r,a):o.trackUnreference(e,t,s,r,a)}if(h.trackStale&&(n===F.REFERENCE||n===F.RELEASE)){const o=this.getOrCreateTracker(h,i,!0);n===F.REFERENCE?o.trackReference(e,t,s,r,a):o.trackUnreference(e,t,s,r,a)}}}}}const Y="undefined"!=typeof window&&void 0!==window.performance?performance.now.bind(performance):Date.now.bind(Date);class G extends ${__callback;execute(){this.__callback(this)}}class H{maxEntities;defaultComponentStorage;registry;systems;systemsByClass=new Map;lastTime=Y()/1e3;executing;shapeLog;writeLog;shapeLogFramePointer;writeLogFramePointer;stats;indexer;userCallbackSystem;callbackSystem;deferredControls=new Map;constructor({defs:e,maxEntities:t=1e4,maxLimboEntities:r=Math.ceil(t/5),maxLimboComponents:n=Math.ceil(t/5),maxShapeChangesPerFrame:a=2*t,maxWritesPerFrame:h=4*t,maxRefChangesPerFrame:c=t,defaultComponentStorage:d="sparse"}){if(t>s)throw new Error("maxEntities too high, the limit is 4194304");const{componentTypes:l,systemTypes:f}=this.splitDefs(e);if(l.length>i)throw new Error("Too many component types, the limit is 512");this.stats=new j,this.maxEntities=t,this.defaultComponentStorage=d,this.shapeLog=new o(a,"maxShapeChangesPerFrame"),this.shapeLogFramePointer=this.shapeLog.createPointer(),this.registry=new D(t,r,n,l.flat(1/0),this),this.indexer=new z(this,c),this.registry.initializeComponentTypes(),this.systems=this.normalizeAndInitSystems(f),this.systems.some((e=>e.hasWriteQueries))&&(this.writeLog=new o(h,"maxWritesPerFrame"),this.writeLogFramePointer=this.writeLog.createPointer()),this.userCallbackSystem=new G,this.callbackSystem=new M(this.userCallbackSystem,this),this.callbackSystem.rwMasks.read=void 0,this.callbackSystem.rwMasks.write=void 0}normalizeAndInitSystems(e){const t=[],s=e.flat(1/0);for(let e=0;e<s.length;e++){const r=s[e],i=new r,n=s[e+1];n&&"function"!=typeof n&&(Object.assign(i,n),e++);const a=new M(i,this);t.push(a),this.systemsByClass.set(r,a)}return t}splitDefs(e){const t=[],s=[];let r=!1;for(const i of e.flat(1/0))if("function"==typeof i)r=i.__system,(r?s:t).push(i);else{if(!r)throw new Error("Unexpected value in world defs: "+i);s.push(i),r=!1}return{componentTypes:t,systemTypes:s}}execute(e,t,s){if(this.executing)throw new Error("Recursive system execution not allowed");this.executing=!0,void 0===e&&(e=Y()/1e3),void 0===t&&(t=e-this.lastTime),this.lastTime=e;for(const r of s??this.systems)this.registry.executingSystem=r,r.execute(e,t),this.flush();this.registry.executingSystem=void 0,this.executing=!1,this.processEndOfFrame()}executeFunction(e){if(this.executing)throw new Error("Ad hoc function execution not allowed while world is executing");this.executing=!0,this.registry.executingSystem=this.callbackSystem,this.userCallbackSystem.__callback=e,this.callbackSystem.execute(0,0),this.flush(),this.registry.executingSystem=void 0,this.executing=!1,this.processEndOfFrame()}processEndOfFrame(){this.registry.processEndOfFrame(),this.indexer.processEndOfFrame(),this.gatherFrameStats(),this.processDeferredControls()}gatherFrameStats(){this.stats.frames+=1,this.stats.maxShapeChangesPerFrame=this.shapeLog.countSince(this.shapeLogFramePointer),this.stats.maxWritesPerFrame=this.writeLog?.countSince(this.writeLogFramePointer)??0}flush(){this.registry.flush(),this.indexer.flush(),this.shapeLog.commit(),this.writeLog?.commit()}createEntity(e){const t=this.registry.createEntity(e);return this.executing||this.flush(),t}control(e){this.checkControlOverlap(e),this.deferRequestedRunState(e.stop,N.STOPPED),this.deferRequestedRunState(e.suspend,N.SUSPENDED),this.deferRequestedRunState(e.restart,N.RUNNING),this.executing||this.processDeferredControls()}deferRequestedRunState(e,t){for(const s of e.flat(1/0)){if(!s.__system)continue;const e=this.systemsByClass.get(s);if(!e)throw new Error(`System ${s.name} not defined for this world`);this.deferredControls.set(e,t)}}checkControlOverlap(e){const t=new Set,s=new Set;for(const s of e.stop.flat(1/0))s.__system&&t.add(s);for(const r of e.suspend.flat(1/0))if(r.__system){if(t.has(r))throw new Error(`Request to both stop and suspend system ${r.name}`);s.add(r)}for(const r of e.restart.flat(1/0))if(r.__system){if(t.has(r))throw new Error(`Request to both stop and restart system ${r.name}`);if(s.has(r))throw new Error(`Request to both suspend and restart system ${r.name}`)}}processDeferredControls(){if(this.deferredControls.size){for(const[e,t]of this.deferredControls.entries())switch(t){case N.STOPPED:e.stop();break;case N.SUSPENDED:e.suspend();break;case N.RUNNING:e.restart()}this.deferredControls.clear()}}}const V=[];e.Entity=S,e.Query=B,e.System=$,e.Type=f,e.World=class{__dispatcher;constructor(e){this.__dispatcher=new H(e)}build(e){this.__dispatcher.executeFunction(e)}createEntity(...e){this.__dispatcher.createEntity(e)}execute(e,t){this.__dispatcher.execute(e,t)}control(e){this.__dispatcher.control(e)}get stats(){return this.__dispatcher.stats}},e.component=function(e){if("function"!=typeof e)return t=>{t.options=e,V.push(t)};V.push(e)},e.componentTypes=V,e.prop=function(e){return function(t,s){t.constructor.schema||(t.constructor.schema={});const r="type"in e?e:{type:e};t.constructor.schema[s]=r}},Object.defineProperty(e,"__esModule",{value:!0})})); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).becsy={})}(this,(function(e){"use strict";const t=22,s=4194304,i=4194303,r=512;class n{size;bytes;constructor(e){this.size=e,this.bytes=new Uint32Array(Math.ceil(e/32))}get(e){if(e<0||e>=this.size)throw new Error(`Bit index out of bounds: ${e}`);return 0!=(this.bytes[e>>>5]&1<<(31&e))}set(e){if(e<0||e>=this.size)throw new Error(`Bit index out of bounds: ${e}`);this.bytes[e>>>5]|=1<<(31&e)}unset(e){if(e<0||e>=this.size)throw new Error(`Bit index out of bounds: ${e}`);this.bytes[e>>>5]&=~(1<<(31&e))}clear(){this.bytes.fill(0)}}const a=[];class o{maxEntries;configParamName;localProcessingAllowed;data;corral;constructor(e,t,s=!1){this.maxEntries=e,this.configParamName=t,this.localProcessingAllowed=s;const i=new SharedArrayBuffer((e+2)*Uint32Array.BYTES_PER_ELEMENT);this.data=new Uint32Array(i);const r=new SharedArrayBuffer((e+2)*Uint32Array.BYTES_PER_ELEMENT);this.corral=new Uint32Array(r)}push(e){const t=this.corral[0];t>=this.maxEntries&&this.throwCapacityExceeded(),t&&this.corral[t]===e||(this.corral[t+2]=e,this.corral[0]+=1)}commit(e){if(!e&&this.localProcessingAllowed)throw new Error("Cannot use blind commit when log local processing is allowed");const t=this.corral[0];if(!t)return!0;let s=this.data[0];if(e&&(e.generation!==this.data[1]||e.index!==s||e.corralGeneration!==this.corral[1]||e.corralIndex!==this.corral[0]))return!1;const i=Math.min(t,this.maxEntries-s);for(this.data.set(this.corral.subarray(2,i+2),s+2),i<t&&this.data.set(this.corral.subarray(i+2,t+2),2),s+=t;s>=this.maxEntries;)s-=this.maxEntries,this.data[1]+=1;return this.data[0]=s,this.corral[0]=0,this.corral[1]+=1,e&&(e.index=s,e.generation=this.data[1]),!0}createPointer(e){return e?(e.index=this.data[0],e.generation=this.data[1],e.corralIndex=this.corral[0],e.corralGeneration=this.corral[1],e):{index:this.data[0],generation:this.data[1],corralIndex:this.corral[0],corralGeneration:this.corral[1]}}hasUpdatesSince(e){return this.checkPointer(e),!(e.index===this.data[0]&&e.generation===this.data[1]&&(e.corralGeneration===this.corral[1]?e.corralIndex===this.corral[0]:0===this.corral[0]))}processSince(e,t){this.checkPointers(e,t);let s=a;const i=t?.index??this.data[0],r=t?.generation??this.data[1];if(e.generation===r)if(e.index<i)s=[this.data,e.index+2,i+2,!1],e.index=i;else{const t=this.corral[0],i=this.corral[1];(e.corralGeneration===i?e.corralIndex<t:t)&&(s=[this.corral,e.corralIndex+2,t+2,!0],e.corralIndex=t,e.corralGeneration=i)}else s=[this.data,e.index+2,this.data.length,!1],e.index=0,e.generation=r;return s}processAndCommitSince(e){const t=this.processSince(e);return t[0]?t:this.commit(e)?a:this.processSince(e)}countSince(e,t){if(this.checkPointers(e,t),this.corral[0])throw new Error("Internal error, should commit log before counting");const s=e.index,i=t?.index??this.data[0],r=t?.generation??this.data[1];return e.index=i,e.generation=r,s===i&&e.generation===r?0:s<i?i-s:this.maxEntries-(s-i)}checkPointers(e,t){if(this.checkPointer(e),t&&(this.checkPointer(t),e.index>t.index&&e.generation>=t.generation))throw new RangeError("Internal error, start pointer exceeds end pointer")}checkPointer(e){const t=this.data[0];let s=e.generation;if(e.index===t?s+1<this.data[1]&&this.throwCapacityExceeded():(e.index>t&&(s+=1),s!==this.data[1]&&this.throwCapacityExceeded()),e.corralGeneration>this.corral[1])throw new Error("Internal error, pointer corral generation older than corral");if(e.corralGeneration===this.corral[1]&&e.corralIndex>this.corral[0])throw new Error("Internal error, pointer past end of log corral area")}throwCapacityExceeded(){throw new Error(`Log capacity exceeded, please raise ${this.configParamName} above ${this.maxEntries}`)}}class h{maxItems;configParamName;data;constructor(e,t){this.maxItems=e,this.configParamName=t,this.data=new Uint32Array(new SharedArrayBuffer((e+1)*Uint32Array.BYTES_PER_ELEMENT))}get length(){return this.data[0]}take(){const e=this.data[0]--;if(e<=0)throw new RangeError(`Pool capacity exceeded, please raise ${this.configParamName} above ${this.maxItems}`);return this.data[e]}refill(e){if(!e.length)return;const t=this.length,s=t+e.length;if(s>this.maxItems)throw new Error("Internal error, refill exceeded pool capacity");this.data.set(e,t+1),this.data[0]=s}fillWithDescendingIntegers(e){const t=this.length;for(let s=this.data.length-1;s>t;s--)this.data[s]=e++;this.data[0]=this.data.length-1}}const c=new TextEncoder,d=new TextDecoder;function l(e){throw new Error(`Component is not writable; use entity.write(${e.type.name}) to acquire a writable version`)}function f(e,t){if(e.__invalid)throw new Error(`Component instance for ${t.type.name} is no longer valid, as you already bound it to another entity`)}class u{defaultValue;constructor(e){this.defaultValue=e}static boolean;static uint8;static int8;static uint16;static int16;static uint32;static int32;static float32;static float64;static staticString;static dynamicString;static object;static weakObject;static ref;static backrefs}class p extends u{NumberArray;constructor(e){super(0),this.NumberArray=e}defineElastic(e,t){let s,i;t.updateBuffer=()=>{const r=e.capacity*this.NumberArray.BYTES_PER_ELEMENT,n=t.buffer?.byteLength!==r;(n||t.buffer!==s)&&(s=n?new SharedArrayBuffer(r):t.buffer,i=new this.NumberArray(s),n&&t.buffer&&i.set(new this.NumberArray(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){return f(this,e),i[e.index]},set(t){f(this,e),i[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){return f(this,e),i[e.index]},set(t){l(e)}})}defineFixed(e,t){const s=e.capacity*this.NumberArray.BYTES_PER_ELEMENT,i=new SharedArrayBuffer(s),r=new this.NumberArray(i);t.buffer=i,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){return f(this,e),r[e.index]},set(t){f(this,e),r[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){return f(this,e),r[e.index]},set(t){l(e)}})}}class g extends u{choices;choicesIndex=new Map;TypedArray;constructor(e){if(super(e[0]),this.choices=e,!e?.length)throw new Error("No choices specified for Type.staticString");e.length<256?this.TypedArray=Uint8Array:e.length<65536?this.TypedArray=Uint16Array:this.TypedArray=Uint32Array;for(let t=0;t<e.length;t++)this.choicesIndex.set(e[t],t)}defineElastic(e,t){let s,i;const r=this.choices,n=this.choicesIndex;t.updateBuffer=()=>{const r=e.capacity*this.TypedArray.BYTES_PER_ELEMENT,n=t.buffer?.byteLength!==r;(n||t.buffer!==s)&&(s=n?new SharedArrayBuffer(r):t.buffer,i=new this.TypedArray(s),n&&t.buffer&&i.set(new this.TypedArray(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){f(this,e);const t=i[e.index],s=r[t];if(void 0===s)throw new Error(`Invalid static string index: ${t}`);return s},set(t){f(this,e);const s=n.get(t);if(void 0===s)throw new Error(`Static string not in set: "${t}"`);i[e.index]=s}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){f(this,e);const t=i[e.index],s=r[t];if(void 0===s)throw new Error(`Invalid static string index: ${t}`);return s},set(t){l(e)}})}defineFixed(e,t){const s=this.choices,i=this.choicesIndex,r=e.capacity*this.TypedArray.BYTES_PER_ELEMENT,n=new SharedArrayBuffer(r),a=new this.TypedArray(n);t.buffer=n,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){f(this,e);const t=a[e.index],i=s[t];if(void 0===i)throw new Error(`Invalid static string index: ${t}`);return i},set(t){f(this,e);const s=i.get(t);if(void 0===s)throw new Error(`Static string not in set: "${t}"`);a[e.index]=s}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){f(this,e);const t=a[e.index],i=s[t];if(void 0===i)throw new Error(`Invalid static string index: ${t}`);return i},set(t){l(e)}})}}class y extends u{maxUtf8Length;lengthsStride;bytesStride;constructor(e){super(""),this.maxUtf8Length=e+e%2,this.lengthsStride=e/2+1,this.bytesStride=this.maxUtf8Length+2}defineElastic(e,t){let s,i,r;const n=this.maxUtf8Length,a=this.lengthsStride,o=this.bytesStride;t.updateBuffer=()=>{const n=e.capacity*(this.maxUtf8Length+Uint16Array.BYTES_PER_ELEMENT),a=t.buffer?.byteLength!==n;(a||t.buffer!==s)&&(s=a?new SharedArrayBuffer(n):t.buffer,i=new Uint16Array(s),r=new Uint8Array(s),a&&t.buffer&&r.set(new Uint8Array(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){f(this,e);const t=i[e.index*a];return d.decode(new Uint8Array(r.buffer,e.index*o+2,t))},set(t){f(this,e);const s=c.encode(t);if(s.byteLength>n)throw new Error(`Dynamic string length > ${n} after encoding: ${t}`);i[e.index*a]=s.byteLength,r.set(s,e.index*o+2)}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){f(this,e);const t=i[e.index*a];return d.decode(new Uint8Array(r.buffer,e.index*o+2,t))},set(t){l(e)}})}defineFixed(e,t){const s=this.maxUtf8Length,i=this.lengthsStride,r=this.bytesStride,n=e.capacity*(this.maxUtf8Length+Uint16Array.BYTES_PER_ELEMENT),a=new SharedArrayBuffer(n),o=new Uint16Array(a),h=new Uint8Array(a);t.buffer=a,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){f(this,e);const t=o[e.index*i];return d.decode(new Uint8Array(h.buffer,e.index*r+2,t))},set(t){f(this,e);const n=c.encode(t);if(n.byteLength>s)throw new Error(`Dynamic string length > ${s} after encoding: ${t}`);o[e.index*i]=n.byteLength,h.set(n,e.index*r+2)}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){f(this,e);const t=o[e.index*i];return d.decode(new Uint8Array(h.buffer,e.index*r+2,t))},set(t){l(e)}})}}const m=2**31;const w=[];class _ extends u{type;fieldName;trackDeletedBackrefs;constructor(e,t,s){super(w),this.type=e,this.fieldName=t,this.trackDeletedBackrefs=s}defineElastic(e,t){const s=this.fieldName?this.type?.__binding.fields.find((e=>e.name===this.fieldName)):void 0;if(this.fieldName&&!s)throw new Error(`Backrefs field ${e.type.name}.${t.name} refers to an unknown field ${this.type.name}.${this.fieldName}`);if(s&&s.type!==u.ref)throw new Error(`Backrefs field ${e.type.name}.${t.name} refers to a field ${this.type.name}.${this.fieldName} that is not a ref`);if(this.fieldName&&!this.type)throw new Error(`Backrefs selector has field but no component in ${e.type.name}.${t.name}`);if(this.type&&!this.fieldName&&!this.type.__binding.refFields.length)throw new Error(`Backrefs field ${e.type.name}.${t.name} refers to component ${this.type.name} that has no ref fields`);const i=this.trackDeletedBackrefs,r=e.dispatcher.indexer;r.registerSelector();const n=r.registerSelector(e.type,this.type,s?.seq,this.trackDeletedBackrefs),a={enumerable:!0,configurable:!0,get(){if(f(this,e),!i&&e.dispatcher.registry.includeRecentlyDeleted)throw new Error(`Backrefs field ${e.type.name}.${t.name} not configured to track recently deleted refs`);return r.getBackrefs(e.entityId,n)},set(t){if(f(this,e),t!==w)throw new Error("Backrefs properties are computed automatically, you cannot set them")}};Object.defineProperty(e.writableInstance,t.name,a),Object.defineProperty(e.readonlyInstance,t.name,a)}defineFixed(e,t){this.defineElastic(e,t)}}u.boolean=new class extends u{constructor(){super(!1)}defineElastic(e,t){let s,i;t.updateBuffer=()=>{const r=t.buffer?.byteLength!==e.capacity;(r||t.buffer!==s)&&(s=r?new SharedArrayBuffer(e.capacity):t.buffer,i=new Uint8Array(s),r&&t.buffer&&i.set(new Uint8Array(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){return f(this,e),Boolean(i[e.index])},set(t){f(this,e),i[e.index]=t?1:0}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){return f(this,e),Boolean(i[e.index])},set(t){l(e)}})}defineFixed(e,t){const s=new SharedArrayBuffer(e.capacity),i=new Uint8Array(s);t.buffer=s,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){return f(this,e),Boolean(i[e.index])},set(t){f(this,e),i[e.index]=t?1:0}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){return f(this,e),Boolean(i[e.index])},set(t){l(e)}})}},u.uint8=new p(Uint8Array),u.int8=new p(Int8Array),u.uint16=new p(Uint16Array),u.int16=new p(Int16Array),u.uint32=new p(Uint32Array),u.int32=new p(Int32Array),u.float32=new p(Float32Array),u.float64=new p(Float64Array),u.staticString=e=>new g(e),u.dynamicString=e=>new y(e),u.ref=new class extends u{constructor(){super(void 0)}defineElastic(e,t){let s,r;const n=e.dispatcher.indexer,a=e.dispatcher.registry,o=a.pool;n.registerSelector(),t.updateBuffer=()=>{const i=e.capacity*Int32Array.BYTES_PER_ELEMENT,n=t.buffer?.byteLength!==i;if(n||t.buffer!==s){if(s=n?new SharedArrayBuffer(i):t.buffer,r=new Int32Array(s),n&&t.buffer){const e=new Int32Array(t.buffer);r.set(e),r.fill(-1,e.length)}else r.fill(-1);t.buffer=s}},t.updateBuffer(),t.clearRef=(s,a,o)=>{if(o)throw new Error("Ref fields have no internal index");if(0!=(r[e.index]&m)!==s)throw new Error("Wrong ref stale state");const h=r[e.index]&i,c=void 0!==a;c&&h!==a||(s?c&&(r[e.index]=-1):r[e.index]|=m,n.trackRefChange(e.entityId,e.type,t.seq,void 0,h,-1,s))},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){f(this,e);const t=r[e.index];if(!(-1===t||t&m&&!a.includeRecentlyDeleted))return o.borrowTemporarily(t&i)},set(s){if(f(this,e),s&&!a.hasShape(s.__id,a.Alive,!1))throw new Error("Referencing a deleted entity is not allowed");const i=r[e.index],o=s?.__id??-1;i!==o&&(r[e.index]=o,n.trackRefChange(e.entityId,e.type,t.seq,void 0,i,o,!0))}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){f(this,e);const t=r[e.index];if(!(-1===t||t&m&&!a.includeRecentlyDeleted))return o.borrowTemporarily(t&i)},set(t){l(e)}})}defineFixed(e,t){const s=e.capacity*Int32Array.BYTES_PER_ELEMENT,r=new SharedArrayBuffer(s),n=new Int32Array(r);n.fill(-1),t.buffer=r;const a=e.dispatcher.indexer,o=e.dispatcher.registry,h=o.pool;a.registerSelector(),t.clearRef=(s,r,o)=>{if(o)throw new Error("Ref fields have no internal index");if(0!=(n[e.index]&m)!==s)throw new Error("Wrong ref stale state");const h=n[e.index]&i,c=void 0!==r;c&&h!==r||(s?c&&(n[e.index]=-1):n[e.index]|=m,a.trackRefChange(e.entityId,e.type,t.seq,void 0,h,-1,s))},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){f(this,e);const t=n[e.index];if(!(-1===t||t&m&&!o.includeRecentlyDeleted))return h.borrowTemporarily(t&i)},set(s){if(f(this,e),s&&!o.hasShape(s.__id,o.Alive,!1))throw new Error("Referencing a deleted entity is not allowed");const i=n[e.index],r=s?.__id??-1;i!==r&&(n[e.index]=r,a.trackRefChange(e.entityId,e.type,t.seq,void 0,i,r,!0))}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){f(this,e);const t=n[e.index];if(!(-1===t||t&m&&!o.includeRecentlyDeleted))return h.borrowTemporarily(t&i)},set(t){l(e)}})}},u.backrefs=(e,t,s=!1)=>new _(e,t,s),u.object=new class extends u{constructor(){super(void 0)}defineElastic(e,t){const s=[];t.localBuffer=s,t.updateBuffer=()=>{},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){return f(this,e),s[e.index]},set(t){f(this,e),s[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){return f(this,e),s[e.index]},set(t){l(e)}})}defineFixed(e,t){const s=new Array(e.capacity);t.localBuffer=s,t.updateBuffer=()=>{},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){return f(this,e),s[e.index]},set(t){f(this,e),s[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){return f(this,e),s[e.index]},set(t){l(e)}})}},u.weakObject=new class extends u{finalizers;constructor(){super(void 0)}defineElastic(e,t){const s=[];t.localBuffer=s,t.updateBuffer=()=>{};const i=this.initFinalizers(e);Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){f(this,e);const t=s[e.index];return null==t?t:t.deref()},set(r){if(f(this,e),null!=r){const s=new WeakRef(r);i?.register(r,{type:e.type,field:t,weakRef:s,id:e.entityId,index:e.index}),r=s}s[e.index]=r}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){f(this,e);const t=s[e.index];return null==t?t:t.deref()},set(t){l(e)}})}defineFixed(e,t){const s=new Array(e.capacity);t.localBuffer=s,t.updateBuffer=()=>{};const i=this.initFinalizers(e);Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){f(this,e);const t=s[e.index];return null==t?t:t.deref()},set(r){if(f(this,e),null!=r){const s=new WeakRef(r);i?.register(r,{type:e.type,field:t,weakRef:s,id:e.entityId,index:e.index}),r=s}s[e.index]=r}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){f(this,e);const t=s[e.index];return null==t?t:t.deref()},set(t){l(e)}})}initFinalizers(e){if(!e.trackedWrites)return;if(this.finalizers)return this.finalizers;const t=e.dispatcher;return t.writeLog&&"undefined"!=typeof FinalizationRegistry?(this.finalizers=new FinalizationRegistry((({type:e,field:s,weakRef:i,id:r,index:n})=>{s.localBuffer?.[n]===i&&t.registry.trackWrite(r,e)})),this.finalizers):void 0}};class E{type;fields;dispatcher;capacity;storage;elastic;readonlyInstance;writableInstance;shapeOffset;shapeMask;refFields;trackedWrites=!1;internallyIndexed=!1;entityId=0;index=0;constructor(e,t,s,i,r,n){this.type=e,this.fields=t,this.dispatcher=s,this.capacity=i,this.storage=r,this.elastic=n,this.readonlyInstance=new e,this.writableInstance=new e,this.shapeOffset=e.id>>5,this.shapeMask=1<<(31&e.id),this.refFields=t.filter((e=>e.type===u.ref))}}function b(e){if(!e.__binding)throw new Error(`Component ${e.name} not defined; add to world defs`)}class x{maxEntities;binding;fields;index;spares;constructor(e,t,s){this.maxEntities=e,this.binding=t,this.fields=s,this.growSpares(),this.growCapacity()}acquireIndex(e){let t=this.index[e];if(-1===t){if(this.spares[3]>0)t=this.spares[4+--this.spares[3]];else{if(this.spares[1]===this.spares[2]){if(!this.binding.elastic)throw new Error(`Storage exhausted for component ${this.binding.type.name}; raise its capacity above ${this.binding.capacity}`);this.binding.capacity=Math.min(this.maxEntities,2*this.binding.capacity),this.growCapacity()}t=this.spares[1]++}this.index[e]=t}return t}releaseIndex(e){if(-1===this.index[e])throw new Error(`Internal error, index for entity ${e} not allocated`);this.spares[3]===this.spares.length-4&&this.growSpares(),this.spares[4+this.spares[3]++]=this.index[e],this.index[e]=-1}growCapacity(){this.binding.dispatcher.stats.for(this.binding.type).capacity=this.binding.capacity;const e=this.ArrayType,t=e.BYTES_PER_ELEMENT!==this.spares?.[0];if(!this.index||t){const t=new e(new SharedArrayBuffer(this.maxEntities*e.BYTES_PER_ELEMENT));this.index?t.set(this.index):t.fill(-1),this.index=t}if(this.spares&&t){const t=new e(new SharedArrayBuffer(this.spares.length*e.BYTES_PER_ELEMENT));t.set(this.spares),t[0]=e.BYTES_PER_ELEMENT,this.spares=t}if(this.spares[2]=this.binding.capacity,this.binding.elastic)for(const e of this.fields)e.updateBuffer()}growSpares(){const e=this.ArrayType,t=this.spares?Math.min(this.maxEntities,2*(this.spares.length-4)):8,s=new e(new SharedArrayBuffer((4+t)*e.BYTES_PER_ELEMENT));this.spares?s.set(this.spares):(s[0]=e.BYTES_PER_ELEMENT,s[2]=this.binding.capacity),this.spares=s}get ArrayType(){const e=this.binding.capacity;return e<=127?Int8Array:e<=32767?Int16Array:Int32Array}}function k(e,t,s){const i=function(e){const t=e.schema,s=[];if(t){let i=0;for(const e in t){let r=t[e];(r instanceof u||"function"==typeof r)&&(r={type:r}),"function"==typeof r.type&&(r.type=r.type()),"default"in r||(r.default=r.type.defaultValue),s.push({name:e,seq:i++,type:r.type,default:r.default})}if(i>128)throw new Error(`Component ${e.name} declares too many fields`)}return s}(t),r=i.length?t.options?.storage??s.defaultComponentStorage:"sparse",n="sparse"===r?s.maxEntities:Math.min(s.maxEntities,t.options?.capacity??0),a=t.options?.initialCapacity??8;if(void 0!==t.options?.capacity){if("sparse"===r)throw new Error(`Component type ${t.name} cannot combine custom capacity with sparse storage`);if(t.options.capacity<=0)throw new Error(`Component type ${t.name} capacity option must be great than zero: got ${n}`);if(void 0!==t.options.initialCapacity)throw new Error(`Component type ${t.name} cannot have both capacity and initialCapacity options`)}if(("undefined"==typeof process||"test"!==process.env.NODE_ENV)&&t.__bind)throw new Error(`Component type ${t.name} is already in use in another world`);t.id=e;const o=new E(t,i,s,n||a,r,!n);t.__binding=o}function R(e){const t=e.__binding;for(const e of t.fields)t.elastic?e.type.defineElastic(t,e):e.type.defineFixed(t,e);let s,i;function r(e){e?(t.writableInstance.__invalid=!0,t.writableInstance=Object.create(i)):(t.readonlyInstance.__invalid=!0,t.readonlyInstance=Object.create(s))}switch(s=t.readonlyInstance,i=t.writableInstance,t.readonlyInstance=Object.create(s),t.readonlyInstance.__invalid=!0,t.writableInstance=Object.create(i),t.writableInstance.__invalid=!0,t.storage){case"sparse":t.dispatcher.stats.for(e).capacity=t.capacity,e.__bind=(e,s)=>(t.entityId=e,t.index=e,r(s),s?t.writableInstance:t.readonlyInstance),e.__allocate=e=>(t.entityId=e,t.index=e,r(!0),t.writableInstance);break;case"packed":{const s=new x(t.dispatcher.maxEntities,t,t.fields);e.__bind=(i,n)=>{if(t.entityId=i,t.index=s.index[i],-1===t.index)throw new Error(`Attempt to bind unacquired entity ${i} to ${e.name}`);return r(n),n?t.writableInstance:t.readonlyInstance},e.__allocate=e=>(t.entityId=e,t.index=s.acquireIndex(e),r(!0),t.writableInstance),e.__free=e=>{s.releaseIndex(e)};break}case"compact":throw new Error("Not yet implemented");default:throw new Error(`Invalid storage type "${t.storage}`)}}class S{__registry;__id;constructor(e){this.__registry=e}add(e,t){if(this.__checkMask(e,!0),!this.__registry.hasShape(this.__id,this.__registry.Alive,!1))throw new Error("Entity has been deleted");if(this.__registry.hasShape(this.__id,e,!1))throw new Error(`Entity already has a ${e.name} component`);return this.__registry.setShape(this.__id,e),this.__registry.dispatcher.stats.for(e).numEntities+=1,function(e,t,s){if(b(e),void 0!==s)for(const t in s)if(!e.schema?.[t])throw new Error(`Property ${t} not defined for component ${e.name}`);const i=e.__allocate(t);for(const t of e.__binding.fields)i[t.name]=s?.[t.name]??t.default}(e,this.__id,t),this}addAll(...e){for(let t=0;t<e.length;t++){const s=e[t];if("function"!=typeof s)throw new Error(`Bad arguments to bulk add: expected component type, got: ${s}`);let i=e[t+1];"function"==typeof i?i=void 0:t++,this.add(s,i)}return this}remove(e){this.__checkHas(e,!1),this.__checkMask(e,!0),this.__registry.clearShape(this.__id,e)}removeAll(...e){for(const t of e)this.remove(t)}has(e){return this.__checkMask(e,!1),this.__registry.hasShape(this.__id,e,!0)}read(e){return this.__checkMask(e,!1),this.__checkHas(e,!0),e.__bind(this.__id,!1)}write(e){return this.__checkMask(e,!0),this.__checkHas(e,!0),e.__binding.trackedWrites&&this.__registry.trackWrite(this.__id,e),e.__bind(this.__id,!0)}delete(){const e=this.__registry.Alive;for(const t of this.__registry.types)this.__registry.hasShape(this.__id,t,!1)&&(t!==e&&this.__checkMask(t,!0),this.__registry.clearShape(this.__id,t));this.__registry.queueDeletion(this.__id),this.__registry.dispatcher.indexer.clearAllRefs(this.__id,!1)}__checkMask(e,t){P(e,this.__registry.executingSystem,t)}__checkHas(e,t){if(!this.__registry.hasShape(this.__id,e,t))throw new Error(`Entity doesn't have a ${e.name} component`)}}function P(e,t,s){b(e);const i=s?t?.rwMasks.write:t?.rwMasks.read;if(!(!i||0!=((i[e.__binding.shapeOffset]??0)&e.__binding.shapeMask)))throw new Error(`System didn't mark component ${e.name} as ${s?"writable":"readable"}`)}function v(e,t){b(t);const s=t.__binding.shapeOffset;s>=e.length&&(e.length=s+1,e.fill(0,e.length,s)),e[s]|=t.__binding.shapeMask}class L{pool;entities=[];constructor(e){this.pool=e}add(e){this.entities.push(this.pool.borrowTemporarily(e))}clear(){this.entities.length&&this.entities.splice(0,1/0)}}class I{pool;entities=[];lookupTable;constructor(e,t){this.pool=e,this.lookupTable=new Int32Array(t),this.lookupTable.fill(-1)}add(e){const t=this.entities.push(this.pool.borrow(e))-1;this.lookupTable[e]=t}remove(e){const t=this.lookupTable[e];if(t<0)throw new Error("Internal error, entity not in list");this.pool.return(e),this.lookupTable[e]=-1;const s=this.entities.pop();t<this.entities.length&&(this.entities[t]=s,this.lookupTable[s.__id]=t)}has(e){return this.lookupTable[e]>=0}clear(){for(const e of this.entities)this.pool.return(e.__id);this.entities=[],this.lookupTable.fill(-1)}}var C;!function(e){e[e.all=1]="all",e[e.added=2]="added",e[e.removed=4]="removed",e[e.changed=8]="changed",e[e.addedOrChanged=16]="addedOrChanged",e[e.changedOrRemoved=32]="changedOrRemoved",e[e.addedChangedOrRemoved=64]="addedChangedOrRemoved"}(C||(C={}));const T=C.added|C.removed|C.changed|C.addedOrChanged|C.changedOrRemoved|C.addedChangedOrRemoved,A=C.changed|C.addedOrChanged|C.changedOrRemoved|C.addedChangedOrRemoved;class O{query;system;results={};flavors=0;withMask;withoutMask;trackMask;hasTransientResults;hasChangedResults;currentEntities;changedEntities;constructor(e,t){this.query=e,this.system=t,e.__results=this.results,e.__systemName=t.name}complete(){const e=this.system.dispatcher;if(this.hasTransientResults=Boolean(this.flavors&T),this.hasChangedResults=Boolean(this.flavors&A),this.hasChangedResults&&!this.trackMask)throw new Error("Query for changed entities must track at least one component");this.flavors&C.all?this.results.all=new I(e.registry.pool,e.maxEntities):this.currentEntities=new n(e.maxEntities),this.hasTransientResults&&this.allocateTransientResultLists(),this.flavors&&this.system.shapeQueries.push(this),this.hasChangedResults&&(this.changedEntities=new n(e.maxEntities),this.system.writeQueries.push(this))}allocateTransientResultLists(){this.flavors&C.added&&this.allocateResult("added"),this.flavors&C.removed&&this.allocateResult("removed"),this.flavors&C.changed&&this.allocateResult("changed"),this.flavors&C.addedOrChanged&&this.allocateResult("addedOrChanged"),this.flavors&C.changedOrRemoved&&this.allocateResult("changedOrRemoved"),this.flavors&C.addedChangedOrRemoved&&this.allocateResult("addedChangedOrRemoved")}allocateResult(e){const t=this.system.dispatcher;this.results[e]=new L(t.registry.pool)}clearTransientResults(){this.hasTransientResults&&(this.results.added?.clear(),this.results.removed?.clear(),this.results.changed?.clear(),this.results.addedOrChanged?.clear(),this.results.changedOrRemoved?.clear(),this.results.addedChangedOrRemoved?.clear(),this.changedEntities?.clear())}clearAllResults(){this.clearTransientResults(),this.results.all?.clear()}handleShapeUpdate(e){const t=this.system.dispatcher.registry,s=this.results.all?.has(e)??this.currentEntities.get(e),i=t.matchShape(e,this.withMask,this.withoutMask);i&&!s?(this.currentEntities?.set(e),this.results.all?.add(e),this.results.added?.add(e),this.results.addedOrChanged?.add(e),this.results.addedChangedOrRemoved?.add(e)):!i&&s&&(this.currentEntities?.unset(e),this.results.all?.remove(e),this.results.removed?.add(e),this.results.changedOrRemoved?.add(e),this.results.addedChangedOrRemoved?.add(e))}handleWrite(e,t,s){!this.changedEntities.get(e)&&(this.trackMask[t]??0)&s&&(this.changedEntities.set(e),this.results.changed?.add(e),this.results.addedOrChanged?.add(e),this.results.changedOrRemoved?.add(e),this.results.addedChangedOrRemoved?.add(e))}}class B{__callback;__userQuery;__query;__system;__lastTypes;constructor(e,t){this.__callback=e,this.__userQuery=t}__build(e){try{this.__system=e,this.__query=new O(this.__userQuery,e),this.__callback(this),this.__query.complete()}catch(t){throw t.message=`Failed to build query in system ${e.name}: ${t.message}`,t}}get and(){return this}get but(){return this}get also(){return this}get all(){return this.__query.flavors|=C.all,this}get added(){return this.__query.flavors|=C.added,this}get removed(){return this.__query.flavors|=C.removed,this}get changed(){return this.__query.flavors|=C.changed,this}get addedOrChanged(){return this.__query.flavors|=C.addedOrChanged,this}get changedOrRemoved(){return this.__query.flavors|=C.changedOrRemoved,this}get addedChangedOrRemoved(){return this.__query.flavors|=C.addedChangedOrRemoved,this}with(...e){return this.set(this.__system.rwMasks.read,e),this.set("withMask"),this}without(...e){return this.set(this.__system.rwMasks.read,e),this.set("withoutMask",e),this}using(...e){return this.set(this.__system.rwMasks.read,e),this}get track(){this.set("trackMask");for(const e of this.__lastTypes)e.__binding.trackedWrites=!0;return this}get read(){return this}get write(){return this.set(this.__system.rwMasks.write),this}set(e,t,s){if(e){if(t||(t=this.__lastTypes),!t)throw new Error("No component type to apply query modifier to");if(this.__lastTypes=t,"string"==typeof e){if(s&&this.__query[e])throw new Error(`Only one ${s} allowed`);this.__query[e]||(this.__query[e]=[]),e=this.__query[e]}else if(s&&e.some((e=>0!==e)))throw new Error(`Only one ${s} allowed`);for(const s of t)v(e,s)}}}class N{__results;__systemName;get all(){return this.__checkList("all"),this.__results.all.entities}get added(){return this.__checkList("added"),this.__results.added.entities}get removed(){return this.__checkList("removed"),this.__results.removed.entities}get changed(){return this.__checkList("changed"),this.__results.changed.entities}get addedOrChanged(){return this.__checkList("addedOrChanged"),this.__results.addedOrChanged.entities}get changedOrRemoved(){return this.__checkList("changedOrRemoved"),this.__results.changedOrRemoved.entities}get addedChangedOrRemoved(){return this.__checkList("addedChangedOrRemoved"),this.__results.addedChangedOrRemoved.entities}__checkList(e){if(!this.__results[e])throw new Error(`Query '${e}' not configured, please add .${e} to your query definition in system ${this.__systemName}`)}}var F,$;!function(e){e[e.RUNNING=0]="RUNNING",e[e.STOPPED=1]="STOPPED"}(F||(F={}));class M{type;constructor(e){this.type=e}}class U{static __system=!0;__queryBuilders=[];__dispatcher;time;delta;get name(){return this.constructor.name}query(e){const t=new N,s=new B(e,t);if(!this.__queryBuilders)throw new Error(`Attempt to create a new query after world initialized in system ${this.name}`);return this.__queryBuilders.push(s),t}attach(e){return new M(e)}createEntity(...e){return this.__dispatcher.createEntity(e)}accessRecentlyDeletedData(e=!0){this.__dispatcher.registry.includeRecentlyDeleted=e}initialize(){}execute(){}}class D{system;dispatcher;rwMasks={read:[],write:[]};shapeQueries=[];writeQueries=[];hasWriteQueries;processedEntities;shapeLogPointer;writeLogPointer;state=F.RUNNING;get name(){return this.system.name}constructor(e,t){this.system=e,this.dispatcher=t,e.__dispatcher=t,this.shapeLogPointer=t.shapeLog.createPointer(),this.writeLogPointer=t.writeLog?.createPointer(),this.processedEntities=new n(t.maxEntities);for(const t of e.__queryBuilders)t.__build(this);e.__queryBuilders=null,this.hasWriteQueries=!!this.writeQueries.length}replaceAttachmentPlaceholders(){for(const e in this.system)if(this.system[e]instanceof M){const t=this.system[e].type,s=this.dispatcher.systemsByClass.get(t);if(!s)throw new Error(`Attached system ${t.name} not defined in this world`);this.system[e]=s}}async initialize(){await Promise.resolve(this.system.initialize())}execute(e,t){this.state===F.RUNNING&&(this.system.time=e,this.system.delta=t,this.runQueries(),this.system.execute())}runQueries(){const e=this.dispatcher.shapeLog.hasUpdatesSince(this.shapeLogPointer),t=this.hasWriteQueries&&this.dispatcher.writeLog.hasUpdatesSince(this.writeLogPointer);if(e||t){this.processedEntities.clear();for(const e of this.shapeQueries)e.clearTransientResults();e&&this.__updateShapeQueries(),t&&this.__updateWriteQueries()}}__updateShapeQueries(){const e=this.dispatcher.shapeLog;let t,s,i;for(;[t,s,i]=e.processSince(this.shapeLogPointer),t;)for(let e=s;e<i;e++){const s=t[e];if(!this.processedEntities.get(s)){this.processedEntities.set(s);for(const e of this.shapeQueries)e.handleShapeUpdate(s)}}}__updateWriteQueries(){const e=this.dispatcher.writeLog;let s,r,n;for(;[s,r,n]=e.processSince(this.writeLogPointer),s;)for(let e=r;e<n;e++){const r=s[e],n=r&i;if(!this.processedEntities.get(n)){const e=r>>>t;for(const t of this.writeQueries)t.handleWrite(n,e>>5,1<<(31&e))}}}stop(){if(this.state!==F.STOPPED){this.state=F.STOPPED;for(const e of this.shapeQueries)e.clearAllResults()}}restart(){if(this.state===F.STOPPED){const e=this.dispatcher.registry,t=e.Alive;for(let s=0;s<this.dispatcher.maxEntities;s++)if(e.hasShape(s,t,!1))for(const e of this.shapeQueries)e.handleShapeUpdate(s);for(const e of this.shapeQueries)e.clearTransientResults();this.dispatcher.shapeLog.createPointer(this.shapeLogPointer),this.dispatcher.writeLog?.createPointer(this.writeLogPointer)}this.state=F.RUNNING}}class q{registry;borrowed;borrowCounts;spares=[];temporarilyBorrowedIds=[];constructor(e,t){this.registry=e,this.borrowed=Array.from({length:t}),this.borrowCounts=new Int32Array(t)}borrow(e){this.borrowCounts[e]+=1;let t=this.borrowed[e];return t||(t=this.borrowed[e]=this.spares.pop()??new S(this.registry),t.__id=e),t}borrowTemporarily(e){const t=this.borrow(e);return this.temporarilyBorrowedIds.push(e),t}returnTemporaryBorrows(){for(const e of this.temporarilyBorrowedIds)this.return(e);this.temporarilyBorrowedIds.splice(0,1/0)}return(e){if(!this.borrowCounts[e])throw new Error("Internal error, returning entity with no borrows");--this.borrowCounts[e]<=0&&(this.spares.push(this.borrowed[e]),this.borrowed[e]=void 0)}}class j{types;dispatcher;stride;shapes;staleShapes;entityIdPool;pool;executingSystem;includeRecentlyDeleted=!1;deletionLog;prevDeletionPointer;oldDeletionPointer;removalLog;prevRemovalPointer;oldRemovalPointer;Alive=class{};constructor(e,t,s,i,r){this.types=i,this.dispatcher=r,this.stride=Math.ceil(i.length/32);const n=e*this.stride*4;this.shapes=new Uint32Array(new SharedArrayBuffer(n)),this.staleShapes=new Uint32Array(new SharedArrayBuffer(n)),this.entityIdPool=new h(e,"maxEntities"),this.entityIdPool.fillWithDescendingIntegers(0),this.pool=new q(this,e),this.deletionLog=new o(t,"maxLimboEntities"),this.prevDeletionPointer=this.deletionLog.createPointer(),this.oldDeletionPointer=this.deletionLog.createPointer(),this.removalLog=new o(s,"maxLimboComponents"),this.prevRemovalPointer=this.removalLog.createPointer(),this.oldRemovalPointer=this.removalLog.createPointer()}initializeComponentTypes(){this.types.unshift(this.Alive);let e=0;for(const t of this.types)k(e++,t,this.dispatcher);for(const e of this.types)R(e);{const e=this.types[0].__binding;if(0!==e.shapeOffset||1!==e.shapeMask)throw new Error("Alive component was not assigned first available shape mask")}}createEntity(e){const t=this.entityIdPool.take(),s=t*this.stride;this.shapes[s]=1,this.stride>1&&this.shapes.fill(0,s+1,s+this.stride);const i=this.pool.borrowTemporarily(t);return e&&i.addAll(...e),this.dispatcher.stats.numEntities+=1,i}queueDeletion(e){this.deletionLog.push(e)}flush(){this.includeRecentlyDeleted=!1,this.pool.returnTemporaryBorrows(),this.deletionLog.commit(),this.removalLog.commit()}processEndOfFrame(){this.processDeletionLog(),this.processRemovalLog()}processDeletionLog(){this.deletionLog.commit();let e,t,s,i=0;for(;[e,t,s]=this.deletionLog.processSince(this.oldDeletionPointer,this.prevDeletionPointer),e;){for(let i=t;i<s;i++)this.dispatcher.indexer.clearAllRefs(e[i],!0);const r=e.subarray(t,s);this.entityIdPool.refill(r),i+=r.length}this.dispatcher.stats.numEntities-=i,this.dispatcher.stats.maxLimboEntities=i,this.deletionLog.createPointer(this.prevDeletionPointer)}processRemovalLog(){this.removalLog.commit();let e,s,r,n=0;for(;[e,s,r]=this.removalLog.processSince(this.oldRemovalPointer,this.prevRemovalPointer),e;){for(let n=s;n<r;n++){const s=e[n],r=s&i,a=s>>>t,o=this.types[a],h=r*this.stride+o.__binding.shapeOffset,c=o.__binding.shapeMask;0==(this.shapes[h]&c)&&(this.staleShapes[h]&=~c,this.clearRefs(r,o,!0),o.__free?.(r))}n+=r-s}this.dispatcher.stats.maxLimboComponents=n,this.removalLog.createPointer(this.prevRemovalPointer)}hasShape(e,t,s){const i=e*this.stride+t.__binding.shapeOffset,r=t.__binding.shapeMask;return 0!=(this.shapes[i]&r)||!(!s||!this.includeRecentlyDeleted||0==(this.staleShapes[i]&r))}setShape(e,t){const s=e*this.stride+t.__binding.shapeOffset,i=t.__binding.shapeMask;this.shapes[s]|=i,this.staleShapes[s]|=i,this.dispatcher.shapeLog.push(e)}clearShape(e,s){const i=this.clearRefs(e,s,!1);(s.__free||i)&&this.removalLog.push(e|s.id<<t),this.shapes[e*this.stride+s.__binding.shapeOffset]&=~s.__binding.shapeMask,this.dispatcher.shapeLog.push(e),this.dispatcher.stats.for(s).numEntities-=1}trackWrite(e,s){this.dispatcher.writeLog.push(e|s.id<<t)}clearRefs(e,t,s){const i=!!t.__binding.refFields.length;if(i){t.__bind(e,!0);for(const e of t.__binding.refFields)e.clearRef(s)}return i}matchShape(e,t,s){const i=e*this.stride;if(t)for(let e=0;e<t.length;e++){const s=t[e];if((this.shapes[i+e]&s)!==s)return!1}if(s)for(let e=0;e<s.length;e++){const t=s[e];if(0!=(this.shapes[i+e]&t))return!1}return!0}}class W{_numEntities=0;maxEntities=0;capacity=0;get numEntities(){return this._numEntities}set numEntities(e){this._numEntities=e,e>this.maxEntities&&(this.maxEntities=e)}toString(){return`${this.numEntities.toLocaleString()} of ${this.maxEntities.toLocaleString()} peak (capacity ${this.capacity.toLocaleString()})`}}class z{frames=0;_numEntities=0;maxEntities=0;_maxLimboEntities=0;_maxLimboComponents=0;_maxRefChangesPerFrame=0;_maxShapeChangesPerFrame=0;_maxWritesPerFrame=0;components=Object.create(null);get numEntities(){return this._numEntities}set numEntities(e){this._numEntities=e,e>this.maxEntities&&(this.maxEntities=e)}get maxLimboEntities(){return this._maxLimboEntities}set maxLimboEntities(e){e>this._maxLimboEntities&&(this._maxLimboEntities=e)}get maxLimboComponents(){return this._maxLimboComponents}set maxLimboComponents(e){e>this._maxLimboComponents&&(this._maxLimboComponents=e)}get maxRefChangesPerFrame(){return this._maxRefChangesPerFrame}set maxRefChangesPerFrame(e){e>this._maxRefChangesPerFrame&&(this._maxRefChangesPerFrame=e)}get maxShapeChangesPerFrame(){return this._maxShapeChangesPerFrame}set maxShapeChangesPerFrame(e){e>this._maxShapeChangesPerFrame&&(this._maxShapeChangesPerFrame=e)}get maxWritesPerFrame(){return this._maxWritesPerFrame}set maxWritesPerFrame(e){e>this._maxWritesPerFrame&&(this._maxWritesPerFrame=e)}for(e){return this.components[e.name]=this.components[e.name]??new W}toString(){return`World stats:\n frames: ${this.frames.toLocaleString()}\n entities: ${this.numEntities.toLocaleString()} of ${this.maxEntities.toLocaleString()} max (${this.maxLimboEntities.toLocaleString()} limbo max)\n refs: ${this.maxRefChangesPerFrame.toLocaleString()} ref changes/frame max\n logs: ${this.maxShapeChangesPerFrame.toLocaleString()} shape changes/frame max, ${this.maxWritesPerFrame.toLocaleString()} writes/frame max`}}!function(e){e[e.REFERENCE=0]="REFERENCE",e[e.UNREFERENCE=1073741824]="UNREFERENCE",e[e.RELEASE=2147483648]="RELEASE"}($||($={}));const Q=$.REFERENCE|$.UNREFERENCE|$.RELEASE;class Y{targetEntityId;selector;dispatcher;entities=[];tags;entityIndex;clearing=!1;registry;constructor(e,t,s){this.targetEntityId=e,this.selector=t,this.dispatcher=s;const i=t.sourceType?.__binding;t.matchType&&(t.matchSeq||1===i.refFields.length)&&!i.internallyIndexed||(this.tags=[]),this.registry=s.registry}clearAllRefs(e){if(!this.tags)throw new Error("Unreferencing an untagged tracker");this.clearing=!0;for(let t=0;t<this.entities.length;t++){const s=this.entities[t].__id,i=this.tags[t];if("number"==typeof i)this.clearRef(s,i,e);else for(const t of i)this.clearRef(s,t,e)}this.entities=[],this.tags=[],this.entityIndex=void 0,this.clearing=!1}clearRef(e,t,s){const i=511&t,r=t>>>9&127,n=t>>>16,a=this.registry.types[i];P(a,this.registry.executingSystem,!0),a.__bind(e,!0),a.__binding.fields[r].clearRef(s,this.targetEntityId,n)}trackReference(e,t,s,i,r){if(this.clearing)throw new Error("Cannot track a new reference while clearing tracker");r&&this.checkWriteMask();let n=this.getEntityIndex(e);void 0===n&&(n=this.addEntity(e,r)),this.addTag(n,this.makeTag(t,s,i))}trackUnreference(e,t,s,i,r){if(this.clearing)return;r&&this.checkWriteMask();const n=this.getEntityIndex(e);if(void 0===n)throw new Error("Entity backref not tracked");this.removeTag(n,this.makeTag(t,s,i))&&this.removeEntity(n,e,r)}getEntityIndex(e){if(this.entityIndex)return this.entityIndex[e];const t=this.entities.findIndex((t=>t.__id===e));return t>=0?t:void 0}indexEntities(){if(this.entityIndex)throw new Error("Entities already indexed");this.entityIndex=new Array(this.dispatcher.maxEntities);for(let e=0;e<this.entities.length;e++)this.entityIndex[this.entities[e].__id]=e}addTag(e,t){if(!this.tags)return;const s=this.tags[e];if(void 0===s)this.tags[e]=t;else if("number"==typeof s){if(s===t)throw new Error("Ref already tracked");this.tags[e]=[s,t]}else if(Array.isArray(s)){if(s.includes(t))throw new Error("Ref already tracked");if(s.length>=1e3){(this.tags[e]=new Set(s)).add(t)}else s.push(t)}else{if(s.has(t))throw new Error("Ref already tracked");s.add(t)}}removeTag(e,t){if(!this.tags)return!0;const s=this.tags[e];if(void 0===s)throw new Error("Ref not tracked");if("number"==typeof s){if(s!==t)throw new Error("Ref not tracked");return delete this.tags[e],!0}if(Array.isArray(s)){const e=s.indexOf(t);if(-1===e)throw new Error("Ref not tracked");return s.splice(e,1),!this.tags.length}return s.delete(t),!s.size}makeTag(e,t,s){return e|t<<9|(void 0===s?0:s<<16)}addEntity(e,t){const s=this.entities.length;return this.entities.push(this.registry.pool.borrow(e)),this.entityIndex?this.entityIndex[e]=s:s>100&&this.indexEntities(),t&&this.trackBackrefsChange(),s}removeEntity(e,t,s){this.registry.pool.return(t);const i=this.entities.pop();this.entityIndex&&delete this.entityIndex[e],this.entities.length>e&&(this.entities[e]=i,this.entityIndex&&(this.entityIndex[i.__id]=e)),s&&this.trackBackrefsChange()}trackBackrefsChange(){for(const e of this.selector.targetTypes)e.__binding.trackedWrites&&this.registry.trackWrite(this.targetEntityId,e)}checkWriteMask(){const e=this.registry.executingSystem;for(const t of this.selector.targetTypes)P(t,e,!0)}}class G{dispatcher;maxRefChangesPerFrame;refLog;refLogPointer;refLogStatsPointer;selectorIdsBySourceKey=new Map;selectors=[];trackers=new Map;registry;constructor(e,t){this.dispatcher=e,this.maxRefChangesPerFrame=t,this.registry=e.registry}processEndOfFrame(){this.flush(),this.dispatcher.stats.maxRefChangesPerFrame=this.refLog?.countSince(this.refLogStatsPointer)??0}registerSelector(e,t,s,i=!1){e&&b(e),t&&b(t),this.refLog||(this.refLog=new o(this.maxRefChangesPerFrame,"maxRefChangesPerFrame",!0),this.refLogPointer=this.refLog.createPointer(),this.refLogStatsPointer=this.refLog.createPointer());const n=t?void 0===s?-2-t.id:t.id|s<<9:-1;let a=this.selectorIdsBySourceKey.get(n);if(void 0===a){this.selectors.length||(i=!0);const o={id:this.selectors.length,targetTypes:e?[e]:[],sourceType:t,matchType:!!t,matchSeq:void 0!==s,sourceTypeId:t?.id,sourceSeq:s,trackStale:i};if(this.selectors.push(o),a=o.id,this.selectorIdsBySourceKey.set(n,a),a>r)throw new Error("Too many distinct backrefs selectors")}else{const t=this.selectors[a];t.trackStale=t.trackStale||i,e&&t.targetTypes.push(e)}return a}getBackrefs(e,t=0){const s=this.selectors[t];return this.getOrCreateTracker(s,e,this.registry.includeRecentlyDeleted).entities}trackRefChange(e,t,s,i,r,n,a){if(!this.refLog)throw new Error("Trying to trackRefChange without a refLog");if(r===n)throw new Error("No-op call to trackRefChange");-1!==r&&this.pushRefLogEntry(e,t,s,i,r,a?$.RELEASE:$.UNREFERENCE),-1!==n&&this.pushRefLogEntry(e,t,s,i,n,$.REFERENCE)}clearAllRefs(e,t){this.selectors.length&&this.getTracker(this.selectors[0],e,t)?.clearAllRefs(t)}pushRefLogEntry(e,s,i,r,n,a){const o=void 0!==r;if(o!==s.__binding.internallyIndexed)throw new Error("Inconsistent internally indexed flag");this.refLog.push(e|s.id<<t),this.refLog.push(n|i<<t|a|(o?2**29:0)),o&&this.refLog.push(r),this.processEntry(e,s.id,i,r,n,a,!0)}getOrCreateTracker(e,s,i){let r,n=this.getTracker(e,s,i);if(n)return n;if(i&&!e.trackStale)throw new Error("Selector not configured for stale tracking");return n=new Y(s,e,this.dispatcher),this.trackers.set(s|e.id<<t,n),e.trackStale&&(r=new Y(s,e,this.dispatcher),this.trackers.set(s|e.id<<t|2**31,r)),i?r:n}getTracker(e,s,i){return this.trackers.get(s|e.id<<t|(i?2**31:0))}flush(){if(this.refLog)for(;;){const[e,s,r,n]=this.refLog.processAndCommitSince(this.refLogPointer);if(!e)break;if(!n)for(let n=s;n<r;n+=2){const s=e[n],r=e[n+1],a=s&i,o=s>>>t,h=r&i,c=r>>>t&127,d=(r&Q)>>>30,l=0!=(r&2**29),f=l?e[n+2]:void 0;l&&(n+=1),this.processEntry(a,o,c,f,h,d,!1)}}}processEntry(e,t,s,i,r,n,a){for(let o=0;o<this.selectors.length;o++){const h=this.selectors[o];if(!(h.matchType&&h.sourceTypeId!==t||h.matchSeq&&h.sourceSeq!==s)){if(n===$.REFERENCE||n===$.UNREFERENCE){const o=this.getOrCreateTracker(h,r,!1);n===$.REFERENCE?o.trackReference(e,t,s,i,a):o.trackUnreference(e,t,s,i,a)}if(h.trackStale&&(n===$.REFERENCE||n===$.RELEASE)){const o=this.getOrCreateTracker(h,r,!0);n===$.REFERENCE?o.trackReference(e,t,s,i,a):o.trackUnreference(e,t,s,i,a)}}}}}const H="undefined"!=typeof window&&void 0!==window.performance?performance.now.bind(performance):Date.now.bind(Date);class V extends U{__callback;execute(){this.__callback(this)}}class K{maxEntities;defaultComponentStorage;registry;systems;systemsByClass=new Map;lastTime=H()/1e3;executing;shapeLog;writeLog;shapeLogFramePointer;writeLogFramePointer;stats;indexer;userCallbackSystem;callbackSystem;deferredControls=new Map;constructor({defs:e,maxEntities:t=1e4,maxLimboEntities:i=Math.ceil(t/5),maxLimboComponents:n=Math.ceil(t/5),maxShapeChangesPerFrame:a=2*t,maxWritesPerFrame:h=4*t,maxRefChangesPerFrame:c=t,defaultComponentStorage:d="sparse"}){if(t>s)throw new Error("maxEntities too high, the limit is 4194304");const{componentTypes:l,systemTypes:f}=this.splitDefs(e);if(l.length>r)throw new Error("Too many component types, the limit is 512");this.stats=new z,this.maxEntities=t,this.defaultComponentStorage=d,this.shapeLog=new o(a,"maxShapeChangesPerFrame"),this.shapeLogFramePointer=this.shapeLog.createPointer(),this.registry=new j(t,i,n,l.flat(1/0),this),this.indexer=new G(this,c),this.registry.initializeComponentTypes(),this.systems=this.normalizeAndInitSystems(f),this.systems.some((e=>e.hasWriteQueries))&&(this.writeLog=new o(h,"maxWritesPerFrame"),this.writeLogFramePointer=this.writeLog.createPointer()),this.userCallbackSystem=new V,this.callbackSystem=new D(this.userCallbackSystem,this),this.callbackSystem.rwMasks.read=void 0,this.callbackSystem.rwMasks.write=void 0}normalizeAndInitSystems(e){const t=[],s=e.flat(1/0);for(let e=0;e<s.length;e++){const i=s[e],r=new i,n=s[e+1];n&&"function"!=typeof n&&(Object.assign(r,n),e++);const a=new D(r,this);t.push(a),this.systemsByClass.set(i,a)}for(const e of t)e.replaceAttachmentPlaceholders();return t}splitDefs(e){const t=[],s=[];let i=!1;for(const r of e.flat(1/0))if("function"==typeof r)i=r.__system,(i?s:t).push(r);else{if(!i)throw new Error("Unexpected value in world defs: "+r);s.push(r),i=!1}return{componentTypes:t,systemTypes:s}}async initialize(){await Promise.all(this.systems.map((e=>e.initialize())))}async execute(e,t,s){if(this.executing)throw new Error("Recursive system execution not allowed");this.executing=!0,void 0===e&&(e=H()/1e3),void 0===t&&(t=e-this.lastTime),this.lastTime=e;for(const i of s??this.systems)this.registry.executingSystem=i,i.execute(e,t),this.flush();this.registry.executingSystem=void 0,this.executing=!1,this.processEndOfFrame()}executeFunction(e){if(this.executing)throw new Error("Ad hoc function execution not allowed while world is executing");this.executing=!0,this.registry.executingSystem=this.callbackSystem,this.userCallbackSystem.__callback=e,this.callbackSystem.execute(0,0),this.flush(),this.registry.executingSystem=void 0,this.executing=!1,this.processEndOfFrame()}processEndOfFrame(){this.registry.processEndOfFrame(),this.indexer.processEndOfFrame(),this.gatherFrameStats(),this.processDeferredControls()}gatherFrameStats(){this.stats.frames+=1,this.stats.maxShapeChangesPerFrame=this.shapeLog.countSince(this.shapeLogFramePointer),this.stats.maxWritesPerFrame=this.writeLog?.countSince(this.writeLogFramePointer)??0}flush(){this.registry.flush(),this.indexer.flush(),this.shapeLog.commit(),this.writeLog?.commit()}createEntity(e){const t=this.registry.createEntity(e);return this.executing||this.flush(),t}control(e){this.checkControlOverlap(e),this.deferRequestedRunState(e.stop,F.STOPPED),this.deferRequestedRunState(e.restart,F.RUNNING),this.executing||this.processDeferredControls()}deferRequestedRunState(e,t){for(const s of e.flat(1/0)){if(!s.__system)continue;const e=this.systemsByClass.get(s);if(!e)throw new Error(`System ${s.name} not defined for this world`);this.deferredControls.set(e,t)}}checkControlOverlap(e){const t=new Set;for(const s of e.stop.flat(1/0))s.__system&&t.add(s);for(const s of e.restart.flat(1/0))if(s.__system&&t.has(s))throw new Error(`Request to both stop and restart system ${s.name}`)}processDeferredControls(){if(this.deferredControls.size){for(const[e,t]of this.deferredControls.entries())switch(t){case F.STOPPED:e.stop();break;case F.RUNNING:e.restart()}this.deferredControls.clear()}}}const J={};class X{__dispatcher;static async create(e){const t=new X(e,J);return await t.__dispatcher.initialize(),t}constructor(e,t){if(t!==J)throw new Error("Don't call World constructor directly; use World.create instead");this.__dispatcher=new K(e)}build(e){this.__dispatcher.executeFunction(e)}createEntity(...e){this.__dispatcher.createEntity(e)}execute(e,t){return this.__dispatcher.execute(e,t)}control(e){this.__dispatcher.control(e)}get stats(){return this.__dispatcher.stats}}const Z=[];e.Entity=S,e.Query=N,e.System=U,e.Type=u,e.World=X,e.component=function(e){if("function"!=typeof e)return t=>{t.options=e,Z.push(t)};Z.push(e)},e.componentTypes=Z,e.field=function(e){return function(t,s){t.constructor.schema||(t.constructor.schema={});const i="type"in e?e:{type:e};t.constructor.schema[s]=i}},Object.defineProperty(e,"__esModule",{value:!0})})); | ||
//# sourceMappingURL=index.umd.min.js.map |
{ | ||
"name": "@lastolivegames/becsy", | ||
"type": "module", | ||
"version": "0.4.1", | ||
"version": "0.5.0", | ||
"scripts": { | ||
"test": "jest --config jestconfig.json --detectOpenHandles", | ||
"test:watch": "jest --watch --config jestconfig.json --detectOpenHandles", | ||
"bench": "rollup --config rollup.benchmarks.config.mjs && cp index.* perf.* lib && env NODE_ENV=test node --expose-gc --enable-source-maps --es-module-specifier-resolution=node lib/benchmarks/index.js", | ||
"bench:watch": "tsc-watch --onSuccess \"env NODE_ENV=test node --expose-gc --enable-source-maps --es-module-specifier-resolution=node lib/benchmarks/index.js\"", | ||
"perf": "tsc && rollup --config rollup.benchmarks.config.mjs && cp index.* perf.* lib && env NODE_ENV=test node --expose-gc --enable-source-maps --es-module-specifier-resolution=node lib/benchmarks/index.js", | ||
"deopt": "rm *.log && node --trace-ic --enable-source-maps --es-module-specifier-resolution=node lib/tests/performance.test.js && mv *.log v8.pre.log && node striplog.cjs && deoptigate", | ||
@@ -11,0 +10,0 @@ "flame": "clinic flame -- node --enable-source-maps --es-module-specifier-resolution=node lib/tests/performance.test.js", |
@@ -132,4 +132,4 @@ interface LogPointer { | ||
} | ||
interface SystemType { | ||
new (): System; | ||
interface SystemType<S extends System> { | ||
new (): S; | ||
} | ||
@@ -142,7 +142,10 @@ declare abstract class System { | ||
delta: number; | ||
// TODO: support schedule builder | ||
get name(): string; | ||
query(buildCallback: (q: QueryBuilder) => void): Query; | ||
attach<S extends System>(systemType: SystemType<S>): S; | ||
createEntity(...initialComponents: (ComponentType<any> | any)[]): Entity; | ||
accessRecentlyDeletedData(toggle?: boolean): void; | ||
abstract execute(): void; | ||
initialize(): void | Promise<void>; // eslint-disable-line @typescript-eslint/no-empty-function | ||
execute(): void; // eslint-disable-line @typescript-eslint/no-empty-function | ||
} | ||
@@ -162,2 +165,4 @@ declare class SystemBox { | ||
constructor(system: System, dispatcher: Dispatcher); | ||
replaceAttachmentPlaceholders(): void; | ||
initialize(): Promise<void>; | ||
execute(time: number, delta: number): void; | ||
@@ -169,3 +174,2 @@ private runQueries; | ||
restart(): void; | ||
suspend(): void; | ||
} | ||
@@ -231,3 +235,3 @@ declare class ComponentStats { | ||
// https://stackoverflow.com/questions/67467302/type-for-an-interleaved-array-of-classes-and-values | ||
type DefsArray = (ComponentType<any> | SystemType | any | DefsArray)[]; | ||
type DefsArray = (ComponentType<any> | SystemType<System> | any | DefsArray)[]; | ||
interface WorldOptions { | ||
@@ -245,3 +249,2 @@ defs: DefsArray; | ||
stop: DefsArray; | ||
suspend: DefsArray; | ||
restart: DefsArray; | ||
@@ -254,3 +257,3 @@ } | ||
private readonly systems; | ||
private readonly systemsByClass; | ||
readonly systemsByClass: Map<SystemType<System>, SystemBox>; | ||
private lastTime; | ||
@@ -270,3 +273,4 @@ executing: boolean; | ||
private splitDefs; | ||
execute(time?: number, delta?: number, systems?: SystemBox[]): void; | ||
initialize(): Promise<void>; | ||
execute(time?: number, delta?: number, systems?: SystemBox[]): Promise<void>; | ||
executeFunction(fn: (system: System) => void): void; | ||
@@ -366,2 +370,3 @@ private processEndOfFrame; | ||
static weakObject: Type<any>; | ||
// TODO: add autoremove/autodelete when nulled out | ||
static ref: Type<Entity | undefined>; | ||
@@ -393,3 +398,6 @@ static backrefs: (type?: ComponentType<any>, fieldName?: string, trackDeletedBackrefs?: boolean) => Type<Entity[]>; | ||
} | ||
interface ComponentType<C> { | ||
interface Component { | ||
__invalid?: boolean; | ||
} | ||
interface ComponentType<C extends Component> { | ||
new (): C; | ||
@@ -416,4 +424,4 @@ schema?: Schema; | ||
readonly elastic: boolean; | ||
readonly readonlyInstance: C; | ||
readonly writableInstance: C; | ||
readonlyInstance: C; | ||
writableInstance: C; | ||
readonly shapeOffset: number; | ||
@@ -430,6 +438,7 @@ readonly shapeMask: number; | ||
private readonly __dispatcher; | ||
constructor(options: WorldOptions); | ||
static create(options: WorldOptions): Promise<World>; | ||
private constructor(); | ||
build(callback: (system: System) => void): void; | ||
createEntity(...initialComponents: (ComponentType<any> | any)[]): void; | ||
execute(time?: number, delta?: number): void; | ||
execute(time?: number, delta?: number): Promise<void>; | ||
control(options: ControlOptions): void; | ||
@@ -442,7 +451,7 @@ get stats(): Stats; | ||
} | ||
declare function prop<JSType>(practicalOptions: PropOptions<JSType> | Type<any> | (() => Type<any>)): (target: any, name: string) => void; | ||
declare function field<JSType>(practicalOptions: PropOptions<JSType> | Type<any> | (() => Type<any>)): (target: any, name: string) => void; | ||
declare const componentTypes: ComponentType<any>[]; | ||
declare function component(constructor: ComponentType<any>): void; | ||
declare function component(options: ComponentOptions): (constructor: ComponentType<any>) => void; | ||
export { World, Type, Entity, System, SystemType, componentTypes, component, prop, Query, ComponentType }; | ||
export { World, Type, Entity, System, SystemType, componentTypes, component, field, Query, ComponentType }; | ||
//# sourceMappingURL=perf.d.ts.map |
@@ -132,4 +132,4 @@ interface LogPointer { | ||
} | ||
interface SystemType { | ||
new (): System; | ||
interface SystemType<S extends System> { | ||
new (): S; | ||
} | ||
@@ -142,7 +142,10 @@ declare abstract class System { | ||
delta: number; | ||
// TODO: support schedule builder | ||
get name(): string; | ||
query(buildCallback: (q: QueryBuilder) => void): Query; | ||
attach<S extends System>(systemType: SystemType<S>): S; | ||
createEntity(...initialComponents: (ComponentType<any> | any)[]): Entity; | ||
accessRecentlyDeletedData(toggle?: boolean): void; | ||
abstract execute(): void; | ||
initialize(): void | Promise<void>; // eslint-disable-line @typescript-eslint/no-empty-function | ||
execute(): void; // eslint-disable-line @typescript-eslint/no-empty-function | ||
} | ||
@@ -162,2 +165,4 @@ declare class SystemBox { | ||
constructor(system: System, dispatcher: Dispatcher); | ||
replaceAttachmentPlaceholders(): void; | ||
initialize(): Promise<void>; | ||
execute(time: number, delta: number): void; | ||
@@ -169,3 +174,2 @@ private runQueries; | ||
restart(): void; | ||
suspend(): void; | ||
} | ||
@@ -231,3 +235,3 @@ declare class ComponentStats { | ||
// https://stackoverflow.com/questions/67467302/type-for-an-interleaved-array-of-classes-and-values | ||
type DefsArray = (ComponentType<any> | SystemType | any | DefsArray)[]; | ||
type DefsArray = (ComponentType<any> | SystemType<System> | any | DefsArray)[]; | ||
interface WorldOptions { | ||
@@ -245,3 +249,2 @@ defs: DefsArray; | ||
stop: DefsArray; | ||
suspend: DefsArray; | ||
restart: DefsArray; | ||
@@ -254,3 +257,3 @@ } | ||
private readonly systems; | ||
private readonly systemsByClass; | ||
readonly systemsByClass: Map<SystemType<System>, SystemBox>; | ||
private lastTime; | ||
@@ -270,3 +273,4 @@ executing: boolean; | ||
private splitDefs; | ||
execute(time?: number, delta?: number, systems?: SystemBox[]): void; | ||
initialize(): Promise<void>; | ||
execute(time?: number, delta?: number, systems?: SystemBox[]): Promise<void>; | ||
executeFunction(fn: (system: System) => void): void; | ||
@@ -366,2 +370,3 @@ private processEndOfFrame; | ||
static weakObject: Type<any>; | ||
// TODO: add autoremove/autodelete when nulled out | ||
static ref: Type<Entity | undefined>; | ||
@@ -393,3 +398,6 @@ static backrefs: (type?: ComponentType<any>, fieldName?: string, trackDeletedBackrefs?: boolean) => Type<Entity[]>; | ||
} | ||
interface ComponentType<C> { | ||
interface Component { | ||
__invalid?: boolean; | ||
} | ||
interface ComponentType<C extends Component> { | ||
new (): C; | ||
@@ -416,4 +424,4 @@ schema?: Schema; | ||
readonly elastic: boolean; | ||
readonly readonlyInstance: C; | ||
readonly writableInstance: C; | ||
readonlyInstance: C; | ||
writableInstance: C; | ||
readonly shapeOffset: number; | ||
@@ -430,6 +438,7 @@ readonly shapeMask: number; | ||
private readonly __dispatcher; | ||
constructor(options: WorldOptions); | ||
static create(options: WorldOptions): Promise<World>; | ||
private constructor(); | ||
build(callback: (system: System) => void): void; | ||
createEntity(...initialComponents: (ComponentType<any> | any)[]): void; | ||
execute(time?: number, delta?: number): void; | ||
execute(time?: number, delta?: number): Promise<void>; | ||
control(options: ControlOptions): void; | ||
@@ -442,7 +451,7 @@ get stats(): Stats; | ||
} | ||
declare function prop<JSType>(practicalOptions: PropOptions<JSType> | Type<any> | (() => Type<any>)): (target: any, name: string) => void; | ||
declare function field<JSType>(practicalOptions: PropOptions<JSType> | Type<any> | (() => Type<any>)): (target: any, name: string) => void; | ||
declare const componentTypes: ComponentType<any>[]; | ||
declare function component(constructor: ComponentType<any>): void; | ||
declare function component(options: ComponentOptions): (constructor: ComponentType<any>) => void; | ||
export { World, Type, Entity, System, SystemType, componentTypes, component, prop, Query, ComponentType }; | ||
export { World, Type, Entity, System, SystemType, componentTypes, component, field, Query, ComponentType }; | ||
//# sourceMappingURL=perf.min.d.ts.map |
@@ -1,2 +0,2 @@ | ||
class e{size;bytes;constructor(e){this.size=e,this.bytes=new Uint32Array(Math.ceil(e/32))}get(e){return 0!=(this.bytes[e>>>5]&1<<(31&e))}set(e){this.bytes[e>>>5]|=1<<(31&e)}unset(e){this.bytes[e>>>5]&=~(1<<(31&e))}clear(){this.bytes.fill(0)}}const t=[];class s{maxEntries;configParamName;localProcessingAllowed;data;corral;constructor(e,t,s=!1){this.maxEntries=e,this.configParamName=t,this.localProcessingAllowed=s;const i=new SharedArrayBuffer((e+2)*Uint32Array.BYTES_PER_ELEMENT);this.data=new Uint32Array(i);const r=new SharedArrayBuffer((e+2)*Uint32Array.BYTES_PER_ELEMENT);this.corral=new Uint32Array(r)}push(e){const t=this.corral[0];t&&this.corral[t]===e||(this.corral[t+2]=e,this.corral[0]+=1)}commit(e){const t=this.corral[0];if(!t)return!0;let s=this.data[0];if(e&&(e.generation!==this.data[1]||e.index!==s||e.corralGeneration!==this.corral[1]||e.corralIndex!==this.corral[0]))return!1;const i=Math.min(t,this.maxEntries-s);for(this.data.set(this.corral.subarray(2,i+2),s+2),i<t&&this.data.set(this.corral.subarray(i+2,t+2),2),s+=t;s>=this.maxEntries;)s-=this.maxEntries,this.data[1]+=1;return this.data[0]=s,this.corral[0]=0,this.corral[1]+=1,e&&(e.index=s,e.generation=this.data[1]),!0}createPointer(e){return e?(e.index=this.data[0],e.generation=this.data[1],e.corralIndex=this.corral[0],e.corralGeneration=this.corral[1],e):{index:this.data[0],generation:this.data[1],corralIndex:this.corral[0],corralGeneration:this.corral[1]}}hasUpdatesSince(e){return!(e.index===this.data[0]&&e.generation===this.data[1]&&(e.corralGeneration===this.corral[1]?e.corralIndex===this.corral[0]:0===this.corral[0]))}processSince(e,s){let i=t;const r=s?.index??this.data[0],n=s?.generation??this.data[1];if(e.generation===n)if(e.index<r)i=[this.data,e.index+2,r+2,!1],e.index=r;else{const t=this.corral[0],s=this.corral[1];(e.corralGeneration===s?e.corralIndex<t:t)&&(i=[this.corral,e.corralIndex+2,t+2,!0],e.corralIndex=t,e.corralGeneration=s)}else i=[this.data,e.index+2,this.data.length,!1],e.index=0,e.generation=n;return i}processAndCommitSince(e){const s=this.processSince(e);return s[0]?s:this.commit(e)?t:this.processSince(e)}countSince(e,t){const s=e.index,i=t?.index??this.data[0],r=t?.generation??this.data[1];return e.index=i,e.generation=r,s===i&&e.generation===r?0:s<i?i-s:this.maxEntries-(s-i)}checkPointers(e,t){this.checkPointer(e),t&&this.checkPointer(t)}checkPointer(e){const t=this.data[0];let s=e.generation;e.index===t?s+1<this.data[1]&&this.throwCapacityExceeded():(e.index>t&&(s+=1),s!==this.data[1]&&this.throwCapacityExceeded())}throwCapacityExceeded(){throw new Error(`Log capacity exceeded, please raise ${this.configParamName} above ${this.maxEntries}`)}}class i{maxItems;configParamName;data;constructor(e,t){this.maxItems=e,this.configParamName=t,this.data=new Uint32Array(new SharedArrayBuffer((e+1)*Uint32Array.BYTES_PER_ELEMENT))}get length(){return this.data[0]}take(){const e=this.data[0]--;return this.data[e]}refill(e){if(!e.length)return;const t=this.length,s=t+e.length;this.data.set(e,t+1),this.data[0]=s}fillWithDescendingIntegers(e){const t=this.length;for(let s=this.data.length-1;s>t;s--)this.data[s]=e++;this.data[0]=this.data.length-1}}const r=new TextEncoder,n=new TextDecoder;function a(e){throw new Error(`Component is not writable; use entity.write(${e.type.name}) to acquire a writable version`)}class o{defaultValue;constructor(e){this.defaultValue=e}static boolean;static uint8;static int8;static uint16;static int16;static uint32;static int32;static float32;static float64;static staticString;static dynamicString;static object;static weakObject;static ref;static backrefs}class h extends o{NumberArray;constructor(e){super(0),this.NumberArray=e}defineElastic(e,t){let s,i;t.updateBuffer=()=>{const r=e.capacity*this.NumberArray.BYTES_PER_ELEMENT,n=t.buffer?.byteLength!==r;(n||t.buffer!==s)&&(s=n?new SharedArrayBuffer(r):t.buffer,i=new this.NumberArray(s),n&&t.buffer&&i.set(new this.NumberArray(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>i[e.index],set(t){i[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>i[e.index],set(t){a(e)}})}defineFixed(e,t){const s=e.capacity*this.NumberArray.BYTES_PER_ELEMENT,i=new SharedArrayBuffer(s),r=new this.NumberArray(i);t.buffer=i,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>r[e.index],set(t){r[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>r[e.index],set(t){a(e)}})}}class c extends o{choices;choicesIndex=new Map;TypedArray;constructor(e){if(super(e[0]),this.choices=e,!e?.length)throw new Error("No choices specified for Type.staticString");e.length<256?this.TypedArray=Uint8Array:e.length<65536?this.TypedArray=Uint16Array:this.TypedArray=Uint32Array;for(let t=0;t<e.length;t++)this.choicesIndex.set(e[t],t)}defineElastic(e,t){let s,i;const r=this.choices,n=this.choicesIndex;t.updateBuffer=()=>{const r=e.capacity*this.TypedArray.BYTES_PER_ELEMENT,n=t.buffer?.byteLength!==r;(n||t.buffer!==s)&&(s=n?new SharedArrayBuffer(r):t.buffer,i=new this.TypedArray(s),n&&t.buffer&&i.set(new this.TypedArray(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=i[e.index],s=r[t];if(void 0===s)throw new Error(`Invalid static string index: ${t}`);return s},set(t){const s=n.get(t);if(void 0===s)throw new Error(`Static string not in set: "${t}"`);i[e.index]=s}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=i[e.index],s=r[t];if(void 0===s)throw new Error(`Invalid static string index: ${t}`);return s},set(t){a(e)}})}defineFixed(e,t){const s=this.choices,i=this.choicesIndex,r=e.capacity*this.TypedArray.BYTES_PER_ELEMENT,n=new SharedArrayBuffer(r),o=new this.TypedArray(n);t.buffer=n,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=o[e.index],i=s[t];if(void 0===i)throw new Error(`Invalid static string index: ${t}`);return i},set(t){const s=i.get(t);if(void 0===s)throw new Error(`Static string not in set: "${t}"`);o[e.index]=s}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=o[e.index],i=s[t];if(void 0===i)throw new Error(`Invalid static string index: ${t}`);return i},set(t){a(e)}})}}class d extends o{maxUtf8Length;lengthsStride;bytesStride;constructor(e){super(""),this.maxUtf8Length=e+e%2,this.lengthsStride=e/2+1,this.bytesStride=this.maxUtf8Length+2}defineElastic(e,t){let s,i,o;const h=this.maxUtf8Length,c=this.lengthsStride,d=this.bytesStride;t.updateBuffer=()=>{const r=e.capacity*(this.maxUtf8Length+Uint16Array.BYTES_PER_ELEMENT),n=t.buffer?.byteLength!==r;(n||t.buffer!==s)&&(s=n?new SharedArrayBuffer(r):t.buffer,i=new Uint16Array(s),o=new Uint8Array(s),n&&t.buffer&&o.set(new Uint8Array(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=i[e.index*c];return n.decode(new Uint8Array(o.buffer,e.index*d+2,t))},set(t){const s=r.encode(t);if(s.byteLength>h)throw new Error(`Dynamic string length > ${h} after encoding: ${t}`);i[e.index*c]=s.byteLength,o.set(s,e.index*d+2)}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=i[e.index*c];return n.decode(new Uint8Array(o.buffer,e.index*d+2,t))},set(t){a(e)}})}defineFixed(e,t){const s=this.maxUtf8Length,i=this.lengthsStride,o=this.bytesStride,h=e.capacity*(this.maxUtf8Length+Uint16Array.BYTES_PER_ELEMENT),c=new SharedArrayBuffer(h),d=new Uint16Array(c),l=new Uint8Array(c);t.buffer=c,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=d[e.index*i];return n.decode(new Uint8Array(l.buffer,e.index*o+2,t))},set(t){const n=r.encode(t);if(n.byteLength>s)throw new Error(`Dynamic string length > ${s} after encoding: ${t}`);d[e.index*i]=n.byteLength,l.set(n,e.index*o+2)}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=d[e.index*i];return n.decode(new Uint8Array(l.buffer,e.index*o+2,t))},set(t){a(e)}})}}const l=[];class f extends o{type;fieldName;trackDeletedBackrefs;constructor(e,t,s){super(l),this.type=e,this.fieldName=t,this.trackDeletedBackrefs=s}defineElastic(e,t){const s=this.fieldName?this.type?.__binding.fields.find((e=>e.name===this.fieldName)):void 0;this.trackDeletedBackrefs;const i=e.dispatcher.indexer;i.registerSelector();const r=i.registerSelector(e.type,this.type,s?.seq,this.trackDeletedBackrefs),n={enumerable:!0,configurable:!0,get:()=>i.getBackrefs(e.entityId,r),set(e){}};Object.defineProperty(e.writableInstance,t.name,n),Object.defineProperty(e.readonlyInstance,t.name,n)}defineFixed(e,t){this.defineElastic(e,t)}}o.boolean=new class extends o{constructor(){super(!1)}defineElastic(e,t){let s,i;t.updateBuffer=()=>{const r=t.buffer?.byteLength!==e.capacity;(r||t.buffer!==s)&&(s=r?new SharedArrayBuffer(e.capacity):t.buffer,i=new Uint8Array(s),r&&t.buffer&&i.set(new Uint8Array(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>Boolean(i[e.index]),set(t){i[e.index]=t?1:0}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>Boolean(i[e.index]),set(t){a(e)}})}defineFixed(e,t){const s=new SharedArrayBuffer(e.capacity),i=new Uint8Array(s);t.buffer=s,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>Boolean(i[e.index]),set(t){i[e.index]=t?1:0}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>Boolean(i[e.index]),set(t){a(e)}})}},o.uint8=new h(Uint8Array),o.int8=new h(Int8Array),o.uint16=new h(Uint16Array),o.int16=new h(Int16Array),o.uint32=new h(Uint32Array),o.int32=new h(Int32Array),o.float32=new h(Float32Array),o.float64=new h(Float64Array),o.staticString=e=>new c(e),o.dynamicString=e=>new d(e),o.ref=new class extends o{constructor(){super(void 0)}defineElastic(e,t){let s,i;const r=e.dispatcher.indexer,n=e.dispatcher.registry,o=n.pool;r.registerSelector(),t.updateBuffer=()=>{const r=e.capacity*Int32Array.BYTES_PER_ELEMENT,n=t.buffer?.byteLength!==r;if(n||t.buffer!==s){if(s=n?new SharedArrayBuffer(r):t.buffer,i=new Int32Array(s),n&&t.buffer){const e=new Int32Array(t.buffer);i.set(e),i.fill(-1,e.length)}else i.fill(-1);t.buffer=s}},t.updateBuffer(),t.clearRef=(s,n,a)=>{const o=4194303&i[e.index],h=void 0!==n;h&&o!==n||(s?h&&(i[e.index]=-1):i[e.index]|=2147483648,r.trackRefChange(e.entityId,e.type,t.seq,void 0,o,-1,s))},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=i[e.index];if(!(-1===t||2147483648&t&&!n.includeRecentlyDeleted))return o.borrowTemporarily(4194303&t)},set(s){const n=i[e.index],a=s?.__id??-1;n!==a&&(i[e.index]=a,r.trackRefChange(e.entityId,e.type,t.seq,void 0,n,a,!0))}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=i[e.index];if(!(-1===t||2147483648&t&&!n.includeRecentlyDeleted))return o.borrowTemporarily(4194303&t)},set(t){a(e)}})}defineFixed(e,t){const s=e.capacity*Int32Array.BYTES_PER_ELEMENT,i=new SharedArrayBuffer(s),r=new Int32Array(i);r.fill(-1),t.buffer=i;const n=e.dispatcher.indexer,o=e.dispatcher.registry,h=o.pool;n.registerSelector(),t.clearRef=(s,i,a)=>{const o=4194303&r[e.index],h=void 0!==i;h&&o!==i||(s?h&&(r[e.index]=-1):r[e.index]|=2147483648,n.trackRefChange(e.entityId,e.type,t.seq,void 0,o,-1,s))},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=r[e.index];if(!(-1===t||2147483648&t&&!o.includeRecentlyDeleted))return h.borrowTemporarily(4194303&t)},set(s){const i=r[e.index],a=s?.__id??-1;i!==a&&(r[e.index]=a,n.trackRefChange(e.entityId,e.type,t.seq,void 0,i,a,!0))}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=r[e.index];if(!(-1===t||2147483648&t&&!o.includeRecentlyDeleted))return h.borrowTemporarily(4194303&t)},set(t){a(e)}})}},o.backrefs=(e,t,s=!1)=>new f(e,t,s),o.object=new class extends o{constructor(){super(void 0)}defineElastic(e,t){const s=[];t.localBuffer=s,t.updateBuffer=()=>{},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>s[e.index],set(t){s[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>s[e.index],set(t){a(e)}})}defineFixed(e,t){const s=new Array(e.capacity);t.localBuffer=s,t.updateBuffer=()=>{},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>s[e.index],set(t){s[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>s[e.index],set(t){a(e)}})}},o.weakObject=new class extends o{finalizers;constructor(){super(void 0)}defineElastic(e,t){const s=[];t.localBuffer=s,t.updateBuffer=()=>{};const i=this.initFinalizers(e);Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=s[e.index];return null==t?t:t.deref()},set(r){if(null!=r){const s=new WeakRef(r);i?.register(r,{type:e.type,field:t,weakRef:s,id:e.entityId,index:e.index}),r=s}s[e.index]=r}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=s[e.index];return null==t?t:t.deref()},set(t){a(e)}})}defineFixed(e,t){const s=new Array(e.capacity);t.localBuffer=s,t.updateBuffer=()=>{};const i=this.initFinalizers(e);Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=s[e.index];return null==t?t:t.deref()},set(r){if(null!=r){const s=new WeakRef(r);i?.register(r,{type:e.type,field:t,weakRef:s,id:e.entityId,index:e.index}),r=s}s[e.index]=r}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=s[e.index];return null==t?t:t.deref()},set(t){a(e)}})}initFinalizers(e){if(!e.trackedWrites)return;if(this.finalizers)return this.finalizers;const t=e.dispatcher;return t.writeLog&&"undefined"!=typeof FinalizationRegistry?(this.finalizers=new FinalizationRegistry((({type:e,field:s,weakRef:i,id:r,index:n})=>{s.localBuffer?.[n]===i&&t.registry.trackWrite(r,e)})),this.finalizers):void 0}};class u{type;fields;dispatcher;capacity;storage;elastic;readonlyInstance;writableInstance;shapeOffset;shapeMask;refFields;trackedWrites=!1;internallyIndexed=!1;entityId=0;index=0;constructor(e,t,s,i,r,n){this.type=e,this.fields=t,this.dispatcher=s,this.capacity=i,this.storage=r,this.elastic=n,this.readonlyInstance=new e,this.writableInstance=new e,this.shapeOffset=e.id>>5,this.shapeMask=1<<(31&e.id),this.refFields=t.filter((e=>e.type===o.ref))}}class g{maxEntities;binding;fields;index;spares;constructor(e,t,s){this.maxEntities=e,this.binding=t,this.fields=s,this.growSpares(),this.growCapacity()}acquireIndex(e){let t=this.index[e];return-1===t&&(this.spares[3]>0?t=this.spares[4+--this.spares[3]]:(this.spares[1]===this.spares[2]&&(this.binding.capacity=Math.min(this.maxEntities,2*this.binding.capacity),this.growCapacity()),t=this.spares[1]++),this.index[e]=t),t}releaseIndex(e){this.spares[3]===this.spares.length-4&&this.growSpares(),this.spares[4+this.spares[3]++]=this.index[e],this.index[e]=-1}growCapacity(){const e=this.ArrayType,t=e.BYTES_PER_ELEMENT!==this.spares?.[0];if(!this.index||t){const t=new e(new SharedArrayBuffer(this.maxEntities*e.BYTES_PER_ELEMENT));this.index?t.set(this.index):t.fill(-1),this.index=t}if(this.spares&&t){const t=new e(new SharedArrayBuffer(this.spares.length*e.BYTES_PER_ELEMENT));t.set(this.spares),t[0]=e.BYTES_PER_ELEMENT,this.spares=t}if(this.spares[2]=this.binding.capacity,this.binding.elastic)for(const e of this.fields)e.updateBuffer()}growSpares(){const e=this.ArrayType,t=this.spares?Math.min(this.maxEntities,2*(this.spares.length-4)):8,s=new e(new SharedArrayBuffer((4+t)*e.BYTES_PER_ELEMENT));this.spares?s.set(this.spares):(s[0]=e.BYTES_PER_ELEMENT,s[2]=this.binding.capacity),this.spares=s}get ArrayType(){const e=this.binding.capacity;return e<=127?Int8Array:e<=32767?Int16Array:Int32Array}}function y(e,t,s){const i=function(e){const t=e.schema,s=[];if(t){let e=0;for(const i in t){let r=t[i];(r instanceof o||"function"==typeof r)&&(r={type:r}),"function"==typeof r.type&&(r.type=r.type()),"default"in r||(r.default=r.type.defaultValue),s.push({name:i,seq:e++,type:r.type,default:r.default})}}return s}(t),r=i.length?t.options?.storage??s.defaultComponentStorage:"sparse",n="sparse"===r?s.maxEntities:Math.min(s.maxEntities,t.options?.capacity??0),a=t.options?.initialCapacity??8;t.id=e;const h=new u(t,i,s,n||a,r,!n);t.__binding=h}function p(e){const t=e.__binding;for(const e of t.fields)t.elastic?e.type.defineElastic(t,e):e.type.defineFixed(t,e);switch(t.storage){case"sparse":e.__bind=(e,s)=>(t.entityId=e,t.index=e,s?t.writableInstance:t.readonlyInstance),e.__allocate=e=>(t.entityId=e,t.index=e,t.writableInstance);break;case"packed":{const s=new g(t.dispatcher.maxEntities,t,t.fields);e.__bind=(e,i)=>(t.entityId=e,t.index=s.index[e],i?t.writableInstance:t.readonlyInstance),e.__allocate=e=>(t.entityId=e,t.index=s.acquireIndex(e),t.writableInstance),e.__free=e=>{s.releaseIndex(e)};break}case"compact":throw new Error("Not yet implemented")}}class m{__registry;__id;constructor(e){this.__registry=e}add(e,t){return this.__registry.setShape(this.__id,e),function(e,t,s){const i=e.__allocate(t);for(const t of e.__binding.fields)i[t.name]=s?.[t.name]??t.default}(e,this.__id,t),this}addAll(...e){for(let t=0;t<e.length;t++){const s=e[t];let i=e[t+1];"function"==typeof i?i=void 0:t++,this.add(s,i)}return this}remove(e){this.__registry.clearShape(this.__id,e)}removeAll(...e){for(const t of e)this.remove(t)}has(e){return this.__registry.hasShape(this.__id,e,!0)}read(e){return e.__bind(this.__id,!1)}write(e){return e.__binding.trackedWrites&&this.__registry.trackWrite(this.__id,e),e.__bind(this.__id,!0)}delete(){this.__registry.Alive;for(const e of this.__registry.types)this.__registry.hasShape(this.__id,e,!1)&&this.__registry.clearShape(this.__id,e);this.__registry.queueDeletion(this.__id),this.__registry.dispatcher.indexer.clearAllRefs(this.__id,!1)}__checkMask(e,t){_(e,this.__registry.executingSystem,t)}__checkHas(e,t){if(!this.__registry.hasShape(this.__id,e,t))throw new Error(`Entity doesn't have a ${e.name} component`)}}function _(e,t,s){!function(e){if(!e.__binding)throw new Error(`Component ${e.name} not defined; add to world defs`)}(e);const i=s?t?.rwMasks.write:t?.rwMasks.read;if(!(!i||0!=((i[e.__binding.shapeOffset]??0)&e.__binding.shapeMask)))throw new Error(`System didn't mark component ${e.name} as ${s?"writable":"readable"}`)}function b(e,t){const s=t.__binding.shapeOffset;s>=e.length&&(e.length=s+1,e.fill(0,e.length,s)),e[s]|=t.__binding.shapeMask}class E{pool;entities=[];constructor(e){this.pool=e}add(e){this.entities.push(this.pool.borrowTemporarily(e))}clear(){this.entities.length&&this.entities.splice(0,1/0)}}class w{pool;entities=[];lookupTable;constructor(e,t){this.pool=e,this.lookupTable=new Int32Array(t),this.lookupTable.fill(-1)}add(e){const t=this.entities.push(this.pool.borrow(e))-1;this.lookupTable[e]=t}remove(e){const t=this.lookupTable[e];if(t<0)throw new Error("Internal error, entity not in list");this.pool.return(e),this.lookupTable[e]=-1;const s=this.entities.pop();t<this.entities.length&&(this.entities[t]=s,this.lookupTable[s.__id]=t)}has(e){return this.lookupTable[e]>=0}clear(){for(const e of this.entities)this.pool.return(e.__id);this.entities=[],this.lookupTable.fill(-1)}}var x;!function(e){e[e.all=1]="all",e[e.added=2]="added",e[e.removed=4]="removed",e[e.changed=8]="changed",e[e.addedOrChanged=16]="addedOrChanged",e[e.changedOrRemoved=32]="changedOrRemoved",e[e.addedChangedOrRemoved=64]="addedChangedOrRemoved"}(x||(x={}));const R=x.added|x.removed|x.changed|x.addedOrChanged|x.changedOrRemoved|x.addedChangedOrRemoved,S=x.changed|x.addedOrChanged|x.changedOrRemoved|x.addedChangedOrRemoved;class P{query;system;results={};flavors=0;withMask;withoutMask;trackMask;hasTransientResults;hasChangedResults;currentEntities;changedEntities;constructor(e,t){this.query=e,this.system=t,e.__results=this.results,e.__systemName=t.name}complete(){const t=this.system.dispatcher;this.hasTransientResults=Boolean(this.flavors&R),this.hasChangedResults=Boolean(this.flavors&S),this.flavors&x.all?this.results.all=new w(t.registry.pool,t.maxEntities):this.currentEntities=new e(t.maxEntities),this.hasTransientResults&&this.allocateTransientResultLists(),this.flavors&&this.system.shapeQueries.push(this),this.hasChangedResults&&(this.changedEntities=new e(t.maxEntities),this.system.writeQueries.push(this))}allocateTransientResultLists(){this.flavors&x.added&&this.allocateResult("added"),this.flavors&x.removed&&this.allocateResult("removed"),this.flavors&x.changed&&this.allocateResult("changed"),this.flavors&x.addedOrChanged&&this.allocateResult("addedOrChanged"),this.flavors&x.changedOrRemoved&&this.allocateResult("changedOrRemoved"),this.flavors&x.addedChangedOrRemoved&&this.allocateResult("addedChangedOrRemoved")}allocateResult(e){const t=this.system.dispatcher;this.results[e]=new E(t.registry.pool)}clearTransientResults(){this.hasTransientResults&&(this.results.added?.clear(),this.results.removed?.clear(),this.results.changed?.clear(),this.results.addedOrChanged?.clear(),this.results.changedOrRemoved?.clear(),this.results.addedChangedOrRemoved?.clear(),this.changedEntities?.clear())}clearAllResults(){this.clearTransientResults(),this.results.all?.clear()}handleShapeUpdate(e){const t=this.system.dispatcher.registry,s=this.results.all?.has(e)??this.currentEntities.get(e),i=t.matchShape(e,this.withMask,this.withoutMask);i&&!s?(this.currentEntities?.set(e),this.results.all?.add(e),this.results.added?.add(e),this.results.addedOrChanged?.add(e),this.results.addedChangedOrRemoved?.add(e)):!i&&s&&(this.currentEntities?.unset(e),this.results.all?.remove(e),this.results.removed?.add(e),this.results.changedOrRemoved?.add(e),this.results.addedChangedOrRemoved?.add(e))}handleWrite(e,t,s){!this.changedEntities.get(e)&&(this.trackMask[t]??0)&s&&(this.changedEntities.set(e),this.results.changed?.add(e),this.results.addedOrChanged?.add(e),this.results.changedOrRemoved?.add(e),this.results.addedChangedOrRemoved?.add(e))}}class v{__callback;__userQuery;__query;__system;__lastTypes;constructor(e,t){this.__callback=e,this.__userQuery=t}__build(e){try{this.__system=e,this.__query=new P(this.__userQuery,e),this.__callback(this),this.__query.complete()}catch(t){throw t.message=`Failed to build query in system ${e.name}: ${t.message}`,t}}get and(){return this}get but(){return this}get also(){return this}get all(){return this.__query.flavors|=x.all,this}get added(){return this.__query.flavors|=x.added,this}get removed(){return this.__query.flavors|=x.removed,this}get changed(){return this.__query.flavors|=x.changed,this}get addedOrChanged(){return this.__query.flavors|=x.addedOrChanged,this}get changedOrRemoved(){return this.__query.flavors|=x.changedOrRemoved,this}get addedChangedOrRemoved(){return this.__query.flavors|=x.addedChangedOrRemoved,this}with(...e){return this.set(this.__system.rwMasks.read,e),this.set("withMask"),this}without(...e){return this.set(this.__system.rwMasks.read,e),this.set("withoutMask",e),this}using(...e){return this.set(this.__system.rwMasks.read,e),this}get track(){this.set("trackMask");for(const e of this.__lastTypes)e.__binding.trackedWrites=!0;return this}get read(){return this}get write(){return this.set(this.__system.rwMasks.write),this}set(e,t,s){if(e){if(t||(t=this.__lastTypes),!t)throw new Error("No component type to apply query modifier to");if(this.__lastTypes=t,"string"==typeof e){if(s&&this.__query[e])throw new Error(`Only one ${s} allowed`);this.__query[e]||(this.__query[e]=[]),e=this.__query[e]}else if(s&&e.some((e=>0!==e)))throw new Error(`Only one ${s} allowed`);for(const s of t)b(e,s)}}}class k{__results;__systemName;get all(){return this.__results.all.entities}get added(){return this.__results.added.entities}get removed(){return this.__results.removed.entities}get changed(){return this.__results.changed.entities}get addedOrChanged(){return this.__results.addedOrChanged.entities}get changedOrRemoved(){return this.__results.changedOrRemoved.entities}get addedChangedOrRemoved(){return this.__results.addedChangedOrRemoved.entities}__checkList(e){if(!this.__results[e])throw new Error(`Query '${e}' not configured, please add .${e} to your query definition in system ${this.__systemName}`)}}var I,L;!function(e){e[e.RUNNING=0]="RUNNING",e[e.SUSPENDED=1]="SUSPENDED",e[e.STOPPED=2]="STOPPED"}(I||(I={}));class T{static __system=!0;__queryBuilders=[];__dispatcher;time;delta;get name(){return this.constructor.name}query(e){const t=new k,s=new v(e,t);return this.__queryBuilders.push(s),t}createEntity(...e){return this.__dispatcher.createEntity(e)}accessRecentlyDeletedData(e=!0){this.__dispatcher.registry.includeRecentlyDeleted=e}}class A{system;dispatcher;rwMasks={read:[],write:[]};shapeQueries=[];writeQueries=[];hasWriteQueries;processedEntities;shapeLogPointer;writeLogPointer;state=I.RUNNING;get name(){return this.system.name}constructor(t,s){this.system=t,this.dispatcher=s,t.__dispatcher=s,this.shapeLogPointer=s.shapeLog.createPointer(),this.writeLogPointer=s.writeLog?.createPointer(),this.processedEntities=new e(s.maxEntities);for(const e of t.__queryBuilders)e.__build(this);t.__queryBuilders=null,this.hasWriteQueries=!!this.writeQueries.length}execute(e,t){this.state===I.RUNNING&&(this.system.time=e,this.system.delta=t,this.runQueries(),this.system.execute())}runQueries(){const e=this.dispatcher.shapeLog.hasUpdatesSince(this.shapeLogPointer),t=this.hasWriteQueries&&this.dispatcher.writeLog.hasUpdatesSince(this.writeLogPointer);if(e||t){this.processedEntities.clear();for(const e of this.shapeQueries)e.clearTransientResults();e&&this.__updateShapeQueries(),t&&this.__updateWriteQueries()}}__updateShapeQueries(){const e=this.dispatcher.shapeLog;let t,s,i;for(;[t,s,i]=e.processSince(this.shapeLogPointer),t;)for(let e=s;e<i;e++){const s=t[e];if(!this.processedEntities.get(s)){this.processedEntities.set(s);for(const e of this.shapeQueries)e.handleShapeUpdate(s)}}}__updateWriteQueries(){const e=this.dispatcher.writeLog;let t,s,i;for(;[t,s,i]=e.processSince(this.writeLogPointer),t;)for(let e=s;e<i;e++){const s=t[e],i=4194303&s;if(!this.processedEntities.get(i)){const e=s>>>22;for(const t of this.writeQueries)t.handleWrite(i,e>>5,1<<(31&e))}}}stop(){if(this.state!==I.STOPPED){this.state=I.STOPPED;for(const e of this.shapeQueries)e.clearAllResults()}}restart(){if(this.state===I.STOPPED){const e=this.dispatcher.registry,t=e.Alive;for(let s=0;s<this.dispatcher.maxEntities;s++)if(e.hasShape(s,t,!1))for(const e of this.shapeQueries)e.handleShapeUpdate(s);for(const e of this.shapeQueries)e.clearTransientResults();this.dispatcher.shapeLog.createPointer(this.shapeLogPointer),this.dispatcher.writeLog?.createPointer(this.writeLogPointer)}this.state=I.RUNNING}suspend(){this.state===I.STOPPED&&this.restart(),this.state=I.SUSPENDED}}class O{registry;borrowed;borrowCounts;spares=[];temporarilyBorrowedIds=[];constructor(e,t){this.registry=e,this.borrowed=Array.from({length:t}),this.borrowCounts=new Int32Array(t)}borrow(e){this.borrowCounts[e]+=1;let t=this.borrowed[e];return t||(t=this.borrowed[e]=this.spares.pop()??new m(this.registry),t.__id=e),t}borrowTemporarily(e){const t=this.borrow(e);return this.temporarilyBorrowedIds.push(e),t}returnTemporaryBorrows(){for(const e of this.temporarilyBorrowedIds)this.return(e);this.temporarilyBorrowedIds.splice(0,1/0)}return(e){--this.borrowCounts[e]<=0&&(this.spares.push(this.borrowed[e]),this.borrowed[e]=void 0)}}class C{types;dispatcher;stride;shapes;staleShapes;entityIdPool;pool;executingSystem;includeRecentlyDeleted=!1;deletionLog;prevDeletionPointer;oldDeletionPointer;removalLog;prevRemovalPointer;oldRemovalPointer;Alive=class{};constructor(e,t,r,n,a){this.types=n,this.dispatcher=a,this.stride=Math.ceil(n.length/32);const o=e*this.stride*4;this.shapes=new Uint32Array(new SharedArrayBuffer(o)),this.staleShapes=new Uint32Array(new SharedArrayBuffer(o)),this.entityIdPool=new i(e,"maxEntities"),this.entityIdPool.fillWithDescendingIntegers(0),this.pool=new O(this,e),this.deletionLog=new s(t,"maxLimboEntities"),this.prevDeletionPointer=this.deletionLog.createPointer(),this.oldDeletionPointer=this.deletionLog.createPointer(),this.removalLog=new s(r,"maxLimboComponents"),this.prevRemovalPointer=this.removalLog.createPointer(),this.oldRemovalPointer=this.removalLog.createPointer()}initializeComponentTypes(){this.types.unshift(this.Alive);let e=0;for(const t of this.types)y(e++,t,this.dispatcher);for(const e of this.types)p(e)}createEntity(e){const t=this.entityIdPool.take(),s=t*this.stride;this.shapes[s]=1,this.stride>1&&this.shapes.fill(0,s+1,s+this.stride);const i=this.pool.borrowTemporarily(t);return e&&i.addAll(...e),i}queueDeletion(e){this.deletionLog.push(e)}flush(){this.includeRecentlyDeleted=!1,this.pool.returnTemporaryBorrows(),this.deletionLog.commit(),this.removalLog.commit()}processEndOfFrame(){this.processDeletionLog(),this.processRemovalLog()}processDeletionLog(){this.deletionLog.commit();let e,t,s,i=0;for(;[e,t,s]=this.deletionLog.processSince(this.oldDeletionPointer,this.prevDeletionPointer),e;){for(let i=t;i<s;i++)this.dispatcher.indexer.clearAllRefs(e[i],!0);const r=e.subarray(t,s);this.entityIdPool.refill(r),i+=r.length}this.deletionLog.createPointer(this.prevDeletionPointer)}processRemovalLog(){let e,t,s;for(this.removalLog.commit();[e,t,s]=this.removalLog.processSince(this.oldRemovalPointer,this.prevRemovalPointer),e;)for(let i=t;i<s;i++){const t=e[i],s=4194303&t,r=t>>>22,n=this.types[r],a=s*this.stride+n.__binding.shapeOffset,o=n.__binding.shapeMask;0==(this.shapes[a]&o)&&(this.staleShapes[a]&=~o,this.clearRefs(s,n,!0),n.__free?.(s))}this.removalLog.createPointer(this.prevRemovalPointer)}hasShape(e,t,s){const i=e*this.stride+t.__binding.shapeOffset,r=t.__binding.shapeMask;return 0!=(this.shapes[i]&r)||!(!s||!this.includeRecentlyDeleted||0==(this.staleShapes[i]&r))}setShape(e,t){const s=e*this.stride+t.__binding.shapeOffset,i=t.__binding.shapeMask;this.shapes[s]|=i,this.staleShapes[s]|=i,this.dispatcher.shapeLog.push(e)}clearShape(e,t){const s=this.clearRefs(e,t,!1);(t.__free||s)&&this.removalLog.push(e|t.id<<22),this.shapes[e*this.stride+t.__binding.shapeOffset]&=~t.__binding.shapeMask,this.dispatcher.shapeLog.push(e)}trackWrite(e,t){this.dispatcher.writeLog.push(e|t.id<<22)}clearRefs(e,t,s){const i=!!t.__binding.refFields.length;if(i){t.__bind(e,!0);for(const e of t.__binding.refFields)e.clearRef(s)}return i}matchShape(e,t,s){const i=e*this.stride;if(t)for(let e=0;e<t.length;e++){const s=t[e];if((this.shapes[i+e]&s)!==s)return!1}if(s)for(let e=0;e<s.length;e++){const t=s[e];if(0!=(this.shapes[i+e]&t))return!1}return!0}}!function(e){e[e.REFERENCE=0]="REFERENCE",e[e.UNREFERENCE=1073741824]="UNREFERENCE",e[e.RELEASE=2147483648]="RELEASE"}(L||(L={}));const B=L.REFERENCE|L.UNREFERENCE|L.RELEASE;class N{targetEntityId;selector;dispatcher;entities=[];tags;entityIndex;clearing=!1;registry;constructor(e,t,s){this.targetEntityId=e,this.selector=t,this.dispatcher=s;const i=t.sourceType?.__binding;t.matchType&&(t.matchSeq||1===i.refFields.length)&&!i.internallyIndexed||(this.tags=[]),this.registry=s.registry}clearAllRefs(e){this.clearing=!0;for(let t=0;t<this.entities.length;t++){const s=this.entities[t].__id,i=this.tags[t];if("number"==typeof i)this.clearRef(s,i,e);else for(const t of i)this.clearRef(s,t,e)}this.entities=[],this.tags=[],this.entityIndex=void 0,this.clearing=!1}clearRef(e,t,s){const i=511&t,r=t>>>9&127,n=t>>>16,a=this.registry.types[i];a.__bind(e,!0),a.__binding.fields[r].clearRef(s,this.targetEntityId,n)}trackReference(e,t,s,i,r){let n=this.getEntityIndex(e);void 0===n&&(n=this.addEntity(e,r)),this.addTag(n,this.makeTag(t,s,i))}trackUnreference(e,t,s,i,r){if(this.clearing)return;const n=this.getEntityIndex(e);this.removeTag(n,this.makeTag(t,s,i))&&this.removeEntity(n,e,r)}getEntityIndex(e){if(this.entityIndex)return this.entityIndex[e];const t=this.entities.findIndex((t=>t.__id===e));return t>=0?t:void 0}indexEntities(){this.entityIndex=new Array(this.dispatcher.maxEntities);for(let e=0;e<this.entities.length;e++)this.entityIndex[this.entities[e].__id]=e}addTag(e,t){if(!this.tags)return;const s=this.tags[e];if(void 0===s)this.tags[e]=t;else if("number"==typeof s)this.tags[e]=[s,t];else if(Array.isArray(s))if(s.length>=1e3){(this.tags[e]=new Set(s)).add(t)}else s.push(t);else s.add(t)}removeTag(e,t){if(!this.tags)return!0;const s=this.tags[e];if("number"==typeof s)return delete this.tags[e],!0;if(Array.isArray(s)){const e=s.indexOf(t);return s.splice(e,1),!this.tags.length}return s.delete(t),!s.size}makeTag(e,t,s){return e|t<<9|(void 0===s?0:s<<16)}addEntity(e,t){const s=this.entities.length;return this.entities.push(this.registry.pool.borrow(e)),this.entityIndex?this.entityIndex[e]=s:s>100&&this.indexEntities(),t&&this.trackBackrefsChange(),s}removeEntity(e,t,s){this.registry.pool.return(t);const i=this.entities.pop();this.entityIndex&&delete this.entityIndex[e],this.entities.length>e&&(this.entities[e]=i,this.entityIndex&&(this.entityIndex[i.__id]=e)),s&&this.trackBackrefsChange()}trackBackrefsChange(){for(const e of this.selector.targetTypes)e.__binding.trackedWrites&&this.registry.trackWrite(this.targetEntityId,e)}checkWriteMask(){const e=this.registry.executingSystem;for(const t of this.selector.targetTypes)_(t,e,!0)}}class F{dispatcher;maxRefChangesPerFrame;refLog;refLogPointer;refLogStatsPointer;selectorIdsBySourceKey=new Map;selectors=[];trackers=new Map;registry;constructor(e,t){this.dispatcher=e,this.maxRefChangesPerFrame=t,this.registry=e.registry}processEndOfFrame(){this.flush()}registerSelector(e,t,i,r=!1){this.refLog||(this.refLog=new s(this.maxRefChangesPerFrame,"maxRefChangesPerFrame",!0),this.refLogPointer=this.refLog.createPointer(),this.refLogStatsPointer=this.refLog.createPointer());const n=t?void 0===i?-2-t.id:t.id|i<<9:-1;let a=this.selectorIdsBySourceKey.get(n);if(void 0===a){this.selectors.length||(r=!0);const s={id:this.selectors.length,targetTypes:e?[e]:[],sourceType:t,matchType:!!t,matchSeq:void 0!==i,sourceTypeId:t?.id,sourceSeq:i,trackStale:r};this.selectors.push(s),a=s.id,this.selectorIdsBySourceKey.set(n,a)}else{const t=this.selectors[a];t.trackStale=t.trackStale||r,e&&t.targetTypes.push(e)}return a}getBackrefs(e,t=0){const s=this.selectors[t];return this.getOrCreateTracker(s,e,this.registry.includeRecentlyDeleted).entities}trackRefChange(e,t,s,i,r,n,a){-1!==r&&this.pushRefLogEntry(e,t,s,i,r,a?L.RELEASE:L.UNREFERENCE),-1!==n&&this.pushRefLogEntry(e,t,s,i,n,L.REFERENCE)}clearAllRefs(e,t){this.selectors.length&&this.getTracker(this.selectors[0],e,t)?.clearAllRefs(t)}pushRefLogEntry(e,t,s,i,r,n){const a=void 0!==i;this.refLog.push(e|t.id<<22),this.refLog.push(r|s<<22|n|(a?2**29:0)),a&&this.refLog.push(i),this.processEntry(e,t.id,s,i,r,n,!0)}getOrCreateTracker(e,t,s){let i,r=this.getTracker(e,t,s);return r||(r=new N(t,e,this.dispatcher),this.trackers.set(t|e.id<<22,r),e.trackStale&&(i=new N(t,e,this.dispatcher),this.trackers.set(t|e.id<<22|2**31,i)),s?i:r)}getTracker(e,t,s){return this.trackers.get(t|e.id<<22|(s?2**31:0))}flush(){if(this.refLog)for(;;){const[e,t,s,i]=this.refLog.processAndCommitSince(this.refLogPointer);if(!e)break;if(!i)for(let i=t;i<s;i+=2){const t=e[i],s=e[i+1],r=4194303&t,n=t>>>22,a=4194303&s,o=s>>>22&127,h=(s&B)>>>30,c=0!=(s&2**29),d=c?e[i+2]:void 0;c&&(i+=1),this.processEntry(r,n,o,d,a,h,!1)}}}processEntry(e,t,s,i,r,n,a){for(let o=0;o<this.selectors.length;o++){const h=this.selectors[o];if(!(h.matchType&&h.sourceTypeId!==t||h.matchSeq&&h.sourceSeq!==s)){if(n===L.REFERENCE||n===L.UNREFERENCE){const o=this.getOrCreateTracker(h,r,!1);n===L.REFERENCE?o.trackReference(e,t,s,i,a):o.trackUnreference(e,t,s,i,a)}if(h.trackStale&&(n===L.REFERENCE||n===L.RELEASE)){const o=this.getOrCreateTracker(h,r,!0);n===L.REFERENCE?o.trackReference(e,t,s,i,a):o.trackUnreference(e,t,s,i,a)}}}}}const U="undefined"!=typeof window&&void 0!==window.performance?performance.now.bind(performance):Date.now.bind(Date);class M extends T{__callback;execute(){this.__callback(this)}}class D{maxEntities;defaultComponentStorage;registry;systems;systemsByClass=new Map;lastTime=U()/1e3;executing;shapeLog;writeLog;shapeLogFramePointer;writeLogFramePointer;stats;indexer;userCallbackSystem;callbackSystem;deferredControls=new Map;constructor({defs:e,maxEntities:t=1e4,maxLimboEntities:i=Math.ceil(t/5),maxLimboComponents:r=Math.ceil(t/5),maxShapeChangesPerFrame:n=2*t,maxWritesPerFrame:a=4*t,maxRefChangesPerFrame:o=t,defaultComponentStorage:h="sparse"}){if(t>4194304)throw new Error("maxEntities too high, the limit is 4194304");const{componentTypes:c,systemTypes:d}=this.splitDefs(e);if(c.length>512)throw new Error("Too many component types, the limit is 512");this.maxEntities=t,this.defaultComponentStorage=h,this.shapeLog=new s(n,"maxShapeChangesPerFrame"),this.shapeLogFramePointer=this.shapeLog.createPointer(),this.registry=new C(t,i,r,c.flat(1/0),this),this.indexer=new F(this,o),this.registry.initializeComponentTypes(),this.systems=this.normalizeAndInitSystems(d),this.systems.some((e=>e.hasWriteQueries))&&(this.writeLog=new s(a,"maxWritesPerFrame"),this.writeLogFramePointer=this.writeLog.createPointer()),this.userCallbackSystem=new M,this.callbackSystem=new A(this.userCallbackSystem,this),this.callbackSystem.rwMasks.read=void 0,this.callbackSystem.rwMasks.write=void 0}normalizeAndInitSystems(e){const t=[],s=e.flat(1/0);for(let e=0;e<s.length;e++){const i=s[e],r=new i,n=s[e+1];n&&"function"!=typeof n&&(Object.assign(r,n),e++);const a=new A(r,this);t.push(a),this.systemsByClass.set(i,a)}return t}splitDefs(e){const t=[],s=[];let i=!1;for(const r of e.flat(1/0))"function"==typeof r?(i=r.__system,(i?s:t).push(r)):(s.push(r),i=!1);return{componentTypes:t,systemTypes:s}}execute(e,t,s){this.executing=!0,void 0===e&&(e=U()/1e3),void 0===t&&(t=e-this.lastTime),this.lastTime=e;for(const i of s??this.systems)this.registry.executingSystem=i,i.execute(e,t),this.flush();this.registry.executingSystem=void 0,this.executing=!1,this.processEndOfFrame()}executeFunction(e){this.executing=!0,this.registry.executingSystem=this.callbackSystem,this.userCallbackSystem.__callback=e,this.callbackSystem.execute(0,0),this.flush(),this.registry.executingSystem=void 0,this.executing=!1,this.processEndOfFrame()}processEndOfFrame(){this.registry.processEndOfFrame(),this.indexer.processEndOfFrame(),this.processDeferredControls()}gatherFrameStats(){this.stats.frames+=1,this.stats.maxShapeChangesPerFrame=this.shapeLog.countSince(this.shapeLogFramePointer),this.stats.maxWritesPerFrame=this.writeLog?.countSince(this.writeLogFramePointer)??0}flush(){this.registry.flush(),this.indexer.flush(),this.shapeLog.commit(),this.writeLog?.commit()}createEntity(e){const t=this.registry.createEntity(e);return this.executing||this.flush(),t}control(e){this.deferRequestedRunState(e.stop,I.STOPPED),this.deferRequestedRunState(e.suspend,I.SUSPENDED),this.deferRequestedRunState(e.restart,I.RUNNING),this.executing||this.processDeferredControls()}deferRequestedRunState(e,t){for(const s of e.flat(1/0)){if(!s.__system)continue;const e=this.systemsByClass.get(s);this.deferredControls.set(e,t)}}checkControlOverlap(e){const t=new Set,s=new Set;for(const s of e.stop.flat(1/0))s.__system&&t.add(s);for(const i of e.suspend.flat(1/0))if(i.__system){if(t.has(i))throw new Error(`Request to both stop and suspend system ${i.name}`);s.add(i)}for(const i of e.restart.flat(1/0))if(i.__system){if(t.has(i))throw new Error(`Request to both stop and restart system ${i.name}`);if(s.has(i))throw new Error(`Request to both suspend and restart system ${i.name}`)}}processDeferredControls(){if(this.deferredControls.size){for(const[e,t]of this.deferredControls.entries())switch(t){case I.STOPPED:e.stop();break;case I.SUSPENDED:e.suspend();break;case I.RUNNING:e.restart()}this.deferredControls.clear()}}}class q{__dispatcher;constructor(e){this.__dispatcher=new D(e)}build(e){this.__dispatcher.executeFunction(e)}createEntity(...e){this.__dispatcher.createEntity(e)}execute(e,t){this.__dispatcher.execute(e,t)}control(e){this.__dispatcher.control(e)}get stats(){return this.__dispatcher.stats}}function j(e){return function(t,s){t.constructor.schema||(t.constructor.schema={});const i="type"in e?e:{type:e};t.constructor.schema[s]=i}}const $=[];function Q(e){if("function"!=typeof e)return t=>{t.options=e,$.push(t)};$.push(e)}export{m as Entity,k as Query,T as System,o as Type,q as World,Q as component,$ as componentTypes,j as prop}; | ||
class e{size;bytes;constructor(e){this.size=e,this.bytes=new Uint32Array(Math.ceil(e/32))}get(e){return 0!=(this.bytes[e>>>5]&1<<(31&e))}set(e){this.bytes[e>>>5]|=1<<(31&e)}unset(e){this.bytes[e>>>5]&=~(1<<(31&e))}clear(){this.bytes.fill(0)}}const t=[];class s{maxEntries;configParamName;localProcessingAllowed;data;corral;constructor(e,t,s=!1){this.maxEntries=e,this.configParamName=t,this.localProcessingAllowed=s;const i=new SharedArrayBuffer((e+2)*Uint32Array.BYTES_PER_ELEMENT);this.data=new Uint32Array(i);const r=new SharedArrayBuffer((e+2)*Uint32Array.BYTES_PER_ELEMENT);this.corral=new Uint32Array(r)}push(e){const t=this.corral[0];t&&this.corral[t]===e||(this.corral[t+2]=e,this.corral[0]+=1)}commit(e){const t=this.corral[0];if(!t)return!0;let s=this.data[0];if(e&&(e.generation!==this.data[1]||e.index!==s||e.corralGeneration!==this.corral[1]||e.corralIndex!==this.corral[0]))return!1;const i=Math.min(t,this.maxEntries-s);for(this.data.set(this.corral.subarray(2,i+2),s+2),i<t&&this.data.set(this.corral.subarray(i+2,t+2),2),s+=t;s>=this.maxEntries;)s-=this.maxEntries,this.data[1]+=1;return this.data[0]=s,this.corral[0]=0,this.corral[1]+=1,e&&(e.index=s,e.generation=this.data[1]),!0}createPointer(e){return e?(e.index=this.data[0],e.generation=this.data[1],e.corralIndex=this.corral[0],e.corralGeneration=this.corral[1],e):{index:this.data[0],generation:this.data[1],corralIndex:this.corral[0],corralGeneration:this.corral[1]}}hasUpdatesSince(e){return!(e.index===this.data[0]&&e.generation===this.data[1]&&(e.corralGeneration===this.corral[1]?e.corralIndex===this.corral[0]:0===this.corral[0]))}processSince(e,s){let i=t;const r=s?.index??this.data[0],n=s?.generation??this.data[1];if(e.generation===n)if(e.index<r)i=[this.data,e.index+2,r+2,!1],e.index=r;else{const t=this.corral[0],s=this.corral[1];(e.corralGeneration===s?e.corralIndex<t:t)&&(i=[this.corral,e.corralIndex+2,t+2,!0],e.corralIndex=t,e.corralGeneration=s)}else i=[this.data,e.index+2,this.data.length,!1],e.index=0,e.generation=n;return i}processAndCommitSince(e){const s=this.processSince(e);return s[0]?s:this.commit(e)?t:this.processSince(e)}countSince(e,t){const s=e.index,i=t?.index??this.data[0],r=t?.generation??this.data[1];return e.index=i,e.generation=r,s===i&&e.generation===r?0:s<i?i-s:this.maxEntries-(s-i)}checkPointers(e,t){this.checkPointer(e),t&&this.checkPointer(t)}checkPointer(e){const t=this.data[0];let s=e.generation;e.index===t?s+1<this.data[1]&&this.throwCapacityExceeded():(e.index>t&&(s+=1),s!==this.data[1]&&this.throwCapacityExceeded())}throwCapacityExceeded(){throw new Error(`Log capacity exceeded, please raise ${this.configParamName} above ${this.maxEntries}`)}}class i{maxItems;configParamName;data;constructor(e,t){this.maxItems=e,this.configParamName=t,this.data=new Uint32Array(new SharedArrayBuffer((e+1)*Uint32Array.BYTES_PER_ELEMENT))}get length(){return this.data[0]}take(){const e=this.data[0]--;return this.data[e]}refill(e){if(!e.length)return;const t=this.length,s=t+e.length;this.data.set(e,t+1),this.data[0]=s}fillWithDescendingIntegers(e){const t=this.length;for(let s=this.data.length-1;s>t;s--)this.data[s]=e++;this.data[0]=this.data.length-1}}const r=new TextEncoder,n=new TextDecoder;function a(e){throw new Error(`Component is not writable; use entity.write(${e.type.name}) to acquire a writable version`)}class o{defaultValue;constructor(e){this.defaultValue=e}static boolean;static uint8;static int8;static uint16;static int16;static uint32;static int32;static float32;static float64;static staticString;static dynamicString;static object;static weakObject;static ref;static backrefs}class h extends o{NumberArray;constructor(e){super(0),this.NumberArray=e}defineElastic(e,t){let s,i;t.updateBuffer=()=>{const r=e.capacity*this.NumberArray.BYTES_PER_ELEMENT,n=t.buffer?.byteLength!==r;(n||t.buffer!==s)&&(s=n?new SharedArrayBuffer(r):t.buffer,i=new this.NumberArray(s),n&&t.buffer&&i.set(new this.NumberArray(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>i[e.index],set(t){i[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>i[e.index],set(t){a(e)}})}defineFixed(e,t){const s=e.capacity*this.NumberArray.BYTES_PER_ELEMENT,i=new SharedArrayBuffer(s),r=new this.NumberArray(i);t.buffer=i,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>r[e.index],set(t){r[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>r[e.index],set(t){a(e)}})}}class c extends o{choices;choicesIndex=new Map;TypedArray;constructor(e){if(super(e[0]),this.choices=e,!e?.length)throw new Error("No choices specified for Type.staticString");e.length<256?this.TypedArray=Uint8Array:e.length<65536?this.TypedArray=Uint16Array:this.TypedArray=Uint32Array;for(let t=0;t<e.length;t++)this.choicesIndex.set(e[t],t)}defineElastic(e,t){let s,i;const r=this.choices,n=this.choicesIndex;t.updateBuffer=()=>{const r=e.capacity*this.TypedArray.BYTES_PER_ELEMENT,n=t.buffer?.byteLength!==r;(n||t.buffer!==s)&&(s=n?new SharedArrayBuffer(r):t.buffer,i=new this.TypedArray(s),n&&t.buffer&&i.set(new this.TypedArray(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=i[e.index],s=r[t];if(void 0===s)throw new Error(`Invalid static string index: ${t}`);return s},set(t){const s=n.get(t);if(void 0===s)throw new Error(`Static string not in set: "${t}"`);i[e.index]=s}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=i[e.index],s=r[t];if(void 0===s)throw new Error(`Invalid static string index: ${t}`);return s},set(t){a(e)}})}defineFixed(e,t){const s=this.choices,i=this.choicesIndex,r=e.capacity*this.TypedArray.BYTES_PER_ELEMENT,n=new SharedArrayBuffer(r),o=new this.TypedArray(n);t.buffer=n,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=o[e.index],i=s[t];if(void 0===i)throw new Error(`Invalid static string index: ${t}`);return i},set(t){const s=i.get(t);if(void 0===s)throw new Error(`Static string not in set: "${t}"`);o[e.index]=s}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=o[e.index],i=s[t];if(void 0===i)throw new Error(`Invalid static string index: ${t}`);return i},set(t){a(e)}})}}class d extends o{maxUtf8Length;lengthsStride;bytesStride;constructor(e){super(""),this.maxUtf8Length=e+e%2,this.lengthsStride=e/2+1,this.bytesStride=this.maxUtf8Length+2}defineElastic(e,t){let s,i,o;const h=this.maxUtf8Length,c=this.lengthsStride,d=this.bytesStride;t.updateBuffer=()=>{const r=e.capacity*(this.maxUtf8Length+Uint16Array.BYTES_PER_ELEMENT),n=t.buffer?.byteLength!==r;(n||t.buffer!==s)&&(s=n?new SharedArrayBuffer(r):t.buffer,i=new Uint16Array(s),o=new Uint8Array(s),n&&t.buffer&&o.set(new Uint8Array(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=i[e.index*c];return n.decode(new Uint8Array(o.buffer,e.index*d+2,t))},set(t){const s=r.encode(t);if(s.byteLength>h)throw new Error(`Dynamic string length > ${h} after encoding: ${t}`);i[e.index*c]=s.byteLength,o.set(s,e.index*d+2)}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=i[e.index*c];return n.decode(new Uint8Array(o.buffer,e.index*d+2,t))},set(t){a(e)}})}defineFixed(e,t){const s=this.maxUtf8Length,i=this.lengthsStride,o=this.bytesStride,h=e.capacity*(this.maxUtf8Length+Uint16Array.BYTES_PER_ELEMENT),c=new SharedArrayBuffer(h),d=new Uint16Array(c),l=new Uint8Array(c);t.buffer=c,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=d[e.index*i];return n.decode(new Uint8Array(l.buffer,e.index*o+2,t))},set(t){const n=r.encode(t);if(n.byteLength>s)throw new Error(`Dynamic string length > ${s} after encoding: ${t}`);d[e.index*i]=n.byteLength,l.set(n,e.index*o+2)}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=d[e.index*i];return n.decode(new Uint8Array(l.buffer,e.index*o+2,t))},set(t){a(e)}})}}const l=[];class f extends o{type;fieldName;trackDeletedBackrefs;constructor(e,t,s){super(l),this.type=e,this.fieldName=t,this.trackDeletedBackrefs=s}defineElastic(e,t){const s=this.fieldName?this.type?.__binding.fields.find((e=>e.name===this.fieldName)):void 0;this.trackDeletedBackrefs;const i=e.dispatcher.indexer;i.registerSelector();const r=i.registerSelector(e.type,this.type,s?.seq,this.trackDeletedBackrefs),n={enumerable:!0,configurable:!0,get:()=>i.getBackrefs(e.entityId,r),set(e){}};Object.defineProperty(e.writableInstance,t.name,n),Object.defineProperty(e.readonlyInstance,t.name,n)}defineFixed(e,t){this.defineElastic(e,t)}}o.boolean=new class extends o{constructor(){super(!1)}defineElastic(e,t){let s,i;t.updateBuffer=()=>{const r=t.buffer?.byteLength!==e.capacity;(r||t.buffer!==s)&&(s=r?new SharedArrayBuffer(e.capacity):t.buffer,i=new Uint8Array(s),r&&t.buffer&&i.set(new Uint8Array(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>Boolean(i[e.index]),set(t){i[e.index]=t?1:0}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>Boolean(i[e.index]),set(t){a(e)}})}defineFixed(e,t){const s=new SharedArrayBuffer(e.capacity),i=new Uint8Array(s);t.buffer=s,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>Boolean(i[e.index]),set(t){i[e.index]=t?1:0}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>Boolean(i[e.index]),set(t){a(e)}})}},o.uint8=new h(Uint8Array),o.int8=new h(Int8Array),o.uint16=new h(Uint16Array),o.int16=new h(Int16Array),o.uint32=new h(Uint32Array),o.int32=new h(Int32Array),o.float32=new h(Float32Array),o.float64=new h(Float64Array),o.staticString=e=>new c(e),o.dynamicString=e=>new d(e),o.ref=new class extends o{constructor(){super(void 0)}defineElastic(e,t){let s,i;const r=e.dispatcher.indexer,n=e.dispatcher.registry,o=n.pool;r.registerSelector(),t.updateBuffer=()=>{const r=e.capacity*Int32Array.BYTES_PER_ELEMENT,n=t.buffer?.byteLength!==r;if(n||t.buffer!==s){if(s=n?new SharedArrayBuffer(r):t.buffer,i=new Int32Array(s),n&&t.buffer){const e=new Int32Array(t.buffer);i.set(e),i.fill(-1,e.length)}else i.fill(-1);t.buffer=s}},t.updateBuffer(),t.clearRef=(s,n,a)=>{const o=4194303&i[e.index],h=void 0!==n;h&&o!==n||(s?h&&(i[e.index]=-1):i[e.index]|=2147483648,r.trackRefChange(e.entityId,e.type,t.seq,void 0,o,-1,s))},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=i[e.index];if(!(-1===t||2147483648&t&&!n.includeRecentlyDeleted))return o.borrowTemporarily(4194303&t)},set(s){const n=i[e.index],a=s?.__id??-1;n!==a&&(i[e.index]=a,r.trackRefChange(e.entityId,e.type,t.seq,void 0,n,a,!0))}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=i[e.index];if(!(-1===t||2147483648&t&&!n.includeRecentlyDeleted))return o.borrowTemporarily(4194303&t)},set(t){a(e)}})}defineFixed(e,t){const s=e.capacity*Int32Array.BYTES_PER_ELEMENT,i=new SharedArrayBuffer(s),r=new Int32Array(i);r.fill(-1),t.buffer=i;const n=e.dispatcher.indexer,o=e.dispatcher.registry,h=o.pool;n.registerSelector(),t.clearRef=(s,i,a)=>{const o=4194303&r[e.index],h=void 0!==i;h&&o!==i||(s?h&&(r[e.index]=-1):r[e.index]|=2147483648,n.trackRefChange(e.entityId,e.type,t.seq,void 0,o,-1,s))},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=r[e.index];if(!(-1===t||2147483648&t&&!o.includeRecentlyDeleted))return h.borrowTemporarily(4194303&t)},set(s){const i=r[e.index],a=s?.__id??-1;i!==a&&(r[e.index]=a,n.trackRefChange(e.entityId,e.type,t.seq,void 0,i,a,!0))}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=r[e.index];if(!(-1===t||2147483648&t&&!o.includeRecentlyDeleted))return h.borrowTemporarily(4194303&t)},set(t){a(e)}})}},o.backrefs=(e,t,s=!1)=>new f(e,t,s),o.object=new class extends o{constructor(){super(void 0)}defineElastic(e,t){const s=[];t.localBuffer=s,t.updateBuffer=()=>{},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>s[e.index],set(t){s[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>s[e.index],set(t){a(e)}})}defineFixed(e,t){const s=new Array(e.capacity);t.localBuffer=s,t.updateBuffer=()=>{},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>s[e.index],set(t){s[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>s[e.index],set(t){a(e)}})}},o.weakObject=new class extends o{finalizers;constructor(){super(void 0)}defineElastic(e,t){const s=[];t.localBuffer=s,t.updateBuffer=()=>{};const i=this.initFinalizers(e);Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=s[e.index];return null==t?t:t.deref()},set(r){if(null!=r){const s=new WeakRef(r);i?.register(r,{type:e.type,field:t,weakRef:s,id:e.entityId,index:e.index}),r=s}s[e.index]=r}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=s[e.index];return null==t?t:t.deref()},set(t){a(e)}})}defineFixed(e,t){const s=new Array(e.capacity);t.localBuffer=s,t.updateBuffer=()=>{};const i=this.initFinalizers(e);Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=s[e.index];return null==t?t:t.deref()},set(r){if(null!=r){const s=new WeakRef(r);i?.register(r,{type:e.type,field:t,weakRef:s,id:e.entityId,index:e.index}),r=s}s[e.index]=r}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=s[e.index];return null==t?t:t.deref()},set(t){a(e)}})}initFinalizers(e){if(!e.trackedWrites)return;if(this.finalizers)return this.finalizers;const t=e.dispatcher;return t.writeLog&&"undefined"!=typeof FinalizationRegistry?(this.finalizers=new FinalizationRegistry((({type:e,field:s,weakRef:i,id:r,index:n})=>{s.localBuffer?.[n]===i&&t.registry.trackWrite(r,e)})),this.finalizers):void 0}};class u{type;fields;dispatcher;capacity;storage;elastic;readonlyInstance;writableInstance;shapeOffset;shapeMask;refFields;trackedWrites=!1;internallyIndexed=!1;entityId=0;index=0;constructor(e,t,s,i,r,n){this.type=e,this.fields=t,this.dispatcher=s,this.capacity=i,this.storage=r,this.elastic=n,this.readonlyInstance=new e,this.writableInstance=new e,this.shapeOffset=e.id>>5,this.shapeMask=1<<(31&e.id),this.refFields=t.filter((e=>e.type===o.ref))}}class y{maxEntities;binding;fields;index;spares;constructor(e,t,s){this.maxEntities=e,this.binding=t,this.fields=s,this.growSpares(),this.growCapacity()}acquireIndex(e){let t=this.index[e];return-1===t&&(this.spares[3]>0?t=this.spares[4+--this.spares[3]]:(this.spares[1]===this.spares[2]&&(this.binding.capacity=Math.min(this.maxEntities,2*this.binding.capacity),this.growCapacity()),t=this.spares[1]++),this.index[e]=t),t}releaseIndex(e){this.spares[3]===this.spares.length-4&&this.growSpares(),this.spares[4+this.spares[3]++]=this.index[e],this.index[e]=-1}growCapacity(){const e=this.ArrayType,t=e.BYTES_PER_ELEMENT!==this.spares?.[0];if(!this.index||t){const t=new e(new SharedArrayBuffer(this.maxEntities*e.BYTES_PER_ELEMENT));this.index?t.set(this.index):t.fill(-1),this.index=t}if(this.spares&&t){const t=new e(new SharedArrayBuffer(this.spares.length*e.BYTES_PER_ELEMENT));t.set(this.spares),t[0]=e.BYTES_PER_ELEMENT,this.spares=t}if(this.spares[2]=this.binding.capacity,this.binding.elastic)for(const e of this.fields)e.updateBuffer()}growSpares(){const e=this.ArrayType,t=this.spares?Math.min(this.maxEntities,2*(this.spares.length-4)):8,s=new e(new SharedArrayBuffer((4+t)*e.BYTES_PER_ELEMENT));this.spares?s.set(this.spares):(s[0]=e.BYTES_PER_ELEMENT,s[2]=this.binding.capacity),this.spares=s}get ArrayType(){const e=this.binding.capacity;return e<=127?Int8Array:e<=32767?Int16Array:Int32Array}}function g(e,t,s){const i=function(e){const t=e.schema,s=[];if(t){let e=0;for(const i in t){let r=t[i];(r instanceof o||"function"==typeof r)&&(r={type:r}),"function"==typeof r.type&&(r.type=r.type()),"default"in r||(r.default=r.type.defaultValue),s.push({name:i,seq:e++,type:r.type,default:r.default})}}return s}(t),r=i.length?t.options?.storage??s.defaultComponentStorage:"sparse",n="sparse"===r?s.maxEntities:Math.min(s.maxEntities,t.options?.capacity??0),a=t.options?.initialCapacity??8;t.id=e;const h=new u(t,i,s,n||a,r,!n);t.__binding=h}function p(e){const t=e.__binding;for(const e of t.fields)t.elastic?e.type.defineElastic(t,e):e.type.defineFixed(t,e);switch(t.storage){case"sparse":e.__bind=(e,s)=>(t.entityId=e,t.index=e,s?t.writableInstance:t.readonlyInstance),e.__allocate=e=>(t.entityId=e,t.index=e,t.writableInstance);break;case"packed":{const s=new y(t.dispatcher.maxEntities,t,t.fields);e.__bind=(e,i)=>(t.entityId=e,t.index=s.index[e],i?t.writableInstance:t.readonlyInstance),e.__allocate=e=>(t.entityId=e,t.index=s.acquireIndex(e),t.writableInstance),e.__free=e=>{s.releaseIndex(e)};break}case"compact":throw new Error("Not yet implemented")}}class m{__registry;__id;constructor(e){this.__registry=e}add(e,t){return this.__registry.setShape(this.__id,e),function(e,t,s){const i=e.__allocate(t);for(const t of e.__binding.fields)i[t.name]=s?.[t.name]??t.default}(e,this.__id,t),this}addAll(...e){for(let t=0;t<e.length;t++){const s=e[t];let i=e[t+1];"function"==typeof i?i=void 0:t++,this.add(s,i)}return this}remove(e){this.__registry.clearShape(this.__id,e)}removeAll(...e){for(const t of e)this.remove(t)}has(e){return this.__registry.hasShape(this.__id,e,!0)}read(e){return e.__bind(this.__id,!1)}write(e){return e.__binding.trackedWrites&&this.__registry.trackWrite(this.__id,e),e.__bind(this.__id,!0)}delete(){this.__registry.Alive;for(const e of this.__registry.types)this.__registry.hasShape(this.__id,e,!1)&&this.__registry.clearShape(this.__id,e);this.__registry.queueDeletion(this.__id),this.__registry.dispatcher.indexer.clearAllRefs(this.__id,!1)}__checkMask(e,t){_(e,this.__registry.executingSystem,t)}__checkHas(e,t){if(!this.__registry.hasShape(this.__id,e,t))throw new Error(`Entity doesn't have a ${e.name} component`)}}function _(e,t,s){!function(e){if(!e.__binding)throw new Error(`Component ${e.name} not defined; add to world defs`)}(e);const i=s?t?.rwMasks.write:t?.rwMasks.read;if(!(!i||0!=((i[e.__binding.shapeOffset]??0)&e.__binding.shapeMask)))throw new Error(`System didn't mark component ${e.name} as ${s?"writable":"readable"}`)}function b(e,t){const s=t.__binding.shapeOffset;s>=e.length&&(e.length=s+1,e.fill(0,e.length,s)),e[s]|=t.__binding.shapeMask}class w{pool;entities=[];constructor(e){this.pool=e}add(e){this.entities.push(this.pool.borrowTemporarily(e))}clear(){this.entities.length&&this.entities.splice(0,1/0)}}class E{pool;entities=[];lookupTable;constructor(e,t){this.pool=e,this.lookupTable=new Int32Array(t),this.lookupTable.fill(-1)}add(e){const t=this.entities.push(this.pool.borrow(e))-1;this.lookupTable[e]=t}remove(e){const t=this.lookupTable[e];if(t<0)throw new Error("Internal error, entity not in list");this.pool.return(e),this.lookupTable[e]=-1;const s=this.entities.pop();t<this.entities.length&&(this.entities[t]=s,this.lookupTable[s.__id]=t)}has(e){return this.lookupTable[e]>=0}clear(){for(const e of this.entities)this.pool.return(e.__id);this.entities=[],this.lookupTable.fill(-1)}}var x;!function(e){e[e.all=1]="all",e[e.added=2]="added",e[e.removed=4]="removed",e[e.changed=8]="changed",e[e.addedOrChanged=16]="addedOrChanged",e[e.changedOrRemoved=32]="changedOrRemoved",e[e.addedChangedOrRemoved=64]="addedChangedOrRemoved"}(x||(x={}));const R=x.added|x.removed|x.changed|x.addedOrChanged|x.changedOrRemoved|x.addedChangedOrRemoved,S=x.changed|x.addedOrChanged|x.changedOrRemoved|x.addedChangedOrRemoved;class v{query;system;results={};flavors=0;withMask;withoutMask;trackMask;hasTransientResults;hasChangedResults;currentEntities;changedEntities;constructor(e,t){this.query=e,this.system=t,e.__results=this.results,e.__systemName=t.name}complete(){const t=this.system.dispatcher;this.hasTransientResults=Boolean(this.flavors&R),this.hasChangedResults=Boolean(this.flavors&S),this.flavors&x.all?this.results.all=new E(t.registry.pool,t.maxEntities):this.currentEntities=new e(t.maxEntities),this.hasTransientResults&&this.allocateTransientResultLists(),this.flavors&&this.system.shapeQueries.push(this),this.hasChangedResults&&(this.changedEntities=new e(t.maxEntities),this.system.writeQueries.push(this))}allocateTransientResultLists(){this.flavors&x.added&&this.allocateResult("added"),this.flavors&x.removed&&this.allocateResult("removed"),this.flavors&x.changed&&this.allocateResult("changed"),this.flavors&x.addedOrChanged&&this.allocateResult("addedOrChanged"),this.flavors&x.changedOrRemoved&&this.allocateResult("changedOrRemoved"),this.flavors&x.addedChangedOrRemoved&&this.allocateResult("addedChangedOrRemoved")}allocateResult(e){const t=this.system.dispatcher;this.results[e]=new w(t.registry.pool)}clearTransientResults(){this.hasTransientResults&&(this.results.added?.clear(),this.results.removed?.clear(),this.results.changed?.clear(),this.results.addedOrChanged?.clear(),this.results.changedOrRemoved?.clear(),this.results.addedChangedOrRemoved?.clear(),this.changedEntities?.clear())}clearAllResults(){this.clearTransientResults(),this.results.all?.clear()}handleShapeUpdate(e){const t=this.system.dispatcher.registry,s=this.results.all?.has(e)??this.currentEntities.get(e),i=t.matchShape(e,this.withMask,this.withoutMask);i&&!s?(this.currentEntities?.set(e),this.results.all?.add(e),this.results.added?.add(e),this.results.addedOrChanged?.add(e),this.results.addedChangedOrRemoved?.add(e)):!i&&s&&(this.currentEntities?.unset(e),this.results.all?.remove(e),this.results.removed?.add(e),this.results.changedOrRemoved?.add(e),this.results.addedChangedOrRemoved?.add(e))}handleWrite(e,t,s){!this.changedEntities.get(e)&&(this.trackMask[t]??0)&s&&(this.changedEntities.set(e),this.results.changed?.add(e),this.results.addedOrChanged?.add(e),this.results.changedOrRemoved?.add(e),this.results.addedChangedOrRemoved?.add(e))}}class P{__callback;__userQuery;__query;__system;__lastTypes;constructor(e,t){this.__callback=e,this.__userQuery=t}__build(e){try{this.__system=e,this.__query=new v(this.__userQuery,e),this.__callback(this),this.__query.complete()}catch(t){throw t.message=`Failed to build query in system ${e.name}: ${t.message}`,t}}get and(){return this}get but(){return this}get also(){return this}get all(){return this.__query.flavors|=x.all,this}get added(){return this.__query.flavors|=x.added,this}get removed(){return this.__query.flavors|=x.removed,this}get changed(){return this.__query.flavors|=x.changed,this}get addedOrChanged(){return this.__query.flavors|=x.addedOrChanged,this}get changedOrRemoved(){return this.__query.flavors|=x.changedOrRemoved,this}get addedChangedOrRemoved(){return this.__query.flavors|=x.addedChangedOrRemoved,this}with(...e){return this.set(this.__system.rwMasks.read,e),this.set("withMask"),this}without(...e){return this.set(this.__system.rwMasks.read,e),this.set("withoutMask",e),this}using(...e){return this.set(this.__system.rwMasks.read,e),this}get track(){this.set("trackMask");for(const e of this.__lastTypes)e.__binding.trackedWrites=!0;return this}get read(){return this}get write(){return this.set(this.__system.rwMasks.write),this}set(e,t,s){if(e){if(t||(t=this.__lastTypes),!t)throw new Error("No component type to apply query modifier to");if(this.__lastTypes=t,"string"==typeof e){if(s&&this.__query[e])throw new Error(`Only one ${s} allowed`);this.__query[e]||(this.__query[e]=[]),e=this.__query[e]}else if(s&&e.some((e=>0!==e)))throw new Error(`Only one ${s} allowed`);for(const s of t)b(e,s)}}}class k{__results;__systemName;get all(){return this.__results.all.entities}get added(){return this.__results.added.entities}get removed(){return this.__results.removed.entities}get changed(){return this.__results.changed.entities}get addedOrChanged(){return this.__results.addedOrChanged.entities}get changedOrRemoved(){return this.__results.changedOrRemoved.entities}get addedChangedOrRemoved(){return this.__results.addedChangedOrRemoved.entities}__checkList(e){if(!this.__results[e])throw new Error(`Query '${e}' not configured, please add .${e} to your query definition in system ${this.__systemName}`)}}var I,L;!function(e){e[e.RUNNING=0]="RUNNING",e[e.STOPPED=1]="STOPPED"}(I||(I={}));class T{type;constructor(e){this.type=e}}class A{static __system=!0;__queryBuilders=[];__dispatcher;time;delta;get name(){return this.constructor.name}query(e){const t=new k,s=new P(e,t);return this.__queryBuilders.push(s),t}attach(e){return new T(e)}createEntity(...e){return this.__dispatcher.createEntity(e)}accessRecentlyDeletedData(e=!0){this.__dispatcher.registry.includeRecentlyDeleted=e}initialize(){}execute(){}}class C{system;dispatcher;rwMasks={read:[],write:[]};shapeQueries=[];writeQueries=[];hasWriteQueries;processedEntities;shapeLogPointer;writeLogPointer;state=I.RUNNING;get name(){return this.system.name}constructor(t,s){this.system=t,this.dispatcher=s,t.__dispatcher=s,this.shapeLogPointer=s.shapeLog.createPointer(),this.writeLogPointer=s.writeLog?.createPointer(),this.processedEntities=new e(s.maxEntities);for(const e of t.__queryBuilders)e.__build(this);t.__queryBuilders=null,this.hasWriteQueries=!!this.writeQueries.length}replaceAttachmentPlaceholders(){for(const e in this.system)if(this.system[e]instanceof T){const t=this.system[e].type,s=this.dispatcher.systemsByClass.get(t);this.system[e]=s}}async initialize(){await Promise.resolve(this.system.initialize())}execute(e,t){this.state===I.RUNNING&&(this.system.time=e,this.system.delta=t,this.runQueries(),this.system.execute())}runQueries(){const e=this.dispatcher.shapeLog.hasUpdatesSince(this.shapeLogPointer),t=this.hasWriteQueries&&this.dispatcher.writeLog.hasUpdatesSince(this.writeLogPointer);if(e||t){this.processedEntities.clear();for(const e of this.shapeQueries)e.clearTransientResults();e&&this.__updateShapeQueries(),t&&this.__updateWriteQueries()}}__updateShapeQueries(){const e=this.dispatcher.shapeLog;let t,s,i;for(;[t,s,i]=e.processSince(this.shapeLogPointer),t;)for(let e=s;e<i;e++){const s=t[e];if(!this.processedEntities.get(s)){this.processedEntities.set(s);for(const e of this.shapeQueries)e.handleShapeUpdate(s)}}}__updateWriteQueries(){const e=this.dispatcher.writeLog;let t,s,i;for(;[t,s,i]=e.processSince(this.writeLogPointer),t;)for(let e=s;e<i;e++){const s=t[e],i=4194303&s;if(!this.processedEntities.get(i)){const e=s>>>22;for(const t of this.writeQueries)t.handleWrite(i,e>>5,1<<(31&e))}}}stop(){if(this.state!==I.STOPPED){this.state=I.STOPPED;for(const e of this.shapeQueries)e.clearAllResults()}}restart(){if(this.state===I.STOPPED){const e=this.dispatcher.registry,t=e.Alive;for(let s=0;s<this.dispatcher.maxEntities;s++)if(e.hasShape(s,t,!1))for(const e of this.shapeQueries)e.handleShapeUpdate(s);for(const e of this.shapeQueries)e.clearTransientResults();this.dispatcher.shapeLog.createPointer(this.shapeLogPointer),this.dispatcher.writeLog?.createPointer(this.writeLogPointer)}this.state=I.RUNNING}}class O{registry;borrowed;borrowCounts;spares=[];temporarilyBorrowedIds=[];constructor(e,t){this.registry=e,this.borrowed=Array.from({length:t}),this.borrowCounts=new Int32Array(t)}borrow(e){this.borrowCounts[e]+=1;let t=this.borrowed[e];return t||(t=this.borrowed[e]=this.spares.pop()??new m(this.registry),t.__id=e),t}borrowTemporarily(e){const t=this.borrow(e);return this.temporarilyBorrowedIds.push(e),t}returnTemporaryBorrows(){for(const e of this.temporarilyBorrowedIds)this.return(e);this.temporarilyBorrowedIds.splice(0,1/0)}return(e){--this.borrowCounts[e]<=0&&(this.spares.push(this.borrowed[e]),this.borrowed[e]=void 0)}}class B{types;dispatcher;stride;shapes;staleShapes;entityIdPool;pool;executingSystem;includeRecentlyDeleted=!1;deletionLog;prevDeletionPointer;oldDeletionPointer;removalLog;prevRemovalPointer;oldRemovalPointer;Alive=class{};constructor(e,t,r,n,a){this.types=n,this.dispatcher=a,this.stride=Math.ceil(n.length/32);const o=e*this.stride*4;this.shapes=new Uint32Array(new SharedArrayBuffer(o)),this.staleShapes=new Uint32Array(new SharedArrayBuffer(o)),this.entityIdPool=new i(e,"maxEntities"),this.entityIdPool.fillWithDescendingIntegers(0),this.pool=new O(this,e),this.deletionLog=new s(t,"maxLimboEntities"),this.prevDeletionPointer=this.deletionLog.createPointer(),this.oldDeletionPointer=this.deletionLog.createPointer(),this.removalLog=new s(r,"maxLimboComponents"),this.prevRemovalPointer=this.removalLog.createPointer(),this.oldRemovalPointer=this.removalLog.createPointer()}initializeComponentTypes(){this.types.unshift(this.Alive);let e=0;for(const t of this.types)g(e++,t,this.dispatcher);for(const e of this.types)p(e)}createEntity(e){const t=this.entityIdPool.take(),s=t*this.stride;this.shapes[s]=1,this.stride>1&&this.shapes.fill(0,s+1,s+this.stride);const i=this.pool.borrowTemporarily(t);return e&&i.addAll(...e),i}queueDeletion(e){this.deletionLog.push(e)}flush(){this.includeRecentlyDeleted=!1,this.pool.returnTemporaryBorrows(),this.deletionLog.commit(),this.removalLog.commit()}processEndOfFrame(){this.processDeletionLog(),this.processRemovalLog()}processDeletionLog(){this.deletionLog.commit();let e,t,s,i=0;for(;[e,t,s]=this.deletionLog.processSince(this.oldDeletionPointer,this.prevDeletionPointer),e;){for(let i=t;i<s;i++)this.dispatcher.indexer.clearAllRefs(e[i],!0);const r=e.subarray(t,s);this.entityIdPool.refill(r),i+=r.length}this.deletionLog.createPointer(this.prevDeletionPointer)}processRemovalLog(){let e,t,s;for(this.removalLog.commit();[e,t,s]=this.removalLog.processSince(this.oldRemovalPointer,this.prevRemovalPointer),e;)for(let i=t;i<s;i++){const t=e[i],s=4194303&t,r=t>>>22,n=this.types[r],a=s*this.stride+n.__binding.shapeOffset,o=n.__binding.shapeMask;0==(this.shapes[a]&o)&&(this.staleShapes[a]&=~o,this.clearRefs(s,n,!0),n.__free?.(s))}this.removalLog.createPointer(this.prevRemovalPointer)}hasShape(e,t,s){const i=e*this.stride+t.__binding.shapeOffset,r=t.__binding.shapeMask;return 0!=(this.shapes[i]&r)||!(!s||!this.includeRecentlyDeleted||0==(this.staleShapes[i]&r))}setShape(e,t){const s=e*this.stride+t.__binding.shapeOffset,i=t.__binding.shapeMask;this.shapes[s]|=i,this.staleShapes[s]|=i,this.dispatcher.shapeLog.push(e)}clearShape(e,t){const s=this.clearRefs(e,t,!1);(t.__free||s)&&this.removalLog.push(e|t.id<<22),this.shapes[e*this.stride+t.__binding.shapeOffset]&=~t.__binding.shapeMask,this.dispatcher.shapeLog.push(e)}trackWrite(e,t){this.dispatcher.writeLog.push(e|t.id<<22)}clearRefs(e,t,s){const i=!!t.__binding.refFields.length;if(i){t.__bind(e,!0);for(const e of t.__binding.refFields)e.clearRef(s)}return i}matchShape(e,t,s){const i=e*this.stride;if(t)for(let e=0;e<t.length;e++){const s=t[e];if((this.shapes[i+e]&s)!==s)return!1}if(s)for(let e=0;e<s.length;e++){const t=s[e];if(0!=(this.shapes[i+e]&t))return!1}return!0}}!function(e){e[e.REFERENCE=0]="REFERENCE",e[e.UNREFERENCE=1073741824]="UNREFERENCE",e[e.RELEASE=2147483648]="RELEASE"}(L||(L={}));const N=L.REFERENCE|L.UNREFERENCE|L.RELEASE;class F{targetEntityId;selector;dispatcher;entities=[];tags;entityIndex;clearing=!1;registry;constructor(e,t,s){this.targetEntityId=e,this.selector=t,this.dispatcher=s;const i=t.sourceType?.__binding;t.matchType&&(t.matchSeq||1===i.refFields.length)&&!i.internallyIndexed||(this.tags=[]),this.registry=s.registry}clearAllRefs(e){this.clearing=!0;for(let t=0;t<this.entities.length;t++){const s=this.entities[t].__id,i=this.tags[t];if("number"==typeof i)this.clearRef(s,i,e);else for(const t of i)this.clearRef(s,t,e)}this.entities=[],this.tags=[],this.entityIndex=void 0,this.clearing=!1}clearRef(e,t,s){const i=511&t,r=t>>>9&127,n=t>>>16,a=this.registry.types[i];a.__bind(e,!0),a.__binding.fields[r].clearRef(s,this.targetEntityId,n)}trackReference(e,t,s,i,r){let n=this.getEntityIndex(e);void 0===n&&(n=this.addEntity(e,r)),this.addTag(n,this.makeTag(t,s,i))}trackUnreference(e,t,s,i,r){if(this.clearing)return;const n=this.getEntityIndex(e);this.removeTag(n,this.makeTag(t,s,i))&&this.removeEntity(n,e,r)}getEntityIndex(e){if(this.entityIndex)return this.entityIndex[e];const t=this.entities.findIndex((t=>t.__id===e));return t>=0?t:void 0}indexEntities(){this.entityIndex=new Array(this.dispatcher.maxEntities);for(let e=0;e<this.entities.length;e++)this.entityIndex[this.entities[e].__id]=e}addTag(e,t){if(!this.tags)return;const s=this.tags[e];if(void 0===s)this.tags[e]=t;else if("number"==typeof s)this.tags[e]=[s,t];else if(Array.isArray(s))if(s.length>=1e3){(this.tags[e]=new Set(s)).add(t)}else s.push(t);else s.add(t)}removeTag(e,t){if(!this.tags)return!0;const s=this.tags[e];if("number"==typeof s)return delete this.tags[e],!0;if(Array.isArray(s)){const e=s.indexOf(t);return s.splice(e,1),!this.tags.length}return s.delete(t),!s.size}makeTag(e,t,s){return e|t<<9|(void 0===s?0:s<<16)}addEntity(e,t){const s=this.entities.length;return this.entities.push(this.registry.pool.borrow(e)),this.entityIndex?this.entityIndex[e]=s:s>100&&this.indexEntities(),t&&this.trackBackrefsChange(),s}removeEntity(e,t,s){this.registry.pool.return(t);const i=this.entities.pop();this.entityIndex&&delete this.entityIndex[e],this.entities.length>e&&(this.entities[e]=i,this.entityIndex&&(this.entityIndex[i.__id]=e)),s&&this.trackBackrefsChange()}trackBackrefsChange(){for(const e of this.selector.targetTypes)e.__binding.trackedWrites&&this.registry.trackWrite(this.targetEntityId,e)}checkWriteMask(){const e=this.registry.executingSystem;for(const t of this.selector.targetTypes)_(t,e,!0)}}class M{dispatcher;maxRefChangesPerFrame;refLog;refLogPointer;refLogStatsPointer;selectorIdsBySourceKey=new Map;selectors=[];trackers=new Map;registry;constructor(e,t){this.dispatcher=e,this.maxRefChangesPerFrame=t,this.registry=e.registry}processEndOfFrame(){this.flush()}registerSelector(e,t,i,r=!1){this.refLog||(this.refLog=new s(this.maxRefChangesPerFrame,"maxRefChangesPerFrame",!0),this.refLogPointer=this.refLog.createPointer(),this.refLogStatsPointer=this.refLog.createPointer());const n=t?void 0===i?-2-t.id:t.id|i<<9:-1;let a=this.selectorIdsBySourceKey.get(n);if(void 0===a){this.selectors.length||(r=!0);const s={id:this.selectors.length,targetTypes:e?[e]:[],sourceType:t,matchType:!!t,matchSeq:void 0!==i,sourceTypeId:t?.id,sourceSeq:i,trackStale:r};this.selectors.push(s),a=s.id,this.selectorIdsBySourceKey.set(n,a)}else{const t=this.selectors[a];t.trackStale=t.trackStale||r,e&&t.targetTypes.push(e)}return a}getBackrefs(e,t=0){const s=this.selectors[t];return this.getOrCreateTracker(s,e,this.registry.includeRecentlyDeleted).entities}trackRefChange(e,t,s,i,r,n,a){-1!==r&&this.pushRefLogEntry(e,t,s,i,r,a?L.RELEASE:L.UNREFERENCE),-1!==n&&this.pushRefLogEntry(e,t,s,i,n,L.REFERENCE)}clearAllRefs(e,t){this.selectors.length&&this.getTracker(this.selectors[0],e,t)?.clearAllRefs(t)}pushRefLogEntry(e,t,s,i,r,n){const a=void 0!==i;this.refLog.push(e|t.id<<22),this.refLog.push(r|s<<22|n|(a?2**29:0)),a&&this.refLog.push(i),this.processEntry(e,t.id,s,i,r,n,!0)}getOrCreateTracker(e,t,s){let i,r=this.getTracker(e,t,s);return r||(r=new F(t,e,this.dispatcher),this.trackers.set(t|e.id<<22,r),e.trackStale&&(i=new F(t,e,this.dispatcher),this.trackers.set(t|e.id<<22|2**31,i)),s?i:r)}getTracker(e,t,s){return this.trackers.get(t|e.id<<22|(s?2**31:0))}flush(){if(this.refLog)for(;;){const[e,t,s,i]=this.refLog.processAndCommitSince(this.refLogPointer);if(!e)break;if(!i)for(let i=t;i<s;i+=2){const t=e[i],s=e[i+1],r=4194303&t,n=t>>>22,a=4194303&s,o=s>>>22&127,h=(s&N)>>>30,c=0!=(s&2**29),d=c?e[i+2]:void 0;c&&(i+=1),this.processEntry(r,n,o,d,a,h,!1)}}}processEntry(e,t,s,i,r,n,a){for(let o=0;o<this.selectors.length;o++){const h=this.selectors[o];if(!(h.matchType&&h.sourceTypeId!==t||h.matchSeq&&h.sourceSeq!==s)){if(n===L.REFERENCE||n===L.UNREFERENCE){const o=this.getOrCreateTracker(h,r,!1);n===L.REFERENCE?o.trackReference(e,t,s,i,a):o.trackUnreference(e,t,s,i,a)}if(h.trackStale&&(n===L.REFERENCE||n===L.RELEASE)){const o=this.getOrCreateTracker(h,r,!0);n===L.REFERENCE?o.trackReference(e,t,s,i,a):o.trackUnreference(e,t,s,i,a)}}}}}const U="undefined"!=typeof window&&void 0!==window.performance?performance.now.bind(performance):Date.now.bind(Date);class D extends A{__callback;execute(){this.__callback(this)}}class q{maxEntities;defaultComponentStorage;registry;systems;systemsByClass=new Map;lastTime=U()/1e3;executing;shapeLog;writeLog;shapeLogFramePointer;writeLogFramePointer;stats;indexer;userCallbackSystem;callbackSystem;deferredControls=new Map;constructor({defs:e,maxEntities:t=1e4,maxLimboEntities:i=Math.ceil(t/5),maxLimboComponents:r=Math.ceil(t/5),maxShapeChangesPerFrame:n=2*t,maxWritesPerFrame:a=4*t,maxRefChangesPerFrame:o=t,defaultComponentStorage:h="sparse"}){if(t>4194304)throw new Error("maxEntities too high, the limit is 4194304");const{componentTypes:c,systemTypes:d}=this.splitDefs(e);if(c.length>512)throw new Error("Too many component types, the limit is 512");this.maxEntities=t,this.defaultComponentStorage=h,this.shapeLog=new s(n,"maxShapeChangesPerFrame"),this.shapeLogFramePointer=this.shapeLog.createPointer(),this.registry=new B(t,i,r,c.flat(1/0),this),this.indexer=new M(this,o),this.registry.initializeComponentTypes(),this.systems=this.normalizeAndInitSystems(d),this.systems.some((e=>e.hasWriteQueries))&&(this.writeLog=new s(a,"maxWritesPerFrame"),this.writeLogFramePointer=this.writeLog.createPointer()),this.userCallbackSystem=new D,this.callbackSystem=new C(this.userCallbackSystem,this),this.callbackSystem.rwMasks.read=void 0,this.callbackSystem.rwMasks.write=void 0}normalizeAndInitSystems(e){const t=[],s=e.flat(1/0);for(let e=0;e<s.length;e++){const i=s[e],r=new i,n=s[e+1];n&&"function"!=typeof n&&(Object.assign(r,n),e++);const a=new C(r,this);t.push(a),this.systemsByClass.set(i,a)}for(const e of t)e.replaceAttachmentPlaceholders();return t}splitDefs(e){const t=[],s=[];let i=!1;for(const r of e.flat(1/0))"function"==typeof r?(i=r.__system,(i?s:t).push(r)):(s.push(r),i=!1);return{componentTypes:t,systemTypes:s}}async initialize(){await Promise.all(this.systems.map((e=>e.initialize())))}async execute(e,t,s){this.executing=!0,void 0===e&&(e=U()/1e3),void 0===t&&(t=e-this.lastTime),this.lastTime=e;for(const i of s??this.systems)this.registry.executingSystem=i,i.execute(e,t),this.flush();this.registry.executingSystem=void 0,this.executing=!1,this.processEndOfFrame()}executeFunction(e){this.executing=!0,this.registry.executingSystem=this.callbackSystem,this.userCallbackSystem.__callback=e,this.callbackSystem.execute(0,0),this.flush(),this.registry.executingSystem=void 0,this.executing=!1,this.processEndOfFrame()}processEndOfFrame(){this.registry.processEndOfFrame(),this.indexer.processEndOfFrame(),this.processDeferredControls()}gatherFrameStats(){this.stats.frames+=1,this.stats.maxShapeChangesPerFrame=this.shapeLog.countSince(this.shapeLogFramePointer),this.stats.maxWritesPerFrame=this.writeLog?.countSince(this.writeLogFramePointer)??0}flush(){this.registry.flush(),this.indexer.flush(),this.shapeLog.commit(),this.writeLog?.commit()}createEntity(e){const t=this.registry.createEntity(e);return this.executing||this.flush(),t}control(e){this.deferRequestedRunState(e.stop,I.STOPPED),this.deferRequestedRunState(e.restart,I.RUNNING),this.executing||this.processDeferredControls()}deferRequestedRunState(e,t){for(const s of e.flat(1/0)){if(!s.__system)continue;const e=this.systemsByClass.get(s);this.deferredControls.set(e,t)}}checkControlOverlap(e){const t=new Set;for(const s of e.stop.flat(1/0))s.__system&&t.add(s);for(const s of e.restart.flat(1/0))if(s.__system&&t.has(s))throw new Error(`Request to both stop and restart system ${s.name}`)}processDeferredControls(){if(this.deferredControls.size){for(const[e,t]of this.deferredControls.entries())switch(t){case I.STOPPED:e.stop();break;case I.RUNNING:e.restart()}this.deferredControls.clear()}}}const j={};class W{__dispatcher;static async create(e){const t=new W(e,j);return await t.__dispatcher.initialize(),t}constructor(e,t){if(t!==j)throw new Error("Don't call World constructor directly; use World.create instead");this.__dispatcher=new q(e)}build(e){this.__dispatcher.executeFunction(e)}createEntity(...e){this.__dispatcher.createEntity(e)}execute(e,t){return this.__dispatcher.execute(e,t)}control(e){this.__dispatcher.control(e)}get stats(){return this.__dispatcher.stats}}function Q(e){return function(t,s){t.constructor.schema||(t.constructor.schema={});const i="type"in e?e:{type:e};t.constructor.schema[s]=i}}const $=[];function z(e){if("function"!=typeof e)return t=>{t.options=e,$.push(t)};$.push(e)}export{m as Entity,k as Query,A as System,o as Type,W as World,z as component,$ as componentTypes,Q as field}; | ||
//# sourceMappingURL=perf.min.js.map |
@@ -132,4 +132,4 @@ interface LogPointer { | ||
} | ||
interface SystemType { | ||
new (): System; | ||
interface SystemType<S extends System> { | ||
new (): S; | ||
} | ||
@@ -142,7 +142,10 @@ declare abstract class System { | ||
delta: number; | ||
// TODO: support schedule builder | ||
get name(): string; | ||
query(buildCallback: (q: QueryBuilder) => void): Query; | ||
attach<S extends System>(systemType: SystemType<S>): S; | ||
createEntity(...initialComponents: (ComponentType<any> | any)[]): Entity; | ||
accessRecentlyDeletedData(toggle?: boolean): void; | ||
abstract execute(): void; | ||
initialize(): void | Promise<void>; // eslint-disable-line @typescript-eslint/no-empty-function | ||
execute(): void; // eslint-disable-line @typescript-eslint/no-empty-function | ||
} | ||
@@ -162,2 +165,4 @@ declare class SystemBox { | ||
constructor(system: System, dispatcher: Dispatcher); | ||
replaceAttachmentPlaceholders(): void; | ||
initialize(): Promise<void>; | ||
execute(time: number, delta: number): void; | ||
@@ -169,3 +174,2 @@ private runQueries; | ||
restart(): void; | ||
suspend(): void; | ||
} | ||
@@ -231,3 +235,3 @@ declare class ComponentStats { | ||
// https://stackoverflow.com/questions/67467302/type-for-an-interleaved-array-of-classes-and-values | ||
type DefsArray = (ComponentType<any> | SystemType | any | DefsArray)[]; | ||
type DefsArray = (ComponentType<any> | SystemType<System> | any | DefsArray)[]; | ||
interface WorldOptions { | ||
@@ -245,3 +249,2 @@ defs: DefsArray; | ||
stop: DefsArray; | ||
suspend: DefsArray; | ||
restart: DefsArray; | ||
@@ -254,3 +257,3 @@ } | ||
private readonly systems; | ||
private readonly systemsByClass; | ||
readonly systemsByClass: Map<SystemType<System>, SystemBox>; | ||
private lastTime; | ||
@@ -270,3 +273,4 @@ executing: boolean; | ||
private splitDefs; | ||
execute(time?: number, delta?: number, systems?: SystemBox[]): void; | ||
initialize(): Promise<void>; | ||
execute(time?: number, delta?: number, systems?: SystemBox[]): Promise<void>; | ||
executeFunction(fn: (system: System) => void): void; | ||
@@ -366,2 +370,3 @@ private processEndOfFrame; | ||
static weakObject: Type<any>; | ||
// TODO: add autoremove/autodelete when nulled out | ||
static ref: Type<Entity | undefined>; | ||
@@ -393,3 +398,6 @@ static backrefs: (type?: ComponentType<any>, fieldName?: string, trackDeletedBackrefs?: boolean) => Type<Entity[]>; | ||
} | ||
interface ComponentType<C> { | ||
interface Component { | ||
__invalid?: boolean; | ||
} | ||
interface ComponentType<C extends Component> { | ||
new (): C; | ||
@@ -416,4 +424,4 @@ schema?: Schema; | ||
readonly elastic: boolean; | ||
readonly readonlyInstance: C; | ||
readonly writableInstance: C; | ||
readonlyInstance: C; | ||
writableInstance: C; | ||
readonly shapeOffset: number; | ||
@@ -430,6 +438,7 @@ readonly shapeMask: number; | ||
private readonly __dispatcher; | ||
constructor(options: WorldOptions); | ||
static create(options: WorldOptions): Promise<World>; | ||
private constructor(); | ||
build(callback: (system: System) => void): void; | ||
createEntity(...initialComponents: (ComponentType<any> | any)[]): void; | ||
execute(time?: number, delta?: number): void; | ||
execute(time?: number, delta?: number): Promise<void>; | ||
control(options: ControlOptions): void; | ||
@@ -442,7 +451,7 @@ get stats(): Stats; | ||
} | ||
declare function prop<JSType>(practicalOptions: PropOptions<JSType> | Type<any> | (() => Type<any>)): (target: any, name: string) => void; | ||
declare function field<JSType>(practicalOptions: PropOptions<JSType> | Type<any> | (() => Type<any>)): (target: any, name: string) => void; | ||
declare const componentTypes: ComponentType<any>[]; | ||
declare function component(constructor: ComponentType<any>): void; | ||
declare function component(options: ComponentOptions): (constructor: ComponentType<any>) => void; | ||
export { World, Type, Entity, System, SystemType, componentTypes, component, prop, Query, ComponentType }; | ||
export { World, Type, Entity, System, SystemType, componentTypes, component, field, Query, ComponentType }; | ||
//# sourceMappingURL=perf.umd.d.ts.map |
@@ -132,4 +132,4 @@ interface LogPointer { | ||
} | ||
interface SystemType { | ||
new (): System; | ||
interface SystemType<S extends System> { | ||
new (): S; | ||
} | ||
@@ -142,7 +142,10 @@ declare abstract class System { | ||
delta: number; | ||
// TODO: support schedule builder | ||
get name(): string; | ||
query(buildCallback: (q: QueryBuilder) => void): Query; | ||
attach<S extends System>(systemType: SystemType<S>): S; | ||
createEntity(...initialComponents: (ComponentType<any> | any)[]): Entity; | ||
accessRecentlyDeletedData(toggle?: boolean): void; | ||
abstract execute(): void; | ||
initialize(): void | Promise<void>; // eslint-disable-line @typescript-eslint/no-empty-function | ||
execute(): void; // eslint-disable-line @typescript-eslint/no-empty-function | ||
} | ||
@@ -162,2 +165,4 @@ declare class SystemBox { | ||
constructor(system: System, dispatcher: Dispatcher); | ||
replaceAttachmentPlaceholders(): void; | ||
initialize(): Promise<void>; | ||
execute(time: number, delta: number): void; | ||
@@ -169,3 +174,2 @@ private runQueries; | ||
restart(): void; | ||
suspend(): void; | ||
} | ||
@@ -231,3 +235,3 @@ declare class ComponentStats { | ||
// https://stackoverflow.com/questions/67467302/type-for-an-interleaved-array-of-classes-and-values | ||
type DefsArray = (ComponentType<any> | SystemType | any | DefsArray)[]; | ||
type DefsArray = (ComponentType<any> | SystemType<System> | any | DefsArray)[]; | ||
interface WorldOptions { | ||
@@ -245,3 +249,2 @@ defs: DefsArray; | ||
stop: DefsArray; | ||
suspend: DefsArray; | ||
restart: DefsArray; | ||
@@ -254,3 +257,3 @@ } | ||
private readonly systems; | ||
private readonly systemsByClass; | ||
readonly systemsByClass: Map<SystemType<System>, SystemBox>; | ||
private lastTime; | ||
@@ -270,3 +273,4 @@ executing: boolean; | ||
private splitDefs; | ||
execute(time?: number, delta?: number, systems?: SystemBox[]): void; | ||
initialize(): Promise<void>; | ||
execute(time?: number, delta?: number, systems?: SystemBox[]): Promise<void>; | ||
executeFunction(fn: (system: System) => void): void; | ||
@@ -366,2 +370,3 @@ private processEndOfFrame; | ||
static weakObject: Type<any>; | ||
// TODO: add autoremove/autodelete when nulled out | ||
static ref: Type<Entity | undefined>; | ||
@@ -393,3 +398,6 @@ static backrefs: (type?: ComponentType<any>, fieldName?: string, trackDeletedBackrefs?: boolean) => Type<Entity[]>; | ||
} | ||
interface ComponentType<C> { | ||
interface Component { | ||
__invalid?: boolean; | ||
} | ||
interface ComponentType<C extends Component> { | ||
new (): C; | ||
@@ -416,4 +424,4 @@ schema?: Schema; | ||
readonly elastic: boolean; | ||
readonly readonlyInstance: C; | ||
readonly writableInstance: C; | ||
readonlyInstance: C; | ||
writableInstance: C; | ||
readonly shapeOffset: number; | ||
@@ -430,6 +438,7 @@ readonly shapeMask: number; | ||
private readonly __dispatcher; | ||
constructor(options: WorldOptions); | ||
static create(options: WorldOptions): Promise<World>; | ||
private constructor(); | ||
build(callback: (system: System) => void): void; | ||
createEntity(...initialComponents: (ComponentType<any> | any)[]): void; | ||
execute(time?: number, delta?: number): void; | ||
execute(time?: number, delta?: number): Promise<void>; | ||
control(options: ControlOptions): void; | ||
@@ -442,7 +451,7 @@ get stats(): Stats; | ||
} | ||
declare function prop<JSType>(practicalOptions: PropOptions<JSType> | Type<any> | (() => Type<any>)): (target: any, name: string) => void; | ||
declare function field<JSType>(practicalOptions: PropOptions<JSType> | Type<any> | (() => Type<any>)): (target: any, name: string) => void; | ||
declare const componentTypes: ComponentType<any>[]; | ||
declare function component(constructor: ComponentType<any>): void; | ||
declare function component(options: ComponentOptions): (constructor: ComponentType<any>) => void; | ||
export { World, Type, Entity, System, SystemType, componentTypes, component, prop, Query, ComponentType }; | ||
export { World, Type, Entity, System, SystemType, componentTypes, component, field, Query, ComponentType }; | ||
//# sourceMappingURL=perf.umd.min.d.ts.map |
@@ -1,2 +0,2 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).becsy={})}(this,(function(e){"use strict";const t=22,s=4194304,i=4194303;class r{size;bytes;constructor(e){this.size=e,this.bytes=new Uint32Array(Math.ceil(e/32))}get(e){return 0!=(this.bytes[e>>>5]&1<<(31&e))}set(e){this.bytes[e>>>5]|=1<<(31&e)}unset(e){this.bytes[e>>>5]&=~(1<<(31&e))}clear(){this.bytes.fill(0)}}const n=[];class a{maxEntries;configParamName;localProcessingAllowed;data;corral;constructor(e,t,s=!1){this.maxEntries=e,this.configParamName=t,this.localProcessingAllowed=s;const i=new SharedArrayBuffer((e+2)*Uint32Array.BYTES_PER_ELEMENT);this.data=new Uint32Array(i);const r=new SharedArrayBuffer((e+2)*Uint32Array.BYTES_PER_ELEMENT);this.corral=new Uint32Array(r)}push(e){const t=this.corral[0];t&&this.corral[t]===e||(this.corral[t+2]=e,this.corral[0]+=1)}commit(e){const t=this.corral[0];if(!t)return!0;let s=this.data[0];if(e&&(e.generation!==this.data[1]||e.index!==s||e.corralGeneration!==this.corral[1]||e.corralIndex!==this.corral[0]))return!1;const i=Math.min(t,this.maxEntries-s);for(this.data.set(this.corral.subarray(2,i+2),s+2),i<t&&this.data.set(this.corral.subarray(i+2,t+2),2),s+=t;s>=this.maxEntries;)s-=this.maxEntries,this.data[1]+=1;return this.data[0]=s,this.corral[0]=0,this.corral[1]+=1,e&&(e.index=s,e.generation=this.data[1]),!0}createPointer(e){return e?(e.index=this.data[0],e.generation=this.data[1],e.corralIndex=this.corral[0],e.corralGeneration=this.corral[1],e):{index:this.data[0],generation:this.data[1],corralIndex:this.corral[0],corralGeneration:this.corral[1]}}hasUpdatesSince(e){return!(e.index===this.data[0]&&e.generation===this.data[1]&&(e.corralGeneration===this.corral[1]?e.corralIndex===this.corral[0]:0===this.corral[0]))}processSince(e,t){let s=n;const i=t?.index??this.data[0],r=t?.generation??this.data[1];if(e.generation===r)if(e.index<i)s=[this.data,e.index+2,i+2,!1],e.index=i;else{const t=this.corral[0],i=this.corral[1];(e.corralGeneration===i?e.corralIndex<t:t)&&(s=[this.corral,e.corralIndex+2,t+2,!0],e.corralIndex=t,e.corralGeneration=i)}else s=[this.data,e.index+2,this.data.length,!1],e.index=0,e.generation=r;return s}processAndCommitSince(e){const t=this.processSince(e);return t[0]?t:this.commit(e)?n:this.processSince(e)}countSince(e,t){const s=e.index,i=t?.index??this.data[0],r=t?.generation??this.data[1];return e.index=i,e.generation=r,s===i&&e.generation===r?0:s<i?i-s:this.maxEntries-(s-i)}checkPointers(e,t){this.checkPointer(e),t&&this.checkPointer(t)}checkPointer(e){const t=this.data[0];let s=e.generation;e.index===t?s+1<this.data[1]&&this.throwCapacityExceeded():(e.index>t&&(s+=1),s!==this.data[1]&&this.throwCapacityExceeded())}throwCapacityExceeded(){throw new Error(`Log capacity exceeded, please raise ${this.configParamName} above ${this.maxEntries}`)}}class o{maxItems;configParamName;data;constructor(e,t){this.maxItems=e,this.configParamName=t,this.data=new Uint32Array(new SharedArrayBuffer((e+1)*Uint32Array.BYTES_PER_ELEMENT))}get length(){return this.data[0]}take(){const e=this.data[0]--;return this.data[e]}refill(e){if(!e.length)return;const t=this.length,s=t+e.length;this.data.set(e,t+1),this.data[0]=s}fillWithDescendingIntegers(e){const t=this.length;for(let s=this.data.length-1;s>t;s--)this.data[s]=e++;this.data[0]=this.data.length-1}}const h=new TextEncoder,c=new TextDecoder;function d(e){throw new Error(`Component is not writable; use entity.write(${e.type.name}) to acquire a writable version`)}class l{defaultValue;constructor(e){this.defaultValue=e}static boolean;static uint8;static int8;static uint16;static int16;static uint32;static int32;static float32;static float64;static staticString;static dynamicString;static object;static weakObject;static ref;static backrefs}class f extends l{NumberArray;constructor(e){super(0),this.NumberArray=e}defineElastic(e,t){let s,i;t.updateBuffer=()=>{const r=e.capacity*this.NumberArray.BYTES_PER_ELEMENT,n=t.buffer?.byteLength!==r;(n||t.buffer!==s)&&(s=n?new SharedArrayBuffer(r):t.buffer,i=new this.NumberArray(s),n&&t.buffer&&i.set(new this.NumberArray(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>i[e.index],set(t){i[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>i[e.index],set(t){d(e)}})}defineFixed(e,t){const s=e.capacity*this.NumberArray.BYTES_PER_ELEMENT,i=new SharedArrayBuffer(s),r=new this.NumberArray(i);t.buffer=i,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>r[e.index],set(t){r[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>r[e.index],set(t){d(e)}})}}class u extends l{choices;choicesIndex=new Map;TypedArray;constructor(e){if(super(e[0]),this.choices=e,!e?.length)throw new Error("No choices specified for Type.staticString");e.length<256?this.TypedArray=Uint8Array:e.length<65536?this.TypedArray=Uint16Array:this.TypedArray=Uint32Array;for(let t=0;t<e.length;t++)this.choicesIndex.set(e[t],t)}defineElastic(e,t){let s,i;const r=this.choices,n=this.choicesIndex;t.updateBuffer=()=>{const r=e.capacity*this.TypedArray.BYTES_PER_ELEMENT,n=t.buffer?.byteLength!==r;(n||t.buffer!==s)&&(s=n?new SharedArrayBuffer(r):t.buffer,i=new this.TypedArray(s),n&&t.buffer&&i.set(new this.TypedArray(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=i[e.index],s=r[t];if(void 0===s)throw new Error(`Invalid static string index: ${t}`);return s},set(t){const s=n.get(t);if(void 0===s)throw new Error(`Static string not in set: "${t}"`);i[e.index]=s}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=i[e.index],s=r[t];if(void 0===s)throw new Error(`Invalid static string index: ${t}`);return s},set(t){d(e)}})}defineFixed(e,t){const s=this.choices,i=this.choicesIndex,r=e.capacity*this.TypedArray.BYTES_PER_ELEMENT,n=new SharedArrayBuffer(r),a=new this.TypedArray(n);t.buffer=n,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=a[e.index],i=s[t];if(void 0===i)throw new Error(`Invalid static string index: ${t}`);return i},set(t){const s=i.get(t);if(void 0===s)throw new Error(`Static string not in set: "${t}"`);a[e.index]=s}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=a[e.index],i=s[t];if(void 0===i)throw new Error(`Invalid static string index: ${t}`);return i},set(t){d(e)}})}}class y extends l{maxUtf8Length;lengthsStride;bytesStride;constructor(e){super(""),this.maxUtf8Length=e+e%2,this.lengthsStride=e/2+1,this.bytesStride=this.maxUtf8Length+2}defineElastic(e,t){let s,i,r;const n=this.maxUtf8Length,a=this.lengthsStride,o=this.bytesStride;t.updateBuffer=()=>{const n=e.capacity*(this.maxUtf8Length+Uint16Array.BYTES_PER_ELEMENT),a=t.buffer?.byteLength!==n;(a||t.buffer!==s)&&(s=a?new SharedArrayBuffer(n):t.buffer,i=new Uint16Array(s),r=new Uint8Array(s),a&&t.buffer&&r.set(new Uint8Array(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=i[e.index*a];return c.decode(new Uint8Array(r.buffer,e.index*o+2,t))},set(t){const s=h.encode(t);if(s.byteLength>n)throw new Error(`Dynamic string length > ${n} after encoding: ${t}`);i[e.index*a]=s.byteLength,r.set(s,e.index*o+2)}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=i[e.index*a];return c.decode(new Uint8Array(r.buffer,e.index*o+2,t))},set(t){d(e)}})}defineFixed(e,t){const s=this.maxUtf8Length,i=this.lengthsStride,r=this.bytesStride,n=e.capacity*(this.maxUtf8Length+Uint16Array.BYTES_PER_ELEMENT),a=new SharedArrayBuffer(n),o=new Uint16Array(a),l=new Uint8Array(a);t.buffer=a,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=o[e.index*i];return c.decode(new Uint8Array(l.buffer,e.index*r+2,t))},set(t){const n=h.encode(t);if(n.byteLength>s)throw new Error(`Dynamic string length > ${s} after encoding: ${t}`);o[e.index*i]=n.byteLength,l.set(n,e.index*r+2)}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=o[e.index*i];return c.decode(new Uint8Array(l.buffer,e.index*r+2,t))},set(t){d(e)}})}}const g=2**31;const p=[];class m extends l{type;fieldName;trackDeletedBackrefs;constructor(e,t,s){super(p),this.type=e,this.fieldName=t,this.trackDeletedBackrefs=s}defineElastic(e,t){const s=this.fieldName?this.type?.__binding.fields.find((e=>e.name===this.fieldName)):void 0;this.trackDeletedBackrefs;const i=e.dispatcher.indexer;i.registerSelector();const r=i.registerSelector(e.type,this.type,s?.seq,this.trackDeletedBackrefs),n={enumerable:!0,configurable:!0,get:()=>i.getBackrefs(e.entityId,r),set(e){}};Object.defineProperty(e.writableInstance,t.name,n),Object.defineProperty(e.readonlyInstance,t.name,n)}defineFixed(e,t){this.defineElastic(e,t)}}l.boolean=new class extends l{constructor(){super(!1)}defineElastic(e,t){let s,i;t.updateBuffer=()=>{const r=t.buffer?.byteLength!==e.capacity;(r||t.buffer!==s)&&(s=r?new SharedArrayBuffer(e.capacity):t.buffer,i=new Uint8Array(s),r&&t.buffer&&i.set(new Uint8Array(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>Boolean(i[e.index]),set(t){i[e.index]=t?1:0}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>Boolean(i[e.index]),set(t){d(e)}})}defineFixed(e,t){const s=new SharedArrayBuffer(e.capacity),i=new Uint8Array(s);t.buffer=s,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>Boolean(i[e.index]),set(t){i[e.index]=t?1:0}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>Boolean(i[e.index]),set(t){d(e)}})}},l.uint8=new f(Uint8Array),l.int8=new f(Int8Array),l.uint16=new f(Uint16Array),l.int16=new f(Int16Array),l.uint32=new f(Uint32Array),l.int32=new f(Int32Array),l.float32=new f(Float32Array),l.float64=new f(Float64Array),l.staticString=e=>new u(e),l.dynamicString=e=>new y(e),l.ref=new class extends l{constructor(){super(void 0)}defineElastic(e,t){let s,r;const n=e.dispatcher.indexer,a=e.dispatcher.registry,o=a.pool;n.registerSelector(),t.updateBuffer=()=>{const i=e.capacity*Int32Array.BYTES_PER_ELEMENT,n=t.buffer?.byteLength!==i;if(n||t.buffer!==s){if(s=n?new SharedArrayBuffer(i):t.buffer,r=new Int32Array(s),n&&t.buffer){const e=new Int32Array(t.buffer);r.set(e),r.fill(-1,e.length)}else r.fill(-1);t.buffer=s}},t.updateBuffer(),t.clearRef=(s,a,o)=>{const h=r[e.index]&i,c=void 0!==a;c&&h!==a||(s?c&&(r[e.index]=-1):r[e.index]|=g,n.trackRefChange(e.entityId,e.type,t.seq,void 0,h,-1,s))},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=r[e.index];if(!(-1===t||t&g&&!a.includeRecentlyDeleted))return o.borrowTemporarily(t&i)},set(s){const i=r[e.index],a=s?.__id??-1;i!==a&&(r[e.index]=a,n.trackRefChange(e.entityId,e.type,t.seq,void 0,i,a,!0))}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=r[e.index];if(!(-1===t||t&g&&!a.includeRecentlyDeleted))return o.borrowTemporarily(t&i)},set(t){d(e)}})}defineFixed(e,t){const s=e.capacity*Int32Array.BYTES_PER_ELEMENT,r=new SharedArrayBuffer(s),n=new Int32Array(r);n.fill(-1),t.buffer=r;const a=e.dispatcher.indexer,o=e.dispatcher.registry,h=o.pool;a.registerSelector(),t.clearRef=(s,r,o)=>{const h=n[e.index]&i,c=void 0!==r;c&&h!==r||(s?c&&(n[e.index]=-1):n[e.index]|=g,a.trackRefChange(e.entityId,e.type,t.seq,void 0,h,-1,s))},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=n[e.index];if(!(-1===t||t&g&&!o.includeRecentlyDeleted))return h.borrowTemporarily(t&i)},set(s){const i=n[e.index],r=s?.__id??-1;i!==r&&(n[e.index]=r,a.trackRefChange(e.entityId,e.type,t.seq,void 0,i,r,!0))}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=n[e.index];if(!(-1===t||t&g&&!o.includeRecentlyDeleted))return h.borrowTemporarily(t&i)},set(t){d(e)}})}},l.backrefs=(e,t,s=!1)=>new m(e,t,s),l.object=new class extends l{constructor(){super(void 0)}defineElastic(e,t){const s=[];t.localBuffer=s,t.updateBuffer=()=>{},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>s[e.index],set(t){s[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>s[e.index],set(t){d(e)}})}defineFixed(e,t){const s=new Array(e.capacity);t.localBuffer=s,t.updateBuffer=()=>{},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>s[e.index],set(t){s[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>s[e.index],set(t){d(e)}})}},l.weakObject=new class extends l{finalizers;constructor(){super(void 0)}defineElastic(e,t){const s=[];t.localBuffer=s,t.updateBuffer=()=>{};const i=this.initFinalizers(e);Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=s[e.index];return null==t?t:t.deref()},set(r){if(null!=r){const s=new WeakRef(r);i?.register(r,{type:e.type,field:t,weakRef:s,id:e.entityId,index:e.index}),r=s}s[e.index]=r}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=s[e.index];return null==t?t:t.deref()},set(t){d(e)}})}defineFixed(e,t){const s=new Array(e.capacity);t.localBuffer=s,t.updateBuffer=()=>{};const i=this.initFinalizers(e);Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=s[e.index];return null==t?t:t.deref()},set(r){if(null!=r){const s=new WeakRef(r);i?.register(r,{type:e.type,field:t,weakRef:s,id:e.entityId,index:e.index}),r=s}s[e.index]=r}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=s[e.index];return null==t?t:t.deref()},set(t){d(e)}})}initFinalizers(e){if(!e.trackedWrites)return;if(this.finalizers)return this.finalizers;const t=e.dispatcher;return t.writeLog&&"undefined"!=typeof FinalizationRegistry?(this.finalizers=new FinalizationRegistry((({type:e,field:s,weakRef:i,id:r,index:n})=>{s.localBuffer?.[n]===i&&t.registry.trackWrite(r,e)})),this.finalizers):void 0}};class _{type;fields;dispatcher;capacity;storage;elastic;readonlyInstance;writableInstance;shapeOffset;shapeMask;refFields;trackedWrites=!1;internallyIndexed=!1;entityId=0;index=0;constructor(e,t,s,i,r,n){this.type=e,this.fields=t,this.dispatcher=s,this.capacity=i,this.storage=r,this.elastic=n,this.readonlyInstance=new e,this.writableInstance=new e,this.shapeOffset=e.id>>5,this.shapeMask=1<<(31&e.id),this.refFields=t.filter((e=>e.type===l.ref))}}class b{maxEntities;binding;fields;index;spares;constructor(e,t,s){this.maxEntities=e,this.binding=t,this.fields=s,this.growSpares(),this.growCapacity()}acquireIndex(e){let t=this.index[e];return-1===t&&(this.spares[3]>0?t=this.spares[4+--this.spares[3]]:(this.spares[1]===this.spares[2]&&(this.binding.capacity=Math.min(this.maxEntities,2*this.binding.capacity),this.growCapacity()),t=this.spares[1]++),this.index[e]=t),t}releaseIndex(e){this.spares[3]===this.spares.length-4&&this.growSpares(),this.spares[4+this.spares[3]++]=this.index[e],this.index[e]=-1}growCapacity(){const e=this.ArrayType,t=e.BYTES_PER_ELEMENT!==this.spares?.[0];if(!this.index||t){const t=new e(new SharedArrayBuffer(this.maxEntities*e.BYTES_PER_ELEMENT));this.index?t.set(this.index):t.fill(-1),this.index=t}if(this.spares&&t){const t=new e(new SharedArrayBuffer(this.spares.length*e.BYTES_PER_ELEMENT));t.set(this.spares),t[0]=e.BYTES_PER_ELEMENT,this.spares=t}if(this.spares[2]=this.binding.capacity,this.binding.elastic)for(const e of this.fields)e.updateBuffer()}growSpares(){const e=this.ArrayType,t=this.spares?Math.min(this.maxEntities,2*(this.spares.length-4)):8,s=new e(new SharedArrayBuffer((4+t)*e.BYTES_PER_ELEMENT));this.spares?s.set(this.spares):(s[0]=e.BYTES_PER_ELEMENT,s[2]=this.binding.capacity),this.spares=s}get ArrayType(){const e=this.binding.capacity;return e<=127?Int8Array:e<=32767?Int16Array:Int32Array}}function E(e,t,s){const i=function(e){const t=e.schema,s=[];if(t){let e=0;for(const i in t){let r=t[i];(r instanceof l||"function"==typeof r)&&(r={type:r}),"function"==typeof r.type&&(r.type=r.type()),"default"in r||(r.default=r.type.defaultValue),s.push({name:i,seq:e++,type:r.type,default:r.default})}}return s}(t),r=i.length?t.options?.storage??s.defaultComponentStorage:"sparse",n="sparse"===r?s.maxEntities:Math.min(s.maxEntities,t.options?.capacity??0),a=t.options?.initialCapacity??8;t.id=e;const o=new _(t,i,s,n||a,r,!n);t.__binding=o}function w(e){const t=e.__binding;for(const e of t.fields)t.elastic?e.type.defineElastic(t,e):e.type.defineFixed(t,e);switch(t.storage){case"sparse":e.__bind=(e,s)=>(t.entityId=e,t.index=e,s?t.writableInstance:t.readonlyInstance),e.__allocate=e=>(t.entityId=e,t.index=e,t.writableInstance);break;case"packed":{const s=new b(t.dispatcher.maxEntities,t,t.fields);e.__bind=(e,i)=>(t.entityId=e,t.index=s.index[e],i?t.writableInstance:t.readonlyInstance),e.__allocate=e=>(t.entityId=e,t.index=s.acquireIndex(e),t.writableInstance),e.__free=e=>{s.releaseIndex(e)};break}case"compact":throw new Error("Not yet implemented")}}class x{__registry;__id;constructor(e){this.__registry=e}add(e,t){return this.__registry.setShape(this.__id,e),function(e,t,s){const i=e.__allocate(t);for(const t of e.__binding.fields)i[t.name]=s?.[t.name]??t.default}(e,this.__id,t),this}addAll(...e){for(let t=0;t<e.length;t++){const s=e[t];let i=e[t+1];"function"==typeof i?i=void 0:t++,this.add(s,i)}return this}remove(e){this.__registry.clearShape(this.__id,e)}removeAll(...e){for(const t of e)this.remove(t)}has(e){return this.__registry.hasShape(this.__id,e,!0)}read(e){return e.__bind(this.__id,!1)}write(e){return e.__binding.trackedWrites&&this.__registry.trackWrite(this.__id,e),e.__bind(this.__id,!0)}delete(){this.__registry.Alive;for(const e of this.__registry.types)this.__registry.hasShape(this.__id,e,!1)&&this.__registry.clearShape(this.__id,e);this.__registry.queueDeletion(this.__id),this.__registry.dispatcher.indexer.clearAllRefs(this.__id,!1)}__checkMask(e,t){R(e,this.__registry.executingSystem,t)}__checkHas(e,t){if(!this.__registry.hasShape(this.__id,e,t))throw new Error(`Entity doesn't have a ${e.name} component`)}}function R(e,t,s){!function(e){if(!e.__binding)throw new Error(`Component ${e.name} not defined; add to world defs`)}(e);const i=s?t?.rwMasks.write:t?.rwMasks.read;if(!(!i||0!=((i[e.__binding.shapeOffset]??0)&e.__binding.shapeMask)))throw new Error(`System didn't mark component ${e.name} as ${s?"writable":"readable"}`)}function S(e,t){const s=t.__binding.shapeOffset;s>=e.length&&(e.length=s+1,e.fill(0,e.length,s)),e[s]|=t.__binding.shapeMask}class P{pool;entities=[];constructor(e){this.pool=e}add(e){this.entities.push(this.pool.borrowTemporarily(e))}clear(){this.entities.length&&this.entities.splice(0,1/0)}}class v{pool;entities=[];lookupTable;constructor(e,t){this.pool=e,this.lookupTable=new Int32Array(t),this.lookupTable.fill(-1)}add(e){const t=this.entities.push(this.pool.borrow(e))-1;this.lookupTable[e]=t}remove(e){const t=this.lookupTable[e];if(t<0)throw new Error("Internal error, entity not in list");this.pool.return(e),this.lookupTable[e]=-1;const s=this.entities.pop();t<this.entities.length&&(this.entities[t]=s,this.lookupTable[s.__id]=t)}has(e){return this.lookupTable[e]>=0}clear(){for(const e of this.entities)this.pool.return(e.__id);this.entities=[],this.lookupTable.fill(-1)}}var k;!function(e){e[e.all=1]="all",e[e.added=2]="added",e[e.removed=4]="removed",e[e.changed=8]="changed",e[e.addedOrChanged=16]="addedOrChanged",e[e.changedOrRemoved=32]="changedOrRemoved",e[e.addedChangedOrRemoved=64]="addedChangedOrRemoved"}(k||(k={}));const I=k.added|k.removed|k.changed|k.addedOrChanged|k.changedOrRemoved|k.addedChangedOrRemoved,T=k.changed|k.addedOrChanged|k.changedOrRemoved|k.addedChangedOrRemoved;class L{query;system;results={};flavors=0;withMask;withoutMask;trackMask;hasTransientResults;hasChangedResults;currentEntities;changedEntities;constructor(e,t){this.query=e,this.system=t,e.__results=this.results,e.__systemName=t.name}complete(){const e=this.system.dispatcher;this.hasTransientResults=Boolean(this.flavors&I),this.hasChangedResults=Boolean(this.flavors&T),this.flavors&k.all?this.results.all=new v(e.registry.pool,e.maxEntities):this.currentEntities=new r(e.maxEntities),this.hasTransientResults&&this.allocateTransientResultLists(),this.flavors&&this.system.shapeQueries.push(this),this.hasChangedResults&&(this.changedEntities=new r(e.maxEntities),this.system.writeQueries.push(this))}allocateTransientResultLists(){this.flavors&k.added&&this.allocateResult("added"),this.flavors&k.removed&&this.allocateResult("removed"),this.flavors&k.changed&&this.allocateResult("changed"),this.flavors&k.addedOrChanged&&this.allocateResult("addedOrChanged"),this.flavors&k.changedOrRemoved&&this.allocateResult("changedOrRemoved"),this.flavors&k.addedChangedOrRemoved&&this.allocateResult("addedChangedOrRemoved")}allocateResult(e){const t=this.system.dispatcher;this.results[e]=new P(t.registry.pool)}clearTransientResults(){this.hasTransientResults&&(this.results.added?.clear(),this.results.removed?.clear(),this.results.changed?.clear(),this.results.addedOrChanged?.clear(),this.results.changedOrRemoved?.clear(),this.results.addedChangedOrRemoved?.clear(),this.changedEntities?.clear())}clearAllResults(){this.clearTransientResults(),this.results.all?.clear()}handleShapeUpdate(e){const t=this.system.dispatcher.registry,s=this.results.all?.has(e)??this.currentEntities.get(e),i=t.matchShape(e,this.withMask,this.withoutMask);i&&!s?(this.currentEntities?.set(e),this.results.all?.add(e),this.results.added?.add(e),this.results.addedOrChanged?.add(e),this.results.addedChangedOrRemoved?.add(e)):!i&&s&&(this.currentEntities?.unset(e),this.results.all?.remove(e),this.results.removed?.add(e),this.results.changedOrRemoved?.add(e),this.results.addedChangedOrRemoved?.add(e))}handleWrite(e,t,s){!this.changedEntities.get(e)&&(this.trackMask[t]??0)&s&&(this.changedEntities.set(e),this.results.changed?.add(e),this.results.addedOrChanged?.add(e),this.results.changedOrRemoved?.add(e),this.results.addedChangedOrRemoved?.add(e))}}class A{__callback;__userQuery;__query;__system;__lastTypes;constructor(e,t){this.__callback=e,this.__userQuery=t}__build(e){try{this.__system=e,this.__query=new L(this.__userQuery,e),this.__callback(this),this.__query.complete()}catch(t){throw t.message=`Failed to build query in system ${e.name}: ${t.message}`,t}}get and(){return this}get but(){return this}get also(){return this}get all(){return this.__query.flavors|=k.all,this}get added(){return this.__query.flavors|=k.added,this}get removed(){return this.__query.flavors|=k.removed,this}get changed(){return this.__query.flavors|=k.changed,this}get addedOrChanged(){return this.__query.flavors|=k.addedOrChanged,this}get changedOrRemoved(){return this.__query.flavors|=k.changedOrRemoved,this}get addedChangedOrRemoved(){return this.__query.flavors|=k.addedChangedOrRemoved,this}with(...e){return this.set(this.__system.rwMasks.read,e),this.set("withMask"),this}without(...e){return this.set(this.__system.rwMasks.read,e),this.set("withoutMask",e),this}using(...e){return this.set(this.__system.rwMasks.read,e),this}get track(){this.set("trackMask");for(const e of this.__lastTypes)e.__binding.trackedWrites=!0;return this}get read(){return this}get write(){return this.set(this.__system.rwMasks.write),this}set(e,t,s){if(e){if(t||(t=this.__lastTypes),!t)throw new Error("No component type to apply query modifier to");if(this.__lastTypes=t,"string"==typeof e){if(s&&this.__query[e])throw new Error(`Only one ${s} allowed`);this.__query[e]||(this.__query[e]=[]),e=this.__query[e]}else if(s&&e.some((e=>0!==e)))throw new Error(`Only one ${s} allowed`);for(const s of t)S(e,s)}}}class O{__results;__systemName;get all(){return this.__results.all.entities}get added(){return this.__results.added.entities}get removed(){return this.__results.removed.entities}get changed(){return this.__results.changed.entities}get addedOrChanged(){return this.__results.addedOrChanged.entities}get changedOrRemoved(){return this.__results.changedOrRemoved.entities}get addedChangedOrRemoved(){return this.__results.addedChangedOrRemoved.entities}__checkList(e){if(!this.__results[e])throw new Error(`Query '${e}' not configured, please add .${e} to your query definition in system ${this.__systemName}`)}}var C,B;!function(e){e[e.RUNNING=0]="RUNNING",e[e.SUSPENDED=1]="SUSPENDED",e[e.STOPPED=2]="STOPPED"}(C||(C={}));class N{static __system=!0;__queryBuilders=[];__dispatcher;time;delta;get name(){return this.constructor.name}query(e){const t=new O,s=new A(e,t);return this.__queryBuilders.push(s),t}createEntity(...e){return this.__dispatcher.createEntity(e)}accessRecentlyDeletedData(e=!0){this.__dispatcher.registry.includeRecentlyDeleted=e}}class F{system;dispatcher;rwMasks={read:[],write:[]};shapeQueries=[];writeQueries=[];hasWriteQueries;processedEntities;shapeLogPointer;writeLogPointer;state=C.RUNNING;get name(){return this.system.name}constructor(e,t){this.system=e,this.dispatcher=t,e.__dispatcher=t,this.shapeLogPointer=t.shapeLog.createPointer(),this.writeLogPointer=t.writeLog?.createPointer(),this.processedEntities=new r(t.maxEntities);for(const t of e.__queryBuilders)t.__build(this);e.__queryBuilders=null,this.hasWriteQueries=!!this.writeQueries.length}execute(e,t){this.state===C.RUNNING&&(this.system.time=e,this.system.delta=t,this.runQueries(),this.system.execute())}runQueries(){const e=this.dispatcher.shapeLog.hasUpdatesSince(this.shapeLogPointer),t=this.hasWriteQueries&&this.dispatcher.writeLog.hasUpdatesSince(this.writeLogPointer);if(e||t){this.processedEntities.clear();for(const e of this.shapeQueries)e.clearTransientResults();e&&this.__updateShapeQueries(),t&&this.__updateWriteQueries()}}__updateShapeQueries(){const e=this.dispatcher.shapeLog;let t,s,i;for(;[t,s,i]=e.processSince(this.shapeLogPointer),t;)for(let e=s;e<i;e++){const s=t[e];if(!this.processedEntities.get(s)){this.processedEntities.set(s);for(const e of this.shapeQueries)e.handleShapeUpdate(s)}}}__updateWriteQueries(){const e=this.dispatcher.writeLog;let s,r,n;for(;[s,r,n]=e.processSince(this.writeLogPointer),s;)for(let e=r;e<n;e++){const r=s[e],n=r&i;if(!this.processedEntities.get(n)){const e=r>>>t;for(const t of this.writeQueries)t.handleWrite(n,e>>5,1<<(31&e))}}}stop(){if(this.state!==C.STOPPED){this.state=C.STOPPED;for(const e of this.shapeQueries)e.clearAllResults()}}restart(){if(this.state===C.STOPPED){const e=this.dispatcher.registry,t=e.Alive;for(let s=0;s<this.dispatcher.maxEntities;s++)if(e.hasShape(s,t,!1))for(const e of this.shapeQueries)e.handleShapeUpdate(s);for(const e of this.shapeQueries)e.clearTransientResults();this.dispatcher.shapeLog.createPointer(this.shapeLogPointer),this.dispatcher.writeLog?.createPointer(this.writeLogPointer)}this.state=C.RUNNING}suspend(){this.state===C.STOPPED&&this.restart(),this.state=C.SUSPENDED}}class U{registry;borrowed;borrowCounts;spares=[];temporarilyBorrowedIds=[];constructor(e,t){this.registry=e,this.borrowed=Array.from({length:t}),this.borrowCounts=new Int32Array(t)}borrow(e){this.borrowCounts[e]+=1;let t=this.borrowed[e];return t||(t=this.borrowed[e]=this.spares.pop()??new x(this.registry),t.__id=e),t}borrowTemporarily(e){const t=this.borrow(e);return this.temporarilyBorrowedIds.push(e),t}returnTemporaryBorrows(){for(const e of this.temporarilyBorrowedIds)this.return(e);this.temporarilyBorrowedIds.splice(0,1/0)}return(e){--this.borrowCounts[e]<=0&&(this.spares.push(this.borrowed[e]),this.borrowed[e]=void 0)}}class M{types;dispatcher;stride;shapes;staleShapes;entityIdPool;pool;executingSystem;includeRecentlyDeleted=!1;deletionLog;prevDeletionPointer;oldDeletionPointer;removalLog;prevRemovalPointer;oldRemovalPointer;Alive=class{};constructor(e,t,s,i,r){this.types=i,this.dispatcher=r,this.stride=Math.ceil(i.length/32);const n=e*this.stride*4;this.shapes=new Uint32Array(new SharedArrayBuffer(n)),this.staleShapes=new Uint32Array(new SharedArrayBuffer(n)),this.entityIdPool=new o(e,"maxEntities"),this.entityIdPool.fillWithDescendingIntegers(0),this.pool=new U(this,e),this.deletionLog=new a(t,"maxLimboEntities"),this.prevDeletionPointer=this.deletionLog.createPointer(),this.oldDeletionPointer=this.deletionLog.createPointer(),this.removalLog=new a(s,"maxLimboComponents"),this.prevRemovalPointer=this.removalLog.createPointer(),this.oldRemovalPointer=this.removalLog.createPointer()}initializeComponentTypes(){this.types.unshift(this.Alive);let e=0;for(const t of this.types)E(e++,t,this.dispatcher);for(const e of this.types)w(e)}createEntity(e){const t=this.entityIdPool.take(),s=t*this.stride;this.shapes[s]=1,this.stride>1&&this.shapes.fill(0,s+1,s+this.stride);const i=this.pool.borrowTemporarily(t);return e&&i.addAll(...e),i}queueDeletion(e){this.deletionLog.push(e)}flush(){this.includeRecentlyDeleted=!1,this.pool.returnTemporaryBorrows(),this.deletionLog.commit(),this.removalLog.commit()}processEndOfFrame(){this.processDeletionLog(),this.processRemovalLog()}processDeletionLog(){this.deletionLog.commit();let e,t,s,i=0;for(;[e,t,s]=this.deletionLog.processSince(this.oldDeletionPointer,this.prevDeletionPointer),e;){for(let i=t;i<s;i++)this.dispatcher.indexer.clearAllRefs(e[i],!0);const r=e.subarray(t,s);this.entityIdPool.refill(r),i+=r.length}this.deletionLog.createPointer(this.prevDeletionPointer)}processRemovalLog(){let e,s,r;for(this.removalLog.commit();[e,s,r]=this.removalLog.processSince(this.oldRemovalPointer,this.prevRemovalPointer),e;)for(let n=s;n<r;n++){const s=e[n],r=s&i,a=s>>>t,o=this.types[a],h=r*this.stride+o.__binding.shapeOffset,c=o.__binding.shapeMask;0==(this.shapes[h]&c)&&(this.staleShapes[h]&=~c,this.clearRefs(r,o,!0),o.__free?.(r))}this.removalLog.createPointer(this.prevRemovalPointer)}hasShape(e,t,s){const i=e*this.stride+t.__binding.shapeOffset,r=t.__binding.shapeMask;return 0!=(this.shapes[i]&r)||!(!s||!this.includeRecentlyDeleted||0==(this.staleShapes[i]&r))}setShape(e,t){const s=e*this.stride+t.__binding.shapeOffset,i=t.__binding.shapeMask;this.shapes[s]|=i,this.staleShapes[s]|=i,this.dispatcher.shapeLog.push(e)}clearShape(e,s){const i=this.clearRefs(e,s,!1);(s.__free||i)&&this.removalLog.push(e|s.id<<t),this.shapes[e*this.stride+s.__binding.shapeOffset]&=~s.__binding.shapeMask,this.dispatcher.shapeLog.push(e)}trackWrite(e,s){this.dispatcher.writeLog.push(e|s.id<<t)}clearRefs(e,t,s){const i=!!t.__binding.refFields.length;if(i){t.__bind(e,!0);for(const e of t.__binding.refFields)e.clearRef(s)}return i}matchShape(e,t,s){const i=e*this.stride;if(t)for(let e=0;e<t.length;e++){const s=t[e];if((this.shapes[i+e]&s)!==s)return!1}if(s)for(let e=0;e<s.length;e++){const t=s[e];if(0!=(this.shapes[i+e]&t))return!1}return!0}}!function(e){e[e.REFERENCE=0]="REFERENCE",e[e.UNREFERENCE=1073741824]="UNREFERENCE",e[e.RELEASE=2147483648]="RELEASE"}(B||(B={}));const D=B.REFERENCE|B.UNREFERENCE|B.RELEASE;class q{targetEntityId;selector;dispatcher;entities=[];tags;entityIndex;clearing=!1;registry;constructor(e,t,s){this.targetEntityId=e,this.selector=t,this.dispatcher=s;const i=t.sourceType?.__binding;t.matchType&&(t.matchSeq||1===i.refFields.length)&&!i.internallyIndexed||(this.tags=[]),this.registry=s.registry}clearAllRefs(e){this.clearing=!0;for(let t=0;t<this.entities.length;t++){const s=this.entities[t].__id,i=this.tags[t];if("number"==typeof i)this.clearRef(s,i,e);else for(const t of i)this.clearRef(s,t,e)}this.entities=[],this.tags=[],this.entityIndex=void 0,this.clearing=!1}clearRef(e,t,s){const i=511&t,r=t>>>9&127,n=t>>>16,a=this.registry.types[i];a.__bind(e,!0),a.__binding.fields[r].clearRef(s,this.targetEntityId,n)}trackReference(e,t,s,i,r){let n=this.getEntityIndex(e);void 0===n&&(n=this.addEntity(e,r)),this.addTag(n,this.makeTag(t,s,i))}trackUnreference(e,t,s,i,r){if(this.clearing)return;const n=this.getEntityIndex(e);this.removeTag(n,this.makeTag(t,s,i))&&this.removeEntity(n,e,r)}getEntityIndex(e){if(this.entityIndex)return this.entityIndex[e];const t=this.entities.findIndex((t=>t.__id===e));return t>=0?t:void 0}indexEntities(){this.entityIndex=new Array(this.dispatcher.maxEntities);for(let e=0;e<this.entities.length;e++)this.entityIndex[this.entities[e].__id]=e}addTag(e,t){if(!this.tags)return;const s=this.tags[e];if(void 0===s)this.tags[e]=t;else if("number"==typeof s)this.tags[e]=[s,t];else if(Array.isArray(s))if(s.length>=1e3){(this.tags[e]=new Set(s)).add(t)}else s.push(t);else s.add(t)}removeTag(e,t){if(!this.tags)return!0;const s=this.tags[e];if("number"==typeof s)return delete this.tags[e],!0;if(Array.isArray(s)){const e=s.indexOf(t);return s.splice(e,1),!this.tags.length}return s.delete(t),!s.size}makeTag(e,t,s){return e|t<<9|(void 0===s?0:s<<16)}addEntity(e,t){const s=this.entities.length;return this.entities.push(this.registry.pool.borrow(e)),this.entityIndex?this.entityIndex[e]=s:s>100&&this.indexEntities(),t&&this.trackBackrefsChange(),s}removeEntity(e,t,s){this.registry.pool.return(t);const i=this.entities.pop();this.entityIndex&&delete this.entityIndex[e],this.entities.length>e&&(this.entities[e]=i,this.entityIndex&&(this.entityIndex[i.__id]=e)),s&&this.trackBackrefsChange()}trackBackrefsChange(){for(const e of this.selector.targetTypes)e.__binding.trackedWrites&&this.registry.trackWrite(this.targetEntityId,e)}checkWriteMask(){const e=this.registry.executingSystem;for(const t of this.selector.targetTypes)R(t,e,!0)}}class j{dispatcher;maxRefChangesPerFrame;refLog;refLogPointer;refLogStatsPointer;selectorIdsBySourceKey=new Map;selectors=[];trackers=new Map;registry;constructor(e,t){this.dispatcher=e,this.maxRefChangesPerFrame=t,this.registry=e.registry}processEndOfFrame(){this.flush()}registerSelector(e,t,s,i=!1){this.refLog||(this.refLog=new a(this.maxRefChangesPerFrame,"maxRefChangesPerFrame",!0),this.refLogPointer=this.refLog.createPointer(),this.refLogStatsPointer=this.refLog.createPointer());const r=t?void 0===s?-2-t.id:t.id|s<<9:-1;let n=this.selectorIdsBySourceKey.get(r);if(void 0===n){this.selectors.length||(i=!0);const a={id:this.selectors.length,targetTypes:e?[e]:[],sourceType:t,matchType:!!t,matchSeq:void 0!==s,sourceTypeId:t?.id,sourceSeq:s,trackStale:i};this.selectors.push(a),n=a.id,this.selectorIdsBySourceKey.set(r,n)}else{const t=this.selectors[n];t.trackStale=t.trackStale||i,e&&t.targetTypes.push(e)}return n}getBackrefs(e,t=0){const s=this.selectors[t];return this.getOrCreateTracker(s,e,this.registry.includeRecentlyDeleted).entities}trackRefChange(e,t,s,i,r,n,a){-1!==r&&this.pushRefLogEntry(e,t,s,i,r,a?B.RELEASE:B.UNREFERENCE),-1!==n&&this.pushRefLogEntry(e,t,s,i,n,B.REFERENCE)}clearAllRefs(e,t){this.selectors.length&&this.getTracker(this.selectors[0],e,t)?.clearAllRefs(t)}pushRefLogEntry(e,s,i,r,n,a){const o=void 0!==r;this.refLog.push(e|s.id<<t),this.refLog.push(n|i<<t|a|(o?2**29:0)),o&&this.refLog.push(r),this.processEntry(e,s.id,i,r,n,a,!0)}getOrCreateTracker(e,s,i){let r,n=this.getTracker(e,s,i);return n||(n=new q(s,e,this.dispatcher),this.trackers.set(s|e.id<<t,n),e.trackStale&&(r=new q(s,e,this.dispatcher),this.trackers.set(s|e.id<<t|2**31,r)),i?r:n)}getTracker(e,s,i){return this.trackers.get(s|e.id<<t|(i?2**31:0))}flush(){if(this.refLog)for(;;){const[e,s,r,n]=this.refLog.processAndCommitSince(this.refLogPointer);if(!e)break;if(!n)for(let n=s;n<r;n+=2){const s=e[n],r=e[n+1],a=s&i,o=s>>>t,h=r&i,c=r>>>t&127,d=(r&D)>>>30,l=0!=(r&2**29),f=l?e[n+2]:void 0;l&&(n+=1),this.processEntry(a,o,c,f,h,d,!1)}}}processEntry(e,t,s,i,r,n,a){for(let o=0;o<this.selectors.length;o++){const h=this.selectors[o];if(!(h.matchType&&h.sourceTypeId!==t||h.matchSeq&&h.sourceSeq!==s)){if(n===B.REFERENCE||n===B.UNREFERENCE){const o=this.getOrCreateTracker(h,r,!1);n===B.REFERENCE?o.trackReference(e,t,s,i,a):o.trackUnreference(e,t,s,i,a)}if(h.trackStale&&(n===B.REFERENCE||n===B.RELEASE)){const o=this.getOrCreateTracker(h,r,!0);n===B.REFERENCE?o.trackReference(e,t,s,i,a):o.trackUnreference(e,t,s,i,a)}}}}}const $="undefined"!=typeof window&&void 0!==window.performance?performance.now.bind(performance):Date.now.bind(Date);class Q extends N{__callback;execute(){this.__callback(this)}}class W{maxEntities;defaultComponentStorage;registry;systems;systemsByClass=new Map;lastTime=$()/1e3;executing;shapeLog;writeLog;shapeLogFramePointer;writeLogFramePointer;stats;indexer;userCallbackSystem;callbackSystem;deferredControls=new Map;constructor({defs:e,maxEntities:t=1e4,maxLimboEntities:i=Math.ceil(t/5),maxLimboComponents:r=Math.ceil(t/5),maxShapeChangesPerFrame:n=2*t,maxWritesPerFrame:o=4*t,maxRefChangesPerFrame:h=t,defaultComponentStorage:c="sparse"}){if(t>s)throw new Error("maxEntities too high, the limit is 4194304");const{componentTypes:d,systemTypes:l}=this.splitDefs(e);if(d.length>512)throw new Error("Too many component types, the limit is 512");this.maxEntities=t,this.defaultComponentStorage=c,this.shapeLog=new a(n,"maxShapeChangesPerFrame"),this.shapeLogFramePointer=this.shapeLog.createPointer(),this.registry=new M(t,i,r,d.flat(1/0),this),this.indexer=new j(this,h),this.registry.initializeComponentTypes(),this.systems=this.normalizeAndInitSystems(l),this.systems.some((e=>e.hasWriteQueries))&&(this.writeLog=new a(o,"maxWritesPerFrame"),this.writeLogFramePointer=this.writeLog.createPointer()),this.userCallbackSystem=new Q,this.callbackSystem=new F(this.userCallbackSystem,this),this.callbackSystem.rwMasks.read=void 0,this.callbackSystem.rwMasks.write=void 0}normalizeAndInitSystems(e){const t=[],s=e.flat(1/0);for(let e=0;e<s.length;e++){const i=s[e],r=new i,n=s[e+1];n&&"function"!=typeof n&&(Object.assign(r,n),e++);const a=new F(r,this);t.push(a),this.systemsByClass.set(i,a)}return t}splitDefs(e){const t=[],s=[];let i=!1;for(const r of e.flat(1/0))"function"==typeof r?(i=r.__system,(i?s:t).push(r)):(s.push(r),i=!1);return{componentTypes:t,systemTypes:s}}execute(e,t,s){this.executing=!0,void 0===e&&(e=$()/1e3),void 0===t&&(t=e-this.lastTime),this.lastTime=e;for(const i of s??this.systems)this.registry.executingSystem=i,i.execute(e,t),this.flush();this.registry.executingSystem=void 0,this.executing=!1,this.processEndOfFrame()}executeFunction(e){this.executing=!0,this.registry.executingSystem=this.callbackSystem,this.userCallbackSystem.__callback=e,this.callbackSystem.execute(0,0),this.flush(),this.registry.executingSystem=void 0,this.executing=!1,this.processEndOfFrame()}processEndOfFrame(){this.registry.processEndOfFrame(),this.indexer.processEndOfFrame(),this.processDeferredControls()}gatherFrameStats(){this.stats.frames+=1,this.stats.maxShapeChangesPerFrame=this.shapeLog.countSince(this.shapeLogFramePointer),this.stats.maxWritesPerFrame=this.writeLog?.countSince(this.writeLogFramePointer)??0}flush(){this.registry.flush(),this.indexer.flush(),this.shapeLog.commit(),this.writeLog?.commit()}createEntity(e){const t=this.registry.createEntity(e);return this.executing||this.flush(),t}control(e){this.deferRequestedRunState(e.stop,C.STOPPED),this.deferRequestedRunState(e.suspend,C.SUSPENDED),this.deferRequestedRunState(e.restart,C.RUNNING),this.executing||this.processDeferredControls()}deferRequestedRunState(e,t){for(const s of e.flat(1/0)){if(!s.__system)continue;const e=this.systemsByClass.get(s);this.deferredControls.set(e,t)}}checkControlOverlap(e){const t=new Set,s=new Set;for(const s of e.stop.flat(1/0))s.__system&&t.add(s);for(const i of e.suspend.flat(1/0))if(i.__system){if(t.has(i))throw new Error(`Request to both stop and suspend system ${i.name}`);s.add(i)}for(const i of e.restart.flat(1/0))if(i.__system){if(t.has(i))throw new Error(`Request to both stop and restart system ${i.name}`);if(s.has(i))throw new Error(`Request to both suspend and restart system ${i.name}`)}}processDeferredControls(){if(this.deferredControls.size){for(const[e,t]of this.deferredControls.entries())switch(t){case C.STOPPED:e.stop();break;case C.SUSPENDED:e.suspend();break;case C.RUNNING:e.restart()}this.deferredControls.clear()}}}const z=[];e.Entity=x,e.Query=O,e.System=N,e.Type=l,e.World=class{__dispatcher;constructor(e){this.__dispatcher=new W(e)}build(e){this.__dispatcher.executeFunction(e)}createEntity(...e){this.__dispatcher.createEntity(e)}execute(e,t){this.__dispatcher.execute(e,t)}control(e){this.__dispatcher.control(e)}get stats(){return this.__dispatcher.stats}},e.component=function(e){if("function"!=typeof e)return t=>{t.options=e,z.push(t)};z.push(e)},e.componentTypes=z,e.prop=function(e){return function(t,s){t.constructor.schema||(t.constructor.schema={});const i="type"in e?e:{type:e};t.constructor.schema[s]=i}},Object.defineProperty(e,"__esModule",{value:!0})})); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).becsy={})}(this,(function(e){"use strict";const t=22,s=4194304,i=4194303;class r{size;bytes;constructor(e){this.size=e,this.bytes=new Uint32Array(Math.ceil(e/32))}get(e){return 0!=(this.bytes[e>>>5]&1<<(31&e))}set(e){this.bytes[e>>>5]|=1<<(31&e)}unset(e){this.bytes[e>>>5]&=~(1<<(31&e))}clear(){this.bytes.fill(0)}}const n=[];class a{maxEntries;configParamName;localProcessingAllowed;data;corral;constructor(e,t,s=!1){this.maxEntries=e,this.configParamName=t,this.localProcessingAllowed=s;const i=new SharedArrayBuffer((e+2)*Uint32Array.BYTES_PER_ELEMENT);this.data=new Uint32Array(i);const r=new SharedArrayBuffer((e+2)*Uint32Array.BYTES_PER_ELEMENT);this.corral=new Uint32Array(r)}push(e){const t=this.corral[0];t&&this.corral[t]===e||(this.corral[t+2]=e,this.corral[0]+=1)}commit(e){const t=this.corral[0];if(!t)return!0;let s=this.data[0];if(e&&(e.generation!==this.data[1]||e.index!==s||e.corralGeneration!==this.corral[1]||e.corralIndex!==this.corral[0]))return!1;const i=Math.min(t,this.maxEntries-s);for(this.data.set(this.corral.subarray(2,i+2),s+2),i<t&&this.data.set(this.corral.subarray(i+2,t+2),2),s+=t;s>=this.maxEntries;)s-=this.maxEntries,this.data[1]+=1;return this.data[0]=s,this.corral[0]=0,this.corral[1]+=1,e&&(e.index=s,e.generation=this.data[1]),!0}createPointer(e){return e?(e.index=this.data[0],e.generation=this.data[1],e.corralIndex=this.corral[0],e.corralGeneration=this.corral[1],e):{index:this.data[0],generation:this.data[1],corralIndex:this.corral[0],corralGeneration:this.corral[1]}}hasUpdatesSince(e){return!(e.index===this.data[0]&&e.generation===this.data[1]&&(e.corralGeneration===this.corral[1]?e.corralIndex===this.corral[0]:0===this.corral[0]))}processSince(e,t){let s=n;const i=t?.index??this.data[0],r=t?.generation??this.data[1];if(e.generation===r)if(e.index<i)s=[this.data,e.index+2,i+2,!1],e.index=i;else{const t=this.corral[0],i=this.corral[1];(e.corralGeneration===i?e.corralIndex<t:t)&&(s=[this.corral,e.corralIndex+2,t+2,!0],e.corralIndex=t,e.corralGeneration=i)}else s=[this.data,e.index+2,this.data.length,!1],e.index=0,e.generation=r;return s}processAndCommitSince(e){const t=this.processSince(e);return t[0]?t:this.commit(e)?n:this.processSince(e)}countSince(e,t){const s=e.index,i=t?.index??this.data[0],r=t?.generation??this.data[1];return e.index=i,e.generation=r,s===i&&e.generation===r?0:s<i?i-s:this.maxEntries-(s-i)}checkPointers(e,t){this.checkPointer(e),t&&this.checkPointer(t)}checkPointer(e){const t=this.data[0];let s=e.generation;e.index===t?s+1<this.data[1]&&this.throwCapacityExceeded():(e.index>t&&(s+=1),s!==this.data[1]&&this.throwCapacityExceeded())}throwCapacityExceeded(){throw new Error(`Log capacity exceeded, please raise ${this.configParamName} above ${this.maxEntries}`)}}class o{maxItems;configParamName;data;constructor(e,t){this.maxItems=e,this.configParamName=t,this.data=new Uint32Array(new SharedArrayBuffer((e+1)*Uint32Array.BYTES_PER_ELEMENT))}get length(){return this.data[0]}take(){const e=this.data[0]--;return this.data[e]}refill(e){if(!e.length)return;const t=this.length,s=t+e.length;this.data.set(e,t+1),this.data[0]=s}fillWithDescendingIntegers(e){const t=this.length;for(let s=this.data.length-1;s>t;s--)this.data[s]=e++;this.data[0]=this.data.length-1}}const h=new TextEncoder,c=new TextDecoder;function d(e){throw new Error(`Component is not writable; use entity.write(${e.type.name}) to acquire a writable version`)}class l{defaultValue;constructor(e){this.defaultValue=e}static boolean;static uint8;static int8;static uint16;static int16;static uint32;static int32;static float32;static float64;static staticString;static dynamicString;static object;static weakObject;static ref;static backrefs}class f extends l{NumberArray;constructor(e){super(0),this.NumberArray=e}defineElastic(e,t){let s,i;t.updateBuffer=()=>{const r=e.capacity*this.NumberArray.BYTES_PER_ELEMENT,n=t.buffer?.byteLength!==r;(n||t.buffer!==s)&&(s=n?new SharedArrayBuffer(r):t.buffer,i=new this.NumberArray(s),n&&t.buffer&&i.set(new this.NumberArray(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>i[e.index],set(t){i[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>i[e.index],set(t){d(e)}})}defineFixed(e,t){const s=e.capacity*this.NumberArray.BYTES_PER_ELEMENT,i=new SharedArrayBuffer(s),r=new this.NumberArray(i);t.buffer=i,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>r[e.index],set(t){r[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>r[e.index],set(t){d(e)}})}}class u extends l{choices;choicesIndex=new Map;TypedArray;constructor(e){if(super(e[0]),this.choices=e,!e?.length)throw new Error("No choices specified for Type.staticString");e.length<256?this.TypedArray=Uint8Array:e.length<65536?this.TypedArray=Uint16Array:this.TypedArray=Uint32Array;for(let t=0;t<e.length;t++)this.choicesIndex.set(e[t],t)}defineElastic(e,t){let s,i;const r=this.choices,n=this.choicesIndex;t.updateBuffer=()=>{const r=e.capacity*this.TypedArray.BYTES_PER_ELEMENT,n=t.buffer?.byteLength!==r;(n||t.buffer!==s)&&(s=n?new SharedArrayBuffer(r):t.buffer,i=new this.TypedArray(s),n&&t.buffer&&i.set(new this.TypedArray(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=i[e.index],s=r[t];if(void 0===s)throw new Error(`Invalid static string index: ${t}`);return s},set(t){const s=n.get(t);if(void 0===s)throw new Error(`Static string not in set: "${t}"`);i[e.index]=s}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=i[e.index],s=r[t];if(void 0===s)throw new Error(`Invalid static string index: ${t}`);return s},set(t){d(e)}})}defineFixed(e,t){const s=this.choices,i=this.choicesIndex,r=e.capacity*this.TypedArray.BYTES_PER_ELEMENT,n=new SharedArrayBuffer(r),a=new this.TypedArray(n);t.buffer=n,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=a[e.index],i=s[t];if(void 0===i)throw new Error(`Invalid static string index: ${t}`);return i},set(t){const s=i.get(t);if(void 0===s)throw new Error(`Static string not in set: "${t}"`);a[e.index]=s}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=a[e.index],i=s[t];if(void 0===i)throw new Error(`Invalid static string index: ${t}`);return i},set(t){d(e)}})}}class y extends l{maxUtf8Length;lengthsStride;bytesStride;constructor(e){super(""),this.maxUtf8Length=e+e%2,this.lengthsStride=e/2+1,this.bytesStride=this.maxUtf8Length+2}defineElastic(e,t){let s,i,r;const n=this.maxUtf8Length,a=this.lengthsStride,o=this.bytesStride;t.updateBuffer=()=>{const n=e.capacity*(this.maxUtf8Length+Uint16Array.BYTES_PER_ELEMENT),a=t.buffer?.byteLength!==n;(a||t.buffer!==s)&&(s=a?new SharedArrayBuffer(n):t.buffer,i=new Uint16Array(s),r=new Uint8Array(s),a&&t.buffer&&r.set(new Uint8Array(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=i[e.index*a];return c.decode(new Uint8Array(r.buffer,e.index*o+2,t))},set(t){const s=h.encode(t);if(s.byteLength>n)throw new Error(`Dynamic string length > ${n} after encoding: ${t}`);i[e.index*a]=s.byteLength,r.set(s,e.index*o+2)}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=i[e.index*a];return c.decode(new Uint8Array(r.buffer,e.index*o+2,t))},set(t){d(e)}})}defineFixed(e,t){const s=this.maxUtf8Length,i=this.lengthsStride,r=this.bytesStride,n=e.capacity*(this.maxUtf8Length+Uint16Array.BYTES_PER_ELEMENT),a=new SharedArrayBuffer(n),o=new Uint16Array(a),l=new Uint8Array(a);t.buffer=a,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=o[e.index*i];return c.decode(new Uint8Array(l.buffer,e.index*r+2,t))},set(t){const n=h.encode(t);if(n.byteLength>s)throw new Error(`Dynamic string length > ${s} after encoding: ${t}`);o[e.index*i]=n.byteLength,l.set(n,e.index*r+2)}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=o[e.index*i];return c.decode(new Uint8Array(l.buffer,e.index*r+2,t))},set(t){d(e)}})}}const g=2**31;const p=[];class m extends l{type;fieldName;trackDeletedBackrefs;constructor(e,t,s){super(p),this.type=e,this.fieldName=t,this.trackDeletedBackrefs=s}defineElastic(e,t){const s=this.fieldName?this.type?.__binding.fields.find((e=>e.name===this.fieldName)):void 0;this.trackDeletedBackrefs;const i=e.dispatcher.indexer;i.registerSelector();const r=i.registerSelector(e.type,this.type,s?.seq,this.trackDeletedBackrefs),n={enumerable:!0,configurable:!0,get:()=>i.getBackrefs(e.entityId,r),set(e){}};Object.defineProperty(e.writableInstance,t.name,n),Object.defineProperty(e.readonlyInstance,t.name,n)}defineFixed(e,t){this.defineElastic(e,t)}}l.boolean=new class extends l{constructor(){super(!1)}defineElastic(e,t){let s,i;t.updateBuffer=()=>{const r=t.buffer?.byteLength!==e.capacity;(r||t.buffer!==s)&&(s=r?new SharedArrayBuffer(e.capacity):t.buffer,i=new Uint8Array(s),r&&t.buffer&&i.set(new Uint8Array(t.buffer)),t.buffer=s)},t.updateBuffer(),Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>Boolean(i[e.index]),set(t){i[e.index]=t?1:0}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>Boolean(i[e.index]),set(t){d(e)}})}defineFixed(e,t){const s=new SharedArrayBuffer(e.capacity),i=new Uint8Array(s);t.buffer=s,Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>Boolean(i[e.index]),set(t){i[e.index]=t?1:0}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>Boolean(i[e.index]),set(t){d(e)}})}},l.uint8=new f(Uint8Array),l.int8=new f(Int8Array),l.uint16=new f(Uint16Array),l.int16=new f(Int16Array),l.uint32=new f(Uint32Array),l.int32=new f(Int32Array),l.float32=new f(Float32Array),l.float64=new f(Float64Array),l.staticString=e=>new u(e),l.dynamicString=e=>new y(e),l.ref=new class extends l{constructor(){super(void 0)}defineElastic(e,t){let s,r;const n=e.dispatcher.indexer,a=e.dispatcher.registry,o=a.pool;n.registerSelector(),t.updateBuffer=()=>{const i=e.capacity*Int32Array.BYTES_PER_ELEMENT,n=t.buffer?.byteLength!==i;if(n||t.buffer!==s){if(s=n?new SharedArrayBuffer(i):t.buffer,r=new Int32Array(s),n&&t.buffer){const e=new Int32Array(t.buffer);r.set(e),r.fill(-1,e.length)}else r.fill(-1);t.buffer=s}},t.updateBuffer(),t.clearRef=(s,a,o)=>{const h=r[e.index]&i,c=void 0!==a;c&&h!==a||(s?c&&(r[e.index]=-1):r[e.index]|=g,n.trackRefChange(e.entityId,e.type,t.seq,void 0,h,-1,s))},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=r[e.index];if(!(-1===t||t&g&&!a.includeRecentlyDeleted))return o.borrowTemporarily(t&i)},set(s){const i=r[e.index],a=s?.__id??-1;i!==a&&(r[e.index]=a,n.trackRefChange(e.entityId,e.type,t.seq,void 0,i,a,!0))}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=r[e.index];if(!(-1===t||t&g&&!a.includeRecentlyDeleted))return o.borrowTemporarily(t&i)},set(t){d(e)}})}defineFixed(e,t){const s=e.capacity*Int32Array.BYTES_PER_ELEMENT,r=new SharedArrayBuffer(s),n=new Int32Array(r);n.fill(-1),t.buffer=r;const a=e.dispatcher.indexer,o=e.dispatcher.registry,h=o.pool;a.registerSelector(),t.clearRef=(s,r,o)=>{const h=n[e.index]&i,c=void 0!==r;c&&h!==r||(s?c&&(n[e.index]=-1):n[e.index]|=g,a.trackRefChange(e.entityId,e.type,t.seq,void 0,h,-1,s))},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=n[e.index];if(!(-1===t||t&g&&!o.includeRecentlyDeleted))return h.borrowTemporarily(t&i)},set(s){const i=n[e.index],r=s?.__id??-1;i!==r&&(n[e.index]=r,a.trackRefChange(e.entityId,e.type,t.seq,void 0,i,r,!0))}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=n[e.index];if(!(-1===t||t&g&&!o.includeRecentlyDeleted))return h.borrowTemporarily(t&i)},set(t){d(e)}})}},l.backrefs=(e,t,s=!1)=>new m(e,t,s),l.object=new class extends l{constructor(){super(void 0)}defineElastic(e,t){const s=[];t.localBuffer=s,t.updateBuffer=()=>{},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>s[e.index],set(t){s[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>s[e.index],set(t){d(e)}})}defineFixed(e,t){const s=new Array(e.capacity);t.localBuffer=s,t.updateBuffer=()=>{},Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get:()=>s[e.index],set(t){s[e.index]=t}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get:()=>s[e.index],set(t){d(e)}})}},l.weakObject=new class extends l{finalizers;constructor(){super(void 0)}defineElastic(e,t){const s=[];t.localBuffer=s,t.updateBuffer=()=>{};const i=this.initFinalizers(e);Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=s[e.index];return null==t?t:t.deref()},set(r){if(null!=r){const s=new WeakRef(r);i?.register(r,{type:e.type,field:t,weakRef:s,id:e.entityId,index:e.index}),r=s}s[e.index]=r}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=s[e.index];return null==t?t:t.deref()},set(t){d(e)}})}defineFixed(e,t){const s=new Array(e.capacity);t.localBuffer=s,t.updateBuffer=()=>{};const i=this.initFinalizers(e);Object.defineProperty(e.writableInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=s[e.index];return null==t?t:t.deref()},set(r){if(null!=r){const s=new WeakRef(r);i?.register(r,{type:e.type,field:t,weakRef:s,id:e.entityId,index:e.index}),r=s}s[e.index]=r}}),Object.defineProperty(e.readonlyInstance,t.name,{enumerable:!0,configurable:!0,get(){const t=s[e.index];return null==t?t:t.deref()},set(t){d(e)}})}initFinalizers(e){if(!e.trackedWrites)return;if(this.finalizers)return this.finalizers;const t=e.dispatcher;return t.writeLog&&"undefined"!=typeof FinalizationRegistry?(this.finalizers=new FinalizationRegistry((({type:e,field:s,weakRef:i,id:r,index:n})=>{s.localBuffer?.[n]===i&&t.registry.trackWrite(r,e)})),this.finalizers):void 0}};class _{type;fields;dispatcher;capacity;storage;elastic;readonlyInstance;writableInstance;shapeOffset;shapeMask;refFields;trackedWrites=!1;internallyIndexed=!1;entityId=0;index=0;constructor(e,t,s,i,r,n){this.type=e,this.fields=t,this.dispatcher=s,this.capacity=i,this.storage=r,this.elastic=n,this.readonlyInstance=new e,this.writableInstance=new e,this.shapeOffset=e.id>>5,this.shapeMask=1<<(31&e.id),this.refFields=t.filter((e=>e.type===l.ref))}}class b{maxEntities;binding;fields;index;spares;constructor(e,t,s){this.maxEntities=e,this.binding=t,this.fields=s,this.growSpares(),this.growCapacity()}acquireIndex(e){let t=this.index[e];return-1===t&&(this.spares[3]>0?t=this.spares[4+--this.spares[3]]:(this.spares[1]===this.spares[2]&&(this.binding.capacity=Math.min(this.maxEntities,2*this.binding.capacity),this.growCapacity()),t=this.spares[1]++),this.index[e]=t),t}releaseIndex(e){this.spares[3]===this.spares.length-4&&this.growSpares(),this.spares[4+this.spares[3]++]=this.index[e],this.index[e]=-1}growCapacity(){const e=this.ArrayType,t=e.BYTES_PER_ELEMENT!==this.spares?.[0];if(!this.index||t){const t=new e(new SharedArrayBuffer(this.maxEntities*e.BYTES_PER_ELEMENT));this.index?t.set(this.index):t.fill(-1),this.index=t}if(this.spares&&t){const t=new e(new SharedArrayBuffer(this.spares.length*e.BYTES_PER_ELEMENT));t.set(this.spares),t[0]=e.BYTES_PER_ELEMENT,this.spares=t}if(this.spares[2]=this.binding.capacity,this.binding.elastic)for(const e of this.fields)e.updateBuffer()}growSpares(){const e=this.ArrayType,t=this.spares?Math.min(this.maxEntities,2*(this.spares.length-4)):8,s=new e(new SharedArrayBuffer((4+t)*e.BYTES_PER_ELEMENT));this.spares?s.set(this.spares):(s[0]=e.BYTES_PER_ELEMENT,s[2]=this.binding.capacity),this.spares=s}get ArrayType(){const e=this.binding.capacity;return e<=127?Int8Array:e<=32767?Int16Array:Int32Array}}function w(e,t,s){const i=function(e){const t=e.schema,s=[];if(t){let e=0;for(const i in t){let r=t[i];(r instanceof l||"function"==typeof r)&&(r={type:r}),"function"==typeof r.type&&(r.type=r.type()),"default"in r||(r.default=r.type.defaultValue),s.push({name:i,seq:e++,type:r.type,default:r.default})}}return s}(t),r=i.length?t.options?.storage??s.defaultComponentStorage:"sparse",n="sparse"===r?s.maxEntities:Math.min(s.maxEntities,t.options?.capacity??0),a=t.options?.initialCapacity??8;t.id=e;const o=new _(t,i,s,n||a,r,!n);t.__binding=o}function E(e){const t=e.__binding;for(const e of t.fields)t.elastic?e.type.defineElastic(t,e):e.type.defineFixed(t,e);switch(t.storage){case"sparse":e.__bind=(e,s)=>(t.entityId=e,t.index=e,s?t.writableInstance:t.readonlyInstance),e.__allocate=e=>(t.entityId=e,t.index=e,t.writableInstance);break;case"packed":{const s=new b(t.dispatcher.maxEntities,t,t.fields);e.__bind=(e,i)=>(t.entityId=e,t.index=s.index[e],i?t.writableInstance:t.readonlyInstance),e.__allocate=e=>(t.entityId=e,t.index=s.acquireIndex(e),t.writableInstance),e.__free=e=>{s.releaseIndex(e)};break}case"compact":throw new Error("Not yet implemented")}}class x{__registry;__id;constructor(e){this.__registry=e}add(e,t){return this.__registry.setShape(this.__id,e),function(e,t,s){const i=e.__allocate(t);for(const t of e.__binding.fields)i[t.name]=s?.[t.name]??t.default}(e,this.__id,t),this}addAll(...e){for(let t=0;t<e.length;t++){const s=e[t];let i=e[t+1];"function"==typeof i?i=void 0:t++,this.add(s,i)}return this}remove(e){this.__registry.clearShape(this.__id,e)}removeAll(...e){for(const t of e)this.remove(t)}has(e){return this.__registry.hasShape(this.__id,e,!0)}read(e){return e.__bind(this.__id,!1)}write(e){return e.__binding.trackedWrites&&this.__registry.trackWrite(this.__id,e),e.__bind(this.__id,!0)}delete(){this.__registry.Alive;for(const e of this.__registry.types)this.__registry.hasShape(this.__id,e,!1)&&this.__registry.clearShape(this.__id,e);this.__registry.queueDeletion(this.__id),this.__registry.dispatcher.indexer.clearAllRefs(this.__id,!1)}__checkMask(e,t){R(e,this.__registry.executingSystem,t)}__checkHas(e,t){if(!this.__registry.hasShape(this.__id,e,t))throw new Error(`Entity doesn't have a ${e.name} component`)}}function R(e,t,s){!function(e){if(!e.__binding)throw new Error(`Component ${e.name} not defined; add to world defs`)}(e);const i=s?t?.rwMasks.write:t?.rwMasks.read;if(!(!i||0!=((i[e.__binding.shapeOffset]??0)&e.__binding.shapeMask)))throw new Error(`System didn't mark component ${e.name} as ${s?"writable":"readable"}`)}function S(e,t){const s=t.__binding.shapeOffset;s>=e.length&&(e.length=s+1,e.fill(0,e.length,s)),e[s]|=t.__binding.shapeMask}class v{pool;entities=[];constructor(e){this.pool=e}add(e){this.entities.push(this.pool.borrowTemporarily(e))}clear(){this.entities.length&&this.entities.splice(0,1/0)}}class P{pool;entities=[];lookupTable;constructor(e,t){this.pool=e,this.lookupTable=new Int32Array(t),this.lookupTable.fill(-1)}add(e){const t=this.entities.push(this.pool.borrow(e))-1;this.lookupTable[e]=t}remove(e){const t=this.lookupTable[e];if(t<0)throw new Error("Internal error, entity not in list");this.pool.return(e),this.lookupTable[e]=-1;const s=this.entities.pop();t<this.entities.length&&(this.entities[t]=s,this.lookupTable[s.__id]=t)}has(e){return this.lookupTable[e]>=0}clear(){for(const e of this.entities)this.pool.return(e.__id);this.entities=[],this.lookupTable.fill(-1)}}var k;!function(e){e[e.all=1]="all",e[e.added=2]="added",e[e.removed=4]="removed",e[e.changed=8]="changed",e[e.addedOrChanged=16]="addedOrChanged",e[e.changedOrRemoved=32]="changedOrRemoved",e[e.addedChangedOrRemoved=64]="addedChangedOrRemoved"}(k||(k={}));const I=k.added|k.removed|k.changed|k.addedOrChanged|k.changedOrRemoved|k.addedChangedOrRemoved,T=k.changed|k.addedOrChanged|k.changedOrRemoved|k.addedChangedOrRemoved;class L{query;system;results={};flavors=0;withMask;withoutMask;trackMask;hasTransientResults;hasChangedResults;currentEntities;changedEntities;constructor(e,t){this.query=e,this.system=t,e.__results=this.results,e.__systemName=t.name}complete(){const e=this.system.dispatcher;this.hasTransientResults=Boolean(this.flavors&I),this.hasChangedResults=Boolean(this.flavors&T),this.flavors&k.all?this.results.all=new P(e.registry.pool,e.maxEntities):this.currentEntities=new r(e.maxEntities),this.hasTransientResults&&this.allocateTransientResultLists(),this.flavors&&this.system.shapeQueries.push(this),this.hasChangedResults&&(this.changedEntities=new r(e.maxEntities),this.system.writeQueries.push(this))}allocateTransientResultLists(){this.flavors&k.added&&this.allocateResult("added"),this.flavors&k.removed&&this.allocateResult("removed"),this.flavors&k.changed&&this.allocateResult("changed"),this.flavors&k.addedOrChanged&&this.allocateResult("addedOrChanged"),this.flavors&k.changedOrRemoved&&this.allocateResult("changedOrRemoved"),this.flavors&k.addedChangedOrRemoved&&this.allocateResult("addedChangedOrRemoved")}allocateResult(e){const t=this.system.dispatcher;this.results[e]=new v(t.registry.pool)}clearTransientResults(){this.hasTransientResults&&(this.results.added?.clear(),this.results.removed?.clear(),this.results.changed?.clear(),this.results.addedOrChanged?.clear(),this.results.changedOrRemoved?.clear(),this.results.addedChangedOrRemoved?.clear(),this.changedEntities?.clear())}clearAllResults(){this.clearTransientResults(),this.results.all?.clear()}handleShapeUpdate(e){const t=this.system.dispatcher.registry,s=this.results.all?.has(e)??this.currentEntities.get(e),i=t.matchShape(e,this.withMask,this.withoutMask);i&&!s?(this.currentEntities?.set(e),this.results.all?.add(e),this.results.added?.add(e),this.results.addedOrChanged?.add(e),this.results.addedChangedOrRemoved?.add(e)):!i&&s&&(this.currentEntities?.unset(e),this.results.all?.remove(e),this.results.removed?.add(e),this.results.changedOrRemoved?.add(e),this.results.addedChangedOrRemoved?.add(e))}handleWrite(e,t,s){!this.changedEntities.get(e)&&(this.trackMask[t]??0)&s&&(this.changedEntities.set(e),this.results.changed?.add(e),this.results.addedOrChanged?.add(e),this.results.changedOrRemoved?.add(e),this.results.addedChangedOrRemoved?.add(e))}}class A{__callback;__userQuery;__query;__system;__lastTypes;constructor(e,t){this.__callback=e,this.__userQuery=t}__build(e){try{this.__system=e,this.__query=new L(this.__userQuery,e),this.__callback(this),this.__query.complete()}catch(t){throw t.message=`Failed to build query in system ${e.name}: ${t.message}`,t}}get and(){return this}get but(){return this}get also(){return this}get all(){return this.__query.flavors|=k.all,this}get added(){return this.__query.flavors|=k.added,this}get removed(){return this.__query.flavors|=k.removed,this}get changed(){return this.__query.flavors|=k.changed,this}get addedOrChanged(){return this.__query.flavors|=k.addedOrChanged,this}get changedOrRemoved(){return this.__query.flavors|=k.changedOrRemoved,this}get addedChangedOrRemoved(){return this.__query.flavors|=k.addedChangedOrRemoved,this}with(...e){return this.set(this.__system.rwMasks.read,e),this.set("withMask"),this}without(...e){return this.set(this.__system.rwMasks.read,e),this.set("withoutMask",e),this}using(...e){return this.set(this.__system.rwMasks.read,e),this}get track(){this.set("trackMask");for(const e of this.__lastTypes)e.__binding.trackedWrites=!0;return this}get read(){return this}get write(){return this.set(this.__system.rwMasks.write),this}set(e,t,s){if(e){if(t||(t=this.__lastTypes),!t)throw new Error("No component type to apply query modifier to");if(this.__lastTypes=t,"string"==typeof e){if(s&&this.__query[e])throw new Error(`Only one ${s} allowed`);this.__query[e]||(this.__query[e]=[]),e=this.__query[e]}else if(s&&e.some((e=>0!==e)))throw new Error(`Only one ${s} allowed`);for(const s of t)S(e,s)}}}class O{__results;__systemName;get all(){return this.__results.all.entities}get added(){return this.__results.added.entities}get removed(){return this.__results.removed.entities}get changed(){return this.__results.changed.entities}get addedOrChanged(){return this.__results.addedOrChanged.entities}get changedOrRemoved(){return this.__results.changedOrRemoved.entities}get addedChangedOrRemoved(){return this.__results.addedChangedOrRemoved.entities}__checkList(e){if(!this.__results[e])throw new Error(`Query '${e}' not configured, please add .${e} to your query definition in system ${this.__systemName}`)}}var C,B;!function(e){e[e.RUNNING=0]="RUNNING",e[e.STOPPED=1]="STOPPED"}(C||(C={}));class N{type;constructor(e){this.type=e}}class F{static __system=!0;__queryBuilders=[];__dispatcher;time;delta;get name(){return this.constructor.name}query(e){const t=new O,s=new A(e,t);return this.__queryBuilders.push(s),t}attach(e){return new N(e)}createEntity(...e){return this.__dispatcher.createEntity(e)}accessRecentlyDeletedData(e=!0){this.__dispatcher.registry.includeRecentlyDeleted=e}initialize(){}execute(){}}class M{system;dispatcher;rwMasks={read:[],write:[]};shapeQueries=[];writeQueries=[];hasWriteQueries;processedEntities;shapeLogPointer;writeLogPointer;state=C.RUNNING;get name(){return this.system.name}constructor(e,t){this.system=e,this.dispatcher=t,e.__dispatcher=t,this.shapeLogPointer=t.shapeLog.createPointer(),this.writeLogPointer=t.writeLog?.createPointer(),this.processedEntities=new r(t.maxEntities);for(const t of e.__queryBuilders)t.__build(this);e.__queryBuilders=null,this.hasWriteQueries=!!this.writeQueries.length}replaceAttachmentPlaceholders(){for(const e in this.system)if(this.system[e]instanceof N){const t=this.system[e].type,s=this.dispatcher.systemsByClass.get(t);this.system[e]=s}}async initialize(){await Promise.resolve(this.system.initialize())}execute(e,t){this.state===C.RUNNING&&(this.system.time=e,this.system.delta=t,this.runQueries(),this.system.execute())}runQueries(){const e=this.dispatcher.shapeLog.hasUpdatesSince(this.shapeLogPointer),t=this.hasWriteQueries&&this.dispatcher.writeLog.hasUpdatesSince(this.writeLogPointer);if(e||t){this.processedEntities.clear();for(const e of this.shapeQueries)e.clearTransientResults();e&&this.__updateShapeQueries(),t&&this.__updateWriteQueries()}}__updateShapeQueries(){const e=this.dispatcher.shapeLog;let t,s,i;for(;[t,s,i]=e.processSince(this.shapeLogPointer),t;)for(let e=s;e<i;e++){const s=t[e];if(!this.processedEntities.get(s)){this.processedEntities.set(s);for(const e of this.shapeQueries)e.handleShapeUpdate(s)}}}__updateWriteQueries(){const e=this.dispatcher.writeLog;let s,r,n;for(;[s,r,n]=e.processSince(this.writeLogPointer),s;)for(let e=r;e<n;e++){const r=s[e],n=r&i;if(!this.processedEntities.get(n)){const e=r>>>t;for(const t of this.writeQueries)t.handleWrite(n,e>>5,1<<(31&e))}}}stop(){if(this.state!==C.STOPPED){this.state=C.STOPPED;for(const e of this.shapeQueries)e.clearAllResults()}}restart(){if(this.state===C.STOPPED){const e=this.dispatcher.registry,t=e.Alive;for(let s=0;s<this.dispatcher.maxEntities;s++)if(e.hasShape(s,t,!1))for(const e of this.shapeQueries)e.handleShapeUpdate(s);for(const e of this.shapeQueries)e.clearTransientResults();this.dispatcher.shapeLog.createPointer(this.shapeLogPointer),this.dispatcher.writeLog?.createPointer(this.writeLogPointer)}this.state=C.RUNNING}}class U{registry;borrowed;borrowCounts;spares=[];temporarilyBorrowedIds=[];constructor(e,t){this.registry=e,this.borrowed=Array.from({length:t}),this.borrowCounts=new Int32Array(t)}borrow(e){this.borrowCounts[e]+=1;let t=this.borrowed[e];return t||(t=this.borrowed[e]=this.spares.pop()??new x(this.registry),t.__id=e),t}borrowTemporarily(e){const t=this.borrow(e);return this.temporarilyBorrowedIds.push(e),t}returnTemporaryBorrows(){for(const e of this.temporarilyBorrowedIds)this.return(e);this.temporarilyBorrowedIds.splice(0,1/0)}return(e){--this.borrowCounts[e]<=0&&(this.spares.push(this.borrowed[e]),this.borrowed[e]=void 0)}}class D{types;dispatcher;stride;shapes;staleShapes;entityIdPool;pool;executingSystem;includeRecentlyDeleted=!1;deletionLog;prevDeletionPointer;oldDeletionPointer;removalLog;prevRemovalPointer;oldRemovalPointer;Alive=class{};constructor(e,t,s,i,r){this.types=i,this.dispatcher=r,this.stride=Math.ceil(i.length/32);const n=e*this.stride*4;this.shapes=new Uint32Array(new SharedArrayBuffer(n)),this.staleShapes=new Uint32Array(new SharedArrayBuffer(n)),this.entityIdPool=new o(e,"maxEntities"),this.entityIdPool.fillWithDescendingIntegers(0),this.pool=new U(this,e),this.deletionLog=new a(t,"maxLimboEntities"),this.prevDeletionPointer=this.deletionLog.createPointer(),this.oldDeletionPointer=this.deletionLog.createPointer(),this.removalLog=new a(s,"maxLimboComponents"),this.prevRemovalPointer=this.removalLog.createPointer(),this.oldRemovalPointer=this.removalLog.createPointer()}initializeComponentTypes(){this.types.unshift(this.Alive);let e=0;for(const t of this.types)w(e++,t,this.dispatcher);for(const e of this.types)E(e)}createEntity(e){const t=this.entityIdPool.take(),s=t*this.stride;this.shapes[s]=1,this.stride>1&&this.shapes.fill(0,s+1,s+this.stride);const i=this.pool.borrowTemporarily(t);return e&&i.addAll(...e),i}queueDeletion(e){this.deletionLog.push(e)}flush(){this.includeRecentlyDeleted=!1,this.pool.returnTemporaryBorrows(),this.deletionLog.commit(),this.removalLog.commit()}processEndOfFrame(){this.processDeletionLog(),this.processRemovalLog()}processDeletionLog(){this.deletionLog.commit();let e,t,s,i=0;for(;[e,t,s]=this.deletionLog.processSince(this.oldDeletionPointer,this.prevDeletionPointer),e;){for(let i=t;i<s;i++)this.dispatcher.indexer.clearAllRefs(e[i],!0);const r=e.subarray(t,s);this.entityIdPool.refill(r),i+=r.length}this.deletionLog.createPointer(this.prevDeletionPointer)}processRemovalLog(){let e,s,r;for(this.removalLog.commit();[e,s,r]=this.removalLog.processSince(this.oldRemovalPointer,this.prevRemovalPointer),e;)for(let n=s;n<r;n++){const s=e[n],r=s&i,a=s>>>t,o=this.types[a],h=r*this.stride+o.__binding.shapeOffset,c=o.__binding.shapeMask;0==(this.shapes[h]&c)&&(this.staleShapes[h]&=~c,this.clearRefs(r,o,!0),o.__free?.(r))}this.removalLog.createPointer(this.prevRemovalPointer)}hasShape(e,t,s){const i=e*this.stride+t.__binding.shapeOffset,r=t.__binding.shapeMask;return 0!=(this.shapes[i]&r)||!(!s||!this.includeRecentlyDeleted||0==(this.staleShapes[i]&r))}setShape(e,t){const s=e*this.stride+t.__binding.shapeOffset,i=t.__binding.shapeMask;this.shapes[s]|=i,this.staleShapes[s]|=i,this.dispatcher.shapeLog.push(e)}clearShape(e,s){const i=this.clearRefs(e,s,!1);(s.__free||i)&&this.removalLog.push(e|s.id<<t),this.shapes[e*this.stride+s.__binding.shapeOffset]&=~s.__binding.shapeMask,this.dispatcher.shapeLog.push(e)}trackWrite(e,s){this.dispatcher.writeLog.push(e|s.id<<t)}clearRefs(e,t,s){const i=!!t.__binding.refFields.length;if(i){t.__bind(e,!0);for(const e of t.__binding.refFields)e.clearRef(s)}return i}matchShape(e,t,s){const i=e*this.stride;if(t)for(let e=0;e<t.length;e++){const s=t[e];if((this.shapes[i+e]&s)!==s)return!1}if(s)for(let e=0;e<s.length;e++){const t=s[e];if(0!=(this.shapes[i+e]&t))return!1}return!0}}!function(e){e[e.REFERENCE=0]="REFERENCE",e[e.UNREFERENCE=1073741824]="UNREFERENCE",e[e.RELEASE=2147483648]="RELEASE"}(B||(B={}));const q=B.REFERENCE|B.UNREFERENCE|B.RELEASE;class j{targetEntityId;selector;dispatcher;entities=[];tags;entityIndex;clearing=!1;registry;constructor(e,t,s){this.targetEntityId=e,this.selector=t,this.dispatcher=s;const i=t.sourceType?.__binding;t.matchType&&(t.matchSeq||1===i.refFields.length)&&!i.internallyIndexed||(this.tags=[]),this.registry=s.registry}clearAllRefs(e){this.clearing=!0;for(let t=0;t<this.entities.length;t++){const s=this.entities[t].__id,i=this.tags[t];if("number"==typeof i)this.clearRef(s,i,e);else for(const t of i)this.clearRef(s,t,e)}this.entities=[],this.tags=[],this.entityIndex=void 0,this.clearing=!1}clearRef(e,t,s){const i=511&t,r=t>>>9&127,n=t>>>16,a=this.registry.types[i];a.__bind(e,!0),a.__binding.fields[r].clearRef(s,this.targetEntityId,n)}trackReference(e,t,s,i,r){let n=this.getEntityIndex(e);void 0===n&&(n=this.addEntity(e,r)),this.addTag(n,this.makeTag(t,s,i))}trackUnreference(e,t,s,i,r){if(this.clearing)return;const n=this.getEntityIndex(e);this.removeTag(n,this.makeTag(t,s,i))&&this.removeEntity(n,e,r)}getEntityIndex(e){if(this.entityIndex)return this.entityIndex[e];const t=this.entities.findIndex((t=>t.__id===e));return t>=0?t:void 0}indexEntities(){this.entityIndex=new Array(this.dispatcher.maxEntities);for(let e=0;e<this.entities.length;e++)this.entityIndex[this.entities[e].__id]=e}addTag(e,t){if(!this.tags)return;const s=this.tags[e];if(void 0===s)this.tags[e]=t;else if("number"==typeof s)this.tags[e]=[s,t];else if(Array.isArray(s))if(s.length>=1e3){(this.tags[e]=new Set(s)).add(t)}else s.push(t);else s.add(t)}removeTag(e,t){if(!this.tags)return!0;const s=this.tags[e];if("number"==typeof s)return delete this.tags[e],!0;if(Array.isArray(s)){const e=s.indexOf(t);return s.splice(e,1),!this.tags.length}return s.delete(t),!s.size}makeTag(e,t,s){return e|t<<9|(void 0===s?0:s<<16)}addEntity(e,t){const s=this.entities.length;return this.entities.push(this.registry.pool.borrow(e)),this.entityIndex?this.entityIndex[e]=s:s>100&&this.indexEntities(),t&&this.trackBackrefsChange(),s}removeEntity(e,t,s){this.registry.pool.return(t);const i=this.entities.pop();this.entityIndex&&delete this.entityIndex[e],this.entities.length>e&&(this.entities[e]=i,this.entityIndex&&(this.entityIndex[i.__id]=e)),s&&this.trackBackrefsChange()}trackBackrefsChange(){for(const e of this.selector.targetTypes)e.__binding.trackedWrites&&this.registry.trackWrite(this.targetEntityId,e)}checkWriteMask(){const e=this.registry.executingSystem;for(const t of this.selector.targetTypes)R(t,e,!0)}}class W{dispatcher;maxRefChangesPerFrame;refLog;refLogPointer;refLogStatsPointer;selectorIdsBySourceKey=new Map;selectors=[];trackers=new Map;registry;constructor(e,t){this.dispatcher=e,this.maxRefChangesPerFrame=t,this.registry=e.registry}processEndOfFrame(){this.flush()}registerSelector(e,t,s,i=!1){this.refLog||(this.refLog=new a(this.maxRefChangesPerFrame,"maxRefChangesPerFrame",!0),this.refLogPointer=this.refLog.createPointer(),this.refLogStatsPointer=this.refLog.createPointer());const r=t?void 0===s?-2-t.id:t.id|s<<9:-1;let n=this.selectorIdsBySourceKey.get(r);if(void 0===n){this.selectors.length||(i=!0);const a={id:this.selectors.length,targetTypes:e?[e]:[],sourceType:t,matchType:!!t,matchSeq:void 0!==s,sourceTypeId:t?.id,sourceSeq:s,trackStale:i};this.selectors.push(a),n=a.id,this.selectorIdsBySourceKey.set(r,n)}else{const t=this.selectors[n];t.trackStale=t.trackStale||i,e&&t.targetTypes.push(e)}return n}getBackrefs(e,t=0){const s=this.selectors[t];return this.getOrCreateTracker(s,e,this.registry.includeRecentlyDeleted).entities}trackRefChange(e,t,s,i,r,n,a){-1!==r&&this.pushRefLogEntry(e,t,s,i,r,a?B.RELEASE:B.UNREFERENCE),-1!==n&&this.pushRefLogEntry(e,t,s,i,n,B.REFERENCE)}clearAllRefs(e,t){this.selectors.length&&this.getTracker(this.selectors[0],e,t)?.clearAllRefs(t)}pushRefLogEntry(e,s,i,r,n,a){const o=void 0!==r;this.refLog.push(e|s.id<<t),this.refLog.push(n|i<<t|a|(o?2**29:0)),o&&this.refLog.push(r),this.processEntry(e,s.id,i,r,n,a,!0)}getOrCreateTracker(e,s,i){let r,n=this.getTracker(e,s,i);return n||(n=new j(s,e,this.dispatcher),this.trackers.set(s|e.id<<t,n),e.trackStale&&(r=new j(s,e,this.dispatcher),this.trackers.set(s|e.id<<t|2**31,r)),i?r:n)}getTracker(e,s,i){return this.trackers.get(s|e.id<<t|(i?2**31:0))}flush(){if(this.refLog)for(;;){const[e,s,r,n]=this.refLog.processAndCommitSince(this.refLogPointer);if(!e)break;if(!n)for(let n=s;n<r;n+=2){const s=e[n],r=e[n+1],a=s&i,o=s>>>t,h=r&i,c=r>>>t&127,d=(r&q)>>>30,l=0!=(r&2**29),f=l?e[n+2]:void 0;l&&(n+=1),this.processEntry(a,o,c,f,h,d,!1)}}}processEntry(e,t,s,i,r,n,a){for(let o=0;o<this.selectors.length;o++){const h=this.selectors[o];if(!(h.matchType&&h.sourceTypeId!==t||h.matchSeq&&h.sourceSeq!==s)){if(n===B.REFERENCE||n===B.UNREFERENCE){const o=this.getOrCreateTracker(h,r,!1);n===B.REFERENCE?o.trackReference(e,t,s,i,a):o.trackUnreference(e,t,s,i,a)}if(h.trackStale&&(n===B.REFERENCE||n===B.RELEASE)){const o=this.getOrCreateTracker(h,r,!0);n===B.REFERENCE?o.trackReference(e,t,s,i,a):o.trackUnreference(e,t,s,i,a)}}}}}const Q="undefined"!=typeof window&&void 0!==window.performance?performance.now.bind(performance):Date.now.bind(Date);class $ extends F{__callback;execute(){this.__callback(this)}}class z{maxEntities;defaultComponentStorage;registry;systems;systemsByClass=new Map;lastTime=Q()/1e3;executing;shapeLog;writeLog;shapeLogFramePointer;writeLogFramePointer;stats;indexer;userCallbackSystem;callbackSystem;deferredControls=new Map;constructor({defs:e,maxEntities:t=1e4,maxLimboEntities:i=Math.ceil(t/5),maxLimboComponents:r=Math.ceil(t/5),maxShapeChangesPerFrame:n=2*t,maxWritesPerFrame:o=4*t,maxRefChangesPerFrame:h=t,defaultComponentStorage:c="sparse"}){if(t>s)throw new Error("maxEntities too high, the limit is 4194304");const{componentTypes:d,systemTypes:l}=this.splitDefs(e);if(d.length>512)throw new Error("Too many component types, the limit is 512");this.maxEntities=t,this.defaultComponentStorage=c,this.shapeLog=new a(n,"maxShapeChangesPerFrame"),this.shapeLogFramePointer=this.shapeLog.createPointer(),this.registry=new D(t,i,r,d.flat(1/0),this),this.indexer=new W(this,h),this.registry.initializeComponentTypes(),this.systems=this.normalizeAndInitSystems(l),this.systems.some((e=>e.hasWriteQueries))&&(this.writeLog=new a(o,"maxWritesPerFrame"),this.writeLogFramePointer=this.writeLog.createPointer()),this.userCallbackSystem=new $,this.callbackSystem=new M(this.userCallbackSystem,this),this.callbackSystem.rwMasks.read=void 0,this.callbackSystem.rwMasks.write=void 0}normalizeAndInitSystems(e){const t=[],s=e.flat(1/0);for(let e=0;e<s.length;e++){const i=s[e],r=new i,n=s[e+1];n&&"function"!=typeof n&&(Object.assign(r,n),e++);const a=new M(r,this);t.push(a),this.systemsByClass.set(i,a)}for(const e of t)e.replaceAttachmentPlaceholders();return t}splitDefs(e){const t=[],s=[];let i=!1;for(const r of e.flat(1/0))"function"==typeof r?(i=r.__system,(i?s:t).push(r)):(s.push(r),i=!1);return{componentTypes:t,systemTypes:s}}async initialize(){await Promise.all(this.systems.map((e=>e.initialize())))}async execute(e,t,s){this.executing=!0,void 0===e&&(e=Q()/1e3),void 0===t&&(t=e-this.lastTime),this.lastTime=e;for(const i of s??this.systems)this.registry.executingSystem=i,i.execute(e,t),this.flush();this.registry.executingSystem=void 0,this.executing=!1,this.processEndOfFrame()}executeFunction(e){this.executing=!0,this.registry.executingSystem=this.callbackSystem,this.userCallbackSystem.__callback=e,this.callbackSystem.execute(0,0),this.flush(),this.registry.executingSystem=void 0,this.executing=!1,this.processEndOfFrame()}processEndOfFrame(){this.registry.processEndOfFrame(),this.indexer.processEndOfFrame(),this.processDeferredControls()}gatherFrameStats(){this.stats.frames+=1,this.stats.maxShapeChangesPerFrame=this.shapeLog.countSince(this.shapeLogFramePointer),this.stats.maxWritesPerFrame=this.writeLog?.countSince(this.writeLogFramePointer)??0}flush(){this.registry.flush(),this.indexer.flush(),this.shapeLog.commit(),this.writeLog?.commit()}createEntity(e){const t=this.registry.createEntity(e);return this.executing||this.flush(),t}control(e){this.deferRequestedRunState(e.stop,C.STOPPED),this.deferRequestedRunState(e.restart,C.RUNNING),this.executing||this.processDeferredControls()}deferRequestedRunState(e,t){for(const s of e.flat(1/0)){if(!s.__system)continue;const e=this.systemsByClass.get(s);this.deferredControls.set(e,t)}}checkControlOverlap(e){const t=new Set;for(const s of e.stop.flat(1/0))s.__system&&t.add(s);for(const s of e.restart.flat(1/0))if(s.__system&&t.has(s))throw new Error(`Request to both stop and restart system ${s.name}`)}processDeferredControls(){if(this.deferredControls.size){for(const[e,t]of this.deferredControls.entries())switch(t){case C.STOPPED:e.stop();break;case C.RUNNING:e.restart()}this.deferredControls.clear()}}}const Y={};class G{__dispatcher;static async create(e){const t=new G(e,Y);return await t.__dispatcher.initialize(),t}constructor(e,t){if(t!==Y)throw new Error("Don't call World constructor directly; use World.create instead");this.__dispatcher=new z(e)}build(e){this.__dispatcher.executeFunction(e)}createEntity(...e){this.__dispatcher.createEntity(e)}execute(e,t){return this.__dispatcher.execute(e,t)}control(e){this.__dispatcher.control(e)}get stats(){return this.__dispatcher.stats}}const K=[];e.Entity=x,e.Query=O,e.System=F,e.Type=l,e.World=G,e.component=function(e){if("function"!=typeof e)return t=>{t.options=e,K.push(t)};K.push(e)},e.componentTypes=K,e.field=function(e){return function(t,s){t.constructor.schema||(t.constructor.schema={});const i="type"in e?e:{type:e};t.constructor.schema[s]=i}},Object.defineProperty(e,"__esModule",{value:!0})})); | ||
//# sourceMappingURL=perf.umd.min.js.map |
@@ -35,3 +35,7 @@ import {Type} from './type'; | ||
export interface ComponentType<C> { | ||
export interface Component { | ||
__invalid?: boolean; | ||
} | ||
export interface ComponentType<C extends Component> { | ||
new(): C; | ||
@@ -55,4 +59,4 @@ schema?: Schema; | ||
export class Binding<C> { | ||
readonly readonlyInstance: C; | ||
readonly writableInstance: C; | ||
readonlyInstance: C; | ||
writableInstance: C; | ||
readonly shapeOffset: number; | ||
@@ -253,3 +257,3 @@ readonly shapeMask: number; | ||
export function defineAndAllocateComponentType<C>(type: ComponentType<C>): void { | ||
export function defineAndAllocateComponentType<C extends Component>(type: ComponentType<C>): void { | ||
const binding = type.__binding!; | ||
@@ -264,2 +268,22 @@ for (const field of binding.fields) { | ||
let readonlyMaster: C, writableMaster: C; | ||
CHECK: { | ||
readonlyMaster = binding.readonlyInstance; | ||
writableMaster = binding.writableInstance; | ||
binding.readonlyInstance = Object.create(readonlyMaster); | ||
binding.readonlyInstance.__invalid = true; | ||
binding.writableInstance = Object.create(writableMaster); | ||
binding.writableInstance.__invalid = true; | ||
} | ||
function resetComponent(writable: boolean): void { | ||
if (writable) { | ||
binding.writableInstance.__invalid = true; | ||
binding.writableInstance = Object.create(writableMaster); | ||
} else { | ||
binding.readonlyInstance.__invalid = true; | ||
binding.readonlyInstance = Object.create(readonlyMaster); | ||
} | ||
} | ||
switch (binding.storage) { | ||
@@ -272,2 +296,3 @@ case 'sparse': | ||
binding.index = id; | ||
CHECK: resetComponent(writable); | ||
return writable ? binding.writableInstance : binding.readonlyInstance; | ||
@@ -278,2 +303,3 @@ }; | ||
binding.index = id; | ||
CHECK: resetComponent(true); | ||
return binding.writableInstance; | ||
@@ -292,2 +318,3 @@ }; | ||
} | ||
CHECK: resetComponent(writable); | ||
return writable ? binding.writableInstance : binding.readonlyInstance; | ||
@@ -298,2 +325,3 @@ }; | ||
binding.index = storageManager.acquireIndex(id); | ||
CHECK: resetComponent(true); | ||
return binding.writableInstance; | ||
@@ -300,0 +328,0 @@ }; |
@@ -10,3 +10,3 @@ import type {ComponentOptions, ComponentType} from './component'; | ||
export function prop<JSType>( | ||
export function field<JSType>( | ||
practicalOptions: PropOptions<JSType> | Type<any> | (() => Type<any>) | ||
@@ -13,0 +13,0 @@ ) { |
@@ -17,3 +17,3 @@ import type {ComponentStorage, ComponentType} from './component'; | ||
// https://stackoverflow.com/questions/67467302/type-for-an-interleaved-array-of-classes-and-values | ||
type DefsArray = (ComponentType<any> | SystemType | any | DefsArray)[]; | ||
type DefsArray = (ComponentType<any> | SystemType<System> | any | DefsArray)[]; | ||
@@ -33,3 +33,2 @@ export interface WorldOptions { | ||
stop: DefsArray; | ||
suspend: DefsArray; | ||
restart: DefsArray; | ||
@@ -52,3 +51,3 @@ } | ||
private readonly systems: SystemBox[]; | ||
private readonly systemsByClass = new Map<SystemType, SystemBox>(); | ||
readonly systemsByClass = new Map<SystemType<System>, SystemBox>(); | ||
private lastTime = now() / 1000; | ||
@@ -83,2 +82,3 @@ executing: boolean; | ||
} | ||
// TODO: allocate all shared buffers through a central manager | ||
STATS: this.stats = new Stats(); | ||
@@ -104,7 +104,7 @@ this.maxEntities = maxEntities; | ||
private normalizeAndInitSystems(systemTypes: (SystemType | any)[]): SystemBox[] { | ||
private normalizeAndInitSystems(systemTypes: (SystemType<System> | any)[]): SystemBox[] { | ||
const systems = []; | ||
const flatUserSystems = systemTypes.flat(Infinity); | ||
for (let i = 0; i < flatUserSystems.length; i++) { | ||
const SystemClass = flatUserSystems[i] as SystemType; | ||
const SystemClass = flatUserSystems[i] as SystemType<System>; | ||
const system = new SystemClass(); | ||
@@ -120,2 +120,3 @@ const props = flatUserSystems[i + 1]; | ||
} | ||
for (const box of systems) box.replaceAttachmentPlaceholders(); | ||
return systems; | ||
@@ -125,5 +126,5 @@ } | ||
private splitDefs(defs: DefsArray): | ||
{componentTypes: ComponentType<any>[], systemTypes: (SystemType | any)[]} { | ||
{componentTypes: ComponentType<any>[], systemTypes: (SystemType<System> | any)[]} { | ||
const componentTypes: ComponentType<any>[] = []; | ||
const systemTypes: (SystemType | any)[] = []; | ||
const systemTypes: (SystemType<System> | any)[] = []; | ||
let lastDefWasSystem = false; | ||
@@ -143,3 +144,7 @@ for (const def of defs.flat(Infinity)) { | ||
execute(time?: number, delta?: number, systems?: SystemBox[]): void { | ||
async initialize(): Promise<void> { | ||
await Promise.all(this.systems.map(system => system.initialize())); | ||
} | ||
async execute(time?: number, delta?: number, systems?: SystemBox[]): Promise<void> { | ||
CHECK: if (this.executing) throw new Error('Recursive system execution not allowed'); | ||
@@ -203,3 +208,2 @@ this.executing = true; | ||
this.deferRequestedRunState(options.stop, RunState.STOPPED); | ||
this.deferRequestedRunState(options.suspend, RunState.SUSPENDED); | ||
this.deferRequestedRunState(options.restart, RunState.RUNNING); | ||
@@ -219,4 +223,3 @@ if (!this.executing) this.processDeferredControls(); | ||
private checkControlOverlap(options: ControlOptions): void { | ||
const stopSet = new Set<SystemType>(); | ||
const suspendSet = new Set<SystemType>(); | ||
const stopSet = new Set<SystemType<System>>(); | ||
for (const def of options.stop.flat(Infinity)) { | ||
@@ -226,17 +229,5 @@ if (!def.__system) continue; | ||
} | ||
for (const def of options.suspend.flat(Infinity)) { | ||
if (!def.__system) continue; | ||
if (stopSet.has(def)) { | ||
throw new Error(`Request to both stop and suspend system ${def.name}`); | ||
} | ||
suspendSet.add(def); | ||
} | ||
for (const def of options.restart.flat(Infinity)) { | ||
if (!def.__system) continue; | ||
if (stopSet.has(def)) { | ||
throw new Error(`Request to both stop and restart system ${def.name}`); | ||
} | ||
if (suspendSet.has(def)) { | ||
throw new Error(`Request to both suspend and restart system ${def.name}`); | ||
} | ||
if (stopSet.has(def)) throw new Error(`Request to both stop and restart system ${def.name}`); | ||
} | ||
@@ -250,3 +241,2 @@ } | ||
case RunState.STOPPED: system.stop(); break; | ||
case RunState.SUSPENDED: system.suspend(); break; | ||
case RunState.RUNNING: system.restart(); break; | ||
@@ -253,0 +243,0 @@ } |
@@ -6,4 +6,4 @@ export {World} from './world'; | ||
export type {SystemType} from './system'; | ||
export {componentTypes, component, prop} from './decorators'; | ||
export {componentTypes, component, field} from './decorators'; | ||
export {Query} from './query'; | ||
export type {ComponentType} from './component'; |
@@ -9,11 +9,15 @@ import {Bitset, LogPointer} from './datastructures'; | ||
export interface SystemType { | ||
new(): System; | ||
export interface SystemType<S extends System> { | ||
new(): S; | ||
} | ||
export const enum RunState { | ||
RUNNING, SUSPENDED, STOPPED | ||
RUNNING, STOPPED | ||
} | ||
class Placeholder { | ||
constructor(readonly type: SystemType<System>) {} | ||
} | ||
export abstract class System { | ||
@@ -26,2 +30,4 @@ static __system = true; | ||
// TODO: support schedule builder | ||
get name(): string {return this.constructor.name;} | ||
@@ -40,2 +46,6 @@ | ||
attach<S extends System>(systemType: SystemType<S>): S { | ||
return new Placeholder(systemType) as unknown as S; | ||
} | ||
createEntity(...initialComponents: (ComponentType<any> | any)[]): Entity { | ||
@@ -49,3 +59,4 @@ return this.__dispatcher.createEntity(initialComponents); | ||
abstract execute(): void; | ||
initialize(): void | Promise<void> { } // eslint-disable-line @typescript-eslint/no-empty-function | ||
execute(): void { } // eslint-disable-line @typescript-eslint/no-empty-function | ||
} | ||
@@ -75,2 +86,19 @@ | ||
replaceAttachmentPlaceholders(): void { | ||
for (const prop in this.system) { | ||
if ((this.system as any)[prop] instanceof Placeholder) { | ||
const targetSystemType = (this.system as any)[prop].type; | ||
const targetSystem = this.dispatcher.systemsByClass.get(targetSystemType); | ||
CHECK: if (!targetSystem) { | ||
throw new Error(`Attached system ${targetSystemType.name} not defined in this world`); | ||
} | ||
(this.system as any)[prop] = targetSystem; | ||
} | ||
} | ||
} | ||
async initialize(): Promise<void> { | ||
await Promise.resolve(this.system.initialize()); | ||
} | ||
execute(time: number, delta: number): void { | ||
@@ -155,9 +183,2 @@ if (this.state !== RunState.RUNNING) return; | ||
} | ||
suspend(): void { | ||
if (this.state === RunState.STOPPED) this.restart(); | ||
// TODO: find a more efficient way of caching results while suspended than leaving them in the | ||
// original logs, but that doesn't lead to duplicates in the entity lists. | ||
this.state = RunState.SUSPENDED; | ||
} | ||
} |
@@ -1,2 +0,2 @@ | ||
import type {Binding, ComponentType, Field} from './component'; | ||
import type {Binding, Component, ComponentType, Field} from './component'; | ||
import {ENTITY_ID_MASK} from './consts'; | ||
@@ -15,2 +15,11 @@ import type {Entity, EntityId} from './entity'; | ||
function checkInvalid(component: Component, binding: Binding<any>) { | ||
if (component.__invalid) { | ||
throw new Error( | ||
`Component instance for ${binding.type.name} is no longer valid, as you already bound it ` + | ||
`to another entity` | ||
); | ||
} | ||
} | ||
export abstract class Type<JSType> { | ||
@@ -35,5 +44,8 @@ constructor(readonly defaultValue: JSType) {} | ||
static weakObject: Type<any>; | ||
// TODO: add autoremove/autodelete when nulled out | ||
static ref: Type<Entity | undefined>; | ||
static backrefs: (type?: ComponentType<any>, fieldName?: string, trackDeletedBackrefs?: boolean) | ||
=> Type<Entity[]>; | ||
// TODO: add array type | ||
// TODO: add struct type | ||
} | ||
@@ -61,5 +73,7 @@ | ||
get(this: C): boolean { | ||
CHECK: checkInvalid(this, binding); | ||
return Boolean(data[binding.index]); | ||
}, | ||
set(this: C, value: boolean): void { | ||
CHECK: checkInvalid(this, binding); | ||
data[binding.index] = value ? 1 : 0; | ||
@@ -72,2 +86,3 @@ } | ||
get(this: C): boolean { | ||
CHECK: checkInvalid(this, binding); | ||
return Boolean(data[binding.index]); | ||
@@ -89,5 +104,7 @@ }, | ||
get(this: C): boolean { | ||
CHECK: checkInvalid(this, binding); | ||
return Boolean(data[binding.index]); | ||
}, | ||
set(this: C, value: boolean): void { | ||
CHECK: checkInvalid(this, binding); | ||
data[binding.index] = value ? 1 : 0; | ||
@@ -100,2 +117,3 @@ } | ||
get(this: C): boolean { | ||
CHECK: checkInvalid(this, binding); | ||
return Boolean(data[binding.index]); | ||
@@ -142,5 +160,7 @@ }, | ||
get(this: C): number { | ||
CHECK: checkInvalid(this, binding); | ||
return data[binding.index]; | ||
}, | ||
set(this: C, value: number): void { | ||
CHECK: checkInvalid(this, binding); | ||
data[binding.index] = value; | ||
@@ -153,2 +173,3 @@ } | ||
get(this: C): number { | ||
CHECK: checkInvalid(this, binding); | ||
return data[binding.index]; | ||
@@ -171,5 +192,7 @@ }, | ||
get(this: C): number { | ||
CHECK: checkInvalid(this, binding); | ||
return data[binding.index]; | ||
}, | ||
set(this: C, value: number): void { | ||
CHECK: checkInvalid(this, binding); | ||
data[binding.index] = value; | ||
@@ -182,2 +205,3 @@ } | ||
get(this: C): number { | ||
CHECK: checkInvalid(this, binding); | ||
return data[binding.index]; | ||
@@ -224,2 +248,3 @@ }, | ||
get(this: C): string { | ||
CHECK: checkInvalid(this, binding); | ||
const index = data[binding.index]; | ||
@@ -231,2 +256,3 @@ const result = choices[index]; | ||
set(this: C, value: string): void { | ||
CHECK: checkInvalid(this, binding); | ||
const index = choicesIndex.get(value); | ||
@@ -241,2 +267,3 @@ if (index === undefined) throw new Error(`Static string not in set: "${value}"`); | ||
get(this: C): string { | ||
CHECK: checkInvalid(this, binding); | ||
const index = data[binding.index]; | ||
@@ -263,2 +290,3 @@ const result = choices[index]; | ||
get(this: C): string { | ||
CHECK: checkInvalid(this, binding); | ||
const index = data[binding.index]; | ||
@@ -270,2 +298,3 @@ const result = choices[index]; | ||
set(this: C, value: string): void { | ||
CHECK: checkInvalid(this, binding); | ||
const index = choicesIndex.get(value); | ||
@@ -280,2 +309,3 @@ if (index === undefined) throw new Error(`Static string not in set: "${value}"`); | ||
get(this: C): string { | ||
CHECK: checkInvalid(this, binding); | ||
const index = data[binding.index]; | ||
@@ -327,2 +357,3 @@ const result = choices[index]; | ||
get(this: C): string { | ||
CHECK: checkInvalid(this, binding); | ||
const length = lengths[binding.index * lengthsStride]; | ||
@@ -333,2 +364,3 @@ return decoder.decode( | ||
set(this: C, value: string): void { | ||
CHECK: checkInvalid(this, binding); | ||
const encodedString = encoder.encode(value); | ||
@@ -346,2 +378,3 @@ if (encodedString.byteLength > maxUtf8Length) { | ||
get(this: C): string { | ||
CHECK: checkInvalid(this, binding); | ||
const length = lengths[binding.index * lengthsStride]; | ||
@@ -369,2 +402,3 @@ return decoder.decode( | ||
get(this: C): string { | ||
CHECK: checkInvalid(this, binding); | ||
const length = lengths[binding.index * lengthsStride]; | ||
@@ -375,2 +409,3 @@ return decoder.decode( | ||
set(this: C, value: string): void { | ||
CHECK: checkInvalid(this, binding); | ||
const encodedString = encoder.encode(value); | ||
@@ -388,2 +423,3 @@ if (encodedString.byteLength > maxUtf8Length) { | ||
get(this: C): string { | ||
CHECK: checkInvalid(this, binding); | ||
const length = lengths[binding.index * lengthsStride]; | ||
@@ -449,2 +485,3 @@ return decoder.decode( | ||
get(this: C): Entity | undefined { | ||
CHECK: checkInvalid(this, binding); | ||
const id = data[binding.index]; | ||
@@ -455,2 +492,3 @@ if (id === -1 || (id & STALE_REF_BIT) && !registry.includeRecentlyDeleted) return; | ||
set(this: C, value: Entity | undefined | null): void { | ||
CHECK: checkInvalid(this, binding); | ||
CHECK: if (value && !registry.hasShape(value.__id, registry.Alive, false)) { | ||
@@ -471,2 +509,3 @@ throw new Error('Referencing a deleted entity is not allowed'); | ||
get(this: C): Entity | undefined { | ||
CHECK: checkInvalid(this, binding); | ||
const id = data[binding.index]; | ||
@@ -510,2 +549,3 @@ if (id === -1 || (id & STALE_REF_BIT) && !registry.includeRecentlyDeleted) return; | ||
get(this: C): Entity | undefined { | ||
CHECK: checkInvalid(this, binding); | ||
const id = data[binding.index]; | ||
@@ -516,2 +556,3 @@ if (id === -1 || (id & STALE_REF_BIT) && !registry.includeRecentlyDeleted) return; | ||
set(this: C, value: Entity | undefined | null): void { | ||
CHECK: checkInvalid(this, binding); | ||
CHECK: if (value && !registry.hasShape(value.__id, registry.Alive, false)) { | ||
@@ -532,2 +573,3 @@ throw new Error('Referencing a deleted entity is not allowed'); | ||
get(this: C): Entity | undefined { | ||
CHECK: checkInvalid(this, binding); | ||
const id = data[binding.index]; | ||
@@ -590,2 +632,3 @@ if (id === -1 || (id & STALE_REF_BIT) && !registry.includeRecentlyDeleted) return; | ||
get(this: C): Entity[] { | ||
CHECK: checkInvalid(this, binding); | ||
CHECK: if (!trackDeletedBackrefs && binding.dispatcher.registry.includeRecentlyDeleted) { | ||
@@ -599,2 +642,3 @@ throw new Error( | ||
set(this: C, value: Entity[]): void { | ||
CHECK: checkInvalid(this, binding); | ||
CHECK: if (value !== EMPTY_ARRAY) { | ||
@@ -626,5 +670,7 @@ throw new Error('Backrefs properties are computed automatically, you cannot set them'); | ||
get(this: C): any { | ||
CHECK: checkInvalid(this, binding); | ||
return data[binding.index]; | ||
}, | ||
set(this: C, value: any): void { | ||
CHECK: checkInvalid(this, binding); | ||
data[binding.index] = value; | ||
@@ -637,2 +683,3 @@ } | ||
get(this: C): any { | ||
CHECK: checkInvalid(this, binding); | ||
return data[binding.index]; | ||
@@ -654,5 +701,7 @@ }, | ||
get(this: C): any { | ||
CHECK: checkInvalid(this, binding); | ||
return data[binding.index]; | ||
}, | ||
set(this: C, value: any): void { | ||
CHECK: checkInvalid(this, binding); | ||
data[binding.index] = value; | ||
@@ -665,2 +714,3 @@ } | ||
get(this: C): any { | ||
CHECK: checkInvalid(this, binding); | ||
return data[binding.index]; | ||
@@ -693,2 +743,3 @@ }, | ||
get(this: C): any { | ||
CHECK: checkInvalid(this, binding); | ||
const value = data[binding.index]; | ||
@@ -699,2 +750,3 @@ if (value === null || value === undefined) return value; | ||
set(this: C, value: any): void { | ||
CHECK: checkInvalid(this, binding); | ||
if (value !== null && value !== undefined) { | ||
@@ -715,2 +767,3 @@ const weakRef = new WeakRef(value); | ||
get(this: C): any { | ||
CHECK: checkInvalid(this, binding); | ||
const value = data[binding.index]; | ||
@@ -735,2 +788,3 @@ if (value === null || value === undefined) return value; | ||
get(this: C): any { | ||
CHECK: checkInvalid(this, binding); | ||
const value = data[binding.index]; | ||
@@ -741,2 +795,3 @@ if (value === null || value === undefined) return value; | ||
set(this: C, value: any): void { | ||
CHECK: checkInvalid(this, binding); | ||
if (value !== null && value !== undefined) { | ||
@@ -757,2 +812,3 @@ const weakRef = new WeakRef(value); | ||
get(this: C): any { | ||
CHECK: checkInvalid(this, binding); | ||
const value = data[binding.index]; | ||
@@ -759,0 +815,0 @@ if (value === null || value === undefined) return value; |
@@ -6,7 +6,18 @@ import type {ComponentType} from './component'; | ||
const MAGIC_COOKIE = {}; | ||
export class World { | ||
private readonly __dispatcher: Dispatcher; | ||
constructor(options: WorldOptions) { | ||
static async create(options: WorldOptions): Promise<World> { | ||
const world = new World(options, MAGIC_COOKIE); | ||
await world.__dispatcher.initialize(); | ||
return world; | ||
} | ||
private constructor(options: WorldOptions, magicCookie: any) { | ||
if (magicCookie !== MAGIC_COOKIE) { | ||
throw new Error(`Don't call World constructor directly; use World.create instead`); | ||
} | ||
this.__dispatcher = new Dispatcher(options); | ||
@@ -23,4 +34,4 @@ } | ||
execute(time?: number, delta?: number): void { | ||
this.__dispatcher.execute(time, delta); | ||
execute(time?: number, delta?: number): Promise<void> { | ||
return this.__dispatcher.execute(time, delta); | ||
} | ||
@@ -36,1 +47,2 @@ | ||
} | ||
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2325875
52
17344