ecsjs 1.2.0-beta.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/ecs.js CHANGED
@@ -1,2 +1,2 @@
1
- var C="ComponentMap",c="ComponentClassesMap";var i=class extends Map{firstEntry(){return this.size===0?void 0:this.entries().next().value}firstKey(){return this.size===0?void 0:this.keys().next().value}firstValue(){return this.size===0?void 0:this.values().next().value}toJSON(){return{[C]:1,iterable:[...this.entries()]}}toTable(e=!1){let n=[];for(let[t,o]of this.entries()){let s=o,r={};e==!1&&(r["entity.key"]=t),r["entity.type"]=s.constructor.name,n.push({...r,...s})}return n}printTable(e=!1){console.table(this.toTable(e))}static get[Symbol.species](){return Map}},m=class extends Map{toJSON(){return{[c]:1,iterable:[...this.entries()]}}static get[Symbol.species](){return Map}};var y=class extends Error{constructor(){super("Component type is missing the 'name' parameter. i.e. a constructor name")}},p=class extends Error{constructor(n){super(`Component map does not exist for '${n}'`);this.componentName=n}};var l=class{constructor(e,n,...t){this.ecs=e;this.key=n;this.keyMap=this.ecs.getMap(n),this.entries=this.keyMap.entries(),this.components=t.map(o=>this.ecs.getMap(o))}keyMap;components;entries;next(){let e=this.entries.next(),{value:n,done:t}=e;if(t)return{value:n,done:t};let[o,s]=n,r=[o,s];for(let d of this.components)r.push(d.get(o));return{value:r,done:!1}}reset(){this.entries=this.keyMap.entries()}[Symbol.iterator](){return this}};var u=class a{components=new m;nextId=0;register(...e){for(let n of e){let t=n.name;if(t===void 0)throw new y;let o=new i;this.components.set(t,o)}return this}getMap(e){let n=this.components.get(e.name);if(n===void 0)throw new p(e.name);return n}firstEntry(e){return this.getMap(e)?.firstEntry()}firstKey(e,...n){let t=this.getMap(e)?.firstKey();if(arguments.length===1)return t;if(t!==void 0)return[t,...n.map(o=>this.getEntity(t,o))]}firstValue(e,...n){if(arguments.length===1)return this.getMap(e)?.firstValue();let[t,o]=this.getMap(e)?.firstEntry()??[];if(t!==void 0)return[o,...n.map(s=>this.getEntity(t,s))]}getEntity(e,n){let t=this.components.get(n.name);if(t===void 0)throw new p(n.name);return t.get(e)}get(e,...n){return n.length>1?n.map(t=>this.getEntity(e,t)):this.getEntity(e,n[0])}has(e,n){let t=this.components.get(n.name);return t===void 0?!1:t.has(e)}hasAll(e,...n){for(let t=0;t<n.length;t++){let o=n[t],s=this.components.get(o.name);if(s===void 0||s.has(e)===!1)return!1}return!0}hasAny(e,...n){for(let t=0;t<n.length;t++){let o=n[t],s=this.components.get(o.name);if(s!==void 0&&s.has(e))return!0}return!1}setEntity(e,n){let t=this.components.get(n.constructor.name);if(t===void 0)throw new p(n.constructor.name);return t.set(e,n),n}set(e,...n){return n.length>1?n.map(t=>this.setEntity(e,t)):this.setEntity(e,n[0])}remove(e,...n){for(let t of n)this.removeByKey(e,t.name)}removeByKey(e,n){let t=this.components.get(n);if(t===void 0)throw new p(n);return t.get(e)===void 0?!1:t.delete(e)}destroyEntity(...e){let n=0;for(let t=0;t<e.length;t++){let o=e[t];for(let s of this.components.values())s.has(o)&&(s.delete(o),n++)}return n}getNextId(){return this.nextId++,this.nextId}clear(){return this.components.clear(),this}clearComponents(){return this.components.forEach(e=>e.clear()),this}iterator(e,...n){return new l(this,e,...n)}printTable(){return this.components.forEach(e=>console.table(e.toTable(!0))),this}printEntity(e){for(let n of this.components.values()){if(n.has(e)===!1)continue;let t=n.get(e),o={name:t.constructor.name,...t};console.table({[e]:o})}return this}static parse(e){return JSON.parse(e,function(t,o){return o.hasOwnProperty("components")?(Reflect.setPrototypeOf(o,a.prototype),o):o.hasOwnProperty(C)?new i(o.iterable):o.hasOwnProperty(c)?new m(o.iterable):this[t]})}static createWithTracing(e){let n={get(t,o){let s=t[o];return typeof s=="function"&&(e.length===0||e.includes(o))?function(...r){return console.groupCollapsed("ecs trace",o,r),console.trace(),console.groupEnd(),s.apply(this,r)}:s}};return new Proxy(new a,n)}};var f=new u;typeof window<"u"?window.ecs=f:typeof module<"u"&&module!==null&&(module.exports={ecs:f});export{m as ComponentClassesMap,l as ComponentIterator,i as ComponentMap,u as EntityMap,f as ecs};
1
+ var C="ComponentMap",y="ComponentClassesMap";var i=class extends Map{firstEntry(){return this.size===0?void 0:this.entries().next().value}firstKey(){return this.size===0?void 0:this.keys().next().value}firstValue(){return this.size===0?void 0:this.values().next().value}toJSON(){return{[C]:1,iterable:[...this.entries()]}}toTable(n=!1){let e=[];for(let[t,o]of this.entries()){let s=o,r={};n==!1&&(r["entity.key"]=t),r["entity.type"]=s.constructor.name,e.push({...r,...s})}return e}printTable(n=!1){console.table(this.toTable(n))}static get[Symbol.species](){return Map}},m=class extends Map{toJSON(){return{[y]:1,iterable:[...this.entries()]}}static get[Symbol.species](){return Map}};var c=class extends Error{constructor(){super("Component type is missing the 'name' parameter. i.e. a constructor name")}},p=class extends Error{constructor(e){super(`Component map does not exist for '${e}'`);this.componentName=e}};var l=class{constructor(n,e,...t){this.ecs=n;this.key=e;this.keyMap=this.ecs.getMap(e),this.entries=this.keyMap.entries(),this.components=t.map(o=>this.ecs.getMap(o))}keyMap;components;entries;next(){let n=this.entries.next(),{value:e,done:t}=n;if(t)return{value:e,done:t};let[o,s]=e,r=[o,s];for(let d of this.components)r.push(d.get(o));return{value:r,done:!1}}reset(){this.entries=this.keyMap.entries()}[Symbol.iterator](){return this}};var u=class a{components=new m;nextId=0;register(...n){for(let e of n){let t=e.name;if(t===void 0)throw new c;let o=new i;this.components.set(t,o)}return this}getMap(n){let e=this.components.get(n.name);if(e===void 0)throw new p(n.name);return e}firstEntry(n,...e){return e.length===0?this.getMap(n)?.firstEntry():this.firstKey(n,n,...e)}firstKey(n,...e){let t=this.getMap(n)?.firstKey();if(arguments.length===1)return t;if(t!==void 0)return[t,...e.map(o=>this.getEntity(t,o))]}firstValue(n,...e){if(arguments.length===1)return this.getMap(n)?.firstValue();let[t,o]=this.getMap(n)?.firstEntry()??[];if(t!==void 0)return[o,...e.map(s=>this.getEntity(t,s))]}getEntity(n,e){let t=this.components.get(e.name);if(t===void 0)throw new p(e.name);return t.get(n)}get(n,...e){return e.length>1?e.map(t=>this.getEntity(n,t)):this.getEntity(n,e[0])}has(n,e){let t=this.components.get(e.name);return t===void 0?!1:t.has(n)}hasAll(n,...e){for(let t=0;t<e.length;t++){let o=e[t],s=this.components.get(o.name);if(s===void 0||s.has(n)===!1)return!1}return!0}hasAny(n,...e){for(let t=0;t<e.length;t++){let o=e[t],s=this.components.get(o.name);if(s!==void 0&&s.has(n))return!0}return!1}setEntity(n,e){let t=this.components.get(e.constructor.name);if(t===void 0)throw new p(e.constructor.name);return t.set(n,e),e}set(n,...e){return e.length>1?e.map(t=>this.setEntity(n,t)):this.setEntity(n,e[0])}remove(n,...e){for(let t of e)this.removeByKey(n,t.name)}removeByKey(n,e){let t=this.components.get(e);if(t===void 0)throw new p(e);return t.get(n)===void 0?!1:t.delete(n)}destroyEntity(...n){let e=0;for(let t=0;t<n.length;t++){let o=n[t];for(let s of this.components.values())s.has(o)&&(s.delete(o),e++)}return e}getNextId(){return this.nextId++,this.nextId}clear(){return this.components.clear(),this}clearComponents(){return this.components.forEach(n=>n.clear()),this}iterator(n,...e){return new l(this,n,...e)}printTable(){return this.components.forEach(n=>console.table(n.toTable(!0))),this}printEntity(n){for(let e of this.components.values()){if(e.has(n)===!1)continue;let t=e.get(n),o={name:t.constructor.name,...t};console.table({[n]:o})}return this}static parse(n){return JSON.parse(n,function(t,o){return o.hasOwnProperty("components")?(Reflect.setPrototypeOf(o,a.prototype),o):o.hasOwnProperty(C)?new i(o.iterable):o.hasOwnProperty(y)?new m(o.iterable):this[t]})}static createWithTracing(n){let e={get(t,o){let s=t[o];return typeof s=="function"&&(n.length===0||n.includes(o))?function(...r){return console.groupCollapsed("ecs trace",o,r),console.trace(),console.groupEnd(),s.apply(this,r)}:s}};return new Proxy(new a,e)}};var f=new u;typeof window<"u"?window.ecs=f:typeof module<"u"&&module!==null&&(module.exports={ecs:f});export{m as ComponentClassesMap,l as ComponentIterator,i as ComponentMap,u as EntityMap,f as ecs};
2
2
  //# sourceMappingURL=ecs.js.map
