diff --git a/dist/thyseus.d.ts b/dist/thyseus.d.ts index 27a2451..37f0c2c 100644 --- a/dist/thyseus.d.ts +++ b/dist/thyseus.d.ts @@ -502,10 +502,8 @@ declare class SystemDefinition { after(...others: SystemDefinition[]): this; beforeAll(): this; afterAll(): this; - getAndClearDependencies(): { - dependencies: SystemDefinition[]; - implicitPosition: 0 | 1 | -1; - }; + clone(): SystemDefinition; + getAndClearDependencies(): SystemDependencies; } type SystemArguments = { [Index in keyof T]: ReturnType; diff --git a/dist/thyseus.js b/dist/thyseus.js index d0e0aaa..364fcb8 100644 --- a/dist/thyseus.js +++ b/dist/thyseus.js @@ -1,5 +1,5 @@ import { DEV as I } from "esm-env"; -class et { +class st { isLocalToThread() { return !1; } @@ -12,7 +12,7 @@ class et { onAddSystem(t) { } } -class st { +class it { #t = []; #e = 0; #s; @@ -125,14 +125,14 @@ function b(n, t, e) { i = t(i, s); return i; } -function it(n, t) { +function nt(n, t) { b(t, function e(i, s) { s instanceof U || s instanceof W ? (Array.isArray(s.value) ? s.value : [s.value]).forEach( (r) => n.registerComponent(r) ) : s instanceof N && (b(s.l, e), b(s.r, e)); }); } -function nt(n, t, e, i) { +function rt(n, t, e, i) { const s = b( i, function o(h, a) { @@ -211,15 +211,15 @@ class O { ) : !1; } onAddSystem(t) { - this.components.forEach((e) => t.registerComponent(e)), it(t, this.filters); + this.components.forEach((e) => t.registerComponent(e)), nt(t, this.filters); } intoArgument(t) { - const { withs: e, withouts: i } = nt( + const { withs: e, withouts: i } = rt( t.components, this.components, this.optionals, this.filters - ), s = new st(e, i, this.isIndividual, this.components, t.commands); + ), s = new it(e, i, this.isIndividual, this.components, t.commands); return t.queries.push(s), s; } } @@ -246,7 +246,7 @@ const y = { i64: BigInt64Array, f32: Float32Array, f64: Float64Array -}, rt = (n, t, e) => { +}, ot = (n, t, e) => { const i = _.reduce( (r, o, h) => o < t && h < r ? h : r, _.length @@ -261,9 +261,9 @@ const y = { E[m[r]] += e; }; function S(n, t, e, i = 0) { - return T = Math.max(T, t), q |= i, rt(n, t, e), C += e, E; + return T = Math.max(T, t), q |= i, ot(n, t, e), C += e, E; } -function ot() { +function ht() { const n = { schema: q, size: Math.ceil(C / T) * T, @@ -295,7 +295,7 @@ function d(n) { }; }; } -const ht = d("u8"), at = d("u16"), ut = d("u32"), ct = d("u64"), lt = d("i8"), ft = d("i16"), dt = d("i32"), mt = d("i64"), gt = d("f32"), pt = d("f64"), _t = function() { +const at = d("u8"), ut = d("u16"), ct = d("u32"), lt = d("u64"), ft = d("i8"), dt = d("i16"), mt = d("i32"), gt = d("i64"), pt = d("f32"), _t = d("f64"), Et = function() { return function(t, e) { const i = S( e, @@ -313,8 +313,8 @@ const ht = d("u8"), at = d("u16"), ut = d("u32"), ct = d("u64"), lt = d("i8"), f } }); }; -}, Et = new TextEncoder(), wt = new TextDecoder(); -function yt({ +}, wt = new TextEncoder(), yt = new TextDecoder(); +function $t({ characterCount: n, byteLength: t }) { @@ -328,7 +328,7 @@ function yt({ Object.defineProperty(i, s, { enumerable: !0, get() { - return wt.decode( + return yt.decode( this.__$$s.u8.subarray( this.__$$b + r[s], this.__$$b + r[s] + t @@ -336,7 +336,7 @@ function yt({ ).split("\0")[0]; }, set(o) { - Et.encodeInto( + wt.encodeInto( o, this.__$$s.u8.subarray( this.__$$b + r[s], @@ -347,7 +347,7 @@ function yt({ }); }; } -function $t({ type: n, length: t }) { +function Tt({ type: n, length: t }) { return function(i, s) { const r = D[n], o = S( s, @@ -372,7 +372,7 @@ function $t({ type: n, length: t }) { }); }; } -function Tt(n) { +function bt(n) { return function(e, i) { const s = S( i, @@ -397,7 +397,7 @@ function Tt(n) { } function f() { return function(t) { - const { schema: e, size: i, alignment: s } = ot(); + const { schema: e, size: i, alignment: s } = ht(); return class extends t { static schema = e | (t.schema ?? 0); static size = i; @@ -417,21 +417,21 @@ function f() { }; }; } -f.bool = _t; -f.u8 = ht; -f.u16 = at; -f.u32 = ut; -f.u64 = ct; -f.i8 = lt; -f.i16 = ft; -f.i32 = dt; -f.i64 = mt; -f.f32 = gt; -f.f64 = pt; -f.string = yt; -f.array = $t; -f.substruct = Tt; -function Q(n) { +f.bool = Et; +f.u8 = at; +f.u16 = ut; +f.u32 = ct; +f.u64 = lt; +f.i8 = ft; +f.i16 = dt; +f.i32 = mt; +f.i64 = gt; +f.f32 = pt; +f.f64 = _t; +f.string = $t; +f.array = Tt; +f.substruct = bt; +function j(n) { return typeof n == "function" && typeof n.size == "number" && typeof n.alignment == "number" && typeof n.schema == "number"; } class Y { @@ -442,7 +442,7 @@ class Y { this.resource = e ? t.value : t, this.canWrite = e; } isLocalToThread() { - return !Q(this.resource); + return !j(this.resource); } intersectsWith(t) { return t instanceof Y ? this.resource === t.resource && (this.canWrite || t.canWrite) : !1; @@ -454,7 +454,7 @@ class Y { return t.resources.get(this.resource); } } -class bt { +class At { isLocalToThread() { return !0; } @@ -470,11 +470,11 @@ class bt { function g(n) { return (...t) => new n(...t); } -const At = { - Commands: g(et), +const St = { + Commands: g(st), Query: g(O), Res: g(Y), - World: g(bt), + World: g(At), Mut: g($), Optional: g(M), With: g(U), @@ -483,7 +483,7 @@ const At = { return new N(n, t); } }; -class St { +class F { #t = 0; #e = []; #s; @@ -492,7 +492,7 @@ class St { this.#s = t, this.fn = e; } get parameters() { - return this.#s(At); + return this.#s(St); } before(...t) { for (const e of t) @@ -510,6 +510,9 @@ class St { afterAll() { return this.#t = 1, this; } + clone() { + return new F(this.#s, this.fn); + } getAndClearDependencies() { const t = { dependencies: this.#e, @@ -519,7 +522,7 @@ class St { } } function zt(n, t) { - return new St(n, t); + return new F(n, t); } class l { static schema = y.u64 | y.u32; @@ -557,12 +560,12 @@ class l { } } const [, ...vt] = Object.entries(D); -function j(n, t) { +function Z(n, t) { return vt.reduce((e, [i, s]) => ((y[i] & n.schema) === y[i] && (e[i] = new s(e.buffer)), e), t); } -function Z(n, t, e) { +function V(n, t, e) { const i = n.createBuffer(t.size * e); - return j(t, { + return Z(t, { buffer: i, u8: new Uint8Array(i) }); @@ -571,14 +574,14 @@ function Bt(n, t, e) { const i = new n.buffer.constructor( t.size * e ), s = new Uint8Array(i); - return s.set(n.u8), n.buffer = i, n.u8 = s, j(t, n); + return s.set(n.u8), n.buffer = i, n.u8 = s, Z(t, n); } class L { static create(t, e, i, s) { const r = t.config.getNewTableSize(0); return new this( t, - e.reduce((o, h) => (h.size > 0 && o.set(h, Z(t, h, r)), o), /* @__PURE__ */ new Map()), + e.reduce((o, h) => (h.size > 0 && o.set(h, V(t, h, r)), o), /* @__PURE__ */ new Map()), r, i, s @@ -791,13 +794,13 @@ class A { ), this.deleteListener(e)), this.#i.length = 0, i; } } -const V = z( +const G = z( "thyseus::getCommandQueue", (n) => () => { const t = new Map(n.commands.queue); return n.commands.queue.clear(), t; } -), G = z( +), H = z( "thyseus::sendTable", (n) => (t, e, i, s) => { const r = [...w(s)].reduce((h, a, c) => (n.components[a].size > 0 && h.set(n.components[a], t.shift()), h), /* @__PURE__ */ new Map()), o = new L(n, r, e, s, i); @@ -805,7 +808,7 @@ const V = z( for (const h of n.queries) h.testAdd(s, o); } -), H = z( +), J = z( "thyseus::resizeTable", (n) => (t, e, i) => { const s = n.archetypes[t]; @@ -814,7 +817,7 @@ const V = z( for (const o of s.columns.keys()) s.columns.set(o, i[r++]); } -), J = z( +), X = z( "thyseus::resizeTableLengths", (n) => (t) => { n.tableLengths = t; @@ -830,11 +833,11 @@ const V = z( s === void 0 ? n.set(e, i) : s !== 0n && n.set(e, s | i); } return n; -}, X = zt( +}, K = zt( ({ World: n }) => [n()], async function(t) { t.entities.isFull && t.entities.grow(t); - const e = (await t.threads.send(V())).reduce( + const e = (await t.threads.send(G())).reduce( Rt, t.commands.queue ); @@ -844,7 +847,7 @@ const V = z( } ); function qt(n) { - n.registerComponent(l), n.addSystem(X.afterAll()), n.registerThreadChannel(V), n.registerThreadChannel(G), n.registerThreadChannel(H), n.registerThreadChannel(J); + n.registerComponent(l), n.addSystem(K.afterAll()), n.registerThreadChannel(G), n.registerThreadChannel(H), n.registerThreadChannel(J), n.registerThreadChannel(X); } function Ut(n, t) { return n.parameters.some( @@ -853,7 +856,7 @@ function Ut(n, t) { ) ) ? 1 : 0; } -function K(n) { +function tt(n) { return n.map( (t) => n.reduce( (e, i, s) => e | BigInt(Ut(t, i)) << BigInt(s), @@ -861,7 +864,7 @@ function K(n) { ) ); } -function tt(n, t, e) { +function et(n, t, e) { const i = t.map( (r) => r.dependencies.reduce((o, h) => { const a = n.indexOf(h); @@ -888,7 +891,7 @@ function tt(n, t, e) { } return i.forEach((r, o) => i[o] &= e[o]), i; } -function F(n, t, e) { +function k(n, t, e) { for (const i of w(t)) if (n[i] === e) return !1; @@ -900,9 +903,9 @@ const B = (...n) => { class Nt { static fromWorld(t, e, i) { const s = t.threads.queue( - () => K(e) + () => tt(e) ), r = t.threads.queue( - () => tt(e, i, s) + () => et(e, i, s) ), o = t.threads.isMainThread ? e.map(() => !0) : e.map((c) => !c.parameters.some((u) => u.isLocalToThread())), h = t.threads.queue( () => t.createBuffer(8 + e.length * 3) ), a = t.threads.queue( @@ -956,7 +959,7 @@ class Nt { let t = -1; if (await navigator.locks.request(this.#f, () => { t = this.#i.findIndex( - (e, i) => !!e && F(this.#r, this.#c[i], 0) && F(this.#n, this.#h[i], 1) && this.#o[i] + (e, i) => !!e && k(this.#r, this.#c[i], 0) && k(this.#n, this.#h[i], 1) && this.#o[i] ), t !== -1 && (this.#i[t] = 0, this.#n[t] = 1, this.#l--); }), t === -1) { await this.#E(); @@ -983,10 +986,10 @@ class Nt { } class Ot { static fromWorld(t, e, i) { - const s = tt( + const s = et( e, i, - K(e) + tt(e) ), r = s.reduce(function o(h, a, c) { for (const u of w(a)) o(h, s[u], u); @@ -1063,7 +1066,7 @@ class Dt { await i.fn( ...i.parameters.map((s) => s.intoArgument(e)) ); - await X.fn(e); + await K.fn(e); } return e; } @@ -1148,7 +1151,7 @@ function Qt(n, t) { const e = Ft(n); return I && kt(e, t), e; } -const k = 64; +const Q = 64; class jt { static new(t, e) { return new Dt(Qt(t, e), e); @@ -1171,7 +1174,7 @@ class jt { this.#t = t.threads > 1 ? SharedArrayBuffer : ArrayBuffer, this.config = t, this.threads = e, this.tableLengths = this.threads.queue( () => new Uint32Array( this.createBuffer( - k * Uint32Array.BYTES_PER_ELEMENT + Q * Uint32Array.BYTES_PER_ELEMENT ) ) ), this.archetypeLookup.set(0n, 1); @@ -1187,9 +1190,9 @@ class jt { ); this.components = s, this.entities = Ct.fromWorld(this), this.commands = Yt.fromWorld(this), this.executor = i.fromWorld(this, o, h); for (const u of r) - if (Q(u)) { + if (j(u)) { const x = this.threads.queue( - () => Z(this, u, 1) + () => V(this, u, 1) ); this.resources.set( u, @@ -1223,9 +1226,9 @@ class jt { const s = this.tableLengths; this.tableLengths = new Uint32Array( this.createBuffer( - s.length + k * Uint32Array.BYTES_PER_ELEMENT + s.length + Q * Uint32Array.BYTES_PER_ELEMENT ) - ), this.tableLengths.set(s), this.threads.send(J(this.tableLengths)); + ), this.tableLengths.set(s), this.threads.send(X(this.tableLengths)); } const e = this.archetypes.length, i = L.create( this, @@ -1234,7 +1237,7 @@ class jt { e ); this.archetypeLookup.set(t, e), this.archetypes.push(i), this.threads.send( - G( + H( [...i.columns.values()], i.capacity, e, @@ -1247,7 +1250,7 @@ class jt { } #s(t) { t.grow(this), this.threads.send( - H(t.id, t.capacity, [...t.columns.values()]) + J(t.id, t.capacity, [...t.columns.values()]) ); } } @@ -1257,7 +1260,7 @@ function Vt(n) { export { l as Entity, jt as World, - X as applyCommands, + K as applyCommands, z as createThreadChannel, Vt as definePlugin, zt as defineSystem, diff --git a/dist/thyseus.umd.cjs b/dist/thyseus.umd.cjs index cd714d1..ebf853d 100644 --- a/dist/thyseus.umd.cjs +++ b/dist/thyseus.umd.cjs @@ -1 +1 @@ -(function(d,p){typeof exports=="object"&&typeof module<"u"?p(exports,require("esm-env")):typeof define=="function"&&define.amd?define(["exports","esm-env"],p):(d=typeof globalThis<"u"?globalThis:d||self,p(d.Thyseus={},d.esm_env))})(this,function(d,p){"use strict";class nt{isLocalToThread(){return!1}intersectsWith(t){return!1}intoArgument(t){return t.commands}onAddSystem(t){}}class rt{#t=[];#e=0;#s;#i;#n;#r;#o;#h;constructor(t,e,i,s,r){this.#i=t,this.#o=i,this.#n=e,this.#r=s,this.#h=r,this.#s=this.#r.map(o=>new o({},0,r))}get size(){return this.#t.reduce((t,e)=>t+e.size,0)}*[Symbol.iterator](){this.#e>=this.#s.length&&this.#s.push(...this.#r.map(i=>new i({},0,this.#h)));const t=this.#s.slice(this.#e,this.#e+this.#r.length),e=this.#e;this.#e+=this.#r.length;for(const i of this.#t){t.forEach((s,r)=>{const o=this.#s[r+e],h=i.columns.get(o.constructor);h?(t[r]=o,t[r].__$$s=h):t[r]=null});for(let s=0;s(Array.isArray(t)?t:[t]).reduce((i,s,r)=>e[r]?i:i|1n<n.registerComponent(r)):s instanceof R&&(A(s.l,e),A(s.r,e))})}function ht(n,t,e,i){const s=A(i,function o(h,u){if(u instanceof q){const c=U(n,u.value);return{withs:h.withs.map(a=>a|c),withouts:h.withouts}}else if(u instanceof x){const c=U(n,u.value);return{withs:h.withs,withouts:h.withouts.map(a=>a|c)}}else if(u instanceof R){const c=A(u.l,o,h),a=A(u.r,o,h);return{withs:[...c.withs,...a.withs],withouts:[...c.withouts,...a.withouts]}}throw new Error(`Unrecognized filter (${u.constructor.name}) in Query.`)},{withs:[U(n,t,e)],withouts:[0n]}),r=s.withs.reduce((o,h,u)=>(s.withs[u]&s.withouts[u])===0n?o.add(u):o,new Set);return s.withs=s.withs.filter((o,h)=>r.has(h)),s.withouts=s.withouts.filter((o,h)=>r.has(h)),p.DEV&&_(s.withs.length>0,"Tried to construct a query that cannot match any entities."),s}class W{components=[];writes=[];optionals=[];filters;isIndividual;constructor(t,e=[]){this.isIndividual=!Array.isArray(t);const i=Array.isArray(t)?t:[t];for(const s of i){const r=s instanceof b||s instanceof M&&s.value instanceof b;this.writes.push(r),this.optionals.push(s instanceof M);const o=s instanceof b?s.value:s instanceof M?s.value instanceof b?s.value.value:s.value:s;p.DEV&&_(o.size>0,"You may not request direct access to ZSTs - use a With filter instead."),this.components.push(o)}this.filters=e}isLocalToThread(){return!1}intersectsWith(t){return t instanceof W?this.components.some((e,i)=>t.components.some((s,r)=>e===s&&(this.writes[i]||t.writes[r]))):!1}onAddSystem(t){this.components.forEach(e=>t.registerComponent(e)),ot(t,this.filters)}intoArgument(t){const{withs:e,withouts:i}=ht(t.components,this.components,this.optionals,this.filters),s=new rt(e,i,this.isIndividual,this.components,t.commands);return t.queries.push(s),s}}let D=0,S=1,C=0,g=[],y=[],w={};const $={u8:1<<0,u16:1<<1,u32:1<<2,u64:1<<3,i8:1<<4,i16:1<<5,i32:1<<6,i64:1<<7,f32:1<<8,f64:1<<9},N={u8:Uint8Array,u16:Uint16Array,u32:Uint32Array,u64:BigUint64Array,i8:Int8Array,i16:Int16Array,i32:Int32Array,i64:BigInt64Array,f32:Float32Array,f64:Float64Array},ut=(n,t,e)=>{const i=y.reduce((r,o,h)=>o>o)+r[i]]},set(h){this.__$$s[n][(this.__$$b>>o)+r[i]]=h}})}}}const ct=m("u8"),ft=m("u16"),lt=m("u32"),dt=m("u64"),mt=m("i8"),gt=m("i16"),pt=m("i32"),_t=m("i64"),Et=m("f32"),yt=m("f64"),wt=function(){return function(t,e){const i=v(e,Uint8Array.BYTES_PER_ELEMENT,Uint8Array.BYTES_PER_ELEMENT,$.u8);Object.defineProperty(t,e,{enumerable:!0,get(){return!!this.__$$s.u8[this.__$$b+i[e]]},set(s){this.__$$s.u8[this.__$$b+i[e]]=Number(s)}})}},$t=new TextEncoder,Tt=new TextDecoder;function bt({characterCount:n,byteLength:t}){return function(i,s){t??=n*3;const r=v(s,Uint8Array.BYTES_PER_ELEMENT,t);Object.defineProperty(i,s,{enumerable:!0,get(){return Tt.decode(this.__$$s.u8.subarray(this.__$$b+r[s],this.__$$b+r[s]+t)).split("\0")[0]},set(o){$t.encodeInto(o,this.__$$s.u8.subarray(this.__$$b+r[s],this.__$$b+r[s]+t).fill(0))}})}}function At({type:n,length:t}){return function(i,s){const r=N[n],o=v(s,r.BYTES_PER_ELEMENT,r.BYTES_PER_ELEMENT*t,$[n]),h=31-Math.clz32(r.BYTES_PER_ELEMENT);Object.defineProperty(i,s,{enumerable:!0,get(){return this.__$$s[n].subarray((this.__$$b>>h)+o[s],(this.__$$b>>h)+o[s]+t)},set(u){this.__$$s[n].set(u.subarray(0,t),(this.__$$b>>h)+o[s])}})}}function St(n){return function(e,i){const s=v(i,n.alignment,n.size,n.schema);Object.defineProperty(e,i,{enumerable:!0,get(){const r=new n(this.__$$s,0,{});return r.__$$b=this.__$$b+s[i]*n.alignment,r},set(r){this.__$$s.u8.set(r.__$$s,this.__$$b+s[i]*n.alignment)}})}}function f(){return function(t){const{schema:e,size:i,alignment:s}=at();return class extends t{static schema=e|(t.schema??0);static size=i;static alignment=s;__$$s;__$$b;#t;get __$$i(){return this.#t}set __$$i(r){this.#t=r,this.__$$b=r*this.constructor.size}constructor(r,o){super(),this.__$$s=r,this.#t=o,this.__$$b=o*this.constructor.size}}}}f.bool=wt,f.u8=ct,f.u16=ft,f.u32=lt,f.u64=dt,f.i8=mt,f.i16=gt,f.i32=pt,f.i64=_t,f.f32=Et,f.f64=yt,f.string=bt,f.array=At,f.substruct=St;function Q(n){return typeof n=="function"&&typeof n.size=="number"&&typeof n.alignment=="number"&&typeof n.schema=="number"}class O{resource;canWrite;constructor(t){const e=t instanceof b;this.resource=e?t.value:t,this.canWrite=e}isLocalToThread(){return!Q(this.resource)}intersectsWith(t){return t instanceof O?this.resource===t.resource&&(this.canWrite||t.canWrite):!1}onAddSystem(t){t.registerResource(this.resource)}intoArgument(t){return t.resources.get(this.resource)}}class zt{isLocalToThread(){return!0}intersectsWith(t){return!0}intoArgument(t){return t}onAddSystem(t){}}function E(n){return(...t)=>new n(...t)}const vt={Commands:E(nt),Query:E(W),Res:E(O),World:E(zt),Mut:E(b),Optional:E(M),With:E(q),Without:E(x),Or(n,t){return new R(n,t)}};class Bt{#t=0;#e=[];#s;fn;constructor(t,e){this.#s=t,this.fn=e}get parameters(){return this.#s(vt)}before(...t){for(const e of t)e.after(this);return this}after(...t){for(const e of t)this.#e.push(e);return this}beforeAll(){return this.#t=-1,this}afterAll(){return this.#t=1,this}getAndClearDependencies(){const t={dependencies:this.#e,implicitPosition:this.#t};return this.#e=[],this.#t=0,t}}function j(n,t){return new Bt(n,t)}class l{static schema=$.u64|$.u32;static size=8;__$$s;__$$b;#t;#e;constructor(t,e,i){this.__$$s=t,this.#t=e,this.__$$b=e*l.size,this.#e=i}get __$$i(){return this.#t}set __$$i(t){this.#t=t,this.__$$b=t*l.size}get id(){return this.__$$s.u64[this.__$$b>>3]}get index(){return this.__$$s.u32[this.__$$b>>2]}get generation(){return this.__$$s.u32[(this.__$$b>>2)+1]}insert(t){return this.#e.insertInto(this.id,t),this}remove(t){return this.#e.removeFrom(this.id,t),this}despawn(){this.#e.despawn(this.id)}}const[,...Mt]=Object.entries(N);function V(n,t){return Mt.reduce((e,[i,s])=>(($[i]&n.schema)===$[i]&&(e[i]=new s(e.buffer)),e),t)}function Z(n,t,e){const i=n.createBuffer(t.size*e);return V(t,{buffer:i,u8:new Uint8Array(i)})}function Ct(n,t,e){const i=new n.buffer.constructor(t.size*e),s=new Uint8Array(i);return s.set(n.u8),n.buffer=i,n.u8=s,V(t,n)}class L{static create(t,e,i,s){const r=t.config.getNewTableSize(0);return new this(t,e.reduce((o,h)=>(h.size>0&&o.set(h,Z(t,h,r)),o),new Map),r,i,s)}#t;columns;capacity;bitfield;#e;constructor(t,e,i,s,r){this.#t=t,this.columns=e,this.capacity=i,this.bitfield=s,this.#e=r}get id(){return this.#e}get size(){return this.#t.tableLengths[this.#e]}set size(t){this.#t.tableLengths[this.#e]=t}get isFull(){return this.capacity===this.size}delete(t){this.size--;for(const[e,i]of this.columns)i.u8.copyWithin(t*e.size,this.size*e.size,this.size*e.size+e.size),i.u8.fill(0,this.size*e.size,this.size*e.size+e.size)}move(t,e){const i=this.columns.get(l).u64[this.size-1];for(const[s,r]of this.columns)e.columns.has(s)&&e.columns.get(s).u8.set(r.u8.slice(t*s.size,t*s.size+s.size),e.size*s.size);return e.size++,this.delete(t),i}grow(t){this.capacity=t.config.getNewTableSize(this.capacity);for(const[e,i]of this.columns)this.columns.set(e,Ct(i,e,this.capacity))}incrementGeneration(t){this.columns.get(l).u32[(t<<1)+1]++}}const Lt=0x00000000ffffffffn,I=n=>Number(n&Lt),Y=256;class It{static fromWorld(t){const e=BigUint64Array.BYTES_PER_ELEMENT*Y;return new this(t,t.threads.queue(()=>new Uint32Array(t.createBuffer(e))),t.threads.queue(()=>new Uint32Array(t.createBuffer(8))),t.archetypes[0])}#t;#e;#s;#i;constructor(t,e,i,s){this.#t=t,this.#e=e,this.#s=i,this.#i=s}get isFull(){return this.#s[0]>=this.#e.length>>1}spawn(){const t=this.#i.size;for(let e=this.#n();e>=1n,t++}let qt=1;function z(n,t){function e(...i){return[n,qt++,i]}return e.channelName=n,e.onReceive=t,e}const xt=[];class B{static isMainThread=!!globalThis.document;isMainThread=B.isMainThread;static spawn(t,e){return new this(B.isMainThread?Array.from({length:t},()=>new Worker(e,{type:"module"})):[globalThis])}#t=new Map;#e=new Map;#s={};#i=[];#n;constructor(t){this.#n=t;const e=({currentTarget:i,data:[s,r,o]})=>{if(this.#t.has(r)){const h=this.#e.get(r);h.push(o),h.length===this.#n.length&&(this.#t.get(r)(h),this.#t.delete(r),this.#e.delete(r))}else s in this.#s?i.postMessage([s,r,this.#s[s](...o)]):i.postMessage([s,r,null])};for(const i of this.#n)i.addEventListener("message",e)}setListener(t,e){this.#s[t]=e}deleteListener(t){delete this.#s[t]}send(t){return this.#n.length===0?Promise.resolve(xt):new Promise(e=>{for(const i of this.#n)i.postMessage(t);this.#e.set(t[1],[]),this.#t.set(t[1],e)})}queue(t){if(B.isMainThread){const e=t();return this.#i.push(e),e}return this.#i.shift()}async wrapInQueue(t){const e="threadGroup::queue";let i;return this.isMainThread?(i=await t(),await this.send([e,0,[this.#i]])):(i=await new Promise(s=>this.setListener(e,r=>{this.#i=r,s(t())})),this.deleteListener(e)),this.#i.length=0,i}}const G=z("thyseus::getCommandQueue",n=>()=>{const t=new Map(n.commands.queue);return n.commands.queue.clear(),t}),H=z("thyseus::sendTable",n=>(t,e,i,s)=>{const r=[...T(s)].reduce((h,u,c)=>(n.components[u].size>0&&h.set(n.components[u],t.shift()),h),new Map),o=new L(n,r,e,s,i);n.archetypes[i]=o;for(const h of n.queries)h.testAdd(s,o)}),J=z("thyseus::resizeTable",n=>(t,e,i)=>{const s=n.archetypes[t];s.capacity=e;let r=0;for(const o of s.columns.keys())s.columns.set(o,i[r++])}),X=z("thyseus::resizeTableLengths",n=>t=>{n.tableLengths=t}),Rt=z("thyseus::resizeEntityLocations",n=>t=>{n.entities.setLocations(t)}),Ut=(n,t)=>{for(const[e,i]of t){const s=n.get(e);s===void 0?n.set(e,i):s!==0n&&n.set(e,s|i)}return n},F=j(({World:n})=>[n()],async function(t){t.entities.isFull&&t.entities.grow(t);const e=(await t.threads.send(G())).reduce(Ut,t.commands.queue);for(const[i,s]of e)t.moveEntity(i,s);e.clear(),t.entities.resetCursor()});function Wt(n){n.registerComponent(l),n.addSystem(F.afterAll()),n.registerThreadChannel(G),n.registerThreadChannel(H),n.registerThreadChannel(J),n.registerThreadChannel(X)}function Dt(n,t){return n.parameters.some(e=>t.parameters.some(i=>e.intersectsWith(i)||i.intersectsWith(e)))?1:0}function K(n){return n.map(t=>n.reduce((e,i,s)=>e|BigInt(Dt(t,i))<r.dependencies.reduce((o,h)=>{const u=n.indexOf(h);return u===-1?o:o|1n<{_((r&1n<i[o]&=e[o]),i}function et(n,t,e){for(const i of T(t))if(n[i]===e)return!1;return!0}let Nt=0;const P=(...n)=>{};class Ot{static fromWorld(t,e,i){const s=t.threads.queue(()=>K(e)),r=t.threads.queue(()=>tt(e,i,s)),o=t.threads.isMainThread?e.map(()=>!0):e.map(c=>!c.parameters.some(a=>a.isLocalToThread())),h=t.threads.queue(()=>t.createBuffer(8+e.length*3)),u=t.threads.queue(()=>`thyseus::ParallelExecutor${Nt++}`);return new this(t,new Uint32Array(h,0,2),new Uint8Array(h,8,e.length),new Uint8Array(h,8+e.length,e.length),new Uint8Array(h,8+e.length*2,e.length),s,r,o,u)}#t=P;#e=P;#s;#i;#n;#r;#o;#h;#c;#l;#u;#d;#a;#m;constructor(t,e,i,s,r,o,h,u,c){this.#a=t.systems,this.#m=t.arguments,this.#d=t.threads.isMainThread,this.#h=o,this.#c=h,this.#o=u,this.#s=e,this.#i=i,this.#n=s,this.#r=r,this.#u=new BroadcastChannel(c),this.#l=c,this.#u.addEventListener("message",({data:a})=>{a===0?this.#g():a===1?(this.#t(),this.#t=P):(this.#e(),this.#e=P)})}async start(){return this.#f=this.#a.length,this.#s[1]=0,this.#i.fill(1),this.#r.fill(0),this.#n.fill(0),this.#p(),this.#g()}get#f(){return this.#s[0]}set#f(t){this.#s[0]=t}async#g(){for(;this.#f>0;){let t=-1;if(await navigator.locks.request(this.#l,()=>{t=this.#i.findIndex((e,i)=>!!e&&et(this.#r,this.#c[i],0)&&et(this.#n,this.#h[i],1)&&this.#o[i]),t!==-1&&(this.#i[t]=0,this.#n[t]=1,this.#f--)}),t===-1){await this.#E();continue}await this.#a[t](...this.#m[t]),await navigator.locks.request(this.#l,()=>{this.#n[t]=0,this.#r[t]=1,Atomics.add(this.#s,1,1)}),this.#_()}this.#d&&Atomics.load(this.#s,1)!==this.#a.length&&await this.#y()}#p(){this.#u.postMessage(0)}#_(){Atomics.load(this.#s,1)===this.#a.length?this.#u.postMessage(2):this.#u.postMessage(1)}async#E(){return new Promise(t=>this.#t=t)}async#y(){return new Promise(t=>this.#e=t)}}class Yt{static fromWorld(t,e,i){const s=tt(e,i,K(e)),r=s.reduce(function o(h,u,c){for(const a of T(u))o(h,s[a],a);return h.includes(c)||h.push(c),h},[]);return new this(t,r)}#t;#e;#s;constructor(t,e){this.#t=t.systems,this.#e=t.arguments,this.#s=e}async start(){for(const t of this.#s)await this.#t[t](...this.#e[t])}}class Ft{systems=[];#t=[];#e=[];components=new Set;resources=new Set;threadChannels=[];executor;config;url;constructor(t,e){this.config=t,this.url=e,this.executor=t.threads>1?Ot:Yt,Wt(this)}addSystem(t){return this.systems.push(t),this.#t.push(t.getAndClearDependencies()),t.parameters.forEach(e=>e.onAddSystem(this)),this}addStartupSystem(t){return this.#e.push(t),t.parameters.forEach(e=>e.onAddSystem(this)),this}addPlugin(t){return t(this),this}registerComponent(t){return this.components.add(t),this}registerResource(t){return this.resources.add(t),this}registerThreadChannel(t){return this.threadChannels.push(t),this}setExecutor(t){return this.executor=t,this}async build(){const t=B.spawn(this.config.threads-1,this.url),e=await t.wrapInQueue(()=>new it(this.config,t,this.executor,[...this.components],[...this.resources],this.systems,this.#t,this.threadChannels));if(t.isMainThread){await Promise.all(Array.from(e.resources.values(),i=>i.initialize?.(e)));for(const i of this.#e)await i.fn(...i.parameters.map(s=>s.intoArgument(e)));await F.fn(e)}return e}}class kt{static fromWorld(t){return new this(t,t.entities,t.components)}queue=new Map;#t;#e;#s;#i;#n;constructor(t,e,i){this.#t=t,this.#e=e;const s=new ArrayBuffer(8);this.#i=new BigUint64Array(1),this.#s=new l({buffer:s,u8:new Uint8Array(s),u32:new Uint32Array(s),u64:this.#i},0,this),this.#n=i}spawn(){const t=this.#e.spawn();return this.#i[0]=t,this.insertInto(t,l),this.#s}despawn(t){return this.queue.set(t,0n),this}get(t){return this.#i[0]=t,this.#s}insertInto(t,e){this.queue.set(t,this.#r(t)|1n<({threads:1,maxEntities:2**16,getNewTableSize:t=>t===0?8:t*2,...n}),jt=({threads:n,maxEntities:t},e)=>{n>1&&(_(isSecureContext,"Invalid config - Multithreading (threads > 1) requires a secure context."),_(typeof SharedArrayBuffer<"u","Invalid config - Multithreading (threads > 1) requires SharedArrayBuffer."),_(e,"Invalid config - Multithreading (threads > 1) requires a module URL parameter.",TypeError)),_(Number.isInteger(n)&&01?SharedArrayBuffer:ArrayBuffer,this.config=t,this.threads=e,this.tableLengths=this.threads.queue(()=>new Uint32Array(this.createBuffer(st*Uint32Array.BYTES_PER_ELEMENT))),this.archetypeLookup.set(0n,1);const c=L.create(this,[l],0n,1);c.columns.set(l,this.threads.queue(()=>c.columns.get(l))),this.archetypes.push(new Pt(this),c);for(const a of u)this.threads.setListener(a.channelName,a.onReceive(this));this.components=s,this.entities=It.fromWorld(this),this.commands=kt.fromWorld(this),this.executor=i.fromWorld(this,o,h);for(const a of r)if(Q(a)){const k=this.threads.queue(()=>Z(this,a,1));this.resources.set(a,new a(k,0,this.commands))}else e.isMainThread&&this.resources.set(a,new a);for(const a of o)this.systems.push(a.fn),this.arguments.push(a.parameters.map(k=>k.intoArgument(this)))}createBuffer(t){return new this.#t(t)}async update(){return this.executor.start()}moveEntity(t,e){if(!this.entities.isAlive(t))return;const i=this.archetypes[this.entities.getTableIndex(t)],s=this.#e(e);s.isFull&&this.#s(s);const r=this.entities.getRow(t),o=i.move(r,s);e===0n&&s.incrementGeneration(r),this.entities.setRow(o,r),this.entities.setTableIndex(t,s.id),this.entities.setRow(t,s.size-1)}#e(t){if(this.archetypeLookup.has(t))return this.archetypes[this.archetypeLookup.get(t)];if(this.archetypes.length===this.tableLengths.length){const s=this.tableLengths;this.tableLengths=new Uint32Array(this.createBuffer(s.length+st*Uint32Array.BYTES_PER_ELEMENT)),this.tableLengths.set(s),this.threads.send(X(this.tableLengths))}const e=this.archetypes.length,i=L.create(this,[...T(t)].map(s=>this.components[s]),t,e);this.archetypeLookup.set(t,e),this.archetypes.push(i),this.threads.send(H([...i.columns.values()],i.capacity,e,t));for(const s of this.queries)s.testAdd(t,i);return i}#s(t){t.grow(this),this.threads.send(J(t.id,t.capacity,[...t.columns.values()]))}}function Zt(n){return n}d.Entity=l,d.World=it,d.applyCommands=F,d.createThreadChannel=z,d.definePlugin=Zt,d.defineSystem=j,d.struct=f,Object.defineProperty(d,Symbol.toStringTag,{value:"Module"})}); +(function(d,p){typeof exports=="object"&&typeof module<"u"?p(exports,require("esm-env")):typeof define=="function"&&define.amd?define(["exports","esm-env"],p):(d=typeof globalThis<"u"?globalThis:d||self,p(d.Thyseus={},d.esm_env))})(this,function(d,p){"use strict";class rt{isLocalToThread(){return!1}intersectsWith(t){return!1}intoArgument(t){return t.commands}onAddSystem(t){}}class ot{#t=[];#e=0;#s;#i;#n;#r;#o;#h;constructor(t,e,i,s,r){this.#i=t,this.#o=i,this.#n=e,this.#r=s,this.#h=r,this.#s=this.#r.map(o=>new o({},0,r))}get size(){return this.#t.reduce((t,e)=>t+e.size,0)}*[Symbol.iterator](){this.#e>=this.#s.length&&this.#s.push(...this.#r.map(i=>new i({},0,this.#h)));const t=this.#s.slice(this.#e,this.#e+this.#r.length),e=this.#e;this.#e+=this.#r.length;for(const i of this.#t){t.forEach((s,r)=>{const o=this.#s[r+e],h=i.columns.get(o.constructor);h?(t[r]=o,t[r].__$$s=h):t[r]=null});for(let s=0;s(Array.isArray(t)?t:[t]).reduce((i,s,r)=>e[r]?i:i|1n<n.registerComponent(r)):s instanceof R&&(A(s.l,e),A(s.r,e))})}function ut(n,t,e,i){const s=A(i,function o(h,u){if(u instanceof q){const c=U(n,u.value);return{withs:h.withs.map(a=>a|c),withouts:h.withouts}}else if(u instanceof x){const c=U(n,u.value);return{withs:h.withs,withouts:h.withouts.map(a=>a|c)}}else if(u instanceof R){const c=A(u.l,o,h),a=A(u.r,o,h);return{withs:[...c.withs,...a.withs],withouts:[...c.withouts,...a.withouts]}}throw new Error(`Unrecognized filter (${u.constructor.name}) in Query.`)},{withs:[U(n,t,e)],withouts:[0n]}),r=s.withs.reduce((o,h,u)=>(s.withs[u]&s.withouts[u])===0n?o.add(u):o,new Set);return s.withs=s.withs.filter((o,h)=>r.has(h)),s.withouts=s.withouts.filter((o,h)=>r.has(h)),p.DEV&&_(s.withs.length>0,"Tried to construct a query that cannot match any entities."),s}class W{components=[];writes=[];optionals=[];filters;isIndividual;constructor(t,e=[]){this.isIndividual=!Array.isArray(t);const i=Array.isArray(t)?t:[t];for(const s of i){const r=s instanceof b||s instanceof M&&s.value instanceof b;this.writes.push(r),this.optionals.push(s instanceof M);const o=s instanceof b?s.value:s instanceof M?s.value instanceof b?s.value.value:s.value:s;p.DEV&&_(o.size>0,"You may not request direct access to ZSTs - use a With filter instead."),this.components.push(o)}this.filters=e}isLocalToThread(){return!1}intersectsWith(t){return t instanceof W?this.components.some((e,i)=>t.components.some((s,r)=>e===s&&(this.writes[i]||t.writes[r]))):!1}onAddSystem(t){this.components.forEach(e=>t.registerComponent(e)),ht(t,this.filters)}intoArgument(t){const{withs:e,withouts:i}=ut(t.components,this.components,this.optionals,this.filters),s=new ot(e,i,this.isIndividual,this.components,t.commands);return t.queries.push(s),s}}let D=0,S=1,C=0,g=[],y=[],w={};const $={u8:1<<0,u16:1<<1,u32:1<<2,u64:1<<3,i8:1<<4,i16:1<<5,i32:1<<6,i64:1<<7,f32:1<<8,f64:1<<9},N={u8:Uint8Array,u16:Uint16Array,u32:Uint32Array,u64:BigUint64Array,i8:Int8Array,i16:Int16Array,i32:Int32Array,i64:BigInt64Array,f32:Float32Array,f64:Float64Array},at=(n,t,e)=>{const i=y.reduce((r,o,h)=>o>o)+r[i]]},set(h){this.__$$s[n][(this.__$$b>>o)+r[i]]=h}})}}}const lt=m("u8"),ft=m("u16"),dt=m("u32"),mt=m("u64"),gt=m("i8"),pt=m("i16"),_t=m("i32"),Et=m("i64"),yt=m("f32"),wt=m("f64"),$t=function(){return function(t,e){const i=v(e,Uint8Array.BYTES_PER_ELEMENT,Uint8Array.BYTES_PER_ELEMENT,$.u8);Object.defineProperty(t,e,{enumerable:!0,get(){return!!this.__$$s.u8[this.__$$b+i[e]]},set(s){this.__$$s.u8[this.__$$b+i[e]]=Number(s)}})}},Tt=new TextEncoder,bt=new TextDecoder;function At({characterCount:n,byteLength:t}){return function(i,s){t??=n*3;const r=v(s,Uint8Array.BYTES_PER_ELEMENT,t);Object.defineProperty(i,s,{enumerable:!0,get(){return bt.decode(this.__$$s.u8.subarray(this.__$$b+r[s],this.__$$b+r[s]+t)).split("\0")[0]},set(o){Tt.encodeInto(o,this.__$$s.u8.subarray(this.__$$b+r[s],this.__$$b+r[s]+t).fill(0))}})}}function St({type:n,length:t}){return function(i,s){const r=N[n],o=v(s,r.BYTES_PER_ELEMENT,r.BYTES_PER_ELEMENT*t,$[n]),h=31-Math.clz32(r.BYTES_PER_ELEMENT);Object.defineProperty(i,s,{enumerable:!0,get(){return this.__$$s[n].subarray((this.__$$b>>h)+o[s],(this.__$$b>>h)+o[s]+t)},set(u){this.__$$s[n].set(u.subarray(0,t),(this.__$$b>>h)+o[s])}})}}function zt(n){return function(e,i){const s=v(i,n.alignment,n.size,n.schema);Object.defineProperty(e,i,{enumerable:!0,get(){const r=new n(this.__$$s,0,{});return r.__$$b=this.__$$b+s[i]*n.alignment,r},set(r){this.__$$s.u8.set(r.__$$s,this.__$$b+s[i]*n.alignment)}})}}function l(){return function(t){const{schema:e,size:i,alignment:s}=ct();return class extends t{static schema=e|(t.schema??0);static size=i;static alignment=s;__$$s;__$$b;#t;get __$$i(){return this.#t}set __$$i(r){this.#t=r,this.__$$b=r*this.constructor.size}constructor(r,o){super(),this.__$$s=r,this.#t=o,this.__$$b=o*this.constructor.size}}}}l.bool=$t,l.u8=lt,l.u16=ft,l.u32=dt,l.u64=mt,l.i8=gt,l.i16=pt,l.i32=_t,l.i64=Et,l.f32=yt,l.f64=wt,l.string=At,l.array=St,l.substruct=zt;function j(n){return typeof n=="function"&&typeof n.size=="number"&&typeof n.alignment=="number"&&typeof n.schema=="number"}class O{resource;canWrite;constructor(t){const e=t instanceof b;this.resource=e?t.value:t,this.canWrite=e}isLocalToThread(){return!j(this.resource)}intersectsWith(t){return t instanceof O?this.resource===t.resource&&(this.canWrite||t.canWrite):!1}onAddSystem(t){t.registerResource(this.resource)}intoArgument(t){return t.resources.get(this.resource)}}class vt{isLocalToThread(){return!0}intersectsWith(t){return!0}intoArgument(t){return t}onAddSystem(t){}}function E(n){return(...t)=>new n(...t)}const Bt={Commands:E(rt),Query:E(W),Res:E(O),World:E(vt),Mut:E(b),Optional:E(M),With:E(q),Without:E(x),Or(n,t){return new R(n,t)}};class Y{#t=0;#e=[];#s;fn;constructor(t,e){this.#s=t,this.fn=e}get parameters(){return this.#s(Bt)}before(...t){for(const e of t)e.after(this);return this}after(...t){for(const e of t)this.#e.push(e);return this}beforeAll(){return this.#t=-1,this}afterAll(){return this.#t=1,this}clone(){return new Y(this.#s,this.fn)}getAndClearDependencies(){const t={dependencies:this.#e,implicitPosition:this.#t};return this.#e=[],this.#t=0,t}}function V(n,t){return new Y(n,t)}class f{static schema=$.u64|$.u32;static size=8;__$$s;__$$b;#t;#e;constructor(t,e,i){this.__$$s=t,this.#t=e,this.__$$b=e*f.size,this.#e=i}get __$$i(){return this.#t}set __$$i(t){this.#t=t,this.__$$b=t*f.size}get id(){return this.__$$s.u64[this.__$$b>>3]}get index(){return this.__$$s.u32[this.__$$b>>2]}get generation(){return this.__$$s.u32[(this.__$$b>>2)+1]}insert(t){return this.#e.insertInto(this.id,t),this}remove(t){return this.#e.removeFrom(this.id,t),this}despawn(){this.#e.despawn(this.id)}}const[,...Mt]=Object.entries(N);function Z(n,t){return Mt.reduce((e,[i,s])=>(($[i]&n.schema)===$[i]&&(e[i]=new s(e.buffer)),e),t)}function G(n,t,e){const i=n.createBuffer(t.size*e);return Z(t,{buffer:i,u8:new Uint8Array(i)})}function Ct(n,t,e){const i=new n.buffer.constructor(t.size*e),s=new Uint8Array(i);return s.set(n.u8),n.buffer=i,n.u8=s,Z(t,n)}class L{static create(t,e,i,s){const r=t.config.getNewTableSize(0);return new this(t,e.reduce((o,h)=>(h.size>0&&o.set(h,G(t,h,r)),o),new Map),r,i,s)}#t;columns;capacity;bitfield;#e;constructor(t,e,i,s,r){this.#t=t,this.columns=e,this.capacity=i,this.bitfield=s,this.#e=r}get id(){return this.#e}get size(){return this.#t.tableLengths[this.#e]}set size(t){this.#t.tableLengths[this.#e]=t}get isFull(){return this.capacity===this.size}delete(t){this.size--;for(const[e,i]of this.columns)i.u8.copyWithin(t*e.size,this.size*e.size,this.size*e.size+e.size),i.u8.fill(0,this.size*e.size,this.size*e.size+e.size)}move(t,e){const i=this.columns.get(f).u64[this.size-1];for(const[s,r]of this.columns)e.columns.has(s)&&e.columns.get(s).u8.set(r.u8.slice(t*s.size,t*s.size+s.size),e.size*s.size);return e.size++,this.delete(t),i}grow(t){this.capacity=t.config.getNewTableSize(this.capacity);for(const[e,i]of this.columns)this.columns.set(e,Ct(i,e,this.capacity))}incrementGeneration(t){this.columns.get(f).u32[(t<<1)+1]++}}const Lt=0x00000000ffffffffn,I=n=>Number(n&Lt),F=256;class It{static fromWorld(t){const e=BigUint64Array.BYTES_PER_ELEMENT*F;return new this(t,t.threads.queue(()=>new Uint32Array(t.createBuffer(e))),t.threads.queue(()=>new Uint32Array(t.createBuffer(8))),t.archetypes[0])}#t;#e;#s;#i;constructor(t,e,i,s){this.#t=t,this.#e=e,this.#s=i,this.#i=s}get isFull(){return this.#s[0]>=this.#e.length>>1}spawn(){const t=this.#i.size;for(let e=this.#n();e>=1n,t++}let qt=1;function z(n,t){function e(...i){return[n,qt++,i]}return e.channelName=n,e.onReceive=t,e}const xt=[];class B{static isMainThread=!!globalThis.document;isMainThread=B.isMainThread;static spawn(t,e){return new this(B.isMainThread?Array.from({length:t},()=>new Worker(e,{type:"module"})):[globalThis])}#t=new Map;#e=new Map;#s={};#i=[];#n;constructor(t){this.#n=t;const e=({currentTarget:i,data:[s,r,o]})=>{if(this.#t.has(r)){const h=this.#e.get(r);h.push(o),h.length===this.#n.length&&(this.#t.get(r)(h),this.#t.delete(r),this.#e.delete(r))}else s in this.#s?i.postMessage([s,r,this.#s[s](...o)]):i.postMessage([s,r,null])};for(const i of this.#n)i.addEventListener("message",e)}setListener(t,e){this.#s[t]=e}deleteListener(t){delete this.#s[t]}send(t){return this.#n.length===0?Promise.resolve(xt):new Promise(e=>{for(const i of this.#n)i.postMessage(t);this.#e.set(t[1],[]),this.#t.set(t[1],e)})}queue(t){if(B.isMainThread){const e=t();return this.#i.push(e),e}return this.#i.shift()}async wrapInQueue(t){const e="threadGroup::queue";let i;return this.isMainThread?(i=await t(),await this.send([e,0,[this.#i]])):(i=await new Promise(s=>this.setListener(e,r=>{this.#i=r,s(t())})),this.deleteListener(e)),this.#i.length=0,i}}const H=z("thyseus::getCommandQueue",n=>()=>{const t=new Map(n.commands.queue);return n.commands.queue.clear(),t}),J=z("thyseus::sendTable",n=>(t,e,i,s)=>{const r=[...T(s)].reduce((h,u,c)=>(n.components[u].size>0&&h.set(n.components[u],t.shift()),h),new Map),o=new L(n,r,e,s,i);n.archetypes[i]=o;for(const h of n.queries)h.testAdd(s,o)}),X=z("thyseus::resizeTable",n=>(t,e,i)=>{const s=n.archetypes[t];s.capacity=e;let r=0;for(const o of s.columns.keys())s.columns.set(o,i[r++])}),K=z("thyseus::resizeTableLengths",n=>t=>{n.tableLengths=t}),Rt=z("thyseus::resizeEntityLocations",n=>t=>{n.entities.setLocations(t)}),Ut=(n,t)=>{for(const[e,i]of t){const s=n.get(e);s===void 0?n.set(e,i):s!==0n&&n.set(e,s|i)}return n},k=V(({World:n})=>[n()],async function(t){t.entities.isFull&&t.entities.grow(t);const e=(await t.threads.send(H())).reduce(Ut,t.commands.queue);for(const[i,s]of e)t.moveEntity(i,s);e.clear(),t.entities.resetCursor()});function Wt(n){n.registerComponent(f),n.addSystem(k.afterAll()),n.registerThreadChannel(H),n.registerThreadChannel(J),n.registerThreadChannel(X),n.registerThreadChannel(K)}function Dt(n,t){return n.parameters.some(e=>t.parameters.some(i=>e.intersectsWith(i)||i.intersectsWith(e)))?1:0}function tt(n){return n.map(t=>n.reduce((e,i,s)=>e|BigInt(Dt(t,i))<r.dependencies.reduce((o,h)=>{const u=n.indexOf(h);return u===-1?o:o|1n<{_((r&1n<i[o]&=e[o]),i}function st(n,t,e){for(const i of T(t))if(n[i]===e)return!1;return!0}let Nt=0;const P=(...n)=>{};class Ot{static fromWorld(t,e,i){const s=t.threads.queue(()=>tt(e)),r=t.threads.queue(()=>et(e,i,s)),o=t.threads.isMainThread?e.map(()=>!0):e.map(c=>!c.parameters.some(a=>a.isLocalToThread())),h=t.threads.queue(()=>t.createBuffer(8+e.length*3)),u=t.threads.queue(()=>`thyseus::ParallelExecutor${Nt++}`);return new this(t,new Uint32Array(h,0,2),new Uint8Array(h,8,e.length),new Uint8Array(h,8+e.length,e.length),new Uint8Array(h,8+e.length*2,e.length),s,r,o,u)}#t=P;#e=P;#s;#i;#n;#r;#o;#h;#c;#f;#u;#d;#a;#m;constructor(t,e,i,s,r,o,h,u,c){this.#a=t.systems,this.#m=t.arguments,this.#d=t.threads.isMainThread,this.#h=o,this.#c=h,this.#o=u,this.#s=e,this.#i=i,this.#n=s,this.#r=r,this.#u=new BroadcastChannel(c),this.#f=c,this.#u.addEventListener("message",({data:a})=>{a===0?this.#g():a===1?(this.#t(),this.#t=P):(this.#e(),this.#e=P)})}async start(){return this.#l=this.#a.length,this.#s[1]=0,this.#i.fill(1),this.#r.fill(0),this.#n.fill(0),this.#p(),this.#g()}get#l(){return this.#s[0]}set#l(t){this.#s[0]=t}async#g(){for(;this.#l>0;){let t=-1;if(await navigator.locks.request(this.#f,()=>{t=this.#i.findIndex((e,i)=>!!e&&st(this.#r,this.#c[i],0)&&st(this.#n,this.#h[i],1)&&this.#o[i]),t!==-1&&(this.#i[t]=0,this.#n[t]=1,this.#l--)}),t===-1){await this.#E();continue}await this.#a[t](...this.#m[t]),await navigator.locks.request(this.#f,()=>{this.#n[t]=0,this.#r[t]=1,Atomics.add(this.#s,1,1)}),this.#_()}this.#d&&Atomics.load(this.#s,1)!==this.#a.length&&await this.#y()}#p(){this.#u.postMessage(0)}#_(){Atomics.load(this.#s,1)===this.#a.length?this.#u.postMessage(2):this.#u.postMessage(1)}async#E(){return new Promise(t=>this.#t=t)}async#y(){return new Promise(t=>this.#e=t)}}class Yt{static fromWorld(t,e,i){const s=et(e,i,tt(e)),r=s.reduce(function o(h,u,c){for(const a of T(u))o(h,s[a],a);return h.includes(c)||h.push(c),h},[]);return new this(t,r)}#t;#e;#s;constructor(t,e){this.#t=t.systems,this.#e=t.arguments,this.#s=e}async start(){for(const t of this.#s)await this.#t[t](...this.#e[t])}}class Ft{systems=[];#t=[];#e=[];components=new Set;resources=new Set;threadChannels=[];executor;config;url;constructor(t,e){this.config=t,this.url=e,this.executor=t.threads>1?Ot:Yt,Wt(this)}addSystem(t){return this.systems.push(t),this.#t.push(t.getAndClearDependencies()),t.parameters.forEach(e=>e.onAddSystem(this)),this}addStartupSystem(t){return this.#e.push(t),t.parameters.forEach(e=>e.onAddSystem(this)),this}addPlugin(t){return t(this),this}registerComponent(t){return this.components.add(t),this}registerResource(t){return this.resources.add(t),this}registerThreadChannel(t){return this.threadChannels.push(t),this}setExecutor(t){return this.executor=t,this}async build(){const t=B.spawn(this.config.threads-1,this.url),e=await t.wrapInQueue(()=>new nt(this.config,t,this.executor,[...this.components],[...this.resources],this.systems,this.#t,this.threadChannels));if(t.isMainThread){await Promise.all(Array.from(e.resources.values(),i=>i.initialize?.(e)));for(const i of this.#e)await i.fn(...i.parameters.map(s=>s.intoArgument(e)));await k.fn(e)}return e}}class kt{static fromWorld(t){return new this(t,t.entities,t.components)}queue=new Map;#t;#e;#s;#i;#n;constructor(t,e,i){this.#t=t,this.#e=e;const s=new ArrayBuffer(8);this.#i=new BigUint64Array(1),this.#s=new f({buffer:s,u8:new Uint8Array(s),u32:new Uint32Array(s),u64:this.#i},0,this),this.#n=i}spawn(){const t=this.#e.spawn();return this.#i[0]=t,this.insertInto(t,f),this.#s}despawn(t){return this.queue.set(t,0n),this}get(t){return this.#i[0]=t,this.#s}insertInto(t,e){this.queue.set(t,this.#r(t)|1n<({threads:1,maxEntities:2**16,getNewTableSize:t=>t===0?8:t*2,...n}),jt=({threads:n,maxEntities:t},e)=>{n>1&&(_(isSecureContext,"Invalid config - Multithreading (threads > 1) requires a secure context."),_(typeof SharedArrayBuffer<"u","Invalid config - Multithreading (threads > 1) requires SharedArrayBuffer."),_(e,"Invalid config - Multithreading (threads > 1) requires a module URL parameter.",TypeError)),_(Number.isInteger(n)&&01?SharedArrayBuffer:ArrayBuffer,this.config=t,this.threads=e,this.tableLengths=this.threads.queue(()=>new Uint32Array(this.createBuffer(it*Uint32Array.BYTES_PER_ELEMENT))),this.archetypeLookup.set(0n,1);const c=L.create(this,[f],0n,1);c.columns.set(f,this.threads.queue(()=>c.columns.get(f))),this.archetypes.push(new Pt(this),c);for(const a of u)this.threads.setListener(a.channelName,a.onReceive(this));this.components=s,this.entities=It.fromWorld(this),this.commands=kt.fromWorld(this),this.executor=i.fromWorld(this,o,h);for(const a of r)if(j(a)){const Q=this.threads.queue(()=>G(this,a,1));this.resources.set(a,new a(Q,0,this.commands))}else e.isMainThread&&this.resources.set(a,new a);for(const a of o)this.systems.push(a.fn),this.arguments.push(a.parameters.map(Q=>Q.intoArgument(this)))}createBuffer(t){return new this.#t(t)}async update(){return this.executor.start()}moveEntity(t,e){if(!this.entities.isAlive(t))return;const i=this.archetypes[this.entities.getTableIndex(t)],s=this.#e(e);s.isFull&&this.#s(s);const r=this.entities.getRow(t),o=i.move(r,s);e===0n&&s.incrementGeneration(r),this.entities.setRow(o,r),this.entities.setTableIndex(t,s.id),this.entities.setRow(t,s.size-1)}#e(t){if(this.archetypeLookup.has(t))return this.archetypes[this.archetypeLookup.get(t)];if(this.archetypes.length===this.tableLengths.length){const s=this.tableLengths;this.tableLengths=new Uint32Array(this.createBuffer(s.length+it*Uint32Array.BYTES_PER_ELEMENT)),this.tableLengths.set(s),this.threads.send(K(this.tableLengths))}const e=this.archetypes.length,i=L.create(this,[...T(t)].map(s=>this.components[s]),t,e);this.archetypeLookup.set(t,e),this.archetypes.push(i),this.threads.send(J([...i.columns.values()],i.capacity,e,t));for(const s of this.queries)s.testAdd(t,i);return i}#s(t){t.grow(this),this.threads.send(X(t.id,t.capacity,[...t.columns.values()]))}}function Zt(n){return n}d.Entity=f,d.World=nt,d.applyCommands=k,d.createThreadChannel=z,d.definePlugin=Zt,d.defineSystem=V,d.struct=l,Object.defineProperty(d,Symbol.toStringTag,{value:"Module"})});