@arancini/core
Advanced tools
Comparing version 0.1.0 to 0.1.1
@@ -1,6 +0,6 @@ | ||
export * from './space'; | ||
export * from './component'; | ||
export * from './entity'; | ||
export * from './query'; | ||
export * from './space'; | ||
export * from './system'; | ||
export * from './query'; | ||
export * from './world'; |
@@ -7,68 +7,2 @@ var __defProp = Object.defineProperty; | ||
}; | ||
class EventDispatcher { | ||
constructor() { | ||
__publicField(this, "listeners", /* @__PURE__ */ new Set()); | ||
} | ||
add(handler) { | ||
this.listeners.add(handler); | ||
return this; | ||
} | ||
remove(handler) { | ||
this.listeners.delete(handler); | ||
return this; | ||
} | ||
emit(event) { | ||
for (const handler of this.listeners.values()) { | ||
handler(event); | ||
} | ||
} | ||
clear() { | ||
this.listeners.clear(); | ||
} | ||
} | ||
class EventSystem { | ||
constructor(params) { | ||
__publicField(this, "queue", []); | ||
__publicField(this, "dispatchers", /* @__PURE__ */ new Map()); | ||
__publicField(this, "queued"); | ||
this.queued = (params == null ? void 0 : params.queued) || false; | ||
} | ||
tick() { | ||
this.queue.splice(0, this.queue.length).forEach((e) => this.process(e)); | ||
} | ||
on(eventName, handler) { | ||
let eventDispatcher = this.dispatchers.get(eventName); | ||
if (eventDispatcher === void 0) { | ||
eventDispatcher = new EventDispatcher(); | ||
this.dispatchers.set(eventName, eventDispatcher); | ||
} | ||
eventDispatcher.add(handler); | ||
return { | ||
unsubscribe: () => this.unsubscribe(eventName, handler) | ||
}; | ||
} | ||
unsubscribe(eventName, handler) { | ||
const eventHandlers = this.dispatchers.get(eventName); | ||
if (eventHandlers !== void 0) { | ||
eventHandlers.remove(handler); | ||
} | ||
} | ||
emit(event) { | ||
if (this.queued) { | ||
this.queue.push(event); | ||
} else { | ||
this.process(event); | ||
} | ||
} | ||
reset() { | ||
this.dispatchers.clear(); | ||
this.queue = []; | ||
} | ||
process(event) { | ||
const dispatcher = this.dispatchers.get(event.topic); | ||
if (dispatcher !== void 0) { | ||
dispatcher.emit(event); | ||
} | ||
} | ||
} | ||
class BitSet { | ||
@@ -144,29 +78,2 @@ constructor(indices = []) { | ||
}; | ||
class Space { | ||
constructor(world, params) { | ||
__publicField(this, "id"); | ||
__publicField(this, "entities", /* @__PURE__ */ new Map()); | ||
__publicField(this, "events", new EventSystem()); | ||
__publicField(this, "initialised", false); | ||
__publicField(this, "world"); | ||
this.world = world; | ||
this.id = (params == null ? void 0 : params.id) || uniqueId(); | ||
} | ||
get create() { | ||
return { | ||
entity: (components) => { | ||
return this.world.spaceManager.createEntity(this, components); | ||
} | ||
}; | ||
} | ||
emit(event) { | ||
this.events.emit(event); | ||
} | ||
on(eventName, handler) { | ||
return this.events.on(eventName, handler); | ||
} | ||
destroy() { | ||
this.world.spaceManager.removeSpace(this); | ||
} | ||
} | ||
class Component { | ||
@@ -191,2 +98,68 @@ constructor() { | ||
} | ||
class EventDispatcher { | ||
constructor() { | ||
__publicField(this, "listeners", /* @__PURE__ */ new Set()); | ||
} | ||
add(handler) { | ||
this.listeners.add(handler); | ||
return this; | ||
} | ||
remove(handler) { | ||
this.listeners.delete(handler); | ||
return this; | ||
} | ||
emit(event) { | ||
for (const handler of this.listeners.values()) { | ||
handler(event); | ||
} | ||
} | ||
clear() { | ||
this.listeners.clear(); | ||
} | ||
} | ||
class EventSystem { | ||
constructor(params) { | ||
__publicField(this, "queue", []); | ||
__publicField(this, "dispatchers", /* @__PURE__ */ new Map()); | ||
__publicField(this, "queued"); | ||
this.queued = (params == null ? void 0 : params.queued) || false; | ||
} | ||
tick() { | ||
this.queue.splice(0, this.queue.length).forEach((e) => this.process(e)); | ||
} | ||
on(eventName, handler) { | ||
let eventDispatcher = this.dispatchers.get(eventName); | ||
if (eventDispatcher === void 0) { | ||
eventDispatcher = new EventDispatcher(); | ||
this.dispatchers.set(eventName, eventDispatcher); | ||
} | ||
eventDispatcher.add(handler); | ||
return { | ||
unsubscribe: () => this.unsubscribe(eventName, handler) | ||
}; | ||
} | ||
unsubscribe(eventName, handler) { | ||
const eventHandlers = this.dispatchers.get(eventName); | ||
if (eventHandlers !== void 0) { | ||
eventHandlers.remove(handler); | ||
} | ||
} | ||
emit(event) { | ||
if (this.queued) { | ||
this.queue.push(event); | ||
} else { | ||
this.process(event); | ||
} | ||
} | ||
reset() { | ||
this.dispatchers.clear(); | ||
this.queue = []; | ||
} | ||
process(event) { | ||
const dispatcher = this.dispatchers.get(event.topic); | ||
if (dispatcher !== void 0) { | ||
dispatcher.emit(event); | ||
} | ||
} | ||
} | ||
class Entity { | ||
@@ -254,29 +227,2 @@ constructor() { | ||
} | ||
class System { | ||
constructor(world) { | ||
__publicField(this, "enabled", true); | ||
__publicField(this, "world"); | ||
__publicField(this, "__internal", { | ||
queries: /* @__PURE__ */ new Set(), | ||
priority: 0, | ||
order: 0, | ||
class: null | ||
}); | ||
this.world = world; | ||
} | ||
onDestroy() { | ||
} | ||
onInit() { | ||
} | ||
onUpdate(_delta, _time) { | ||
} | ||
destroy() { | ||
this.world.unregisterSystem(this.__internal.class); | ||
} | ||
query(queryDescription) { | ||
const query = this.world.queryManager.createQuery(queryDescription); | ||
this.__internal.queries.add(query); | ||
return query; | ||
} | ||
} | ||
const QueryConditionType = { | ||
@@ -318,2 +264,56 @@ ALL: "all", | ||
} | ||
class Space { | ||
constructor(world, params) { | ||
__publicField(this, "id"); | ||
__publicField(this, "entities", /* @__PURE__ */ new Map()); | ||
__publicField(this, "events", new EventSystem()); | ||
__publicField(this, "initialised", false); | ||
__publicField(this, "world"); | ||
this.world = world; | ||
this.id = (params == null ? void 0 : params.id) || uniqueId(); | ||
} | ||
get create() { | ||
return { | ||
entity: (components) => { | ||
return this.world.spaceManager.createEntity(this, components); | ||
} | ||
}; | ||
} | ||
emit(event) { | ||
this.events.emit(event); | ||
} | ||
on(eventName, handler) { | ||
return this.events.on(eventName, handler); | ||
} | ||
destroy() { | ||
this.world.spaceManager.removeSpace(this); | ||
} | ||
} | ||
class System { | ||
constructor(world) { | ||
__publicField(this, "enabled", true); | ||
__publicField(this, "world"); | ||
__publicField(this, "__internal", { | ||
queries: /* @__PURE__ */ new Set(), | ||
priority: 0, | ||
order: 0, | ||
class: null | ||
}); | ||
this.world = world; | ||
} | ||
onDestroy() { | ||
} | ||
onInit() { | ||
} | ||
onUpdate(_delta, _time) { | ||
} | ||
destroy() { | ||
this.world.unregisterSystem(this.__internal.class); | ||
} | ||
query(queryDescription) { | ||
const query = this.world.queryManager.createQuery(queryDescription); | ||
this.__internal.queries.add(query); | ||
return query; | ||
} | ||
} | ||
class ComponentRegistry { | ||
@@ -320,0 +320,0 @@ constructor(world) { |
@@ -1,1 +0,1 @@ | ||
(function(o,c){typeof exports=="object"&&typeof module!="undefined"?c(exports):typeof define=="function"&&define.amd?define(["exports"],c):(o=typeof globalThis!="undefined"?globalThis:o||self,c(o.index={}))})(this,function(o){"use strict";var I=Object.defineProperty;var O=(o,c,d)=>c in o?I(o,c,{enumerable:!0,configurable:!0,writable:!0,value:d}):o[c]=d;var n=(o,c,d)=>(O(o,typeof c!="symbol"?c+"":c,d),d);class c{constructor(){n(this,"listeners",new Set)}add(e){return this.listeners.add(e),this}remove(e){return this.listeners.delete(e),this}emit(e){for(const t of this.listeners.values())t(e)}clear(){this.listeners.clear()}}class d{constructor(e){n(this,"queue",[]);n(this,"dispatchers",new Map);n(this,"queued");this.queued=(e==null?void 0:e.queued)||!1}tick(){this.queue.splice(0,this.queue.length).forEach(e=>this.process(e))}on(e,t){let s=this.dispatchers.get(e);return s===void 0&&(s=new c,this.dispatchers.set(e,s)),s.add(t),{unsubscribe:()=>this.unsubscribe(e,t)}}unsubscribe(e,t){const s=this.dispatchers.get(e);s!==void 0&&s.remove(t)}emit(e){this.queued?this.queue.push(e):this.process(e)}reset(){this.dispatchers.clear(),this.queue=[]}process(e){const t=this.dispatchers.get(e.topic);t!==void 0&&t.emit(e)}}class h{constructor(e=[]){n(this,"words");this.words=new Uint32Array(8);for(const t of e)this.add(t)}add(e){this.resize(e),this.words[e>>>5]|=1<<e}remove(e){this.resize(e),this.words[e>>>5]&=~(1<<e)}has(e){return(this.words[e>>>5]&1<<e)!==0}resize(e){if(this.words.length<<5>e)return;const t=e+32>>>5,s=new Uint32Array(t<<1);s.set(this.words),this.words=s}reset(){for(let e=0;e<this.words.length;e++)this.words[e]=0}copy(e){const t=new Uint32Array(e.words.length);t.set(e.words),this.words=t}clone(){const e=new Uint32Array(this.words.length);e.set(this.words);const t=new h;return t.words=e,t}containsAll(e){for(let t=0;t<this.words.length;t++)if((~this.words[t]&e.words[t])!==0)return!1;return!0}containsAny(e){for(let t=0;t<this.words.length;t++)if((this.words[t]&e.words[t])!==0)return!0;return!1}}const M=(a,e)=>Object.getOwnPropertyNames(a.prototype).includes(e);let p=0;const u=()=>(p++,p.toString());class m{constructor(e,t){n(this,"id");n(this,"entities",new Map);n(this,"events",new d);n(this,"initialised",!1);n(this,"world");this.world=e,this.id=(t==null?void 0:t.id)||u()}get create(){return{entity:e=>this.world.spaceManager.createEntity(this,e)}}emit(e){this.events.emit(e)}on(e,t){return this.events.on(e,t)}destroy(){this.world.spaceManager.removeSpace(this)}}class f{constructor(){n(this,"id",u());n(this,"entity");n(this,"__internal")}get space(){return this.entity.space}get world(){return this.entity.world}construct(...e){}onDestroy(){}onInit(){}}class g{constructor(){n(this,"id",u());n(this,"alive",!0);n(this,"components",new Map);n(this,"componentsBitSet",new h);n(this,"events",new d);n(this,"initialised",!1);n(this,"space")}get world(){return this.space.world}add(e,...t){if(this.components.has(e))throw new Error(`Cannot add component ${e.name}, entity with id ${this.id} already has this component`);const s=this.world.spaceManager.addComponentToEntity(this,e,t);return this.world.queryManager.onEntityComponentChange(this),s}destroy(){this.world.spaceManager.removeEntity(this,this.space),this.alive=!1}emit(e){this.events.emit(e)}find(e){return this.components.get(e)}get(e){const t=this.components.get(e);if(t!==void 0)return t;throw new Error(`Component ${e}} not in entity ${this.id}`)}has(e){return this.components.has(e)}on(e,t){return this.events.on(e,t)}remove(e){let t;if(e instanceof f){if(!this.components.has(e.__internal.class))throw new Error("Component instance does not exist in Entity");t=e}else if(t=this.find(e),t===void 0)throw new Error("Component does not exist in Entity");return this.world.spaceManager.removeComponentFromEntity(this,t),this.world.queryManager.onEntityComponentChange(this),this}}class E{constructor(e){n(this,"enabled",!0);n(this,"world");n(this,"__internal",{queries:new Set,priority:0,order:0,class:null});this.world=e}onDestroy(){}onInit(){}onUpdate(e,t){}destroy(){this.world.unregisterSystem(this.__internal.class)}query(e){const t=this.world.queryManager.createQuery(e);return this.__internal.queries.add(t),t}}const w={ALL:"all",ANY:"any",NOT:"not"};class y{constructor(e,t){n(this,"key");n(this,"entities",[]);n(this,"onEntityAdded",new c);n(this,"onEntityRemoved",new c);n(this,"world");this.world=e,this.key=t}get first(){return this.entities[0]||void 0}[Symbol.iterator](){return this.entities[Symbol.iterator]()}destroy(){this.world.queryManager.removeQuery(this)}static getDescriptionDedupeString(e){return Array.isArray(e)?e.map(t=>`${t.name}`).join("&"):Object.entries(e).flatMap(([t,s])=>t===w.ALL?s.map(i=>`${i.name}`).sort():[`${t}:${s.sort().map(i=>i.name)}`]).sort().join("&")}}class b{constructor(e){n(this,"components",new Map);n(this,"currentComponentIndex",-1);n(this,"world");this.world=e}getComponentIndex(e){const t=this.components.get(e);return t===void 0?this.registerComponent(e):t}registerComponent(e){let t=this.components.get(e);if(t!==void 0)return t;if(this.currentComponentIndex++,t=this.currentComponentIndex,this.components.set(e,t),this.world.initialised)for(const s of this.world.spaceManager.spaces.values())for(const i of s.entities.values())i.componentsBitSet.resize(this.currentComponentIndex);return t}}class C{constructor(e){n(this,"dedupedQueries",new Map);n(this,"world");this.world=e}createQuery(e){const t=y.getDescriptionDedupeString(e);let s=this.dedupedQueries.get(t);if(s===void 0){const r=Array.isArray(e);if(r&&e.length===0||!r&&(!e.all&&!e.any&&!e.not||e.all&&e.all.length===0||e.any&&e.any.length===0||e.not&&e.not.length===0))throw new Error("Query must have at least one condition");s={dedupeString:t,instances:new Set,description:e,bitSets:this.getQueryBitSets(e),entities:[],entitySet:new Set};const l=this.getQueryResults(s.bitSets);for(const _ of l.values())s.entities.push(_),s.entitySet.add(_);this.dedupedQueries.set(t,s)}const i=new y(this.world,t);return i.entities=s.entities,s.instances.add(i),i}hasQuery(e){const t=y.getDescriptionDedupeString(e);return this.dedupedQueries.has(t)}onEntityComponentChange(e){for(const t of this.dedupedQueries.values()){const s=t.entitySet.has(e),i=this.matchesQueryConditions(t.bitSets,e);if(i&&!s){t.entities.push(e),t.entitySet.add(e);for(const r of t.instances)r.onEntityAdded.emit(e)}else if(!i&&s){const r=t.entities.indexOf(e,0);r!==-1&&t.entities.splice(r,1),t.entitySet.delete(e);for(const l of t.instances)l.onEntityRemoved.emit(e)}}}onEntityRemoved(e){for(const t of this.dedupedQueries.values()){const s=t.entities.indexOf(e,0);s!==-1&&t.entities.splice(s,1),t.entitySet.delete(e);for(const i of t.instances)i.onEntityRemoved.emit(e)}}query(e){const t=y.getDescriptionDedupeString(e),s=this.dedupedQueries.get(t);return s?s.entities:this.getQueryResults(this.getQueryBitSets(e))}removeQuery(e){const t=this.dedupedQueries.get(e.key);t===void 0||!t.instances.has(e)||(t.instances.delete(e),e.onEntityAdded.clear(),e.onEntityRemoved.clear(),t.instances.size===0&&this.dedupedQueries.delete(t.dedupeString))}matchesQueryConditions(e,t){return!(e.all&&!t.componentsBitSet.containsAll(e.all)||e.any&&!t.componentsBitSet.containsAny(e.any)||e.not&&t.componentsBitSet.containsAny(e.not))}getQueryResults(e){const t=[];for(const s of this.world.spaceManager.spaces.values())for(const i of s.entities.values())this.matchesQueryConditions(e,i)&&t.push(i);return t}getQueryBitSets(e){const{all:t,any:s,not:i}=Array.isArray(e)?{all:e,any:void 0,not:void 0}:e,r={};return r.all=t?new h(t.map(l=>this.world.componentRegistry.getComponentIndex(l))):void 0,r.any=s?new h(s.map(l=>this.world.componentRegistry.getComponentIndex(l))):void 0,r.not=i?new h(i.map(l=>this.world.componentRegistry.getComponentIndex(l))):void 0,r}}class v{constructor(e,t){n(this,"availableObjects",[]);n(this,"factory");n(this,"size",0);this.factory=e,t!==void 0&&this.expand(t)}get free(){return this.availableObjects.length}get used(){return this.size-this.availableObjects.length}expand(e){for(let t=0;t<e;t++)this.availableObjects.push(this.factory());this.size+=e}request(){return this.availableObjects.length<=0&&this.expand(Math.round(this.size*.2)+1),this.availableObjects.pop()}release(e){this.availableObjects.push(e)}}class Q{constructor(e){n(this,"objectPools",new Map);n(this,"world");this.world=e}get totalPools(){return this.objectPools.size}get size(){let e=0;for(const t of this.objectPools.values())e+=t.size;return e}get free(){let e=0;for(const t of this.objectPools.values())e+=t.free;return e}get used(){let e=0;for(const t of this.objectPools.values())e+=t.used;return e}request(e){let t=this.objectPools.get(e);return t===void 0&&(t=new v(()=>{const s=new e;return s.__internal={class:e,classIndex:this.world.componentRegistry.getComponentIndex(e)},s}),this.objectPools.set(e,t)),t.request()}release(e){const t=this.objectPools.get(e.__internal.class);t!==void 0&&t.release(e)}}class P{constructor(){n(this,"objectPool",new v(()=>new g))}get size(){return this.objectPool.size}get free(){return this.objectPool.free}get used(){return this.objectPool.used}request(){return this.objectPool.request()}release(e){this.objectPool.release(e)}}class j{constructor(e){n(this,"spaces",new Map);n(this,"componentPool");n(this,"entityPool");n(this,"componentsToRecycle",[]);n(this,"entitiesToRecycle",[]);n(this,"world");this.world=e,this.componentPool=new Q(e),this.entityPool=new P}init(){for(const e of this.spaces.values())this.initialiseSpace(e)}destroy(){for(const e of this.spaces.values())this.removeSpace(e)}createSpace(e){if((e==null?void 0:e.id)&&this.spaces.has(e.id))throw new Error("A space with the provided id already exists");const t=new m(this.world,e);return this.spaces.set(t.id,t),this.world.initialised&&this.initialiseSpace(t),t}initialiseSpace(e){e.initialised=!0;for(const t of e.entities.values())this.initialiseEntity(t)}removeSpace(e){this.spaces.delete(e.id);for(const t of e.entities.values())this.removeEntity(t,e)}createEntity(e,t=[]){var i;const s=this.entityPool.request();s.space=e,e.entities.set(s.id,s);for(const r of t)this.world.spaceManager.addComponentToEntity(s,r.type,(i=r.args)!=null?i:[]);return this.world.queryManager.onEntityComponentChange(s),e.initialised&&this.world.spaceManager.initialiseEntity(s),s}initialiseEntity(e){e.initialised=!0,e.componentsBitSet.resize(this.world.componentRegistry.currentComponentIndex);for(const t of e.components.values())this.initialiseComponent(t)}removeEntity(e,t){e.alive=!1,e.space=null,e.initialised=!1,t.entities.delete(e.id);for(const s of e.components.values())this.removeComponentFromEntity(e,s);this.world.queryManager.onEntityRemoved(e),this.entitiesToRecycle.push(e)}addComponentToEntity(e,t,s){const i=this.componentPool.request(t);return i.entity=e,i.construct(...s),e.components.set(t,i),e.componentsBitSet.add(i.__internal.classIndex),e.initialised&&this.initialiseComponent(i),i}removeComponentFromEntity(e,t){t.onDestroy(),e.components.delete(t.__internal.class),e.componentsBitSet.remove(t.__internal.classIndex),this.componentsToRecycle.push(t)}initialiseComponent(e){e.onInit()}recycle(){const e=this.entitiesToRecycle;this.entitiesToRecycle=[];for(const s of e)s.id=u(),s.events.reset(),s.componentsBitSet.reset(),s.alive=!0,this.entityPool.release(s);const t=this.componentsToRecycle;this.componentsToRecycle=[];for(const s of t)s.id=u(),s.entity=void 0,this.componentPool.release(s)}}class A{constructor(e){n(this,"systems",new Map);n(this,"sortedSystems",[]);n(this,"systemCounter",0);n(this,"initialised",!1);n(this,"world");this.world=e}init(){this.initialised=!0;for(const e of this.systems.values())e.onInit();this.sortSystems()}update(e,t){for(const s of this.sortedSystems.values())s.enabled&&s.onUpdate(e,t)}destroy(){for(const e of this.systems.values())e.onDestroy(),this.systems.delete(e.__internal.class)}registerSystem(e,t){var r;if(this.systems.has(e))throw new Error(`System "${e.name}" has already been registered`);this.systemCounter++;const s=new e(this.world);s.__internal.class=e,s.__internal.priority=(r=t==null?void 0:t.priority)!=null?r:0,s.__internal.order=this.systemCounter,this.systems.set(e,s);const i=M(e,"onUpdate");i&&this.sortedSystems.push(s),this.initialised&&(s.onInit(),i&&this.sortSystems())}unregisterSystem(e){const t=this.systems.get(e);!t||(this.systems.delete(e),this.sortedSystems=this.sortedSystems.filter(s=>s.__internal.class!==e),t.__internal.queries.forEach(s=>{this.world.queryManager.removeQuery(s)}),t.onDestroy())}sortSystems(){this.sortedSystems.sort((e,t)=>t.__internal.priority-e.__internal.priority||e.__internal.order-t.__internal.order)}}const S="__arancini_default_world_space";class R{constructor(){n(this,"id",u());n(this,"initialised",!1);n(this,"time",0);n(this,"defaultSpace");n(this,"events");n(this,"spaceManager");n(this,"queryManager");n(this,"systemManager");n(this,"componentRegistry");this.events=new d,this.componentRegistry=new b(this),this.spaceManager=new j(this),this.queryManager=new C(this),this.systemManager=new A(this),this.defaultSpace=this.create.space({id:S})}get create(){return{entity:e=>this.spaceManager.createEntity(this.defaultSpace,e),space:e=>this.spaceManager.createSpace(e),query:e=>this.queryManager.createQuery(e)}}init(){this.initialised=!0,this.spaceManager.init(),this.systemManager.init()}update(e=0){this.time+=e,this.systemManager.update(e,this.time),this.spaceManager.recycle()}destroy(){this.systemManager.destroy(),this.spaceManager.destroy()}emit(e){this.events.emit(e)}on(e,t){return this.events.on(e,t)}query(e){return this.queryManager.query(e)}registerComponent(e){return this.componentRegistry.registerComponent(e),this}registerSystem(e,t){return this.systemManager.registerSystem(e,t),this}unregisterSystem(e){return this.systemManager.unregisterSystem(e),this}getSystem(e){return this.systemManager.systems.get(e)}getSystems(){return Array.from(this.systemManager.systems.values())}getSpace(e){return this.spaceManager.spaces.get(e)}}o.Component=f,o.Entity=g,o.Query=y,o.QueryConditionType=w,o.Space=m,o.System=E,o.WORLD_DEFAULT_SPACE_ID=S,o.World=R,Object.defineProperties(o,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}); | ||
(function(o,r){typeof exports=="object"&&typeof module!="undefined"?r(exports):typeof define=="function"&&define.amd?define(["exports"],r):(o=typeof globalThis!="undefined"?globalThis:o||self,r(o.index={}))})(this,function(o){"use strict";var I=Object.defineProperty;var O=(o,r,l)=>r in o?I(o,r,{enumerable:!0,configurable:!0,writable:!0,value:l}):o[r]=l;var n=(o,r,l)=>(O(o,typeof r!="symbol"?r+"":r,l),l);class r{constructor(e=[]){n(this,"words");this.words=new Uint32Array(8);for(const t of e)this.add(t)}add(e){this.resize(e),this.words[e>>>5]|=1<<e}remove(e){this.resize(e),this.words[e>>>5]&=~(1<<e)}has(e){return(this.words[e>>>5]&1<<e)!==0}resize(e){if(this.words.length<<5>e)return;const t=e+32>>>5,s=new Uint32Array(t<<1);s.set(this.words),this.words=s}reset(){for(let e=0;e<this.words.length;e++)this.words[e]=0}copy(e){const t=new Uint32Array(e.words.length);t.set(e.words),this.words=t}clone(){const e=new Uint32Array(this.words.length);e.set(this.words);const t=new r;return t.words=e,t}containsAll(e){for(let t=0;t<this.words.length;t++)if((~this.words[t]&e.words[t])!==0)return!1;return!0}containsAny(e){for(let t=0;t<this.words.length;t++)if((this.words[t]&e.words[t])!==0)return!0;return!1}}const l=(c,e)=>Object.getOwnPropertyNames(c.prototype).includes(e);let m=0;const h=()=>(m++,m.toString());class f{constructor(){n(this,"id",h());n(this,"entity");n(this,"__internal")}get space(){return this.entity.space}get world(){return this.entity.world}construct(...e){}onDestroy(){}onInit(){}}class y{constructor(){n(this,"listeners",new Set)}add(e){return this.listeners.add(e),this}remove(e){return this.listeners.delete(e),this}emit(e){for(const t of this.listeners.values())t(e)}clear(){this.listeners.clear()}}class p{constructor(e){n(this,"queue",[]);n(this,"dispatchers",new Map);n(this,"queued");this.queued=(e==null?void 0:e.queued)||!1}tick(){this.queue.splice(0,this.queue.length).forEach(e=>this.process(e))}on(e,t){let s=this.dispatchers.get(e);return s===void 0&&(s=new y,this.dispatchers.set(e,s)),s.add(t),{unsubscribe:()=>this.unsubscribe(e,t)}}unsubscribe(e,t){const s=this.dispatchers.get(e);s!==void 0&&s.remove(t)}emit(e){this.queued?this.queue.push(e):this.process(e)}reset(){this.dispatchers.clear(),this.queue=[]}process(e){const t=this.dispatchers.get(e.topic);t!==void 0&&t.emit(e)}}class g{constructor(){n(this,"id",h());n(this,"alive",!0);n(this,"components",new Map);n(this,"componentsBitSet",new r);n(this,"events",new p);n(this,"initialised",!1);n(this,"space")}get world(){return this.space.world}add(e,...t){if(this.components.has(e))throw new Error(`Cannot add component ${e.name}, entity with id ${this.id} already has this component`);const s=this.world.spaceManager.addComponentToEntity(this,e,t);return this.world.queryManager.onEntityComponentChange(this),s}destroy(){this.world.spaceManager.removeEntity(this,this.space),this.alive=!1}emit(e){this.events.emit(e)}find(e){return this.components.get(e)}get(e){const t=this.components.get(e);if(t!==void 0)return t;throw new Error(`Component ${e}} not in entity ${this.id}`)}has(e){return this.components.has(e)}on(e,t){return this.events.on(e,t)}remove(e){let t;if(e instanceof f){if(!this.components.has(e.__internal.class))throw new Error("Component instance does not exist in Entity");t=e}else if(t=this.find(e),t===void 0)throw new Error("Component does not exist in Entity");return this.world.spaceManager.removeComponentFromEntity(this,t),this.world.queryManager.onEntityComponentChange(this),this}}const w={ALL:"all",ANY:"any",NOT:"not"};class u{constructor(e,t){n(this,"key");n(this,"entities",[]);n(this,"onEntityAdded",new y);n(this,"onEntityRemoved",new y);n(this,"world");this.world=e,this.key=t}get first(){return this.entities[0]||void 0}[Symbol.iterator](){return this.entities[Symbol.iterator]()}destroy(){this.world.queryManager.removeQuery(this)}static getDescriptionDedupeString(e){return Array.isArray(e)?e.map(t=>`${t.name}`).join("&"):Object.entries(e).flatMap(([t,s])=>t===w.ALL?s.map(i=>`${i.name}`).sort():[`${t}:${s.sort().map(i=>i.name)}`]).sort().join("&")}}class v{constructor(e,t){n(this,"id");n(this,"entities",new Map);n(this,"events",new p);n(this,"initialised",!1);n(this,"world");this.world=e,this.id=(t==null?void 0:t.id)||h()}get create(){return{entity:e=>this.world.spaceManager.createEntity(this,e)}}emit(e){this.events.emit(e)}on(e,t){return this.events.on(e,t)}destroy(){this.world.spaceManager.removeSpace(this)}}class E{constructor(e){n(this,"enabled",!0);n(this,"world");n(this,"__internal",{queries:new Set,priority:0,order:0,class:null});this.world=e}onDestroy(){}onInit(){}onUpdate(e,t){}destroy(){this.world.unregisterSystem(this.__internal.class)}query(e){const t=this.world.queryManager.createQuery(e);return this.__internal.queries.add(t),t}}class b{constructor(e){n(this,"components",new Map);n(this,"currentComponentIndex",-1);n(this,"world");this.world=e}getComponentIndex(e){const t=this.components.get(e);return t===void 0?this.registerComponent(e):t}registerComponent(e){let t=this.components.get(e);if(t!==void 0)return t;if(this.currentComponentIndex++,t=this.currentComponentIndex,this.components.set(e,t),this.world.initialised)for(const s of this.world.spaceManager.spaces.values())for(const i of s.entities.values())i.componentsBitSet.resize(this.currentComponentIndex);return t}}class C{constructor(e){n(this,"dedupedQueries",new Map);n(this,"world");this.world=e}createQuery(e){const t=u.getDescriptionDedupeString(e);let s=this.dedupedQueries.get(t);if(s===void 0){const a=Array.isArray(e);if(a&&e.length===0||!a&&(!e.all&&!e.any&&!e.not||e.all&&e.all.length===0||e.any&&e.any.length===0||e.not&&e.not.length===0))throw new Error("Query must have at least one condition");s={dedupeString:t,instances:new Set,description:e,bitSets:this.getQueryBitSets(e),entities:[],entitySet:new Set};const d=this.getQueryResults(s.bitSets);for(const M of d.values())s.entities.push(M),s.entitySet.add(M);this.dedupedQueries.set(t,s)}const i=new u(this.world,t);return i.entities=s.entities,s.instances.add(i),i}hasQuery(e){const t=u.getDescriptionDedupeString(e);return this.dedupedQueries.has(t)}onEntityComponentChange(e){for(const t of this.dedupedQueries.values()){const s=t.entitySet.has(e),i=this.matchesQueryConditions(t.bitSets,e);if(i&&!s){t.entities.push(e),t.entitySet.add(e);for(const a of t.instances)a.onEntityAdded.emit(e)}else if(!i&&s){const a=t.entities.indexOf(e,0);a!==-1&&t.entities.splice(a,1),t.entitySet.delete(e);for(const d of t.instances)d.onEntityRemoved.emit(e)}}}onEntityRemoved(e){for(const t of this.dedupedQueries.values()){const s=t.entities.indexOf(e,0);s!==-1&&t.entities.splice(s,1),t.entitySet.delete(e);for(const i of t.instances)i.onEntityRemoved.emit(e)}}query(e){const t=u.getDescriptionDedupeString(e),s=this.dedupedQueries.get(t);return s?s.entities:this.getQueryResults(this.getQueryBitSets(e))}removeQuery(e){const t=this.dedupedQueries.get(e.key);t===void 0||!t.instances.has(e)||(t.instances.delete(e),e.onEntityAdded.clear(),e.onEntityRemoved.clear(),t.instances.size===0&&this.dedupedQueries.delete(t.dedupeString))}matchesQueryConditions(e,t){return!(e.all&&!t.componentsBitSet.containsAll(e.all)||e.any&&!t.componentsBitSet.containsAny(e.any)||e.not&&t.componentsBitSet.containsAny(e.not))}getQueryResults(e){const t=[];for(const s of this.world.spaceManager.spaces.values())for(const i of s.entities.values())this.matchesQueryConditions(e,i)&&t.push(i);return t}getQueryBitSets(e){const{all:t,any:s,not:i}=Array.isArray(e)?{all:e,any:void 0,not:void 0}:e,a={};return a.all=t?new r(t.map(d=>this.world.componentRegistry.getComponentIndex(d))):void 0,a.any=s?new r(s.map(d=>this.world.componentRegistry.getComponentIndex(d))):void 0,a.not=i?new r(i.map(d=>this.world.componentRegistry.getComponentIndex(d))):void 0,a}}class S{constructor(e,t){n(this,"availableObjects",[]);n(this,"factory");n(this,"size",0);this.factory=e,t!==void 0&&this.expand(t)}get free(){return this.availableObjects.length}get used(){return this.size-this.availableObjects.length}expand(e){for(let t=0;t<e;t++)this.availableObjects.push(this.factory());this.size+=e}request(){return this.availableObjects.length<=0&&this.expand(Math.round(this.size*.2)+1),this.availableObjects.pop()}release(e){this.availableObjects.push(e)}}class Q{constructor(e){n(this,"objectPools",new Map);n(this,"world");this.world=e}get totalPools(){return this.objectPools.size}get size(){let e=0;for(const t of this.objectPools.values())e+=t.size;return e}get free(){let e=0;for(const t of this.objectPools.values())e+=t.free;return e}get used(){let e=0;for(const t of this.objectPools.values())e+=t.used;return e}request(e){let t=this.objectPools.get(e);return t===void 0&&(t=new S(()=>{const s=new e;return s.__internal={class:e,classIndex:this.world.componentRegistry.getComponentIndex(e)},s}),this.objectPools.set(e,t)),t.request()}release(e){const t=this.objectPools.get(e.__internal.class);t!==void 0&&t.release(e)}}class P{constructor(){n(this,"objectPool",new S(()=>new g))}get size(){return this.objectPool.size}get free(){return this.objectPool.free}get used(){return this.objectPool.used}request(){return this.objectPool.request()}release(e){this.objectPool.release(e)}}class j{constructor(e){n(this,"spaces",new Map);n(this,"componentPool");n(this,"entityPool");n(this,"componentsToRecycle",[]);n(this,"entitiesToRecycle",[]);n(this,"world");this.world=e,this.componentPool=new Q(e),this.entityPool=new P}init(){for(const e of this.spaces.values())this.initialiseSpace(e)}destroy(){for(const e of this.spaces.values())this.removeSpace(e)}createSpace(e){if((e==null?void 0:e.id)&&this.spaces.has(e.id))throw new Error("A space with the provided id already exists");const t=new v(this.world,e);return this.spaces.set(t.id,t),this.world.initialised&&this.initialiseSpace(t),t}initialiseSpace(e){e.initialised=!0;for(const t of e.entities.values())this.initialiseEntity(t)}removeSpace(e){this.spaces.delete(e.id);for(const t of e.entities.values())this.removeEntity(t,e)}createEntity(e,t=[]){var i;const s=this.entityPool.request();s.space=e,e.entities.set(s.id,s);for(const a of t)this.world.spaceManager.addComponentToEntity(s,a.type,(i=a.args)!=null?i:[]);return this.world.queryManager.onEntityComponentChange(s),e.initialised&&this.world.spaceManager.initialiseEntity(s),s}initialiseEntity(e){e.initialised=!0,e.componentsBitSet.resize(this.world.componentRegistry.currentComponentIndex);for(const t of e.components.values())this.initialiseComponent(t)}removeEntity(e,t){e.alive=!1,e.space=null,e.initialised=!1,t.entities.delete(e.id);for(const s of e.components.values())this.removeComponentFromEntity(e,s);this.world.queryManager.onEntityRemoved(e),this.entitiesToRecycle.push(e)}addComponentToEntity(e,t,s){const i=this.componentPool.request(t);return i.entity=e,i.construct(...s),e.components.set(t,i),e.componentsBitSet.add(i.__internal.classIndex),e.initialised&&this.initialiseComponent(i),i}removeComponentFromEntity(e,t){t.onDestroy(),e.components.delete(t.__internal.class),e.componentsBitSet.remove(t.__internal.classIndex),this.componentsToRecycle.push(t)}initialiseComponent(e){e.onInit()}recycle(){const e=this.entitiesToRecycle;this.entitiesToRecycle=[];for(const s of e)s.id=h(),s.events.reset(),s.componentsBitSet.reset(),s.alive=!0,this.entityPool.release(s);const t=this.componentsToRecycle;this.componentsToRecycle=[];for(const s of t)s.id=h(),s.entity=void 0,this.componentPool.release(s)}}class A{constructor(e){n(this,"systems",new Map);n(this,"sortedSystems",[]);n(this,"systemCounter",0);n(this,"initialised",!1);n(this,"world");this.world=e}init(){this.initialised=!0;for(const e of this.systems.values())e.onInit();this.sortSystems()}update(e,t){for(const s of this.sortedSystems.values())s.enabled&&s.onUpdate(e,t)}destroy(){for(const e of this.systems.values())e.onDestroy(),this.systems.delete(e.__internal.class)}registerSystem(e,t){var a;if(this.systems.has(e))throw new Error(`System "${e.name}" has already been registered`);this.systemCounter++;const s=new e(this.world);s.__internal.class=e,s.__internal.priority=(a=t==null?void 0:t.priority)!=null?a:0,s.__internal.order=this.systemCounter,this.systems.set(e,s);const i=l(e,"onUpdate");i&&this.sortedSystems.push(s),this.initialised&&(s.onInit(),i&&this.sortSystems())}unregisterSystem(e){const t=this.systems.get(e);!t||(this.systems.delete(e),this.sortedSystems=this.sortedSystems.filter(s=>s.__internal.class!==e),t.__internal.queries.forEach(s=>{this.world.queryManager.removeQuery(s)}),t.onDestroy())}sortSystems(){this.sortedSystems.sort((e,t)=>t.__internal.priority-e.__internal.priority||e.__internal.order-t.__internal.order)}}const _="__arancini_default_world_space";class R{constructor(){n(this,"id",h());n(this,"initialised",!1);n(this,"time",0);n(this,"defaultSpace");n(this,"events");n(this,"spaceManager");n(this,"queryManager");n(this,"systemManager");n(this,"componentRegistry");this.events=new p,this.componentRegistry=new b(this),this.spaceManager=new j(this),this.queryManager=new C(this),this.systemManager=new A(this),this.defaultSpace=this.create.space({id:_})}get create(){return{entity:e=>this.spaceManager.createEntity(this.defaultSpace,e),space:e=>this.spaceManager.createSpace(e),query:e=>this.queryManager.createQuery(e)}}init(){this.initialised=!0,this.spaceManager.init(),this.systemManager.init()}update(e=0){this.time+=e,this.systemManager.update(e,this.time),this.spaceManager.recycle()}destroy(){this.systemManager.destroy(),this.spaceManager.destroy()}emit(e){this.events.emit(e)}on(e,t){return this.events.on(e,t)}query(e){return this.queryManager.query(e)}registerComponent(e){return this.componentRegistry.registerComponent(e),this}registerSystem(e,t){return this.systemManager.registerSystem(e,t),this}unregisterSystem(e){return this.systemManager.unregisterSystem(e),this}getSystem(e){return this.systemManager.systems.get(e)}getSystems(){return Array.from(this.systemManager.systems.values())}getSpace(e){return this.spaceManager.spaces.get(e)}}o.Component=f,o.Entity=g,o.Query=u,o.QueryConditionType=w,o.Space=v,o.System=E,o.WORLD_DEFAULT_SPACE_ID=_,o.World=R,Object.defineProperties(o,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}); |
@@ -7,3 +7,3 @@ { | ||
"license": "MIT", | ||
"version": "0.1.0", | ||
"version": "0.1.1", | ||
"homepage": "https://github.com/isaac-mason/arancini", | ||
@@ -10,0 +10,0 @@ "bugs": { |
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