package/dist/ecs.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/types.ts", "../src/component-map.ts", "../src/errors.ts", "../src/iterators.ts", "../src/entity-map.ts", "../src/ecs.ts"],
4
- "sourcesContent": ["export const ComponentMapKey = \"ComponentMap\"\nexport const ComponentClassesMapKey = \"ComponentClassesMap\"\n\nexport type KeyCollection<T> = { [key: string]: T }\n\nexport interface Component { }\n\n/**\n * @category Types\n * @example\n * \n * class PositionComponent {\n * constructor(x, y) {\n * this.x = x;\n * this.y = y;\n * }\n * }\n */\nexport type ComponentClass<ComponentInstance> = new (...args: any[]) => ComponentInstance\n\n/**\n* Used for infering generic type spread for classes\n*/\nexport type ComponentClasses<TClasses extends Component[]> =\n { [Index in keyof TClasses]: TClasses[Index] }\n\n/**\n * Used for infering generic type spread for class instances\n */\nexport type ComponentInstances<TClasses extends ComponentClass<any>[]> =\n // return a single variadic item when only 1 item is specified\n TClasses['length'] extends 1 ? TClasses[0] extends ComponentClass<infer R> ? R : never\n // otherwise return an array of variadic types\n : {\n [Index in keyof TClasses]: TClasses[Index] extends ComponentClass<infer R> ? R : never\n }\n\nexport type IteratorResult<T> = {\n done: boolean,\n value: T\n}\n\nexport type Iterator<T> = {\n next: () => IteratorResult<T>\n reset: () => void\n [Symbol.iterator]: () => Iterator<T>\n}\n\n/**\n * allow late bound assignment type for intellisense\n * @category Types\n * @example\n * \n * let someIterator: IComponentIterator<[Player, Position]>\n * \n * // assignment made somewhere else in the code\n * const [player, position] = someIterator(Player, Position) ?? []\n * position?.x = 123 // position will have intellisense\n */\nexport type IComponentIterator<T extends Component[]>\n = Iterator<ComponentClasses<[number, ...T]>>", "/*\n ecsjs is an entity component system library for JavaScript\n Copyright (C) 2014 Peter Flannery\n\n This program is free software: you can redistribute it and/or modify\n it under the terms of the GNU Affero General Public License as\n published by the Free Software Foundation, either version 3 of the\n License, or (at your option) any later version.\n\n This program is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Affero General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License\n along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\nimport { ComponentClassesMapKey, ComponentMapKey, type KeyCollection } from './types.js';\n\n/**\n * Component map for storing entity ids and related component data\n * @category Maps\n */\nexport class ComponentMap<TComponentInstance> extends Map<number, TComponentInstance> {\n\n /**\n * Returns the first entity entry\n */\n firstEntry(): [entityId: number, value: TComponentInstance] | undefined {\n if (this.size === 0) return undefined;\n\n const iterator = this.entries();\n const result = iterator.next();\n return result.value;\n }\n\n /**\n * Returns the first entity id\n */\n firstKey(): number | undefined {\n if (this.size === 0) return undefined;\n\n const iterator = this.keys();\n const result = iterator.next();\n return result.value;\n }\n\n /**\n * Returns the first entity value\n */\n firstValue(): TComponentInstance | undefined {\n if (this.size === 0) return undefined;\n\n const iterator = this.values();\n const result = iterator.next();\n return result.value;\n }\n\n /**\n * Called when using JSON.stringify\n */\n toJSON() {\n return { [ComponentMapKey]: 1, iterable: [...this.entries()] };\n }\n\n toTable(excludeKeys = false): any[] {\n const table = []\n for (const [key, value] of this.entries()) {\n const entity = value as { new(): TComponentInstance };\n const meta: KeyCollection<any> = {};\n if (excludeKeys == false) meta[\"entity.key\"] = key;\n meta[\"entity.type\"] = entity.constructor.name;\n table.push({ ...meta, ...entity });\n }\n return table;\n }\n\n /**\n * Prints entity data in a tabular format to the console\n */\n printTable(excludeKeys = false): void {\n console.table(this.toTable(excludeKeys));\n }\n\n static get [Symbol.species]() {\n return Map;\n }\n\n}\n\n/**\n * Component class map for storing registered component maps\n * @category Maps\n */\nexport class ComponentClassesMap extends Map<string, ComponentMap<any>> {\n\n /**\n * Called when using JSON.stringify\n */\n toJSON() {\n return { [ComponentClassesMapKey]: 1, iterable: [...this.entries()] };\n }\n\n static get [Symbol.species]() {\n return Map;\n }\n\n}", "/**\n * Thrown when trying to register a component that is missing a 'name' parameter\n * @category Errors\n */\nexport class ComponentTypeKeyMissing extends Error {\n constructor() {\n super(`Component type is missing the 'name' parameter. i.e. a constructor name`);\n }\n}\n\n/**\n * Thrown when trying to access a component that has not been registered\n * @category Errors\n */\nexport class ComponentNotRegistered extends Error {\n constructor(public componentName: string) {\n super(`Component map does not exist for '${componentName}'`);\n }\n}", "import type { ComponentMap } from './component-map.js';\nimport type { EntityMap } from './entity-map.js';\nimport type { ComponentClass, ComponentInstances, IteratorResult } from './types.js';\n\n/**\n * @category Iterators\n * @example\n * // construct an instance\n * const iterator = new ComponentIterator(entityMap, Player, Position)\n * \n * // iterate each component value that is related to the Player\n * for(const [entityId, player, position] of iterator) { }\n * \n * // you can also reset the iterator back to the start \n * // without having to create a new ComponentIterator instance\n * iterator.reset()\n * for(const [entityId, player, position] of iterator) { }\n */\nexport class ComponentIterator<\n TComponentKey extends ComponentClass<any>,\n TComponentClasses extends ComponentClass<any>[]\n> {\n\n private keyMap: ComponentMap<any>\n private components: ComponentMap<any>[]\n // iteration state\n private entries: MapIterator<[number, TComponentKey]>\n\n /**\n * {@link ComponentNotRegistered} when any of specified component(s) are not registered\n */\n constructor(public ecs: EntityMap, public key: TComponentKey, ...components: TComponentClasses) {\n this.keyMap = this.ecs.getMap(key)!;\n this.entries = this.keyMap.entries();\n this.components = components.map(x => this.ecs.getMap(x)!);\n }\n\n /**\n * gets the next iterator value\n */\n next(): IteratorResult<ComponentInstances<[ComponentClass<number>, TComponentKey, ...TComponentClasses]>> {\n const entry = this.entries.next();\n const { value, done } = entry;\n if (done) return { value: value as any, done };\n\n const [entityId, entityValue] = value;\n const results = [entityId, entityValue]\n for (const x of this.components) {\n results.push(x.get(entityId));\n }\n\n return { value: results as any, done: false };\n }\n\n /**\n * resets the iterator back to the first entry\n */\n reset() {\n this.entries = this.keyMap.entries();\n }\n\n [Symbol.iterator]() { return this; }\n\n}", "/*\n ecsjs is an entity component system library for JavaScript\n Copyright (C) 2014 Peter Flannery\n\n This program is free software: you can redistribute it and/or modify\n it under the terms of the GNU Affero General Public License as\n published by the Free Software Foundation, either version 3 of the\n License, or (at your option) any later version.\n\n This program is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Affero General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License\n along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\nimport { ComponentClassesMap, ComponentMap } from './component-map.js';\nimport { ComponentNotRegistered, ComponentTypeKeyMissing } from './errors.js';\nimport { ComponentIterator } from './iterators.js';\nimport {\n ComponentClassesMapKey,\n ComponentMapKey,\n type Component,\n type ComponentClass,\n type ComponentInstances\n} from './types.js';\n\n/**\n * Class for storing entities and their relationships\n * @category Maps\n */\nexport class EntityMap {\n /**\n * Registered component classes that contain the component instance data\n */\n public components = new ComponentClassesMap()\n\n private nextId: number = 0\n\n /**\n * Registers component classes with the {@link EntityMap}\n * @throwsError {@link ComponentTypeKeyMissing} when the specified component type is missing a 'name' parameter\n * @example\n * // component class\n * class MyComponent {\n * constructor(x) {\n * this.x = x;\n * }\n * }\n *\n * ecs.register(MyComponent);\n * // or mulitple\n * ecs.register(MyComponent1, MyComponent2);\n */\n register<TComponentClasses extends ComponentClass<any>[]>(...componentClasses: TComponentClasses) {\n for (const componentClass of componentClasses) {\n const componentName = componentClass.name;\n if (componentName === undefined) throw new ComponentTypeKeyMissing()\n\n // create the component map\n const componentDataMap: ComponentMap<any> = new ComponentMap();\n this.components.set(componentName, componentDataMap);\n }\n\n // chain\n return this;\n }\n\n /**\n * Gets a component class map\n * @throwsError {@link ComponentNotRegistered} when the specified component is not registered\n * @example\n * const positionMap = ecs.getMap(Position)\n * for(const [entityId, position] of positionMap) {\n * position.x += 1\n * }\n */\n getMap<T>(component: ComponentClass<T>): ComponentMap<T> | undefined {\n const map = this.components.get(component.name);\n if (map === undefined) throw new ComponentNotRegistered(component.name)\n return map\n }\n\n /**\n * Gets the first entity entry for a component class\n * @throwsError {@link ComponentNotRegistered} when the specified component is not registered\n * @example\n * const [entityId, player] = ecs.firstEntry(Player) ?? []\n */\n firstEntry<TComponent>(component: ComponentClass<TComponent>) {\n return this.getMap(component)?.firstEntry();\n }\n\n /**\n * Gets the first entity id for a component class \n * and optionally any related component data\n * @throwsError {@link ComponentNotRegistered} when any of specified component(s) are not registered\n * @example\n * // return the first entity id\n * const entityId = ecs.firstKey(Player)\n * \n * // or return multiple related component in addition to entity id\n * const [entityId, position, direction] = ecs.firstKey(\n * Player,\n * Position,\n * Direction\n * ) ?? []\n */\n firstKey<TKey extends ComponentClass<any>, T extends ComponentClass<any>[]>(\n keyComponent: TKey,\n ...components: T\n ): ComponentInstances<[ComponentClass<number>, ...T]> | undefined;\n firstKey(keyComponent: ComponentClass<any>, ...components: ComponentClass<any>[]) {\n const entityId = this.getMap(keyComponent)?.firstKey();\n\n // single component key\n if (arguments.length === 1) return entityId;\n if (entityId === undefined) return undefined;\n\n // attach multiple related component values\n return [entityId, ...components.map(x => this.getEntity(entityId, x))];\n }\n\n /**\n * Gets the first entity component data for a component class\n * and optionally any related component data\n * @throwsError {@link ComponentNotRegistered} when any of specified component(s) are not registered\n * @example\n * // return the first component value\n * const player = ecs.firstValue(Player)\n * \n * // or multiple related values in addition to the first component\n * const [player, position, direction] = ecs.firstValue(\n * Player,\n * Position,\n * Direction\n * )\n */\n firstValue<TKey extends ComponentClass<any>, T extends ComponentClass<any>[]>(\n keyComponent: TKey,\n ...components: T\n ): ComponentInstances<[TKey, ...T]> | undefined;\n firstValue(keyComponent: ComponentClass<any>, ...components: ComponentClass<any>[]) {\n // single component\n if (arguments.length === 1) return this.getMap(keyComponent)?.firstValue();\n\n // get the first entry\n const [entityId, value] = this.getMap(keyComponent)?.firstEntry() ?? [];\n if (entityId === undefined) return undefined;\n\n // attach multiple related components\n return [value, ...components.map(x => this.getEntity(entityId, x))]\n }\n\n /**\n * @throwsError {@link ComponentNotRegistered} when the specified component is not registered \n */\n private getEntity<T>(entityId: number, component: ComponentClass<T>): T | undefined {\n const map = this.components.get(component.name);\n if (map === undefined) throw new ComponentNotRegistered(component.name)\n\n return map.get(entityId);\n }\n\n /**\n * Gets component values related to an entity id\n * @throwsError {@link ComponentNotRegistered} when any of specified component(s) are not registered\n * @example\n * // get one\n * const player = ecs.get(entityId, Player)\n * \n * // or get multiple\n * const [player, position] = ecs.get(entityId, Player, Position) ?? []\n */\n get<T extends ComponentClass<any>[]>(entityId: number, ...components: T): ComponentInstances<T> | undefined;\n get<T extends Component>(entityId: number, ...components: ComponentClass<T>[]): T | (T | undefined)[] | undefined {\n if (components.length > 1) return components.map(x => this.getEntity(entityId, x))\n\n // return a single component\n return this.getEntity(entityId, components[0])\n }\n\n /**\n * Check if a component exists for an entity\n * @example\n * const exists = ecs.has(entityId, Position)\n */\n has<T>(entityId: number, component: ComponentClass<T>): boolean {\n // get the component map\n const map = this.components.get(component.name);\n if (map === undefined) return false\n\n return map.has(entityId);\n }\n\n /**\n * Checks if all of the specified components exist for an entity\n * @example\n * const hasAll = ecs.hasAll(entityId, Position, Velocity)\n */\n hasAll<T extends ComponentClass<any>[]>(entityId: number, ...components: T): boolean {\n for (let index = 0; index < components.length; index++) {\n const component = components[index];\n const map = this.components.get(component.name);\n if (map === undefined) return false;\n if (map.has(entityId) === false) return false;\n }\n return true\n }\n\n /**\n * Checks if any of the specified components exist for an entity\n * @example\n * const hasAny = ecs.hasAny(entityId, Position, Velocity)\n */\n hasAny<T extends ComponentClass<any>[]>(entityId: number, ...components: T): boolean {\n for (let index = 0; index < components.length; index++) {\n const component = components[index];\n const map = this.components.get(component.name);\n if (map === undefined) continue;\n if (map.has(entityId)) return true;\n }\n return false\n }\n\n private setEntity<T extends Component>(entityId: number, componentData: T): T {\n // get the component map\n const map = this.components.get(componentData.constructor.name);\n if (map === undefined) throw new ComponentNotRegistered(componentData.constructor.name)\n\n // set the entity on the entity map\n map.set(entityId, componentData);\n\n // return instance\n return componentData;\n }\n\n /**\n * Add or update multiple component values for an entity\n * @example\n * // set one\n * const player = ecs.set(entityId, new Player());\n * \n * // or set multiple\n * const [player, position] = ecs.set(\n * entityId,\n * new Player(),\n * new Position()\n * );\n */\n set<T extends Component>(entityId: number, component: T): T;\n set<T extends Component[]>(entityId: number, ...components: T): T;\n set(entityId: number, ...components: Component[]): Component | Component[] {\n if (components.length > 1) return components.map(x => this.setEntity(entityId, x))\n\n // set and return a single component\n return this.setEntity(entityId, components[0])\n }\n\n /**\n * Removes the specified component(s) from an entity\n * @example\n * ecs.remove(entityId, Position);\n */\n remove<T extends ComponentClass<any>[]>(entityId: number, ...components: T) {\n for (const component of components) {\n this.removeByKey(entityId, component.name)\n }\n }\n\n /**\n * Removes the specified component from an entity\n * @throwsError {@link ComponentNotRegistered} when the specified component is not registered\n * @example\n * ecs.removeByKey(entityId, \"Position\");\n */\n removeByKey(entityId: number, componentName: string) {\n // get the entity map\n const entityMap = this.components.get(componentName);\n\n // ensure the map is defined\n if (entityMap === undefined) throw new ComponentNotRegistered(componentName);\n\n // get the entity\n const entity = entityMap.get(entityId);\n if (entity === undefined) return false;\n\n // remove the entity from the entity map\n return entityMap.delete(entityId);\n }\n\n /**\n * Deletes all components from an entity\n * @example\n * const destroyedCount = ecs.destroyEntity(entityId1)\n * \n * // or multiple\n * const destroyedCount = ecs.destroyEntity(entityId1, entityId2)\n */\n destroyEntity(...entityIds: number[]): number {\n let deletedCount = 0;\n for (let index = 0; index < entityIds.length; index++) {\n const entityId = entityIds[index];\n for (const map of this.components.values()) {\n if (map.has(entityId)) {\n map.delete(entityId);\n deletedCount++;\n }\n }\n }\n return deletedCount;\n }\n\n // TODO create id generator\n /**\n * Creates a new entity id for the EntityMap\n * @example\n * const newEntityId = ecs.getNextId()\n * ecs.set(newEntityId, new Player())\n */\n getNextId(): number {\n this.nextId++;\n return this.nextId;\n }\n\n /**\n * Clears all registered components\n */\n clear() {\n this.components.clear();\n return this;\n }\n\n /**\n * Clears all component data\n */\n clearComponents() {\n this.components.forEach(x => x.clear())\n return this;\n }\n\n /**\n * Iterates over each component value that is related to the key component\n * @throwsError {@link ComponentNotRegistered} when any of specified component(s) are not registered\n * @example\n * // iterate each component value that is related to the Player entity\n * const iterator = ecs.iterator(Player, Position)\n * \n * for(const [playerId, player, position] of iterator) { }\n * \n * // you can also declare the type of iterator before it's assigned\n * let iterator: IComponentIterator<[Player, Position]>\n * \n * // then with late bound assignment (keeping the iterator intellisense)\n * iterator = ecs.iterator(Player, Position)\n * \n * for(const [playerId, player, position] of iterator) {\n * const moving = player.isMoving\n * }\n */\n iterator<K extends ComponentClass<any>, T extends ComponentClass<any>[]>(\n keyComponent: K,\n ...components: T\n ): ComponentIterator<K, T>\n iterator(keyComponent: ComponentClass<any>, ...components: ComponentClass<any>[]) {\n return new ComponentIterator(this, keyComponent, ...components) as any;\n }\n\n /**\n * Prints all component maps in a tabular format to the console\n */\n printTable() {\n this.components.forEach(map => console.table(map.toTable(true)));\n return this;\n }\n\n /**\n * Prints all component data for the specified entity id in a tabular format to the console\n */\n printEntity(entityId: number) {\n for (const map of this.components.values()) {\n if (map.has(entityId) === false) continue;\n\n const data = map.get(entityId);\n const columns = {\n name: data.constructor.name,\n ...data\n };\n console.table({ [entityId]: columns });\n }\n\n return this;\n }\n\n /**\n * Parse's the JSON and returns an EntityMap object\n * @example\n * const json = JSON.stringfy(ecs);\n * const restoredMap = ecs.parse(json);\n */\n static parse(json: string): EntityMap {\n const restored = JSON.parse(json, function (key: string, value: any) {\n if (value.hasOwnProperty('components')) {\n Reflect.setPrototypeOf(value, EntityMap.prototype);\n return value;\n }\n if (value.hasOwnProperty(ComponentMapKey)) return new ComponentMap(value.iterable);\n if (value.hasOwnProperty(ComponentClassesMapKey)) return new ComponentClassesMap(value.iterable);\n return this[key];\n });\n return restored;\n }\n\n /**\n * A tracing method used for debugging.\n * Intercepts all functions specified and logs each call to the console.\n * @param {Array} funcFilter A list of function names you want to intercept. If no function names are specified then will log all functions called\n * @return {EntityMap} A new entity map with tracing enabled\n */\n static createWithTracing(funcFilter: any) {\n const traceHandler = {\n get(target: any, propKey: string) {\n const targetValue = target[propKey]\n\n if (typeof targetValue === 'function' && (funcFilter.length === 0 || funcFilter.includes(propKey))) {\n return function (this: any, ...args: any[]) {\n console.groupCollapsed('ecs trace', propKey, args);\n console.trace();\n console.groupEnd();\n return targetValue.apply(this, args);\n }\n }\n\n return targetValue;\n }\n }\n\n return new Proxy(new EntityMap(), traceHandler)\n }\n\n}", "/*\n ecsjs is an entity component system library for JavaScript\n Copyright (C) 2014 Peter Flannery\n\n This program is free software: you can redistribute it and/or modify\n it under the terms of the GNU Affero General Public License as\n published by the Free Software Foundation, either version 3 of the\n License, or (at your option) any later version.\n\n This program is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Affero General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License\n along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\n/**\n * An entity component system library for JavaScript\n * @showCategories\n * @module ecsjs\n */\nimport { EntityMap } from './entity-map.js'\nexport { ComponentClassesMap, ComponentMap } from './component-map.js'\nexport { EntityMap } from './entity-map.js'\nexport type { ComponentNotRegistered, ComponentTypeKeyMissing } from './errors.js'\nexport { ComponentIterator } from './iterators.js'\nexport type { ComponentClass, IComponentIterator } from './types.js'\n\n/**\n * Global instance of an {@link EntityMap}\n * \n * See the [cheat sheet](https://gitlab.com/ecsjs/ecs/-/blob/master/docs/cheat-sheet.md) for more examples\n * @category Constants\n * @example\n * \n * // register component(s)\n * ecs.register(Player, Position)\n * \n * // create an entity\n * const [player, position] = ecs.set(ecs.getNextId(), new Player(), new Position(10, 40))\n */\nexport const ecs = new EntityMap()\n\nif (typeof window !== 'undefined') {\n // @ts-ignore: exports to window\n window.ecs = ecs\n} else if (typeof module !== 'undefined' && module !== null) {\n // exports to nodejs\n module.exports = { ecs };\n}"],
5
- "mappings": "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",
4
+ "sourcesContent": ["export const ComponentMapKey = \"ComponentMap\"\nexport const ComponentClassesMapKey = \"ComponentClassesMap\"\n\nexport type KeyCollection<T> = { [key: string]: T }\n\nexport interface Component { }\n\n/**\n * @category Types\n * @example\n * \n * class PositionComponent {\n * constructor(x, y) {\n * this.x = x;\n * this.y = y;\n * }\n * }\n */\nexport type ComponentClass<ComponentInstance> = new (...args: any[]) => ComponentInstance\n\n/**\n* Used for infering generic type spread for classes\n*/\nexport type ComponentClasses<TClasses extends Component[]> =\n { [Index in keyof TClasses]: TClasses[Index] }\n\n/**\n * Used for infering generic type spread for class instances\n */\nexport type ComponentInstances<TClasses extends ComponentClass<any>[]> =\n // return a single variadic item when only 1 item is specified\n TClasses['length'] extends 1 ? TClasses[0] extends ComponentClass<infer R> ? R : never\n // otherwise return an array of variadic types\n : {\n [Index in keyof TClasses]: TClasses[Index] extends ComponentClass<infer R> ? R : never\n }\n\nexport type IteratorResult<T> = {\n done: boolean,\n value: T\n}\n\nexport type Iterator<T> = {\n next: () => IteratorResult<T>\n reset: () => void\n [Symbol.iterator]: () => Iterator<T>\n}\n\n/**\n * allow late bound assignment type for intellisense\n * @category Types\n * @example\n * \n * let someIterator: IComponentIterator<[Player, Position]>\n * \n * // assignment made somewhere else in the code\n * const [player, position] = someIterator(Player, Position) ?? []\n * position?.x = 123 // position will have intellisense\n */\nexport type IComponentIterator<T extends Component[]>\n = Iterator<ComponentClasses<[number, ...T]>>", "/*\n ecsjs is an entity component system library for JavaScript\n Copyright (C) 2014 Peter Flannery\n\n This program is free software: you can redistribute it and/or modify\n it under the terms of the GNU Affero General Public License as\n published by the Free Software Foundation, either version 3 of the\n License, or (at your option) any later version.\n\n This program is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Affero General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License\n along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\nimport { ComponentClassesMapKey, ComponentMapKey, type KeyCollection } from './types.js';\n\n/**\n * Component map for storing entity ids and related component data\n * @category Maps\n */\nexport class ComponentMap<TComponentInstance> extends Map<number, TComponentInstance> {\n\n /**\n * Returns the first entity entry\n */\n firstEntry(): [entityId: number, value: TComponentInstance] | undefined {\n if (this.size === 0) return undefined;\n\n const iterator = this.entries();\n const result = iterator.next();\n return result.value;\n }\n\n /**\n * Returns the first entity id\n */\n firstKey(): number | undefined {\n if (this.size === 0) return undefined;\n\n const iterator = this.keys();\n const result = iterator.next();\n return result.value;\n }\n\n /**\n * Returns the first entity value\n */\n firstValue(): TComponentInstance | undefined {\n if (this.size === 0) return undefined;\n\n const iterator = this.values();\n const result = iterator.next();\n return result.value;\n }\n\n /**\n * Called when using JSON.stringify\n */\n toJSON() {\n return { [ComponentMapKey]: 1, iterable: [...this.entries()] };\n }\n\n toTable(excludeKeys = false): any[] {\n const table = []\n for (const [key, value] of this.entries()) {\n const entity = value as { new(): TComponentInstance };\n const meta: KeyCollection<any> = {};\n if (excludeKeys == false) meta[\"entity.key\"] = key;\n meta[\"entity.type\"] = entity.constructor.name;\n table.push({ ...meta, ...entity });\n }\n return table;\n }\n\n /**\n * Prints entity data in a tabular format to the console\n */\n printTable(excludeKeys = false): void {\n console.table(this.toTable(excludeKeys));\n }\n\n static get [Symbol.species]() {\n return Map;\n }\n\n}\n\n/**\n * Component class map for storing registered component maps\n * @category Maps\n */\nexport class ComponentClassesMap extends Map<string, ComponentMap<any>> {\n\n /**\n * Called when using JSON.stringify\n */\n toJSON() {\n return { [ComponentClassesMapKey]: 1, iterable: [...this.entries()] };\n }\n\n static get [Symbol.species]() {\n return Map;\n }\n\n}", "/**\n * Thrown when trying to register a component that is missing a 'name' parameter\n * @category Errors\n */\nexport class ComponentTypeKeyMissing extends Error {\n constructor() {\n super(`Component type is missing the 'name' parameter. i.e. a constructor name`);\n }\n}\n\n/**\n * Thrown when trying to access a component that has not been registered\n * @category Errors\n */\nexport class ComponentNotRegistered extends Error {\n constructor(public componentName: string) {\n super(`Component map does not exist for '${componentName}'`);\n }\n}", "import type { ComponentMap } from './component-map.js';\nimport type { EntityMap } from './entity-map.js';\nimport type { ComponentClass, ComponentInstances, IteratorResult } from './types.js';\n\n/**\n * @category Iterators\n * @example\n * // construct an instance\n * const iterator = new ComponentIterator(entityMap, Player, Position)\n * \n * // iterate each component value that is related to the Player\n * for(const [entityId, player, position] of iterator) { }\n * \n * // you can also reset the iterator back to the start \n * // without having to create a new ComponentIterator instance\n * iterator.reset()\n * for(const [entityId, player, position] of iterator) { }\n */\nexport class ComponentIterator<\n TComponentKey extends ComponentClass<any>,\n TComponentClasses extends ComponentClass<any>[]\n> {\n\n private keyMap: ComponentMap<any>\n private components: ComponentMap<any>[]\n // iteration state\n private entries: MapIterator<[number, TComponentKey]>\n\n /**\n * {@link ComponentNotRegistered} when any of specified component(s) are not registered\n */\n constructor(public ecs: EntityMap, public key: TComponentKey, ...components: TComponentClasses) {\n this.keyMap = this.ecs.getMap(key)!;\n this.entries = this.keyMap.entries();\n this.components = components.map(x => this.ecs.getMap(x)!);\n }\n\n /**\n * gets the next iterator value\n */\n next(): IteratorResult<ComponentInstances<[ComponentClass<number>, TComponentKey, ...TComponentClasses]>> {\n const entry = this.entries.next();\n const { value, done } = entry;\n if (done) return { value: value as any, done };\n\n const [entityId, entityValue] = value;\n const results = [entityId, entityValue]\n for (const x of this.components) {\n results.push(x.get(entityId));\n }\n\n return { value: results as any, done: false };\n }\n\n /**\n * resets the iterator back to the first entry\n */\n reset() {\n this.entries = this.keyMap.entries();\n }\n\n [Symbol.iterator]() { return this; }\n\n}", "/*\n ecsjs is an entity component system library for JavaScript\n Copyright (C) 2014 Peter Flannery\n\n This program is free software: you can redistribute it and/or modify\n it under the terms of the GNU Affero General Public License as\n published by the Free Software Foundation, either version 3 of the\n License, or (at your option) any later version.\n\n This program is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Affero General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License\n along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\nimport { ComponentClassesMap, ComponentMap } from './component-map.js';\nimport { ComponentNotRegistered, ComponentTypeKeyMissing } from './errors.js';\nimport { ComponentIterator } from './iterators.js';\nimport {\n ComponentClassesMapKey,\n ComponentMapKey,\n type Component,\n type ComponentClass,\n type ComponentInstances\n} from './types.js';\n\n/**\n * Class for storing entities and their relationships\n * @category Maps\n */\nexport class EntityMap {\n /**\n * Registered component classes that contain the component instance data\n */\n public components = new ComponentClassesMap()\n\n private nextId: number = 0\n\n /**\n * Registers component classes with the {@link EntityMap}\n * @throwsError {@link ComponentTypeKeyMissing} when the specified component type is missing a 'name' parameter\n * @example\n * // component class\n * class MyComponent {\n * constructor(x) {\n * this.x = x;\n * }\n * }\n *\n * ecs.register(MyComponent);\n * // or mulitple\n * ecs.register(MyComponent1, MyComponent2);\n */\n register<TComponentClasses extends ComponentClass<any>[]>(...componentClasses: TComponentClasses) {\n for (const componentClass of componentClasses) {\n const componentName = componentClass.name;\n if (componentName === undefined) throw new ComponentTypeKeyMissing()\n\n // create the component map\n const componentDataMap: ComponentMap<any> = new ComponentMap();\n this.components.set(componentName, componentDataMap);\n }\n\n // chain\n return this;\n }\n\n /**\n * Gets a component class map\n * @throwsError {@link ComponentNotRegistered} when the specified component is not registered\n * @example\n * const positionMap = ecs.getMap(Position)\n * for(const [entityId, position] of positionMap) {\n * position.x += 1\n * }\n */\n getMap<T>(component: ComponentClass<T>): ComponentMap<T> | undefined {\n const map = this.components.get(component.name);\n if (map === undefined) throw new ComponentNotRegistered(component.name)\n return map\n }\n\n /**\n * Gets the first entity entry for a component class\n * @throwsError {@link ComponentNotRegistered} when the specified component is not registered\n * @example\n * // return the first entry\n * const [entityId, player] = ecs.firstEntry(Player) ?? []\n * \n * // or return multiple related components in addition to the first entry\n * const [entityId, player, position, direction] = ecs.firstEntry(\n * Player,\n * Position,\n * Direction\n * )\n */\n firstEntry<TKey extends ComponentClass<any>, T extends ComponentClass<any>[]>(\n keyComponent: TKey,\n ...components: T\n ): ComponentInstances<[ComponentClass<number>, TKey, ...T]> | undefined;\n firstEntry(keyComponent: ComponentClass<any>, ...components: ComponentClass<any>[]) {\n if (components.length === 0) return this.getMap(keyComponent)?.firstEntry()\n\n return this.firstKey(keyComponent, keyComponent, ...components);\n }\n\n /**\n * Gets the first entity id for a component class \n * and optionally any related component data\n * @throwsError {@link ComponentNotRegistered} when any of specified component(s) are not registered\n * @example\n * // return the first entity id\n * const entityId = ecs.firstKey(Player)\n * \n * // or return multiple related component in addition to entity id\n * const [entityId, position, direction] = ecs.firstKey(\n * Player,\n * Position,\n * Direction\n * ) ?? []\n */\n firstKey<TKey extends ComponentClass<any>, T extends ComponentClass<any>[]>(\n keyComponent: TKey,\n ...components: T\n ): ComponentInstances<[ComponentClass<number>, ...T]> | undefined;\n firstKey(keyComponent: ComponentClass<any>, ...components: ComponentClass<any>[]) {\n const entityId = this.getMap(keyComponent)?.firstKey();\n\n // single component key\n if (arguments.length === 1) return entityId;\n if (entityId === undefined) return undefined;\n\n // attach multiple related component values\n return [entityId, ...components.map(x => this.getEntity(entityId, x))];\n }\n\n /**\n * Gets the first entity component data for a component class\n * and optionally any related component data\n * @throwsError {@link ComponentNotRegistered} when any of specified component(s) are not registered\n * @example\n * // return the first component value\n * const player = ecs.firstValue(Player)\n * \n * // or multiple related values in addition to the first component\n * const [player, position, direction] = ecs.firstValue(\n * Player,\n * Position,\n * Direction\n * )\n */\n firstValue<TKey extends ComponentClass<any>, T extends ComponentClass<any>[]>(\n keyComponent: TKey,\n ...components: T\n ): ComponentInstances<[TKey, ...T]> | undefined;\n firstValue(keyComponent: ComponentClass<any>, ...components: ComponentClass<any>[]) {\n // single component\n if (arguments.length === 1) return this.getMap(keyComponent)?.firstValue();\n\n // get the first entry\n const [entityId, value] = this.getMap(keyComponent)?.firstEntry() ?? [];\n if (entityId === undefined) return undefined;\n\n // attach multiple related components\n return [value, ...components.map(x => this.getEntity(entityId, x))]\n }\n\n /**\n * @throwsError {@link ComponentNotRegistered} when the specified component is not registered \n */\n private getEntity<T>(entityId: number, component: ComponentClass<T>): T | undefined {\n const map = this.components.get(component.name);\n if (map === undefined) throw new ComponentNotRegistered(component.name)\n\n return map.get(entityId);\n }\n\n /**\n * Gets component values related to an entity id\n * @throwsError {@link ComponentNotRegistered} when any of specified component(s) are not registered\n * @example\n * // get one\n * const player = ecs.get(entityId, Player)\n * \n * // or get multiple\n * const [player, position] = ecs.get(entityId, Player, Position) ?? []\n */\n get<T extends ComponentClass<any>[]>(entityId: number, ...components: T): ComponentInstances<T> | undefined;\n get<T extends Component>(entityId: number, ...components: ComponentClass<T>[]): T | (T | undefined)[] | undefined {\n if (components.length > 1) return components.map(x => this.getEntity(entityId, x))\n\n // return a single component\n return this.getEntity(entityId, components[0])\n }\n\n /**\n * Check if a component exists for an entity\n * @example\n * const exists = ecs.has(entityId, Position)\n */\n has<T>(entityId: number, component: ComponentClass<T>): boolean {\n // get the component map\n const map = this.components.get(component.name);\n if (map === undefined) return false\n\n return map.has(entityId);\n }\n\n /**\n * Checks if all of the specified components exist for an entity\n * @example\n * const hasAll = ecs.hasAll(entityId, Position, Velocity)\n */\n hasAll<T extends ComponentClass<any>[]>(entityId: number, ...components: T): boolean {\n for (let index = 0; index < components.length; index++) {\n const component = components[index];\n const map = this.components.get(component.name);\n if (map === undefined) return false;\n if (map.has(entityId) === false) return false;\n }\n return true\n }\n\n /**\n * Checks if any of the specified components exist for an entity\n * @example\n * const hasAny = ecs.hasAny(entityId, Position, Velocity)\n */\n hasAny<T extends ComponentClass<any>[]>(entityId: number, ...components: T): boolean {\n for (let index = 0; index < components.length; index++) {\n const component = components[index];\n const map = this.components.get(component.name);\n if (map === undefined) continue;\n if (map.has(entityId)) return true;\n }\n return false\n }\n\n private setEntity<T extends Component>(entityId: number, componentData: T): T {\n // get the component map\n const map = this.components.get(componentData.constructor.name);\n if (map === undefined) throw new ComponentNotRegistered(componentData.constructor.name)\n\n // set the entity on the entity map\n map.set(entityId, componentData);\n\n // return instance\n return componentData;\n }\n\n /**\n * Add or update multiple component values for an entity\n * @example\n * // set one\n * const player = ecs.set(entityId, new Player());\n * \n * // or set multiple\n * const [player, position] = ecs.set(\n * entityId,\n * new Player(),\n * new Position()\n * );\n */\n set<T extends Component>(entityId: number, component: T): T;\n set<T extends Component[]>(entityId: number, ...components: T): T;\n set(entityId: number, ...components: Component[]): Component | Component[] {\n if (components.length > 1) return components.map(x => this.setEntity(entityId, x))\n\n // set and return a single component\n return this.setEntity(entityId, components[0])\n }\n\n /**\n * Removes the specified component(s) from an entity\n * @example\n * ecs.remove(entityId, Position);\n */\n remove<T extends ComponentClass<any>[]>(entityId: number, ...components: T) {\n for (const component of components) {\n this.removeByKey(entityId, component.name)\n }\n }\n\n /**\n * Removes the specified component from an entity\n * @throwsError {@link ComponentNotRegistered} when the specified component is not registered\n * @example\n * ecs.removeByKey(entityId, \"Position\");\n */\n removeByKey(entityId: number, componentName: string) {\n // get the entity map\n const entityMap = this.components.get(componentName);\n\n // ensure the map is defined\n if (entityMap === undefined) throw new ComponentNotRegistered(componentName);\n\n // get the entity\n const entity = entityMap.get(entityId);\n if (entity === undefined) return false;\n\n // remove the entity from the entity map\n return entityMap.delete(entityId);\n }\n\n /**\n * Deletes all components from an entity\n * @example\n * const destroyedCount = ecs.destroyEntity(entityId1)\n * \n * // or multiple\n * const destroyedCount = ecs.destroyEntity(entityId1, entityId2)\n */\n destroyEntity(...entityIds: number[]): number {\n let deletedCount = 0;\n for (let index = 0; index < entityIds.length; index++) {\n const entityId = entityIds[index];\n for (const map of this.components.values()) {\n if (map.has(entityId)) {\n map.delete(entityId);\n deletedCount++;\n }\n }\n }\n return deletedCount;\n }\n\n // TODO create id generator\n /**\n * Creates a new entity id for the EntityMap\n * @example\n * const newEntityId = ecs.getNextId()\n * ecs.set(newEntityId, new Player())\n */\n getNextId(): number {\n this.nextId++;\n return this.nextId;\n }\n\n /**\n * Clears all registered components\n */\n clear() {\n this.components.clear();\n return this;\n }\n\n /**\n * Clears all component data\n */\n clearComponents() {\n this.components.forEach(x => x.clear())\n return this;\n }\n\n /**\n * Iterates over each component value that is related to the key component\n * @throwsError {@link ComponentNotRegistered} when any of specified component(s) are not registered\n * @example\n * // iterate each component value that is related to the Player entity\n * const iterator = ecs.iterator(Player, Position)\n * \n * for(const [playerId, player, position] of iterator) { }\n * \n * // you can also declare the type of iterator before it's assigned\n * let iterator: IComponentIterator<[Player, Position]>\n * \n * // then with late bound assignment (keeping the iterator intellisense)\n * iterator = ecs.iterator(Player, Position)\n * \n * for(const [playerId, player, position] of iterator) {\n * const moving = player.isMoving\n * }\n */\n iterator<K extends ComponentClass<any>, T extends ComponentClass<any>[]>(\n keyComponent: K,\n ...components: T\n ): ComponentIterator<K, T>\n iterator(keyComponent: ComponentClass<any>, ...components: ComponentClass<any>[]) {\n return new ComponentIterator(this, keyComponent, ...components) as any;\n }\n\n /**\n * Prints all component maps in a tabular format to the console\n */\n printTable() {\n this.components.forEach(map => console.table(map.toTable(true)));\n return this;\n }\n\n /**\n * Prints all component data for the specified entity id in a tabular format to the console\n */\n printEntity(entityId: number) {\n for (const map of this.components.values()) {\n if (map.has(entityId) === false) continue;\n\n const data = map.get(entityId);\n const columns = {\n name: data.constructor.name,\n ...data\n };\n console.table({ [entityId]: columns });\n }\n\n return this;\n }\n\n /**\n * Parse's the JSON and returns an EntityMap object\n * @example\n * const json = JSON.stringfy(ecs);\n * const restoredMap = ecs.parse(json);\n */\n static parse(json: string): EntityMap {\n const restored = JSON.parse(json, function (key: string, value: any) {\n if (value.hasOwnProperty('components')) {\n Reflect.setPrototypeOf(value, EntityMap.prototype);\n return value;\n }\n if (value.hasOwnProperty(ComponentMapKey)) return new ComponentMap(value.iterable);\n if (value.hasOwnProperty(ComponentClassesMapKey)) return new ComponentClassesMap(value.iterable);\n return this[key];\n });\n return restored;\n }\n\n /**\n * A tracing method used for debugging.\n * Intercepts all functions specified and logs each call to the console.\n * @param {Array} funcFilter A list of function names you want to intercept. If no function names are specified then will log all functions called\n * @return {EntityMap} A new entity map with tracing enabled\n */\n static createWithTracing(funcFilter: any) {\n const traceHandler = {\n get(target: any, propKey: string) {\n const targetValue = target[propKey]\n\n if (typeof targetValue === 'function' && (funcFilter.length === 0 || funcFilter.includes(propKey))) {\n return function (this: any, ...args: any[]) {\n console.groupCollapsed('ecs trace', propKey, args);\n console.trace();\n console.groupEnd();\n return targetValue.apply(this, args);\n }\n }\n\n return targetValue;\n }\n }\n\n return new Proxy(new EntityMap(), traceHandler)\n }\n\n}", "/*\n ecsjs is an entity component system library for JavaScript\n Copyright (C) 2014 Peter Flannery\n\n This program is free software: you can redistribute it and/or modify\n it under the terms of the GNU Affero General Public License as\n published by the Free Software Foundation, either version 3 of the\n License, or (at your option) any later version.\n\n This program is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Affero General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License\n along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\n/**\n * An entity component system library for JavaScript\n * @showCategories\n * @module ecsjs\n */\nimport { EntityMap } from './entity-map.js'\nexport { ComponentClassesMap, ComponentMap } from './component-map.js'\nexport { EntityMap } from './entity-map.js'\nexport type { ComponentNotRegistered, ComponentTypeKeyMissing } from './errors.js'\nexport { ComponentIterator } from './iterators.js'\nexport type { ComponentClass, IComponentIterator } from './types.js'\n\n/**\n * Global instance of an {@link EntityMap}\n * \n * See the [cheat sheet](https://gitlab.com/ecsjs/ecs/-/blob/master/docs/cheat-sheet.md) for more examples\n * @category Constants\n * @example\n * \n * // register component(s)\n * ecs.register(Player, Position)\n * \n * // create an entity\n * const [player, position] = ecs.set(ecs.getNextId(), new Player(), new Position(10, 40))\n */\nexport const ecs = new EntityMap()\n\nif (typeof window !== 'undefined') {\n // @ts-ignore: exports to window\n window.ecs = ecs\n} else if (typeof module !== 'undefined' && module !== null) {\n // exports to nodejs\n module.exports = { ecs };\n}"],
5
+ "mappings": "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",
6
6
  "names": ["ComponentMapKey", "ComponentClassesMapKey", "ComponentMap", "ComponentMapKey", "excludeKeys", "table", "key", "value", "entity", "meta", "ComponentClassesMap", "ComponentClassesMapKey", "ComponentTypeKeyMissing", "ComponentNotRegistered", "componentName", "ComponentIterator", "ecs", "key", "components", "x", "entry", "value", "done", "entityId", "entityValue", "results", "EntityMap", "_EntityMap", "ComponentClassesMap", "componentClasses", "componentClass", "componentName", "ComponentTypeKeyMissing", "componentDataMap", "ComponentMap", "component", "map", "ComponentNotRegistered", "keyComponent", "components", "entityId", "x", "value", "index", "componentData", "entityMap", "entityIds", "deletedCount", "ComponentIterator", "data", "columns", "json", "key", "ComponentMapKey", "ComponentClassesMapKey", "funcFilter", "traceHandler", "target", "propKey", "targetValue", "args", "ecs", "EntityMap"]
