@arancini/core
Advanced tools
Comparing version 0.1.1 to 1.0.0
@@ -6,3 +6,3 @@ import type { ComponentClass } from './component'; | ||
* | ||
* @private used internally, do not use directly | ||
* @private internal class, do not use directly | ||
*/ | ||
@@ -24,8 +24,2 @@ export declare class ComponentRegistry { | ||
/** | ||
* Retrieves a component index for a given component | ||
* @param component the component class | ||
* @returns the component index | ||
*/ | ||
getComponentIndex(component: ComponentClass): number; | ||
/** | ||
* Registers a component | ||
@@ -32,0 +26,0 @@ * @param component the component class to register |
@@ -10,2 +10,3 @@ import { Entity } from './entity'; | ||
new (...args: never[]): T; | ||
componentIndex: number; | ||
}; | ||
@@ -18,3 +19,3 @@ /** | ||
* ```ts | ||
* import { Component, World } from "@arancini/core"; | ||
* import { Component, World } from '@arancini/core' | ||
* | ||
@@ -24,4 +25,4 @@ * class ExampleComponent extends Component { | ||
* // You must take care to set all class properties in the `construct` method. | ||
* x!: number; | ||
* y!: number; | ||
* x!: number | ||
* y!: number | ||
* | ||
@@ -33,4 +34,4 @@ * // Think of the `construct` method as a constructor. | ||
* construct(x: number, y: number) { | ||
* this.x = x; | ||
* this.y = y; | ||
* this.x = x | ||
* this.y = y | ||
* } | ||
@@ -47,15 +48,16 @@ * | ||
* | ||
* // create a world | ||
* const world = new World(); | ||
* // create a world and register the component | ||
* const world = new World() | ||
* world.registerComponent(ExampleComponent) | ||
* | ||
* // create a space | ||
* const space = world.create.space(); | ||
* const space = world.create.space() | ||
* | ||
* // create an entity in the space | ||
* const entity = space.create.entity(); | ||
* const entity = space.create.entity() | ||
* | ||
* // add the example component to the entity | ||
* const x = 1; | ||
* const y = 2; | ||
* entity.add(ExampleComponent, x, y); | ||
* const x = 1 | ||
* const y = 2 | ||
* entity.add(ExampleComponent, x, y) | ||
* ``` | ||
@@ -81,14 +83,7 @@ */ | ||
/** | ||
* @private used internally, do not use directly | ||
* The class the component was constructed from | ||
* @private | ||
*/ | ||
__internal: { | ||
/** | ||
* The class the component was constructed from | ||
*/ | ||
class: ComponentClass; | ||
/** | ||
* The unique index for the component class | ||
*/ | ||
classIndex: number; | ||
}; | ||
_class: ComponentClass; | ||
static componentIndex: number; | ||
/** | ||
@@ -95,0 +90,0 @@ * Method for "constructing" a component instance. |
@@ -16,3 +16,3 @@ import type { ComponentClass } from './component'; | ||
* ```ts | ||
* import { Component, World } from '@arancini/core'; | ||
* import { Component, World } from '@arancini/core' | ||
* | ||
@@ -22,7 +22,10 @@ * // example tag component without any data or behavior | ||
* | ||
* // create a world, space, and an entity | ||
* const world = new World(); | ||
* const space = world.create.space(); | ||
* const entity = world.create.entity(); | ||
* // create a world and register the component | ||
* const world = new World() | ||
* world.registerComponent(ExampleComponent) | ||
* | ||
* // create a space and an entity | ||
* const space = world.create.space() | ||
* const entity = world.create.entity() | ||
* | ||
* // try retrieving a component that isn't in the entity | ||
@@ -33,5 +36,5 @@ * entity.find(ExampleComponent) // returns `undefined` | ||
* // add ExampleComponent to the entity | ||
* const exampleComponent = entity.add(ExampleComponent); | ||
* const exampleComponent = entity.add(ExampleComponent) | ||
* | ||
* entity.has(ExampleComponent); // returns `true` | ||
* entity.has(ExampleComponent) // returns `true` | ||
* entity.get(ExampleComponent) // returns `exampleComponent` | ||
@@ -41,4 +44,4 @@ * entity.get(ExampleComponent) // returns `exampleComponent` | ||
* // subscribe to an entity event | ||
* space.on("event-name", (event) => { | ||
* console.log(event); | ||
* space.on('event-name', (event) => { | ||
* console.log(event) | ||
* }); | ||
@@ -48,3 +51,3 @@ * | ||
* space.emit({ | ||
* topic: "event-name", | ||
* topic: 'event-name', | ||
* data: { x: 0, y: 0 }, | ||
@@ -66,16 +69,2 @@ * }); | ||
/** | ||
* Whether the entity is alive. If false, the entity will be destroyed on the next update | ||
*/ | ||
alive: boolean; | ||
/** | ||
* Map of component classes to components | ||
*/ | ||
components: Map<{ | ||
new (...args: never[]): Component; | ||
}, Component>; | ||
/** | ||
* BitSet containing component indices for Components in this Entitiy | ||
*/ | ||
componentsBitSet: BitSet; | ||
/** | ||
* The event system for the entity | ||
@@ -93,2 +82,14 @@ */ | ||
/** | ||
* The BitSet for the entity | ||
* @private | ||
*/ | ||
_componentsBitSet: BitSet; | ||
/** | ||
* The components for the entity | ||
* @private | ||
*/ | ||
_components: { | ||
[index: string]: Component; | ||
}; | ||
/** | ||
* The World the entity is in | ||
@@ -103,10 +104,12 @@ */ | ||
/** | ||
* Destroy the Entity's components and remove the Entity from the space | ||
* Retrieves a component on an entity by type, throws an error if the component is not in the entity | ||
* @param value a constructor for the component type to retrieve | ||
* @returns the component | ||
*/ | ||
destroy(): void; | ||
get<T extends Component>(value: ComponentClass<T>): T; | ||
/** | ||
* Broadcasts an event to the Entity EventSystem | ||
* @param event the event to broadcast | ||
* Returns all components for the entity | ||
* @returns all components for the entity | ||
*/ | ||
emit<E extends Event | Event>(event: E): void; | ||
getAll(): Component[]; | ||
/** | ||
@@ -119,8 +122,2 @@ * Retrieves a component on an entity by type, returns undefined if the component is not in the entity | ||
/** | ||
* Retrieves a component on an entity by type, throws an error if the component is not in the entity | ||
* @param value a constructor for the component type to retrieve | ||
* @returns the component | ||
*/ | ||
get<T extends Component>(value: ComponentClass<T>): T; | ||
/** | ||
* Returns whether the entity contains the given component | ||
@@ -132,2 +129,8 @@ * @param value the component constructor, a component instance, or the string name of the component | ||
/** | ||
* Removes a component from the entity and destroys it | ||
* The value can either be a Component constructor, or the component instance itself | ||
* @param value the component to remove and destroy | ||
*/ | ||
remove(value: Component | ComponentClass): Entity; | ||
/** | ||
* Adds a handler for entity events | ||
@@ -140,7 +143,10 @@ * @param eventName the event name | ||
/** | ||
* Removes a component from the entity and destroys it | ||
* The value can either be a Component constructor, or the component instance itself | ||
* @param value the component to remove and destroy | ||
* Broadcasts an event to the Entity EventSystem | ||
* @param event the event to broadcast | ||
*/ | ||
remove(value: Component | ComponentClass): Entity; | ||
emit<E extends Event | Event>(event: E): void; | ||
/** | ||
* Destroy the Entity's components and remove the Entity from the space | ||
*/ | ||
destroy(): void; | ||
} |
@@ -81,3 +81,3 @@ var __defProp = Object.defineProperty; | ||
__publicField(this, "entity"); | ||
__publicField(this, "__internal"); | ||
__publicField(this, "_class"); | ||
} | ||
@@ -97,2 +97,3 @@ get space() { | ||
} | ||
__publicField(Component, "componentIndex"); | ||
class EventDispatcher { | ||
@@ -167,8 +168,7 @@ constructor() { | ||
__publicField(this, "id", uniqueId()); | ||
__publicField(this, "alive", true); | ||
__publicField(this, "components", /* @__PURE__ */ new Map()); | ||
__publicField(this, "componentsBitSet", new BitSet()); | ||
__publicField(this, "events", new EventSystem()); | ||
__publicField(this, "initialised", false); | ||
__publicField(this, "space"); | ||
__publicField(this, "_componentsBitSet", new BitSet()); | ||
__publicField(this, "_components", {}); | ||
} | ||
@@ -179,3 +179,3 @@ get world() { | ||
add(clazz, ...args) { | ||
if (this.components.has(clazz)) { | ||
if (this._components[clazz.componentIndex]) { | ||
throw new Error(`Cannot add component ${clazz.name}, entity with id ${this.id} already has this component`); | ||
@@ -187,14 +187,4 @@ } | ||
} | ||
destroy() { | ||
this.world.spaceManager.removeEntity(this, this.space); | ||
this.alive = false; | ||
} | ||
emit(event) { | ||
this.events.emit(event); | ||
} | ||
find(value) { | ||
return this.components.get(value); | ||
} | ||
get(value) { | ||
const component = this.components.get(value); | ||
const component = this._components[value.componentIndex]; | ||
if (component !== void 0) { | ||
@@ -205,12 +195,15 @@ return component; | ||
} | ||
getAll() { | ||
return Object.values(this._components); | ||
} | ||
find(value) { | ||
return this._components[value.componentIndex]; | ||
} | ||
has(value) { | ||
return this.components.has(value); | ||
return this._components[value.componentIndex] !== void 0; | ||
} | ||
on(eventName, handler) { | ||
return this.events.on(eventName, handler); | ||
} | ||
remove(value) { | ||
let component; | ||
if (value instanceof Component) { | ||
if (!this.components.has(value.__internal.class)) { | ||
if (!this._components[value._class.componentIndex]) { | ||
throw new Error("Component instance does not exist in Entity"); | ||
@@ -229,2 +222,11 @@ } | ||
} | ||
on(eventName, handler) { | ||
return this.events.on(eventName, handler); | ||
} | ||
emit(event) { | ||
this.events.emit(event); | ||
} | ||
destroy() { | ||
this.world.spaceManager.destroyEntity(this, this.space); | ||
} | ||
} | ||
@@ -250,3 +252,14 @@ const QueryConditionType = { | ||
[Symbol.iterator]() { | ||
return this.entities[Symbol.iterator](); | ||
let index = this.entities.length; | ||
const result = { | ||
value: void 0, | ||
done: false | ||
}; | ||
return { | ||
next: () => { | ||
result.value = this.entities[--index]; | ||
result.done = index < 0; | ||
return result; | ||
} | ||
}; | ||
} | ||
@@ -292,3 +305,3 @@ destroy() { | ||
destroy() { | ||
this.world.spaceManager.removeSpace(this); | ||
this.world.spaceManager.destroySpace(this); | ||
} | ||
@@ -330,9 +343,2 @@ } | ||
} | ||
getComponentIndex(component) { | ||
const index = this.components.get(component); | ||
if (index === void 0) { | ||
return this.registerComponent(component); | ||
} | ||
return index; | ||
} | ||
registerComponent(component) { | ||
@@ -345,2 +351,3 @@ let componentIndex = this.components.get(component); | ||
componentIndex = this.currentComponentIndex; | ||
component.componentIndex = componentIndex; | ||
this.components.set(component, componentIndex); | ||
@@ -350,3 +357,3 @@ if (this.world.initialised) { | ||
for (const entity of space.entities.values()) { | ||
entity.componentsBitSet.resize(this.currentComponentIndex); | ||
entity._componentsBitSet.resize(this.currentComponentIndex); | ||
} | ||
@@ -451,9 +458,9 @@ } | ||
matchesQueryConditions(queryBitSets, entity) { | ||
if (queryBitSets.all && !entity.componentsBitSet.containsAll(queryBitSets.all)) { | ||
if (queryBitSets.all && !entity._componentsBitSet.containsAll(queryBitSets.all)) { | ||
return false; | ||
} | ||
if (queryBitSets.any && !entity.componentsBitSet.containsAny(queryBitSets.any)) { | ||
if (queryBitSets.any && !entity._componentsBitSet.containsAny(queryBitSets.any)) { | ||
return false; | ||
} | ||
if (queryBitSets.not && entity.componentsBitSet.containsAny(queryBitSets.not)) { | ||
if (queryBitSets.not && entity._componentsBitSet.containsAny(queryBitSets.not)) { | ||
return false; | ||
@@ -477,5 +484,5 @@ } | ||
const queryBitSets = {}; | ||
queryBitSets.all = all ? new BitSet(all.map((component) => this.world.componentRegistry.getComponentIndex(component))) : void 0; | ||
queryBitSets.any = any ? new BitSet(any.map((component) => this.world.componentRegistry.getComponentIndex(component))) : void 0; | ||
queryBitSets.not = not ? new BitSet(not.map((component) => this.world.componentRegistry.getComponentIndex(component))) : void 0; | ||
queryBitSets.all = all ? new BitSet(all.map((component) => component.componentIndex)) : void 0; | ||
queryBitSets.any = any ? new BitSet(any.map((component) => component.componentIndex)) : void 0; | ||
queryBitSets.not = not ? new BitSet(not.map((component) => component.componentIndex)) : void 0; | ||
return queryBitSets; | ||
@@ -517,6 +524,4 @@ } | ||
class ComponentPool { | ||
constructor(world) { | ||
constructor() { | ||
__publicField(this, "objectPools", /* @__PURE__ */ new Map()); | ||
__publicField(this, "world"); | ||
this.world = world; | ||
} | ||
@@ -552,6 +557,3 @@ get totalPools() { | ||
const component = new Clazz(); | ||
component.__internal = { | ||
class: Clazz, | ||
classIndex: this.world.componentRegistry.getComponentIndex(Clazz) | ||
}; | ||
component._class = Clazz; | ||
return component; | ||
@@ -564,3 +566,3 @@ }); | ||
release(component) { | ||
const pool = this.objectPools.get(component.__internal.class); | ||
const pool = this.objectPools.get(component._class); | ||
if (pool !== void 0) { | ||
@@ -596,7 +598,5 @@ pool.release(component); | ||
__publicField(this, "entityPool"); | ||
__publicField(this, "componentsToRecycle", []); | ||
__publicField(this, "entitiesToRecycle", []); | ||
__publicField(this, "world"); | ||
this.world = world; | ||
this.componentPool = new ComponentPool(world); | ||
this.componentPool = new ComponentPool(); | ||
this.entityPool = new EntityPool(); | ||
@@ -611,3 +611,3 @@ } | ||
for (const space of this.spaces.values()) { | ||
this.removeSpace(space); | ||
this.destroySpace(space); | ||
} | ||
@@ -632,6 +632,6 @@ } | ||
} | ||
removeSpace(space) { | ||
destroySpace(space) { | ||
this.spaces.delete(space.id); | ||
for (const entity of space.entities.values()) { | ||
this.removeEntity(entity, space); | ||
this.destroyEntity(entity, space); | ||
} | ||
@@ -655,17 +655,19 @@ } | ||
entity.initialised = true; | ||
entity.componentsBitSet.resize(this.world.componentRegistry.currentComponentIndex); | ||
for (const component of entity.components.values()) { | ||
entity._componentsBitSet.resize(this.world.componentRegistry.currentComponentIndex); | ||
for (const component of Object.values(entity._components)) { | ||
this.initialiseComponent(component); | ||
} | ||
} | ||
removeEntity(entity, space) { | ||
entity.alive = false; | ||
destroyEntity(entity, space) { | ||
entity.space = null; | ||
entity.initialised = false; | ||
space.entities.delete(entity.id); | ||
for (const component of entity.components.values()) { | ||
for (const component of Object.values(entity._components)) { | ||
this.removeComponentFromEntity(entity, component); | ||
} | ||
this.world.queryManager.onEntityRemoved(entity); | ||
this.entitiesToRecycle.push(entity); | ||
entity.id = uniqueId(); | ||
entity.events.reset(); | ||
entity._componentsBitSet.reset(); | ||
this.entityPool.release(entity); | ||
} | ||
@@ -676,4 +678,4 @@ addComponentToEntity(entity, clazz, args) { | ||
component.construct(...args); | ||
entity.components.set(clazz, component); | ||
entity.componentsBitSet.add(component.__internal.classIndex); | ||
entity._components[clazz.componentIndex] = component; | ||
entity._componentsBitSet.add(component._class.componentIndex); | ||
if (entity.initialised) { | ||
@@ -686,5 +688,7 @@ this.initialiseComponent(component); | ||
component.onDestroy(); | ||
entity.components.delete(component.__internal.class); | ||
entity.componentsBitSet.remove(component.__internal.classIndex); | ||
this.componentsToRecycle.push(component); | ||
delete entity._components[component._class.componentIndex]; | ||
entity._componentsBitSet.remove(component._class.componentIndex); | ||
component.id = uniqueId(); | ||
component.entity = void 0; | ||
this.componentPool.release(component); | ||
} | ||
@@ -694,20 +698,2 @@ initialiseComponent(component) { | ||
} | ||
recycle() { | ||
const entities = this.entitiesToRecycle; | ||
this.entitiesToRecycle = []; | ||
for (const entity of entities) { | ||
entity.id = uniqueId(); | ||
entity.events.reset(); | ||
entity.componentsBitSet.reset(); | ||
entity.alive = true; | ||
this.entityPool.release(entity); | ||
} | ||
const components = this.componentsToRecycle; | ||
this.componentsToRecycle = []; | ||
for (const component of components) { | ||
component.id = uniqueId(); | ||
component.entity = void 0; | ||
this.componentPool.release(component); | ||
} | ||
} | ||
} | ||
@@ -823,3 +809,2 @@ class SystemManager { | ||
this.systemManager.update(delta, this.time); | ||
this.spaceManager.recycle(); | ||
} | ||
@@ -826,0 +811,0 @@ destroy() { |
@@ -1,1 +0,1 @@ | ||
(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"}})}); | ||
(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 x=Object.defineProperty;var O=(o,r,l)=>r in o?x(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=(d,e)=>Object.getOwnPropertyNames(d.prototype).includes(e);let f=0;const h=()=>(f++,f.toString());class p{constructor(){n(this,"id",h());n(this,"entity");n(this,"_class")}get space(){return this.entity.space}get world(){return this.entity.world}construct(...e){}onDestroy(){}onInit(){}}n(p,"componentIndex");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 m{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,"events",new m);n(this,"initialised",!1);n(this,"space");n(this,"_componentsBitSet",new r);n(this,"_components",{})}get world(){return this.space.world}add(e,...t){if(this._components[e.componentIndex])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}get(e){const t=this._components[e.componentIndex];if(t!==void 0)return t;throw new Error(`Component ${e}} not in entity ${this.id}`)}getAll(){return Object.values(this._components)}find(e){return this._components[e.componentIndex]}has(e){return this._components[e.componentIndex]!==void 0}remove(e){let t;if(e instanceof p){if(!this._components[e._class.componentIndex])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}on(e,t){return this.events.on(e,t)}emit(e){this.events.emit(e)}destroy(){this.world.spaceManager.destroyEntity(this,this.space)}}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](){let e=this.entities.length;const t={value:void 0,done:!1};return{next:()=>(t.value=this.entities[--e],t.done=e<0,t)}}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 m);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.destroySpace(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}registerComponent(e){let t=this.components.get(e);if(t!==void 0)return t;if(this.currentComponentIndex++,t=this.currentComponentIndex,e.componentIndex=t,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 Q{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 c=this.getQueryResults(s.bitSets);for(const M of c.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 c of t.instances)c.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(c=>c.componentIndex)):void 0,a.any=s?new r(s.map(c=>c.componentIndex)):void 0,a.not=i?new r(i.map(c=>c.componentIndex)):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 C{constructor(){n(this,"objectPools",new Map)}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._class=e,s}),this.objectPools.set(e,t)),t.request()}release(e){const t=this.objectPools.get(e._class);t!==void 0&&t.release(e)}}class I{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,"world");this.world=e,this.componentPool=new C,this.entityPool=new I}init(){for(const e of this.spaces.values())this.initialiseSpace(e)}destroy(){for(const e of this.spaces.values())this.destroySpace(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)}destroySpace(e){this.spaces.delete(e.id);for(const t of e.entities.values())this.destroyEntity(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 Object.values(e._components))this.initialiseComponent(t)}destroyEntity(e,t){e.space=null,e.initialised=!1,t.entities.delete(e.id);for(const s of Object.values(e._components))this.removeComponentFromEntity(e,s);this.world.queryManager.onEntityRemoved(e),e.id=h(),e.events.reset(),e._componentsBitSet.reset(),this.entityPool.release(e)}addComponentToEntity(e,t,s){const i=this.componentPool.request(t);return i.entity=e,i.construct(...s),e._components[t.componentIndex]=i,e._componentsBitSet.add(i._class.componentIndex),e.initialised&&this.initialiseComponent(i),i}removeComponentFromEntity(e,t){t.onDestroy(),delete e._components[t._class.componentIndex],e._componentsBitSet.remove(t._class.componentIndex),t.id=h(),t.entity=void 0,this.componentPool.release(t)}initialiseComponent(e){e.onInit()}}class P{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 A{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 m,this.componentRegistry=new b(this),this.spaceManager=new j(this),this.queryManager=new Q(this),this.systemManager=new P(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)}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=p,o.Entity=g,o.Query=u,o.QueryConditionType=w,o.Space=v,o.System=E,o.WORLD_DEFAULT_SPACE_ID=_,o.World=A,Object.defineProperties(o,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}); |
import type { Component, ComponentClass } from '../component'; | ||
import type { World } from '../world'; | ||
/** | ||
@@ -30,11 +29,2 @@ * ComponentPool that manages reuse of component objects | ||
/** | ||
* The World the ComponentPool is in | ||
*/ | ||
private world; | ||
/** | ||
* Constructor for a ComponentPool | ||
* @param world the World the ComponentPool being created in | ||
*/ | ||
constructor(world: World); | ||
/** | ||
* Requests a component from the component pool | ||
@@ -41,0 +31,0 @@ */ |
@@ -9,12 +9,12 @@ /** | ||
* // create a new pool | ||
* const pool = new ObjectPool(() => new MyObject()); | ||
* const pool = new ObjectPool(() => new MyObject()) | ||
* | ||
* // expand the pool | ||
* pool.expand(10); | ||
* pool.expand(10) | ||
* | ||
* // request an object from the pool | ||
* const object = pool.request(); | ||
* const object = pool.request() | ||
* | ||
* // release the object back into the pool | ||
* pool.release(object); | ||
* pool.release(object) | ||
* ``` | ||
@@ -21,0 +21,0 @@ * |
@@ -39,6 +39,6 @@ import type { ComponentClass } from './component'; | ||
* ```ts | ||
* import { Component, System, World, QueryDescription } from "@arancini/core"; | ||
* import { Component, System, World, QueryDescription } from '@arancini/core' | ||
* | ||
* // create a world | ||
* const world = new World(); | ||
* const world = new World() | ||
* | ||
@@ -52,3 +52,3 @@ * // create some example components | ||
* // create a simple query description | ||
* const simpleQueryDescription: QueryDescription = [ExampleComponentOne, ExampleComponentTwo]; | ||
* const simpleQueryDescription: QueryDescription = [ExampleComponentOne, ExampleComponentTwo] | ||
* | ||
@@ -60,6 +60,6 @@ * // create a complex query description | ||
* not: [ExampleComponentFour], | ||
* }; | ||
* } | ||
* | ||
* // get once-off query results, re-using existing query results if available | ||
* world.query(simpleQueryDescription); | ||
* world.query(simpleQueryDescription) | ||
* | ||
@@ -69,3 +69,3 @@ * // get a query that will update every world update | ||
* all: [ExampleComponentOne] | ||
* }); | ||
* }) | ||
* | ||
@@ -76,10 +76,10 @@ * // create a system with a query | ||
* all: [ExampleComponentOne], | ||
* }); | ||
* }) | ||
* | ||
* onUpdate() { | ||
* this.exampleQueryName.entities.forEach((entity) => console.log(entity)); | ||
* this.exampleQueryName.entities.forEach((entity) => console.log(entity)) | ||
* } | ||
* } | ||
* | ||
* world.registerSystem(ExampleSystem); | ||
* world.registerSystem(ExampleSystem) | ||
* ``` | ||
@@ -109,5 +109,10 @@ */ | ||
/** | ||
* Iterator for all entities matched by the query | ||
* Iterator for entities matched by the query. Iterates over matching entities in reverse order. | ||
*/ | ||
[Symbol.iterator](): IterableIterator<Entity>; | ||
[Symbol.iterator](): { | ||
next: () => { | ||
value: Entity; | ||
done: boolean; | ||
}; | ||
}; | ||
/** | ||
@@ -114,0 +119,0 @@ * The World the Query is in |
@@ -24,10 +24,2 @@ import type { Component, ComponentClass, ComponentDetails } from './component'; | ||
/** | ||
* Components that need recycling | ||
*/ | ||
private componentsToRecycle; | ||
/** | ||
* Entities that need queries recycling | ||
*/ | ||
private entitiesToRecycle; | ||
/** | ||
* The World the entity manager is part of | ||
@@ -61,6 +53,6 @@ */ | ||
/** | ||
* Remove a space | ||
* @param space the space to remove | ||
* Destroys a space | ||
* @param space the space to destroy | ||
*/ | ||
removeSpace(space: Space): void; | ||
destroySpace(space: Space): void; | ||
/** | ||
@@ -79,6 +71,6 @@ * Creates a new entity in a space | ||
/** | ||
* Removes an entity from a space and releases it to the entity object pool | ||
* Destroys an entity and releases it to the entity object pool | ||
* @param entity the entity to release | ||
*/ | ||
removeEntity(entity: Entity, space: Space): void; | ||
destroyEntity(entity: Entity, space: Space): void; | ||
/** | ||
@@ -101,6 +93,2 @@ * Adds a component to an entity | ||
initialiseComponent(component: Component): void; | ||
/** | ||
* Recycles destroyed entities and components | ||
*/ | ||
recycle(): void; | ||
} |
@@ -26,26 +26,26 @@ import type { ComponentDetails } from './component'; | ||
* ```ts | ||
* import { World } from "@arancini/core"; | ||
* import { World } from '@arancini/core' | ||
* | ||
* // create a new world | ||
* const world = new World(); | ||
* const world = new World() | ||
* | ||
* // create a space in the world | ||
* const space = world.create.space(); | ||
* const space = world.create.space() | ||
* | ||
* // create an entity in the space | ||
* const entity = space.create.entity(); | ||
* const entity = space.create.entity() | ||
* | ||
* // subscribe to a space event | ||
* space.on("event-name", (event) => { | ||
* space.on('event-name', (event) => { | ||
* console.log(event); | ||
* }); | ||
* }) | ||
* | ||
* // emit a space event | ||
* space.emit({ | ||
* topic: "event-name", | ||
* topic: 'event-name', | ||
* data: { x: 0, y: 0 }, | ||
* }); | ||
* }) | ||
* | ||
* // destroy the space and all entities in it | ||
* space.destroy(); | ||
* space.destroy() | ||
* ``` | ||
@@ -52,0 +52,0 @@ */ |
@@ -17,7 +17,7 @@ import type { QueryDescription } from './query'; | ||
* not: [ComponentFive], | ||
* }); | ||
* }) | ||
* | ||
* // optionally override the default System constructor | ||
* constructor(world: World) { | ||
* super(world); | ||
* super(world) | ||
* | ||
@@ -24,0 +24,0 @@ * // constructor logic... |
@@ -18,16 +18,16 @@ import type { ComponentClass, ComponentDetails } from './component'; | ||
* ```ts | ||
* import { World } from "@arancini/core"; | ||
* import { World } from '@arancini/core' | ||
* | ||
* const world = new World(); | ||
* const world = new World() | ||
* | ||
* // initialise the world | ||
* world.init(); | ||
* world.init() | ||
* | ||
* // update the world without specifying time elapsed | ||
* // (Systems will be called with a delta of 0) | ||
* world.update(); | ||
* world.update() | ||
* | ||
* // update the world with a specified time elapsed | ||
* // (Systems will be called with a delta of 0.1) | ||
* world.update(0.1); | ||
* world.update(0.1) | ||
* | ||
@@ -37,3 +37,3 @@ * // subscribe to a world event | ||
* // ... | ||
* }); | ||
* }) | ||
* | ||
@@ -40,0 +40,0 @@ * // emit a world event |
{ | ||
"name": "@arancini/core", | ||
"description": "An object based Entity Component System", | ||
"keywords": [ | ||
"gamedev", | ||
"ecs", | ||
"entity-component-system" | ||
], | ||
"type": "module", | ||
@@ -7,3 +13,3 @@ "packageManager": "yarn@3.2.1", | ||
"license": "MIT", | ||
"version": "0.1.1", | ||
"version": "1.0.0", | ||
"homepage": "https://github.com/isaac-mason/arancini", | ||
@@ -14,3 +20,3 @@ "bugs": { | ||
"scripts": { | ||
"test": " NODE_OPTIONS=--experimental-vm-modules jest --coverage", | ||
"test": "NODE_OPTIONS=--experimental-vm-modules jest --coverage", | ||
"test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch", | ||
@@ -17,0 +23,0 @@ "dev": "vite", |
# @arancini/core | ||
Arancini core functionality. | ||
See the [**arancini** README](https://github.com/isaac-mason/arancini/tree/main/packages/arancini) for more information. |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
0
5
80916
2219