@typeonce/ecs
Version:
Entity Component System (ECS) implementation in TypeScript, extensible, working with any renderer, type safe and composable
2 lines • 3.42 kB
JavaScript
var l=Object.defineProperty;var M=(s,e,t)=>e in s?l(s,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):s[e]=t;var d=(s,e,t)=>M(s,typeof e!="symbol"?e+"":e,t);var y=class{constructor(){d(this,"systems",new Map);d(this,"dependencies",new Map)}registerSystem(e){this.systems.set(e._tag,e),this.dependencies.set(e._tag,new Set(e.dependencies))}resolveExecutionOrder(){let e=[],t=new Set,n=new Set,a=o=>{if(n.has(o))throw new Error(`Circular dependency detected: ${o}`);if(t.has(o))return;if(n.add(o),!this.systems.get(o))throw new Error(`System not found: ${o}`);let i=this.dependencies.get(o)??new Set;for(let r of i)a(r);t.add(o),n.delete(o),e.push(o)};for(let o of this.systems.keys())a(o);return e}execute(e){let t=this.resolveExecutionOrder();for(let n of t){let a=this.systems.get(n);a&&a.execute(e)}}};var _=s=>{class e{constructor(n){d(this,"_tag",s);n&&Object.assign(this,n)}}return e.prototype.name=s,e._tag=s,e},R=()=>(s,{execute:e,dependencies:t=[]})=>{class n{constructor(o){d(this,"_tag",s);d(this,"dependencies",t);d(this,"execute",o=>e({...o,input:this.input}));o&&(Object.assign(this,o),Object.defineProperty(this,"input",{get(){return o}}))}}return n.prototype.name=s,n._tag=s,n},x=s=>e=>t=>{let n=s.components.get(t);if(n){let a={},o=!0;for(let[p,i]of Object.entries(e)){let r=n.get(i._tag);if(r)a[p]=r;else{o=!1;break}}if(o)return{entityId:t,...a};throw new Error(`Entity ${t} does not have all required components.`)}throw new Error(`Components for entity ${t} not found`)},E=s=>e=>t=>{try{return x(s)(e)(t)}catch{return}},m=(s,e)=>(t,...n)=>{s.components.has(t)||s.components.set(t,new Map);for(let a=0;a<n.length;a++){let o=n[a];e.push({type:"addComponent",entityId:t,component:o})}},v=(s,e)=>(t,n)=>{s.components.get(t)&&e.push({type:"removeComponent",entityId:t,component:n})},g=s=>()=>{let e=s.nextEntityId++;return s.entities.add(e),e},u=(s,e)=>t=>{s.entities.delete(t)&&e.push({type:"destroyEntity",entityId:t})},C=s=>e=>{s.push(e)},I=s=>e=>s.filter(t=>t.type===e),c=s=>(...e)=>{for(let t of e)s.registry.registerSystem(t)},f=(s,e)=>t=>{let n=new Map,a=E(t)(s);for(let o of t.entities){let p=a(o);p&&n.set(o,p)}if(e){let o=E(t)(Object.fromEntries(e.map(p=>[p._tag,p])));for(let p of t.entities)o(p)&&n.delete(p)}return Array.from(n.values())},b=s=>e=>{let t=f(s)(e);if(t.length===0)throw new Error(`Missing at least one required entity with the following components: ${Object.keys(s).join(", ")}`);return t},T=class s{constructor(){d(this,"registry",new y);d(this,"entities",new Set);d(this,"components",new Map);d(this,"nextEntityId",0)}static create(e){let t=new s,n=[];return e({addComponent:m(t,n),createEntity:g(t),addSystem:c(t)}),t.applyMutations(n),t}update(e){let t=[],n=[];this.registry.execute({world:this,deltaTime:e,getComponentRequired:x(this),getComponent:E(this),createEntity:g(this),addComponent:m(this,n),removeComponent:v(this,n),destroyEntity:u(this,n),addSystem:c(this),poll:I(t),emit:C(t)}),this.applyMutations(n)}applyMutations(e){for(let t=0;t<e.length;t++){let n=e[t];switch(n.type){case"addComponent":this.components.get(n.entityId).set(n.component._tag,n.component);break;case"removeComponent":this.components.get(n.entityId).delete(n.component._tag);break;case"destroyEntity":this.entities.delete(n.entityId);break}}}};var k=Symbol.for("ecs/EntityId");export{_ as Component,T as ECS,R as System,f as query,b as queryRequired};
//# sourceMappingURL=index.mjs.map