ecspresso
Version:
A minimal Entity-Component-System library for typescript and javascript.
5 lines (3 loc) • 8.33 kB
JavaScript
class H{nextId=1;entities=new Map;componentIndices=new Map;createEntity(){let f=this.nextId++,g={id:f,components:{}};return this.entities.set(f,g),g}addComponent(f,g,j){let L=typeof f==="number"?this.entities.get(f):f;if(!L)throw new Error(`Entity ${f} does not exist`);if(L.components[g]=j,!this.componentIndices.has(g))this.componentIndices.set(g,new Set);return this.componentIndices.get(g)?.add(L.id),this}addComponents(f,g){let j=typeof f==="number"?this.entities.get(f):f;if(!j)throw new Error(`Entity ${f} does not exist`);for(let L in g)this.addComponent(j,L,g[L]);return this}removeComponent(f,g){let j=this.entities.get(f);if(!j)throw new Error(`Entity ${f} does not exist`);delete j.components[g],this.componentIndices.get(g)?.delete(f)}getComponent(f,g){let j=this.entities.get(f);if(!j)throw new Error(`Entity ${f} does not exist`);return j.components[g]||null}getEntitiesWithComponents(f=[],g=[]){if(f.length===0){if(g.length===0)return Array.from(this.entities.values());return Array.from(this.entities.values()).filter((D)=>{return g.every((F)=>!(F in D.components))})}let j=f.reduce((D,F)=>{let G=this.componentIndices.get(F),$=G?G.size:0,A=this.componentIndices.get(D)?.size??1/0;return $<A?F:D},f[0]);return Array.from(this.componentIndices.get(j)||[]).filter((D)=>{let F=this.entities.get(D);return F&&f.every((G)=>(G in F.components))&&g.every((G)=>!(G in F.components))}).map((D)=>this.entities.get(D))}removeEntity(f){let g=typeof f==="number"?this.entities.get(f):f;if(!g)return!1;for(let j of Object.keys(g.components))this.componentIndices.get(j)?.delete(g.id);return this.entities.delete(g.id)}getEntity(f){return this.entities.get(f)}}class J{handlers=new Map;subscribe(f,g){return this.addHandler(f,g,!1)}once(f,g){return this.addHandler(f,g,!0)}addHandler(f,g,j){if(!this.handlers.has(f))this.handlers.set(f,[]);let L={callback:g,once:j};return this.handlers.get(f).push(L),()=>{let D=this.handlers.get(f);if(D){let F=D.indexOf(L);if(F!==-1)D.splice(F,1)}}}publish(f,g){let j=this.handlers.get(f);if(!j)return;let L=[...j],D=[];for(let F of L)if(F.callback(g),F.once)D.push(F);if(D.length>0)for(let F of D){let G=j.indexOf(F);if(G!==-1)j.splice(G,1)}}clear(){this.handlers.clear()}clearEvent(f){this.handlers.delete(f)}}class M{resources=new Map;resourceFactories=new Map;initializedResourceKeys=new Set;add(f,g){if(typeof g==="function"&&!/^class\s/.test(Function.prototype.toString.call(g)))this.resourceFactories.set(f,g);else this.resources.set(f,g),this.initializedResourceKeys.add(f);return this}get(f,g){let j=this.resources.get(f);if(j!==void 0)return j;let L=this.resourceFactories.get(f);if(L===void 0)throw new Error(`Resource ${String(f)} not found`);let D=L(g);if(!(D instanceof Promise))this.resources.set(f,D),this.initializedResourceKeys.add(f);return D}has(f){return this.resources.has(f)||this.resourceFactories.has(f)}remove(f){let g=this.resources.delete(f),j=this.resourceFactories.delete(f);if(this.initializedResourceKeys.has(f))this.initializedResourceKeys.delete(f);return g||j}getKeys(){let f=new Set([...this.resources.keys(),...this.resourceFactories.keys()]);return Array.from(f)}needsInitialization(f){return this.resourceFactories.has(f)&&!this.initializedResourceKeys.has(f)}getPendingInitializationKeys(){return Array.from(this.resourceFactories.keys()).filter((f)=>!this.initializedResourceKeys.has(f))}async initializeResource(f,g){if(!this.resourceFactories.has(f)||this.initializedResourceKeys.has(f))return;let L=await this.resourceFactories.get(f)(g);this.resources.set(f,L),this.initializedResourceKeys.add(f),this.resourceFactories.delete(f)}async initializeResources(f,...g){if(g.length===0){let j=this.getPendingInitializationKeys();await Promise.all(j.map((L)=>this.initializeResource(L,f)));return}await Promise.all(g.map((j)=>this.initializeResource(j,f)))}}class U{_label;_ecspresso;_bundle;queries={};processFunction;detachFunction;initializeFunction;eventHandlers;_priority=0;constructor(f,g=null,j=null){this._label=f;this._ecspresso=g;this._bundle=j}get label(){return this._label}get bundle(){return this._bundle}get ecspresso(){return this._ecspresso}setPriority(f){return this._priority=f,this}addQuery(f,g){let j=this;return j.queries={...this.queries,[f]:g},j}setProcess(f){return this.processFunction=f,this}setOnDetach(f){return this.detachFunction=f,this}setOnInitialize(f){return this.initializeFunction=f,this}setEventHandlers(f){return this.eventHandlers=f,this}build(f){let g={label:this._label,entityQueries:this.queries,priority:this._priority};if(this.processFunction)g.process=this.processFunction;if(this.detachFunction)g.onDetach=this.detachFunction;if(this.initializeFunction)g.onInitialize=this.initializeFunction;if(this.eventHandlers)g.eventHandlers=this.eventHandlers;if(this._ecspresso)V(g,this._ecspresso);if(f)V(g,f);return this}}function V(f,g){if(g._systems.push(f),g._sortSystems(),!f.eventHandlers)return;for(let j in f.eventHandlers){let L=f.eventHandlers[j]?.handler;L&&g.eventBus.subscribe(j,(D)=>{L(D,g)})}}function X(f,g){return new U(f,g)}function Y(f,g){return new U(f,null,g)}var Z="0.2.4";class P{static VERSION=Z;_entityManager;_eventBus;_resourceManager;_systems=[];_sortedSystems=[];_installedBundles=new Set;constructor(){this._entityManager=new H,this._eventBus=new J,this._resourceManager=new M,this._sortedSystems=[]}static create(){return new _}addSystem(f){return X(f,this)}update(f){for(let g of this._sortedSystems){if(!g.process)continue;let j={};if(g.entityQueries)for(let L in g.entityQueries){let D=g.entityQueries[L];if(D)j[L]=this._entityManager.getEntitiesWithComponents(D.with,D.without||[])}g.process(j,f,this)}}async initialize(){await this.initializeResources();for(let f of this._systems)await f.onInitialize?.(this)}async initializeResources(...f){await this._resourceManager.initializeResources(this,...f)}_sortSystems(){this._sortedSystems=[...this._systems].sort((f,g)=>{let j=f.priority??0;return(g.priority??0)-j})}updateSystemPriority(f,g){let j=this._systems.find((L)=>L.label===f);if(!j)return!1;return j.priority=g,this._sortSystems(),!0}removeSystem(f){let g=this._systems.findIndex((L)=>L.label===f);if(g===-1)return!1;let j=this._systems[g];if(!j)return!1;if(j.onDetach)j.onDetach(this);return this._systems.splice(g,1),this._sortSystems(),!0}hasResource(f){return this._resourceManager.has(f)}getResource(f){let g=this._resourceManager.get(f,this);if(!g)throw new Error(`Resource "${f.toString()}" not found`);return g}addResource(f,g){return this._resourceManager.add(f,g),this}hasComponent(f,g){return this._entityManager.getComponent(f,g)!==null}getEntitiesWithComponents(f,g=[]){return this._entityManager.getEntitiesWithComponents(f,g)}get installedBundles(){return Array.from(this._installedBundles)}get entityManager(){return this._entityManager}get eventBus(){return this._eventBus}get resourceManager(){return this._resourceManager}_installBundle(f){if(this._installedBundles.has(f.id))return this;this._installedBundles.add(f.id),f.registerSystemsWithEcspresso(this);let g=f.getResources();for(let[j,L]of g.entries())this._resourceManager.add(j,L);return this}}class _{ecspresso;constructor(){this.ecspresso=new P}withBundle(f){return this.ecspresso._installBundle(f),this}build(){return this.ecspresso}}function W(){return`bundle_${Date.now().toString(36)}_${Math.random().toString(36).substring(2,9)}`}class Q{_systems=[];_resources=new Map;_id;constructor(f){this._id=f||W()}get id(){return this._id}set id(f){this._id=f}addSystem(f){let g=Y(f,this);return this._systems.push(g),g}addResource(f,g){return this._resources.set(f,g),this}getSystems(){return this._systems.map((f)=>f.build())}registerSystemsWithEcspresso(f){for(let g of this._systems)g.build(f)}getResources(){return new Map(this._resources)}getResource(f){return this._resources.get(f)}getSystemBuilders(){return[...this._systems]}hasResource(f){return this._resources.has(f)}}function E(f,...g){if(g.length===0)return new Q(f);let j=new Q(f);for(let L of g){for(let D of L.getSystemBuilders())j.addSystem(D.label);for(let[D,F]of L.getResources().entries())j.addResource(D,F)}return j}var o=P;export{E as mergeBundles,o as default,U as SystemBuilder,M as ResourceManager,J as EventBus,H as EntityManager,Q as Bundle};
//# debugId=3209283C5FAC04C164756E2164756E21
//# sourceMappingURL=index.js.map