7
7
  }
@@ -41,9 +41,17 @@ export declare class EntityMap {
41
41
  * Gets the first entity entry for a component class
42
42
  * @throwsError {@link ComponentNotRegistered} when the specified component is not registered
43
43
  * @example
44
+ * // return the first entry
44
45
  * const [entityId, player] = ecs.firstEntry(Player) ?? []
46
+ *
47
+ * // or return multiple related components in addition to the first entry
48
+ * const [entityId, player, position, direction] = ecs.firstEntry(
49
+ * Player,
50
+ * Position,
51
+ * Direction
52
+ * )
45
53
  */
46
- firstEntry<TComponent>(component: ComponentClass<TComponent>): [entityId: number, value: TComponent] | undefined;
54
+ firstEntry<TKey extends ComponentClass<any>, T extends ComponentClass<any>[]>(keyComponent: TKey, ...components: T): ComponentInstances<[ComponentClass<number>, TKey, ...T]> | undefined;
47
55
  /**
48
56
  * Gets the first entity id for a component class
49
57
  * and optionally any related component data
@@ -1 +1 @@
1
- {"version":3,"file":"entity-map.d.ts","sourceRoot":"","sources":["../../../src/entity-map.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"entity-map.d.ts","sourceRoot":"","sources":["../../../src/entity-map.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "title": "ECS JS",
3
3
  "name": "ecsjs",
4
- "version": "1.2.0-beta.1",
4
+ "version": "1.2.0",
5
5
  "description": "An entity component system library for JavaScript",
6
6
  "author": "2013+ pflannery (https://gitlab.com/pflannery)",
7
7
  "license": "GNU GPL v3",
@@ -38,18 +38,18 @@
38
38
  ],
39
39
  "devDependencies": {
40
40
  "@types/mocha": "10.0.10",
41
- "@types/node": "20.17.24",
41
+ "@types/node": "20.17.30",
42
42
  "@types/source-map-support": "0.5.10",
43
43
  "c8": "10.1.3",
44
- "esbuild": "0.25.1",
44
+ "esbuild": "0.25.2",
45
45
  "js-build-tasks": "1.0.0-rc.18",
46
46
  "mocha": "11.1.0",
47
47
  "mocha-ui-esm": "1.0.0-beta.14",
48
48
  "mochaccino": "1.2.0",
49
49
  "rimraf": "6.0.1",
50
50
  "source-map-support": "0.5.21",
51
- "typedoc": "0.28.1",
52
- "typescript": "5.8.2"
51
+ "typedoc": "0.28.2",
52
+ "typescript": "5.8.3"
53
53
  },
54
54
  "scripts": {
55
55
  "compile": "task",
package/src/entity-map.ts CHANGED
@@ -86,10 +86,24 @@ export class EntityMap {
86
86
  * Gets the first entity entry for a component class
87
87
  * @throwsError {@link ComponentNotRegistered} when the specified component is not registered
88
88
  * @example
89
+ * // return the first entry
89
90
  * const [entityId, player] = ecs.firstEntry(Player) ?? []
91
+ *
92
+ * // or return multiple related components in addition to the first entry
93
+ * const [entityId, player, position, direction] = ecs.firstEntry(
94
+ * Player,
95
+ * Position,
96
+ * Direction
97
+ * )
90
98
  */
91
- firstEntry<TComponent>(component: ComponentClass<TComponent>) {
92
- return this.getMap(component)?.firstEntry();
99
+ firstEntry<TKey extends ComponentClass<any>, T extends ComponentClass<any>[]>(
100
+ keyComponent: TKey,
101
+ ...components: T
102
+ ): ComponentInstances<[ComponentClass<number>, TKey, ...T]> | undefined;
103
+ firstEntry(keyComponent: ComponentClass<any>, ...components: ComponentClass<any>[]) {
104
+ if (components.length === 0) return this.getMap(keyComponent)?.firstEntry()
105
+
106
+ return this.firstKey(keyComponent, keyComponent, ...components);
93
107
  }
94
108
 
95
109
  /**