Comparing version 0.2.7 to 0.2.8
@@ -1,2 +0,2 @@ | ||
const e={bool:"bool",int8:"int8",uint8:"uint8",uint8clamped:"uint8clamped",int16:"int16",uint16:"uint16",int32:"int32",uint32:"uint32",float32:"float32",float64:"float64"},t={bool:"bool",int8:Int8Array,uint8:Uint8Array,uint8clamped:Uint8ClampedArray,int16:Int16Array,uint16:Uint16Array,int32:Int32Array,uint32:Uint32Array,float32:Float32Array,float64:Float64Array},n={uint8:255,uint16:65535,uint32:4294967295},r=()=>{let e=1,r=0;const o=(i,s={},a=!0)=>{const c={},l={},f={},y=Object.keys(s),E=y.filter((e=>Array.isArray(s[e])&&"object"==typeof s[e][0])),m=Object.keys(t).reduce(((e,t)=>({...e,[t]:0})),{});let p;return y.forEach((e=>{if("bool"===s[e]){const n=t.uint8,r=i*t.uint8.BYTES_PER_ELEMENT,o=new SharedArrayBuffer(r);l[e]=s[e],c[e]=new n(o),c[e]._boolType=!0}else if(Array.isArray(s[e])&&"string"==typeof s[e][0]){const n=t.uint8,r=i*t.uint8.BYTES_PER_ELEMENT,o=new SharedArrayBuffer(r);l[e]=s[e],c[e]=new n(o)}else if(Array.isArray(s[e])&&"object"==typeof s[e][0]){const{index:o,type:a,length:l}=s[e][0];if(!l)throw new Error("❌ Must define a length for component array.");if(!t[a])throw new Error(`❌ Invalid component array property type ${a}.`);if(!t[o])throw new Error(`❌ Invalid component array index type ${o}.`);if(!n[o])throw new Error(`❌ Index type for component array must be unsigned (non-negative), instead was ${o}.`);if(!f[a]){const e=E.filter((e=>s[e][0].type===a)),n=e.reduce(((e,n)=>e+t[a].BYTES_PER_ELEMENT),0),c=e.reduce(((e,t)=>e+l),0),y=new SharedArrayBuffer((r=n*c*i,4*Math.ceil(r/4))),m=new t[a](y);m._indexType=o,m._indexBytes=t[o].BYTES_PER_ELEMENT,f[a]=m}c[e]={};let y=0;for(let t=0;t<i;t++){const n=m[a]+t*l,r=n+l;c[e][t]=f[a].subarray(n,r),y=r}m[a]=y,c[e]._reset=t=>c[e][t].fill(0),c[e]._set=(t,n)=>c[e][t].set(n,0)}else if("object"==typeof s[e])c[e]=o(i,s[e],!1);else if("string"==typeof s[e]){const n=s[e],r=i*t[n].BYTES_PER_ELEMENT,o=new SharedArrayBuffer(r);c[e]=new t[n](o)}else{if("function"!=typeof s[e])throw new Error("ECS Error: invalid property type "+s[e]);{const t=s[e],n=i*t.BYTES_PER_ELEMENT,r=new SharedArrayBuffer(n);c[e]=new t(r)}}var r})),Object.defineProperty(c,"_schema",{value:s}),Object.defineProperty(c,"_props",{value:Object.keys(s)}),Object.defineProperty(c,"_mapping",{value:e=>l[e]}),Object.defineProperty(c,"_reset",{value:e=>{for(const t of c._props)ArrayBuffer.isView(c[t])?ArrayBuffer.isView(c[t][e])?c[t][e].fill(0):c[t][e]=0:c[t]._reset(e)}}),Object.defineProperty(c,"_set",{value:(e,t)=>{for(const n in t){c._mapping(n)&&"string"==typeof t[n]?c.enum(n,e,t[n]):ArrayBuffer.isView(c[n])?c[n][e]=t[n]:Array.isArray(t[n])&&ArrayBuffer.isView(c[n][e])?c[n][e].set(t[n],0):"object"==typeof c[n]&&c[n]._set(e,t[n])}}}),Object.defineProperty(c,"_get",{value:e=>{const t={};for(const n of c._props){c._mapping(n)?t[n]=c.enum(n,e):ArrayBuffer.isView(c[n])?t[n]=c[n][e]:"object"==typeof c[n]&&(ArrayBuffer.isView(c[n][e])?t[n]=Array.from(c[n][e]):t[n]=c[n]._get(e))}return t}}),Object.defineProperty(c,"_flatten",{value:(e=[])=>{if(p)return p;for(const t of c._props)ArrayBuffer.isView(c[t])?e.push(c[t]):"object"==typeof c[t]&&c[t]._flatten(e);return p=e,e}}),Object.defineProperty(c,"_bitflag",{value:e}),Object.defineProperty(c,"_generationId",{value:r}),Object.defineProperty(c,"check",{value:e=>(e&c._bitflag)===c._bitflag}),Object.defineProperty(c,"enum",{value:(e,t,n)=>{const r=c._mapping(e);if(r){if(!n)return r[c[e][t]];{const o=r.indexOf(n);if(-1===o)return void console.warn(`Value '${n}' is not part of enum.`);c[e][t]=o}}else console.warn("Property is not an enum.")}}),a&&(e*=2,e>=Math.pow(2,32)&&(e=1,r+=1)),c};return o};export default(t={})=>{const n=r(),o=(({maxEntities:e=1e4,maxComponentTypes:t=128,tickRate:n=30,devtools:r=!1})=>({maxEntities:e,maxComponentTypes:t,maxGenerations:Math.ceil(t/32),tickRate:n,devtools:r}))(t),i=(({maxEntities:e,maxGenerations:t})=>({entities:Array.from({length:t},(()=>new Uint32Array(e))),components:{},systems:{}}))(o),{entityCount:s,addEntity:a,removeEntity:c,commitEntityRemovals:l,getEntityCursor:f}=((e,t)=>{const{entities:n,systems:r}=t,o=[],i=[],s=new Uint8Array(e.maxEntities);let a=0;return{entityCount:()=>a-o.length,addEntity:()=>{if(a>=e.maxEntities)return void console.warn("❌ Could not add entity, maximum number of entities reached.");const t=o.length>0?o.pop():a++;return s[t]=1,t},removeEntity:e=>{i.push(e)},commitEntityRemovals:()=>{if(0!==i.length){for(let e of i)if(0!==s[e]){for(const t in r)r[t].remove(e);o.push(e),s[e]=0;for(let t of n)t[e]=0}i.length=0}},getEntityCursor:()=>a}})(o,i),{getGeneration:y,registerComponent:E,addComponent:m,removeComponent:p,removeAllComponents:u,hasComponent:d,commitComponentRemovals:_}=((e,t,n)=>{const{entities:r,components:o,systems:i}=t,s=[];let a=0;const c=e=>{if(void 0===o[e])throw new Error(`❌ Component '${e}' is not registered.`);return o[e]},l=(e,t)=>{s.push(e,t)},f=(e,t)=>{const n=o[e],{_generationId:i,_bitflag:s}=n;return(r[i][t]&s)===s};return{getGeneration:()=>a,registerComponent:(t,r)=>{if(Object.keys(o).length+1>e.maxComponentTypes)throw new Error(`❌ Can not register component '${t}'. Max components '${e.maxComponentTypes}' reached.`);return o[t]=n(e.maxEntities,r),a=o[t]._generationId,o[t]},addComponent:(e,t,n={},o=!0)=>{if(f(e,t))return;const s=c(e),{_generationId:a,_bitflag:l}=s;r[a][t]|=l,o&&s._reset(t),s._set(t,n);for(const e in i){const n=i[e];n.components.length&&n.checkComponent(s)&&n.check(t)&&n.add(t)}},removeComponent:l,removeAllComponents:e=>{Object.keys(o).forEach((t=>{l(t,e)}))},hasComponent:f,commitComponentRemovals:()=>{if(0!==s.length){for(let e=0;e<s.length;e+=2){const t=s[e],n=s[e+1],o=c(t),{_generationId:a,_bitflag:l}=o;if(!(r[a][n]&l))return;r[a][n]&=~l;for(const e in i){const t=i[e];t.components.length&&t.checkComponent(o)&&!t.check(n)&&t.remove(n)}}s.length=0}}}})(o,i,n),{enabled:g,registerSystem:h,toggle:b,step:A}=((e,t,n,r)=>{const{entities:o,components:i,systems:s}=t,a=[];let c=!0;const l=()=>{r(),n()};return{registerSystem:({name:t,components:n=[],enter:r,update:c,exit:f})=>{const y=[],E=new Int32Array(e.maxEntities).fill(-1),m={count:0,name:t,enabled:!0,components:n,localEntities:y,entityIndices:E,update:c,enter:r,exit:f},p=n.map((e=>{if(void 0===i[e])throw new Error(`❌ Cannot register system '${t}', '${e}' is not a registered component.`);return i[e]})),u=Array.from({length:e.maxGenerations},(()=>0));for(const e of p){const{_generationId:t,_bitflag:n}=e;u[t]|=n}m.masks=u,m.check=e=>{for(let t=0;t<u.length;t++){const n=o[t][e],r=u[t];if((n&r)!==r)return!1}return!0},m.checkComponent=e=>(u[e._generationId]&e._bitflag)===e._bitflag;const d=c?c(...p):null,_=r?r(...p):null,g=f?f(...p):null;m.execute=e=>{(e||m.enabled)&&d&&d(y),l()},m.add=e=>{-1===E[e]&&(E[e]=y.push(e)-1,m.count=y.length,_&&_(e))},m.remove=e=>{const t=E[e];if(-1===t)return;const n=y.pop();n!==e&&(y[t]=n,E[n]=t),E[e]=-1,m.count=y.length,g&&g(e)};for(let e=0;e<o[0].length;e++)m.components.length&&m.check(e)&&m.add(e);return s[t]=m,t.includes("query")||a.push(m),m},enabled:e=>e?s[e]?s[e].enabled:void console.warn(`System '${e}' is not registered.`):c,step:(e,t=!1)=>{if("boolean"==typeof e&&(t=e),"string"!=typeof e){if(t||c)for(let e=0;e<a.length;e++)a[e].execute();l()}else s[e].execute(t)},toggle:e=>{if(e)return s[e]?void(s[e].enabled=!s[e].enabled):void console.warn(`System '${e} is not registered.`);c=!c}}})(o,i,l,_),{save:w,load:v}=((e,t,n)=>({save:()=>{const r=n(),o=t(),i=Object.keys(e.components),s=i.map((t=>e.components[t])),a=Object.keys(e.systems),c=a.map((t=>e.systems[t])),l=Math.ceil(i.length/32),f=o*l*Uint32Array.BYTES_PER_ELEMENT,y=s.reduce(((e,t)=>e+t._flatten().reduce(((e,t)=>e+t.BYTES_PER_ELEMENT*o),0)),0),E=c.reduce(((e,t)=>e+t.localEntities.reduce(((e,t)=>e+Uint32Array.BYTES_PER_ELEMENT),0)+Uint32Array.BYTES_PER_ELEMENT),0),m=new ArrayBuffer(f+y+E),p=new DataView(m);let u=0;for(let t=0;t<o;t++)for(let n=0;n<l;n++){const r=e.entities[n];p.setUint32(u,r[t]),u+=Uint32Array.BYTES_PER_ELEMENT}return s.forEach((e=>{e._flatten().forEach((e=>{const t=e.constructor.name.split("Array")[0],n=e.BYTES_PER_ELEMENT,o=r;e._cursorStart=u;for(let r=0;r<o;r++)p["set"+t](u,e[r]),u+=n;e._cursorEnd=u}))})),a.forEach((t=>{const n=e.systems[t];p.setUint32(u,n.localEntities.length),u+=Uint32Array.BYTES_PER_ELEMENT,n.localEntities.forEach((e=>{p.setUint32(u,e),u+=Uint32Array.BYTES_PER_ELEMENT}))})),p.buffer.slice(0,u)},load:r=>{const o=n(),i=t(),s=Object.keys(e.components),a=s.map((t=>e.components[t])),c=Object.keys(e.systems),l=Math.ceil(s.length/32),f=new DataView(r);let y=0;for(let t=0;t<i;t++)for(let n=0;n<l;n++)e.entities[n][t]=f.getUint32(y),y+=Uint32Array.BYTES_PER_ELEMENT;a.forEach((e=>{e._flatten().forEach((e=>{const t=e.constructor.name.split("Array")[0],n=e.BYTES_PER_ELEMENT,r=o;for(let o=0;o<r;o++)e[o]=f["get"+t](y),y+=n}))})),c.forEach((t=>{const n=e.systems[t],r=f.getUint32(y);y+=Uint32Array.BYTES_PER_ELEMENT,n.localEntities.length=0,n.count=0,n.entityIndices.fill(-1);for(let e=0;e<r;e++){const e=f.getUint32(y);n.add(e),y+=Uint32Array.BYTES_PER_ELEMENT}}))}}))(i,s,f);let T=0;return{TYPES:e,config:o,registry:i,entityCount:s,addEntity:a,removeEntity:c,registerComponent:E,removeComponent:p,removeAllComponents:u,addComponent:m,hasComponent:d,registerSystem:h,createQuery:e=>h({name:"query-"+T++,components:e}).localEntities,enabled:g,toggle:b,step:A,save:w,load:v}}; | ||
const e={bool:"bool",i8:Int8Array,ui8:Uint8Array,ui8c:Uint8ClampedArray,i16:Int16Array,ui16:Uint16Array,i32:Int32Array,ui32:Uint32Array,f32:Float32Array,f64:Float64Array},t=255,r=65535,n=(e,t)=>{const r=new e.constructor(new ArrayBuffer(e.buffer.byteLength+t*e.BYTES_PER_ELEMENT));return r.set(e.buffer),r},o=e=>4*Math.ceil(e/4),i={},a=Symbol("managerRef"),s=Symbol("managerSize"),f=Symbol("maps"),c=Symbol("subarrays"),y=Symbol("managerCursor"),u=Symbol("managerRemoved"),l=Symbol("shadow"),p=Symbol("entityMasks"),g=Symbol("entityEnabled"),d=Symbol("deferredEntityRemovals"),E=Symbol("removedEntities");let b=0;const m=e=>{const t=e[E],r=e[k],n=e[g];if(b>=r-r/5){const t=4*Math.ceil(r/2/4);e[x].forEach((e=>{e.manager._grow(t)})),e[k]+=t}const o=t.length>0?t.pop():b;return n[o]=1,b++,o},h=(e,t)=>e[d].push(t);function w(e){return function(){return e}}function _(e){return function(){return e}}const A=Symbol("queries"),S=Symbol("queryMap"),B=Symbol("queryComponents"),M=(e,t,r)=>{e[S].get(t)||P(e,t),e[S].get(t).enter=r},T=(e,t,r)=>{e[S].get(t)||P(e,t),e[S].get(t).exit=r},P=(e,t)=>{e[S].get(t)||e[S].set(t,{});let r=[],n=[],o=[];t[B].forEach((e=>{"function"==typeof e?("QueryNot"===e.name&&n.push(e()),"QueryChanged"===e.name&&(o.push(e()),r.push(e()))):r.push(e)}));const i=r.reduce(((e,t)=>t[s]>e?t[s]:e),0),a=new Uint32Array(i),f=new Uint8Array(i),c=r.map((t=>e[x].get(t).generationId)),y=(e,t)=>(e[t.generationId]||(e[t.generationId]=0),e[t.generationId]|=t.bitflag,e),u=r.map((t=>e[x].get(t))).reduce(y,{}),l=n.map((t=>e[x].get(t))).reduce(y,{});Object.assign(e[S].get(t),{entities:[],changed:[],enabled:f,components:r,notComponents:n,changedComponents:o,masks:u,notMasks:l,generations:c,indices:a}),e[A].add(t);for(let r=0;r<b;r++)e[g][r]&&v(e,t,r)&&R(e,t,r)},j=e=>{const t=function(e){e[S].has(t)||P(e,t);const r=e[S].get(t);return r.changedComponents.length?((e,t)=>{const r=e[S].get(t);return r.changed.length=0,r.changedComponents.forEach((e=>{const t=e._flatten();for(let e=0;e<t.length;e++){const n=t[e];for(let e=0;e<r.entities.length;e++){const t=r.entities[e];n[t]!==n[l][t]&&(r.changed.push(t),n[l][t]=n[t])}}})),r.changed})(e,t):r.entities};return t[B]=e,t},v=(e,t,r)=>{const{masks:n,notMasks:o,generations:i}=e[S].get(t);for(let t=0;t<i.length;t++){const a=i[t],s=n[a];o[a];if((e[p][a][r]&s)!==s)return!1}return!0},I=(e,t,r)=>r.every((r=>((e,t,r)=>{const{generationId:n,bitflag:o}=e[x].get(r),{masks:i}=e[S].get(t);return(i[n]&o)===o})(e,t,r))),R=(e,t,r)=>{const n=e[S].get(t);n.enabled[r]||(n.enabled[r]=!0,n.entities.push(r),n.indices[r]=n.entities.length-1,n.enter&&n.enter(r))},O=(e,t,r)=>{const n=e[S].get(t);n.enabled[r]&&(n.enabled[r]=!1,n.entities.splice(n.indices[r]),n.exit&&n.exit(r))},x=Symbol("componentMap"),L=Symbol("de$deferredComponentRemovals"),N=(p,g)=>((p,g=1e5)=>{const d=Symbol("manager");i[d]={[s]:g,[f]:{},[c]:{},[a]:d,[y]:0,[u]:[]};const E=p?Object.keys(p):[];let b=E.filter((e=>Array.isArray(p[e])&&"object"==typeof p[e][0]));const m=Object.keys(e).reduce(((e,t)=>({...e,[t]:0})),{});if("string"==typeof p){const t=p,r=g*e[t].BYTES_PER_ELEMENT,n=new ArrayBuffer(r);i[d]=new e[t](n)}else if(Array.isArray(p)){b=p;const{type:n,length:a}=p[0],s=a<t?"ui8":a<r?"ui16":"ui32";if(!a)throw new Error("❌ Must define a length for component array.");if(!e[n])throw new Error(`❌ Invalid component array property type ${n}.`);if(!i[d][c][n]){const t=b,r=t.reduce(((t,r)=>t+e[n].BYTES_PER_ELEMENT),0),f=t.reduce(((e,t)=>e+a),0),y=new ArrayBuffer(o(r*f*g)),u=new e[n](y);u._indexType=s,u._indexBytes=e[s].BYTES_PER_ELEMENT,i[d][c][n]=u}let f=0;for(let e=0;e<g;e++){const t=m[n]+e*a,r=t+a;i[d][e]=i[d][c][n].subarray(t,r),f=r}m[n]=f,i[d]._reset=e=>i[d][e].fill(0),i[d]._set=(e,t)=>i[d][e].set(t,0)}else E.forEach((t=>{if("bool"===p[t]){const r=e.uint8,n=g*e.uint8.BYTES_PER_ELEMENT,o=new ArrayBuffer(n);i[d][f][t]=p[t],i[d][t]=new r(o),i[d][t]._boolType=!0}else if(Array.isArray(p[t])&&"string"==typeof p[t][0]){const r=e.uint8,n=g*e.uint8.BYTES_PER_ELEMENT,o=new ArrayBuffer(n);i[d][f][t]=p[t],i[d][t]=new r(o)}else if(Array.isArray(p[t])&&"object"==typeof p[t][0]){const{type:r,length:n}=p[0];if(!n)throw new Error("❌ Must define a length for component array.");if(!e[r])throw new Error(`❌ Invalid component array property type ${r}.`);if(!i[d][c][r]){const t=b.filter((e=>p[e][0].type===r)),a=t.reduce(((t,n)=>t+e[r].BYTES_PER_ELEMENT),0),s=t.reduce(((e,t)=>e+n),0),f=new ArrayBuffer(o(a*s*g)),y=new e[r](f);y._indexType=index,y._indexBytes=e[index].BYTES_PER_ELEMENT,i[d][c][r]=y}i[d][t]={};let a=0;for(let e=0;e<g;e++){const o=m[r]+e*n,s=o+n;i[d][t][e]=i[d][c][r].subarray(o,s),a=s}m[r]=a,i[d][t]._reset=e=>i[d][t][e].fill(0),i[d][t]._set=(e,r)=>i[d][t][e].set(r,0)}else if("object"==typeof p[t])i[d][t]=Manager(g,p[t],!1);else if("string"==typeof p[t]){const r=p[t],n=g*e[r].BYTES_PER_ELEMENT,o=new ArrayBuffer(n),a=new ArrayBuffer(n);i[d][t]=new e[r](o),i[d][t][l]=new e[r](a)}else{if("function"!=typeof p[t])throw new Error("ECS Error: invalid property type "+p[t]);{const e=p[t],r=g*e.BYTES_PER_ELEMENT,n=new ArrayBuffer(r);i[d][t]=new e(n)}}}));let h;return Object.defineProperty(i[d],"_schema",{value:p}),Object.defineProperty(i[d],"_mapping",{value:e=>i[d][f][e]}),Object.defineProperty(i[d],"_reset",{value:e=>{for(const t of i[d]._props)ArrayBuffer.isView(i[d][t])?ArrayBuffer.isView(i[d][t][e])?i[d][t][e].fill(0):i[d][t][e]=0:i[d][t]._reset(e)}}),Object.defineProperty(i[d],"_set",{value:(e,t)=>{for(const r in t)i[d]._mapping(r)&&"string"==typeof t[r]?i[d].enum(r,e,t[r]):ArrayBuffer.isView(i[d][r])?i[d][r][e]=t[r]:Array.isArray(t[r])&&ArrayBuffer.isView(i[d][r][e])?i[d][r][e].set(t[r],0):"object"==typeof i[d][r]&&i[d][r]._set(e,t[r])}}),Object.defineProperty(i[d],"_get",{value:e=>{const t={};for(const r of i[d]._props)i[d]._mapping(r)?t[r]=i[d].enum(r,e):ArrayBuffer.isView(i[d][r])?t[r]=i[d][r][e]:"object"==typeof i[d][r]&&(ArrayBuffer.isView(i[d][r][e])?t[r]=Array.from(i[d][r][e]):t[r]=i[d][r]._get(e));return t}}),Object.defineProperty(i[d],"_props",{value:E}),Object.defineProperty(i[d],"_flatten",{value:(e=[])=>{if(h)return h;for(const t of i[d]._props)ArrayBuffer.isView(i[d][t])?e.push(i[d][t]):"object"==typeof i[d][t]&&i[d][t]._flatten(e);return h=e,e}}),Object.defineProperty(i[d],"enum",{value:(e,t,r)=>{const n=i[d]._mapping(e);if(n){if(!r)return n[i[d][e][t]];{const o=n.indexOf(r);if(-1===o)return void console.warn(`Value '${r}' is not part of enum.`);i[d][e][t]=o}}else console.warn("Property is not an enum.")}}),Object.defineProperty(i[d],"_grow",{value:e=>{i[d][s]+=e;for(const t of i[d]._props)ArrayBuffer.isView(i[d][t])?(i[d][t]=n(i[d][t],e),i[d][t][l]=n(i[d][t],e)):"object"==typeof i[d][t]&&(ArrayBuffer.isView(i[d][t][eid])||i[d][t]._grow())}}),i[d]})(p,g),C=(e,t)=>{e[x].set(t,{generationId:e[p].length-1,bitflag:e[$],manager:t}),(e=>{e[$]*=2,e[$]>=Math.pow(2,32)&&(e[$]=1,e[p].push(new Uint32Array(e[k])))})(e)},V=(e,t)=>{t.forEach((t=>C(e,t)))},Y=(e,t,r)=>{if(((e,t,r)=>{const{generationId:n,bitflag:o}=e[x].get(t);return(e[p][n][r]&o)===o})(e,t,r))return;const{generationId:n,bitflag:o}=e[x].get(t);e[p][n][r]|=o;e[A].forEach((t=>{const n=t[B];if(!I(e,t,n))return;v(e,t,r)&&R(e,t,r)}))},U=(e,t,r)=>e[L].push(t,r),k=Symbol("size"),$=Symbol("bitflag"),q=(e=1e5)=>{const t={};return t[k]=e,t[g]=new Uint8Array(t[k]),t[p]=[new Uint32Array(e)],t[E]=[],t[$]=1,t[x]=new Map,t[S]=new Map,t[A]=new Set,t[L]=[],t[d]=[],t},z=(e,t)=>r=>{t(e(r)),(e=>{const t=e[L];for(let r=0;r<t.length;r+=2){const n=t[r],o=t[r+1],{generationId:i,bitflag:a}=e[x].get(n);if(!(e[p][i][o]&a))return;e[p][i][o]&=~a,e[A].forEach((t=>{const r=t[B];I(e,t,r)&&v(e,t,o)&&O(e,t,o)}))}t.length=0})(r),(e=>{const t=e[d],r=e[A],n=e[E],o=e[g];for(let i=0;i<t.length;i++){const a=t[i];if(0!==o[a]){r.forEach((e=>{O(e,a)})),n.push(a),o[a]=0;for(let t=0;t<e[p].length;t++)e[p][t][a]=0}}t.length=0})(r)},F=e=>t=>{for(let r=0;r<e.length;r++){(0,e[r])(t)}},Q={bool:"bool",i8:"i8",ui8:"ui8",ui8c:"ui8c",i16:"i16",ui16:"ui16",i32:"i32",ui32:"ui32",f32:"f32",f64:"f64"};export{_ as Changed,w as Not,Q as Types,Y as addComponent,m as addEntity,q as createWorld,N as defineComponent,j as defineQuery,z as defineSystem,M as enterQuery,T as exitQuery,F as pipe,C as registerComponent,V as registerComponents,U as removeComponent,h as removeEntity}; | ||
//# sourceMappingURL=index.es.js.map |
@@ -1,2 +0,2 @@ | ||
"use strict";const e={bool:"bool",int8:"int8",uint8:"uint8",uint8clamped:"uint8clamped",int16:"int16",uint16:"uint16",int32:"int32",uint32:"uint32",float32:"float32",float64:"float64"},t={bool:"bool",int8:Int8Array,uint8:Uint8Array,uint8clamped:Uint8ClampedArray,int16:Int16Array,uint16:Uint16Array,int32:Int32Array,uint32:Uint32Array,float32:Float32Array,float64:Float64Array},n={uint8:255,uint16:65535,uint32:4294967295},r=()=>{let e=1,r=0;const o=(i,s={},a=!0)=>{const c={},l={},f={},y=Object.keys(s),E=y.filter((e=>Array.isArray(s[e])&&"object"==typeof s[e][0])),m=Object.keys(t).reduce(((e,t)=>({...e,[t]:0})),{});let p;return y.forEach((e=>{if("bool"===s[e]){const n=t.uint8,r=i*t.uint8.BYTES_PER_ELEMENT,o=new SharedArrayBuffer(r);l[e]=s[e],c[e]=new n(o),c[e]._boolType=!0}else if(Array.isArray(s[e])&&"string"==typeof s[e][0]){const n=t.uint8,r=i*t.uint8.BYTES_PER_ELEMENT,o=new SharedArrayBuffer(r);l[e]=s[e],c[e]=new n(o)}else if(Array.isArray(s[e])&&"object"==typeof s[e][0]){const{index:o,type:a,length:l}=s[e][0];if(!l)throw new Error("❌ Must define a length for component array.");if(!t[a])throw new Error(`❌ Invalid component array property type ${a}.`);if(!t[o])throw new Error(`❌ Invalid component array index type ${o}.`);if(!n[o])throw new Error(`❌ Index type for component array must be unsigned (non-negative), instead was ${o}.`);if(!f[a]){const e=E.filter((e=>s[e][0].type===a)),n=e.reduce(((e,n)=>e+t[a].BYTES_PER_ELEMENT),0),c=e.reduce(((e,t)=>e+l),0),y=new SharedArrayBuffer((r=n*c*i,4*Math.ceil(r/4))),m=new t[a](y);m._indexType=o,m._indexBytes=t[o].BYTES_PER_ELEMENT,f[a]=m}c[e]={};let y=0;for(let t=0;t<i;t++){const n=m[a]+t*l,r=n+l;c[e][t]=f[a].subarray(n,r),y=r}m[a]=y,c[e]._reset=t=>c[e][t].fill(0),c[e]._set=(t,n)=>c[e][t].set(n,0)}else if("object"==typeof s[e])c[e]=o(i,s[e],!1);else if("string"==typeof s[e]){const n=s[e],r=i*t[n].BYTES_PER_ELEMENT,o=new SharedArrayBuffer(r);c[e]=new t[n](o)}else{if("function"!=typeof s[e])throw new Error("ECS Error: invalid property type "+s[e]);{const t=s[e],n=i*t.BYTES_PER_ELEMENT,r=new SharedArrayBuffer(n);c[e]=new t(r)}}var r})),Object.defineProperty(c,"_schema",{value:s}),Object.defineProperty(c,"_props",{value:Object.keys(s)}),Object.defineProperty(c,"_mapping",{value:e=>l[e]}),Object.defineProperty(c,"_reset",{value:e=>{for(const t of c._props)ArrayBuffer.isView(c[t])?ArrayBuffer.isView(c[t][e])?c[t][e].fill(0):c[t][e]=0:c[t]._reset(e)}}),Object.defineProperty(c,"_set",{value:(e,t)=>{for(const n in t){c._mapping(n)&&"string"==typeof t[n]?c.enum(n,e,t[n]):ArrayBuffer.isView(c[n])?c[n][e]=t[n]:Array.isArray(t[n])&&ArrayBuffer.isView(c[n][e])?c[n][e].set(t[n],0):"object"==typeof c[n]&&c[n]._set(e,t[n])}}}),Object.defineProperty(c,"_get",{value:e=>{const t={};for(const n of c._props){c._mapping(n)?t[n]=c.enum(n,e):ArrayBuffer.isView(c[n])?t[n]=c[n][e]:"object"==typeof c[n]&&(ArrayBuffer.isView(c[n][e])?t[n]=Array.from(c[n][e]):t[n]=c[n]._get(e))}return t}}),Object.defineProperty(c,"_flatten",{value:(e=[])=>{if(p)return p;for(const t of c._props)ArrayBuffer.isView(c[t])?e.push(c[t]):"object"==typeof c[t]&&c[t]._flatten(e);return p=e,e}}),Object.defineProperty(c,"_bitflag",{value:e}),Object.defineProperty(c,"_generationId",{value:r}),Object.defineProperty(c,"check",{value:e=>(e&c._bitflag)===c._bitflag}),Object.defineProperty(c,"enum",{value:(e,t,n)=>{const r=c._mapping(e);if(r){if(!n)return r[c[e][t]];{const o=r.indexOf(n);if(-1===o)return void console.warn(`Value '${n}' is not part of enum.`);c[e][t]=o}}else console.warn("Property is not an enum.")}}),a&&(e*=2,e>=Math.pow(2,32)&&(e=1,r+=1)),c};return o};module.exports=(t={})=>{const n=r(),o=(({maxEntities:e=1e4,maxComponentTypes:t=128,tickRate:n=30,devtools:r=!1})=>({maxEntities:e,maxComponentTypes:t,maxGenerations:Math.ceil(t/32),tickRate:n,devtools:r}))(t),i=(({maxEntities:e,maxGenerations:t})=>({entities:Array.from({length:t},(()=>new Uint32Array(e))),components:{},systems:{}}))(o),{entityCount:s,addEntity:a,removeEntity:c,commitEntityRemovals:l,getEntityCursor:f}=((e,t)=>{const{entities:n,systems:r}=t,o=[],i=[],s=new Uint8Array(e.maxEntities);let a=0;return{entityCount:()=>a-o.length,addEntity:()=>{if(a>=e.maxEntities)return void console.warn("❌ Could not add entity, maximum number of entities reached.");const t=o.length>0?o.pop():a++;return s[t]=1,t},removeEntity:e=>{i.push(e)},commitEntityRemovals:()=>{if(0!==i.length){for(let e of i)if(0!==s[e]){for(const t in r)r[t].remove(e);o.push(e),s[e]=0;for(let t of n)t[e]=0}i.length=0}},getEntityCursor:()=>a}})(o,i),{getGeneration:y,registerComponent:E,addComponent:m,removeComponent:p,removeAllComponents:u,hasComponent:d,commitComponentRemovals:_}=((e,t,n)=>{const{entities:r,components:o,systems:i}=t,s=[];let a=0;const c=e=>{if(void 0===o[e])throw new Error(`❌ Component '${e}' is not registered.`);return o[e]},l=(e,t)=>{s.push(e,t)},f=(e,t)=>{const n=o[e],{_generationId:i,_bitflag:s}=n;return(r[i][t]&s)===s};return{getGeneration:()=>a,registerComponent:(t,r)=>{if(Object.keys(o).length+1>e.maxComponentTypes)throw new Error(`❌ Can not register component '${t}'. Max components '${e.maxComponentTypes}' reached.`);return o[t]=n(e.maxEntities,r),a=o[t]._generationId,o[t]},addComponent:(e,t,n={},o=!0)=>{if(f(e,t))return;const s=c(e),{_generationId:a,_bitflag:l}=s;r[a][t]|=l,o&&s._reset(t),s._set(t,n);for(const e in i){const n=i[e];n.components.length&&n.checkComponent(s)&&n.check(t)&&n.add(t)}},removeComponent:l,removeAllComponents:e=>{Object.keys(o).forEach((t=>{l(t,e)}))},hasComponent:f,commitComponentRemovals:()=>{if(0!==s.length){for(let e=0;e<s.length;e+=2){const t=s[e],n=s[e+1],o=c(t),{_generationId:a,_bitflag:l}=o;if(!(r[a][n]&l))return;r[a][n]&=~l;for(const e in i){const t=i[e];t.components.length&&t.checkComponent(o)&&!t.check(n)&&t.remove(n)}}s.length=0}}}})(o,i,n),{enabled:g,registerSystem:h,toggle:b,step:A}=((e,t,n,r)=>{const{entities:o,components:i,systems:s}=t,a=[];let c=!0;const l=()=>{r(),n()};return{registerSystem:({name:t,components:n=[],enter:r,update:c,exit:f})=>{const y=[],E=new Int32Array(e.maxEntities).fill(-1),m={count:0,name:t,enabled:!0,components:n,localEntities:y,entityIndices:E,update:c,enter:r,exit:f},p=n.map((e=>{if(void 0===i[e])throw new Error(`❌ Cannot register system '${t}', '${e}' is not a registered component.`);return i[e]})),u=Array.from({length:e.maxGenerations},(()=>0));for(const e of p){const{_generationId:t,_bitflag:n}=e;u[t]|=n}m.masks=u,m.check=e=>{for(let t=0;t<u.length;t++){const n=o[t][e],r=u[t];if((n&r)!==r)return!1}return!0},m.checkComponent=e=>(u[e._generationId]&e._bitflag)===e._bitflag;const d=c?c(...p):null,_=r?r(...p):null,g=f?f(...p):null;m.execute=e=>{(e||m.enabled)&&d&&d(y),l()},m.add=e=>{-1===E[e]&&(E[e]=y.push(e)-1,m.count=y.length,_&&_(e))},m.remove=e=>{const t=E[e];if(-1===t)return;const n=y.pop();n!==e&&(y[t]=n,E[n]=t),E[e]=-1,m.count=y.length,g&&g(e)};for(let e=0;e<o[0].length;e++)m.components.length&&m.check(e)&&m.add(e);return s[t]=m,t.includes("query")||a.push(m),m},enabled:e=>e?s[e]?s[e].enabled:void console.warn(`System '${e}' is not registered.`):c,step:(e,t=!1)=>{if("boolean"==typeof e&&(t=e),"string"!=typeof e){if(t||c)for(let e=0;e<a.length;e++)a[e].execute();l()}else s[e].execute(t)},toggle:e=>{if(e)return s[e]?void(s[e].enabled=!s[e].enabled):void console.warn(`System '${e} is not registered.`);c=!c}}})(o,i,l,_),{save:w,load:v}=((e,t,n)=>({save:()=>{const r=n(),o=t(),i=Object.keys(e.components),s=i.map((t=>e.components[t])),a=Object.keys(e.systems),c=a.map((t=>e.systems[t])),l=Math.ceil(i.length/32),f=o*l*Uint32Array.BYTES_PER_ELEMENT,y=s.reduce(((e,t)=>e+t._flatten().reduce(((e,t)=>e+t.BYTES_PER_ELEMENT*o),0)),0),E=c.reduce(((e,t)=>e+t.localEntities.reduce(((e,t)=>e+Uint32Array.BYTES_PER_ELEMENT),0)+Uint32Array.BYTES_PER_ELEMENT),0),m=new ArrayBuffer(f+y+E),p=new DataView(m);let u=0;for(let t=0;t<o;t++)for(let n=0;n<l;n++){const r=e.entities[n];p.setUint32(u,r[t]),u+=Uint32Array.BYTES_PER_ELEMENT}return s.forEach((e=>{e._flatten().forEach((e=>{const t=e.constructor.name.split("Array")[0],n=e.BYTES_PER_ELEMENT,o=r;e._cursorStart=u;for(let r=0;r<o;r++)p["set"+t](u,e[r]),u+=n;e._cursorEnd=u}))})),a.forEach((t=>{const n=e.systems[t];p.setUint32(u,n.localEntities.length),u+=Uint32Array.BYTES_PER_ELEMENT,n.localEntities.forEach((e=>{p.setUint32(u,e),u+=Uint32Array.BYTES_PER_ELEMENT}))})),p.buffer.slice(0,u)},load:r=>{const o=n(),i=t(),s=Object.keys(e.components),a=s.map((t=>e.components[t])),c=Object.keys(e.systems),l=Math.ceil(s.length/32),f=new DataView(r);let y=0;for(let t=0;t<i;t++)for(let n=0;n<l;n++)e.entities[n][t]=f.getUint32(y),y+=Uint32Array.BYTES_PER_ELEMENT;a.forEach((e=>{e._flatten().forEach((e=>{const t=e.constructor.name.split("Array")[0],n=e.BYTES_PER_ELEMENT,r=o;for(let o=0;o<r;o++)e[o]=f["get"+t](y),y+=n}))})),c.forEach((t=>{const n=e.systems[t],r=f.getUint32(y);y+=Uint32Array.BYTES_PER_ELEMENT,n.localEntities.length=0,n.count=0,n.entityIndices.fill(-1);for(let e=0;e<r;e++){const e=f.getUint32(y);n.add(e),y+=Uint32Array.BYTES_PER_ELEMENT}}))}}))(i,s,f);let T=0;return{TYPES:e,config:o,registry:i,entityCount:s,addEntity:a,removeEntity:c,registerComponent:E,removeComponent:p,removeAllComponents:u,addComponent:m,hasComponent:d,registerSystem:h,createQuery:e=>h({name:"query-"+T++,components:e}).localEntities,enabled:g,toggle:b,step:A,save:w,load:v}}; | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});const e={bool:"bool",i8:Int8Array,ui8:Uint8Array,ui8c:Uint8ClampedArray,i16:Int16Array,ui16:Uint16Array,i32:Int32Array,ui32:Uint32Array,f32:Float32Array,f64:Float64Array},t=255,r=65535,n=(e,t)=>{const r=new e.constructor(new ArrayBuffer(e.buffer.byteLength+t*e.BYTES_PER_ELEMENT));return r.set(e.buffer),r},o=e=>4*Math.ceil(e/4),i={},s=Symbol("managerRef"),a=Symbol("managerSize"),f=Symbol("maps"),y=Symbol("subarrays"),c=Symbol("managerCursor"),u=Symbol("managerRemoved"),p=Symbol("shadow"),l=Symbol("entityMasks"),g=Symbol("entityEnabled"),d=Symbol("deferredEntityRemovals"),m=Symbol("removedEntities");let E=0;const b=Symbol("queries"),h=Symbol("queryMap"),_=Symbol("queryComponents"),w=(e,t)=>{e[h].get(t)||e[h].set(t,{});let r=[],n=[],o=[];t[_].forEach((e=>{"function"==typeof e?("QueryNot"===e.name&&n.push(e()),"QueryChanged"===e.name&&(o.push(e()),r.push(e()))):r.push(e)}));const i=r.reduce(((e,t)=>t[a]>e?t[a]:e),0),s=new Uint32Array(i),f=new Uint8Array(i),y=r.map((t=>e[M].get(t).generationId)),c=(e,t)=>(e[t.generationId]||(e[t.generationId]=0),e[t.generationId]|=t.bitflag,e),u=r.map((t=>e[M].get(t))).reduce(c,{}),p=n.map((t=>e[M].get(t))).reduce(c,{});Object.assign(e[h].get(t),{entities:[],changed:[],enabled:f,components:r,notComponents:n,changedComponents:o,masks:u,notMasks:p,generations:y,indices:s}),e[b].add(t);for(let r=0;r<E;r++)e[g][r]&&A(e,t,r)&&B(e,t,r)},A=(e,t,r)=>{const{masks:n,notMasks:o,generations:i}=e[h].get(t);for(let t=0;t<i.length;t++){const s=i[t],a=n[s];o[s];if((e[l][s][r]&a)!==a)return!1}return!0},S=(e,t,r)=>r.every((r=>((e,t,r)=>{const{generationId:n,bitflag:o}=e[M].get(r),{masks:i}=e[h].get(t);return(i[n]&o)===o})(e,t,r))),B=(e,t,r)=>{const n=e[h].get(t);n.enabled[r]||(n.enabled[r]=!0,n.entities.push(r),n.indices[r]=n.entities.length-1,n.enter&&n.enter(r))},x=(e,t,r)=>{const n=e[h].get(t);n.enabled[r]&&(n.enabled[r]=!1,n.entities.splice(n.indices[r]),n.exit&&n.exit(r))},M=Symbol("componentMap"),T=Symbol("de$deferredComponentRemovals"),v=(e,t)=>{e[M].set(t,{generationId:e[l].length-1,bitflag:e[j],manager:t}),(e=>{e[j]*=2,e[j]>=Math.pow(2,32)&&(e[j]=1,e[l].push(new Uint32Array(e[P])))})(e)},P=Symbol("size"),j=Symbol("bitflag"),C={bool:"bool",i8:"i8",ui8:"ui8",ui8c:"ui8c",i16:"i16",ui16:"ui16",i32:"i32",ui32:"ui32",f32:"f32",f64:"f64"};exports.Changed=function(e){return function(){return e}},exports.Not=function(e){return function(){return e}},exports.Types=C,exports.addComponent=(e,t,r)=>{if(((e,t,r)=>{const{generationId:n,bitflag:o}=e[M].get(t);return(e[l][n][r]&o)===o})(e,t,r))return;const{generationId:n,bitflag:o}=e[M].get(t);e[l][n][r]|=o;e[b].forEach((t=>{const n=t[_];if(!S(e,t,n))return;A(e,t,r)&&B(e,t,r)}))},exports.addEntity=e=>{const t=e[m],r=e[P],n=e[g];if(E>=r-r/5){const t=4*Math.ceil(r/2/4);e[M].forEach((e=>{e.manager._grow(t)})),e[P]+=t}const o=t.length>0?t.pop():E;return n[o]=1,E++,o},exports.createWorld=(e=1e5)=>{const t={};return t[P]=e,t[g]=new Uint8Array(t[P]),t[l]=[new Uint32Array(e)],t[m]=[],t[j]=1,t[M]=new Map,t[h]=new Map,t[b]=new Set,t[T]=[],t[d]=[],t},exports.defineComponent=(l,g)=>((l,g=1e5)=>{const d=Symbol("manager");i[d]={[a]:g,[f]:{},[y]:{},[s]:d,[c]:0,[u]:[]};const m=l?Object.keys(l):[];let E=m.filter((e=>Array.isArray(l[e])&&"object"==typeof l[e][0]));const b=Object.keys(e).reduce(((e,t)=>({...e,[t]:0})),{});if("string"==typeof l){const t=l,r=g*e[t].BYTES_PER_ELEMENT,n=new ArrayBuffer(r);i[d]=new e[t](n)}else if(Array.isArray(l)){E=l;const{type:n,length:s}=l[0],a=s<t?"ui8":s<r?"ui16":"ui32";if(!s)throw new Error("❌ Must define a length for component array.");if(!e[n])throw new Error(`❌ Invalid component array property type ${n}.`);if(!i[d][y][n]){const t=E,r=t.reduce(((t,r)=>t+e[n].BYTES_PER_ELEMENT),0),f=t.reduce(((e,t)=>e+s),0),c=new ArrayBuffer(o(r*f*g)),u=new e[n](c);u._indexType=a,u._indexBytes=e[a].BYTES_PER_ELEMENT,i[d][y][n]=u}let f=0;for(let e=0;e<g;e++){const t=b[n]+e*s,r=t+s;i[d][e]=i[d][y][n].subarray(t,r),f=r}b[n]=f,i[d]._reset=e=>i[d][e].fill(0),i[d]._set=(e,t)=>i[d][e].set(t,0)}else m.forEach((t=>{if("bool"===l[t]){const r=e.uint8,n=g*e.uint8.BYTES_PER_ELEMENT,o=new ArrayBuffer(n);i[d][f][t]=l[t],i[d][t]=new r(o),i[d][t]._boolType=!0}else if(Array.isArray(l[t])&&"string"==typeof l[t][0]){const r=e.uint8,n=g*e.uint8.BYTES_PER_ELEMENT,o=new ArrayBuffer(n);i[d][f][t]=l[t],i[d][t]=new r(o)}else if(Array.isArray(l[t])&&"object"==typeof l[t][0]){const{type:r,length:n}=l[0];if(!n)throw new Error("❌ Must define a length for component array.");if(!e[r])throw new Error(`❌ Invalid component array property type ${r}.`);if(!i[d][y][r]){const t=E.filter((e=>l[e][0].type===r)),s=t.reduce(((t,n)=>t+e[r].BYTES_PER_ELEMENT),0),a=t.reduce(((e,t)=>e+n),0),f=new ArrayBuffer(o(s*a*g)),c=new e[r](f);c._indexType=index,c._indexBytes=e[index].BYTES_PER_ELEMENT,i[d][y][r]=c}i[d][t]={};let s=0;for(let e=0;e<g;e++){const o=b[r]+e*n,a=o+n;i[d][t][e]=i[d][y][r].subarray(o,a),s=a}b[r]=s,i[d][t]._reset=e=>i[d][t][e].fill(0),i[d][t]._set=(e,r)=>i[d][t][e].set(r,0)}else if("object"==typeof l[t])i[d][t]=Manager(g,l[t],!1);else if("string"==typeof l[t]){const r=l[t],n=g*e[r].BYTES_PER_ELEMENT,o=new ArrayBuffer(n),s=new ArrayBuffer(n);i[d][t]=new e[r](o),i[d][t][p]=new e[r](s)}else{if("function"!=typeof l[t])throw new Error("ECS Error: invalid property type "+l[t]);{const e=l[t],r=g*e.BYTES_PER_ELEMENT,n=new ArrayBuffer(r);i[d][t]=new e(n)}}}));let h;return Object.defineProperty(i[d],"_schema",{value:l}),Object.defineProperty(i[d],"_mapping",{value:e=>i[d][f][e]}),Object.defineProperty(i[d],"_reset",{value:e=>{for(const t of i[d]._props)ArrayBuffer.isView(i[d][t])?ArrayBuffer.isView(i[d][t][e])?i[d][t][e].fill(0):i[d][t][e]=0:i[d][t]._reset(e)}}),Object.defineProperty(i[d],"_set",{value:(e,t)=>{for(const r in t)i[d]._mapping(r)&&"string"==typeof t[r]?i[d].enum(r,e,t[r]):ArrayBuffer.isView(i[d][r])?i[d][r][e]=t[r]:Array.isArray(t[r])&&ArrayBuffer.isView(i[d][r][e])?i[d][r][e].set(t[r],0):"object"==typeof i[d][r]&&i[d][r]._set(e,t[r])}}),Object.defineProperty(i[d],"_get",{value:e=>{const t={};for(const r of i[d]._props)i[d]._mapping(r)?t[r]=i[d].enum(r,e):ArrayBuffer.isView(i[d][r])?t[r]=i[d][r][e]:"object"==typeof i[d][r]&&(ArrayBuffer.isView(i[d][r][e])?t[r]=Array.from(i[d][r][e]):t[r]=i[d][r]._get(e));return t}}),Object.defineProperty(i[d],"_props",{value:m}),Object.defineProperty(i[d],"_flatten",{value:(e=[])=>{if(h)return h;for(const t of i[d]._props)ArrayBuffer.isView(i[d][t])?e.push(i[d][t]):"object"==typeof i[d][t]&&i[d][t]._flatten(e);return h=e,e}}),Object.defineProperty(i[d],"enum",{value:(e,t,r)=>{const n=i[d]._mapping(e);if(n){if(!r)return n[i[d][e][t]];{const o=n.indexOf(r);if(-1===o)return void console.warn(`Value '${r}' is not part of enum.`);i[d][e][t]=o}}else console.warn("Property is not an enum.")}}),Object.defineProperty(i[d],"_grow",{value:e=>{i[d][a]+=e;for(const t of i[d]._props)ArrayBuffer.isView(i[d][t])?(i[d][t]=n(i[d][t],e),i[d][t][p]=n(i[d][t],e)):"object"==typeof i[d][t]&&(ArrayBuffer.isView(i[d][t][eid])||i[d][t]._grow())}}),i[d]})(l,g),exports.defineQuery=e=>{const t=function(e){e[h].has(t)||w(e,t);const r=e[h].get(t);return r.changedComponents.length?((e,t)=>{const r=e[h].get(t);return r.changed.length=0,r.changedComponents.forEach((e=>{const t=e._flatten();for(let e=0;e<t.length;e++){const n=t[e];for(let e=0;e<r.entities.length;e++){const t=r.entities[e];n[t]!==n[p][t]&&(r.changed.push(t),n[p][t]=n[t])}}})),r.changed})(e,t):r.entities};return t[_]=e,t},exports.defineSystem=(e,t)=>r=>{t(e(r)),(e=>{const t=e[T];for(let r=0;r<t.length;r+=2){const n=t[r],o=t[r+1],{generationId:i,bitflag:s}=e[M].get(n);if(!(e[l][i][o]&s))return;e[l][i][o]&=~s,e[b].forEach((t=>{const r=t[_];S(e,t,r)&&A(e,t,o)&&x(e,t,o)}))}t.length=0})(r),(e=>{const t=e[d],r=e[b],n=e[m],o=e[g];for(let i=0;i<t.length;i++){const s=t[i];if(0!==o[s]){r.forEach((e=>{x(e,s)})),n.push(s),o[s]=0;for(let t=0;t<e[l].length;t++)e[l][t][s]=0}}t.length=0})(r)},exports.enterQuery=(e,t,r)=>{e[h].get(t)||w(e,t),e[h].get(t).enter=r},exports.exitQuery=(e,t,r)=>{e[h].get(t)||w(e,t),e[h].get(t).exit=r},exports.pipe=e=>t=>{for(let r=0;r<e.length;r++){(0,e[r])(t)}},exports.registerComponent=v,exports.registerComponents=(e,t)=>{t.forEach((t=>v(e,t)))},exports.removeComponent=(e,t,r)=>e[T].push(t,r),exports.removeEntity=(e,t)=>e[d].push(t); | ||
//# sourceMappingURL=index.min.js.map |
{ | ||
"name": "bitecs", | ||
"version": "0.2.7", | ||
"version": "0.2.8", | ||
"description": "Tiny, data-driven, high performance ECS library written in Javascript", | ||
@@ -5,0 +5,0 @@ "license": "MPL-2.0", |
# 👾 bitECS 👾 | ||
Tiny, data-driven, high performance [ECS](https://en.wikipedia.org/wiki/Entity_component_system) library written using JavaScript TypedArrays. | ||
Functional, tiny, data-oriented, high performance [ECS](https://en.wikipedia.org/wiki/Entity_component_system) library written using JavaScript TypedArrays. | ||
## Features | ||
- Functional | ||
- `<3kb` gzipped | ||
- Zero dependencies | ||
- Node or Browser | ||
- [_Blazing fast_](https://github.com/noctjs/ecs-benchmark) | ||
- [_Killer performance_](https://github.com/noctjs/ecs-benchmark) | ||
@@ -19,47 +20,74 @@ ## Install | ||
```js | ||
import World from 'bitecs' | ||
import { | ||
createWorld, | ||
registerComponent, | ||
registerComponents, | ||
defineComponent, | ||
defineQuery, | ||
enterQuery, | ||
exitQuery, | ||
defineSystem, | ||
addComponent, | ||
removeComponent, | ||
addEntity, | ||
removeEntity, | ||
pipe, | ||
Types, | ||
} from 'bitecs' | ||
// Create a world | ||
const world = World() | ||
// create a world | ||
const world = createWorld() | ||
// Register some components | ||
world.registerComponent('POSITION', { x: 'float32', y: 'float32' }) | ||
world.registerComponent('VELOCITY', { vx: 'int8', vy: 'int8', speed: 'uint16' }) | ||
// define component data stores | ||
const { f32 } = Types | ||
const Vector2 = { x: f32, y: f32 } | ||
const Position = defineComponent(Vector2) | ||
const Velocity = defineComponent(Vector2) | ||
const Health = defineComponent(f32) | ||
const Alive = defineComponent() // "tag" component | ||
// Register a system | ||
world.registerSystem({ | ||
name: 'MOVEMENT', | ||
components: ['POSITION', 'VELOCITY'], | ||
update: (POSITION, VELOCITY) => entities => { | ||
for (let i = 0; i < entities.length; i++) { | ||
const eid = entities[i] | ||
POSITION.x[eid] += VELOCITY.vx[eid] * VELOCITY.speed[eid] | ||
POSITION.y[eid] += VELOCITY.vy[eid] * VELOCITY.speed[eid] | ||
} | ||
// register components on world | ||
registerComponents(world, [Position, Velocity, Health]) // in groups | ||
registerComponent(world, Alive) // or individually | ||
// define a query using components | ||
const movementQuery = defineQuery([Position, Velocity]) | ||
// enter-query hook, called when an entity's components matches the query | ||
enterQuery(world, movementQuery, eid => {}) | ||
// exit-query hook, called when an entity's components no longer matches the query | ||
exitQuery(world, movementQuery, eid => {}) | ||
// define a system using the query | ||
const movementSystem = defineSystem(movementQuery, ents => { | ||
for (let i = 0; i < ents.length; i++) { | ||
const eid = ents[i]; | ||
Position.x[eid] += Velocity.x[eid] | ||
Position.y[eid] += Velocity.y[eid] | ||
} | ||
}) | ||
// Create a query | ||
const positions = world.createQuery(['POSITION']) // array will continuously update, no need to recreate | ||
// add an entity to the world | ||
const eid = addEntity(world) | ||
// Create an entity | ||
const eid = world.addEntity() | ||
// add components to the new entity in the world | ||
addComponent(world, Position, eid) | ||
addComponent(world, Velocity, eid) | ||
// Add components to entity | ||
world.addComponent('POSITION', eid, { x: 100, y: 100 }) | ||
world.addComponent('VELOCITY', eid, { vx: 1, vy: -1, speed: 100 }) | ||
// there are no component getters or setters | ||
// data is accessed directly by entity ID | ||
Velocity.x[eid] = 1 | ||
Velocity.y[eid] = 2 | ||
// Create an event loop and step world | ||
setInterval(() => { | ||
world.step() | ||
}, 1000 / 30) // 30 tick on server | ||
const pipeline = pipe( | ||
movementSystem, | ||
movementSystem, | ||
movementSystem, | ||
) | ||
// For browser, use frame rate | ||
const loop = () => { | ||
world.step() | ||
requestAnimationFrame(loop) | ||
} | ||
loop() | ||
movementSystem(world) // executes movement system on world | ||
pipeline(world) // executes a pipeline of systems on world | ||
``` | ||
Full documentation and feature rich examples can be found [here](DOCS.md). |
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
93
131485
66