UNPKG

@byloth/micro-ecs

Version:

A simple & lightweight ECS (Entity Component System) library for JavaScript and TypeScript. 🕹

1 lines 59.5 kB
{"version":3,"file":"micro-ecs.umd.cjs","sources":["../src/core.ts","../src/contexts/entity.ts","../src/exceptions.ts","../src/entity.ts","../src/component.ts","../src/system.ts","../src/resource.ts","../src/contexts/world.ts","../src/query-manager.ts","../src/world.ts","../src/index.ts"],"sourcesContent":["export default abstract class μObject\n{\n // eslint-disable-next-line camelcase\n private static __μECS_nextId__ = 0;\n\n public readonly id: number;\n\n public constructor()\n {\n this.id = (μObject[\"__μECS_nextId__\"] += 1);\n }\n}\n","import type { Constructor } from \"@byloth/core\";\n\nimport type Entity from \"../entity.js\";\nimport type Component from \"../component.js\";\n\nexport default class EntityContext\n{\n private get _entity(): Entity { return this._component.entity!; }\n\n private readonly _component: Component;\n\n private readonly _dependencies: Set<Component>;\n public get dependencies(): ReadonlySet<Component> { return this._dependencies; }\n\n private _onDispose?: (context: EntityContext) => void;\n\n public constructor(component: Component)\n {\n this._component = component;\n this._dependencies = new Set();\n }\n\n public useComponent<C extends Component>(type: Constructor<C>): C\n {\n const dependency = this._entity[\"_addDependency\"](this._component, type);\n this._dependencies.add(dependency);\n\n return dependency as C;\n }\n\n public releaseComponent<C extends Component>(type: Constructor<C>): void;\n public releaseComponent<C extends Component>(component: C): void;\n public releaseComponent<C extends Component>(component: Constructor<C> | C): void\n {\n const type = (typeof component === \"function\") ? component : component.constructor as Constructor<Component>;\n\n const dependency = this._entity[\"_removeDependency\"](this._component, type);\n this._dependencies.delete(dependency);\n }\n\n public dispose(): void\n {\n if (this._onDispose)\n {\n this._onDispose(this);\n this._onDispose = undefined;\n }\n\n this._dependencies.clear();\n }\n}\n","import { ReferenceException, RuntimeException } from \"@byloth/core\";\n\nexport class AttachmentException extends RuntimeException\n{\n public constructor(message: string, cause?: unknown, name = \"AttachmentException\")\n {\n super(message, cause, name);\n }\n\n public override readonly [Symbol.toStringTag]: string = \"AttachmentException\";\n}\n\nexport class DependencyException extends ReferenceException\n{\n public constructor(message: string, cause?: unknown, name = \"DependencyException\")\n {\n super(message, cause, name);\n }\n\n public override readonly [Symbol.toStringTag]: string = \"DependencyException\";\n}\n","import { ReferenceException, RuntimeException } from \"@byloth/core\";\nimport type { Constructor } from \"@byloth/core\";\n\nimport μObject from \"./core.js\";\nimport type Component from \"./component.js\";\nimport EntityContext from \"./contexts/entity.js\";\nimport { AttachmentException, DependencyException } from \"./exceptions.js\";\nimport type World from \"./world.js\";\n\nexport default class Entity<W extends World = World> extends μObject\n{\n private _isEnabled: boolean;\n public get isEnabled(): boolean { return this._isEnabled; }\n\n private readonly _components: Map<Constructor<Component>, Component>;\n public get components(): ReadonlyMap<Constructor<Component>, Component> { return this._components; }\n\n private _world: W | null;\n public get world(): W | null { return this._world; }\n\n private readonly _contexts: Map<Component, EntityContext>;\n private readonly _dependencies: Map<Component, Set<Component>>;\n\n private _onContextDispose = (context: EntityContext): void =>\n {\n const component = context[\"_component\"];\n\n for (const dependency of context.dependencies)\n {\n const dependants = this._dependencies.get(dependency)!;\n dependants.delete(component);\n\n if (dependants.size === 0) { this._dependencies.delete(dependency); }\n }\n\n this._contexts.delete(component);\n };\n\n public constructor(enabled = true)\n {\n super();\n\n this._isEnabled = enabled;\n\n this._components = new Map();\n\n this._world = null;\n\n this._contexts = new Map();\n this._dependencies = new Map();\n }\n\n private _addDependency(component: Component, type: Constructor<Component>): Component\n {\n const dependency = this._components.get(type);\n if (!(dependency)) { throw new DependencyException(\"The dependency doesn't exist in the entity.\"); }\n\n const dependants = this._dependencies.get(dependency);\n if (dependants)\n {\n if (dependants.has(component))\n {\n throw new DependencyException(\"The dependant already depends on this component.\");\n }\n\n dependants.add(component);\n }\n else { this._dependencies.set(dependency, new Set([component])); }\n\n return dependency;\n }\n private _removeDependency(component: Component, type: Constructor<Component>): Component\n {\n const dependency = this._components.get(type)!;\n const dependants = this._dependencies.get(dependency);\n if (!(dependants?.delete(component)))\n {\n throw new DependencyException(\"The dependant doesn't depend on this component.\");\n }\n\n if (dependants.size === 0) { this._dependencies.delete(dependency); }\n\n return dependency;\n }\n\n private _enableComponent(component: Component): void\n {\n if (!(this._isEnabled)) { return; }\n\n this._world?.[\"_enableEntityComponent\"](this, component);\n }\n private _disableComponent(component: Component): void\n {\n if (!(this._isEnabled)) { return; }\n\n this._world?.[\"_disableEntityComponent\"](this, component);\n }\n\n public addComponent<C extends Component>(component: C): C\n {\n const type = component.constructor as Constructor<Component>;\n if (this._components.has(type)) { throw new ReferenceException(\"The component already exists in the entity.\"); }\n\n try\n {\n component.onAttach(this);\n }\n catch (error)\n {\n throw new AttachmentException(\"It wasn't possible to attach this component to the entity.\", error);\n }\n\n this._components.set(type, component);\n\n if (component.isEnabled) { this._enableComponent(component); }\n return component;\n }\n\n public getComponent<C extends Component>(type: Constructor<C>): C\n {\n const component = this._components.get(type) as C | undefined;\n if (!(component)) { throw new ReferenceException(\"The component doesn't exist in the entity.\"); }\n\n return component;\n }\n public hasComponent(type: Constructor<Component>): boolean\n {\n return this._components.has(type);\n }\n\n public removeComponent<C extends Component>(type: Constructor<C>): C;\n public removeComponent<C extends Component>(component: C): C;\n public removeComponent<C extends Component>(component: Constructor<C> | C): C\n {\n const type = (typeof component === \"function\") ? component : component.constructor as Constructor<Component>;\n\n const _component = this._components.get(type) as C | undefined;\n if (!(_component)) { throw new ReferenceException(\"The component doesn't exist in the entity.\"); }\n\n if (this._dependencies.has(_component))\n {\n throw new DependencyException(\n \"The component has dependants and cannot be removed. Remove them first.\"\n );\n }\n\n const context = this._contexts.get(_component);\n if (context)\n {\n try\n {\n context.dispose();\n }\n catch (error)\n {\n // eslint-disable-next-line no-console\n console.warn(\"An error occurred while disposing the context of the component.\\n\\nSuppressed\", error);\n }\n\n this._contexts.delete(_component);\n }\n\n if (_component.isEnabled) { this._disableComponent(_component); }\n this._components.delete(_component.constructor as Constructor<Component>);\n\n try\n {\n _component.onDetach();\n }\n catch (error)\n {\n // eslint-disable-next-line no-console\n console.warn(\"An error occurred while detaching this component from the entity.\\n\\nSuppressed\", error);\n }\n\n return _component;\n }\n\n public getContext(component: Component): EntityContext\n {\n let context = this._contexts.get(component);\n if (context) { return context; }\n\n context = new EntityContext(component);\n context[\"_onDispose\"] = this._onContextDispose;\n\n this._contexts.set(component, context);\n\n return context;\n }\n\n public enable(): void\n {\n if (this._isEnabled) { throw new RuntimeException(\"The entity is already enabled.\"); }\n this._isEnabled = true;\n\n this._world?.[\"_enableEntity\"](this);\n }\n public disable(): void\n {\n if (!(this._isEnabled)) { throw new RuntimeException(\"The entity is already disabled.\"); }\n this._isEnabled = false;\n\n this._world?.[\"_disableEntity\"](this);\n }\n\n public onAttach(world: W): void\n {\n if (this._world) { throw new ReferenceException(\"The entity is already attached to a world.\"); }\n this._world = world;\n }\n public onDetach(): void\n {\n if (!(this._world)) { throw new ReferenceException(\"The entity isn't attached to any world.\"); }\n this._world = null;\n }\n\n public dispose(): void\n {\n if (this._world)\n {\n throw new RuntimeException(\"The entity must be detached from the world before being disposed.\");\n }\n\n try\n {\n for (const component of this._components.values())\n {\n component.onDetach();\n component.dispose();\n }\n }\n catch (error)\n {\n // eslint-disable-next-line no-console\n console.warn(\"An error occurred while disposing components of the entity.\\n\\nSuppressed\", error);\n }\n\n this._components.clear();\n\n try\n {\n for (const context of this._contexts.values())\n {\n context.dispose();\n }\n }\n catch (error)\n {\n // eslint-disable-next-line no-console\n console.warn(\"An error occurred while disposing contexts of the entity.\\n\\nSuppressed\", error);\n }\n\n this._contexts.clear();\n this._dependencies.clear();\n }\n}\n","import { ReferenceException, RuntimeException } from \"@byloth/core\";\n\nimport μObject from \"./core.js\";\nimport type Entity from \"./entity.js\";\n\nexport default class Component<E extends Entity = Entity> extends μObject\n{\n private _isEnabled: boolean;\n public get isEnabled(): boolean { return this._isEnabled; }\n\n private _entity: E | null;\n public get entity(): E | null { return this._entity; }\n\n public constructor(enabled = true)\n {\n super();\n\n this._isEnabled = enabled;\n\n this._entity = null;\n }\n\n public enable(): void\n {\n if (this._isEnabled) { throw new RuntimeException(\"The component is already enabled.\"); }\n this._isEnabled = true;\n\n this._entity?.[\"_enableComponent\"](this);\n }\n public disable(): void\n {\n if (!(this._isEnabled)) { throw new RuntimeException(\"The component is already disabled.\"); }\n this._isEnabled = false;\n\n this._entity?.[\"_disableComponent\"](this);\n }\n\n public onAttach(entity: E): void\n {\n if (this._entity) { throw new ReferenceException(\"The component is already attached to an entity.\"); }\n this._entity = entity;\n }\n public onDetach(): void\n {\n if (!(this._entity)) { throw new ReferenceException(\"The component isn't attached to any entity.\"); }\n this._entity = null;\n }\n\n public dispose(): void\n {\n if (this._entity)\n {\n throw new RuntimeException(\"The component must be detached from the entity before disposing it.\");\n }\n }\n}\n","import { ReferenceException, RuntimeException } from \"@byloth/core\";\n\nimport μObject from \"./core.js\";\nimport type World from \"./world.js\";\n\nexport default class System<W extends World = World> extends μObject\n{\n public static Sort(a: System, b: System): number\n {\n return a.priority - b.priority;\n }\n\n public readonly priority: number;\n\n private _isEnabled: boolean;\n public get isEnabled(): boolean { return this._isEnabled; }\n\n private _world: W | null;\n public get world(): W | null { return this._world; }\n\n public constructor(priority = 0, enabled = true)\n {\n super();\n\n this.priority = priority;\n\n this._isEnabled = enabled;\n this._world = null;\n }\n\n public enable(): void\n {\n if (this._isEnabled) { throw new RuntimeException(\"The system is already enabled.\"); }\n this._isEnabled = true;\n\n this._world?.[\"_enableSystem\"](this);\n }\n public disable(): void\n {\n if (!(this._isEnabled)) { throw new RuntimeException(\"The system is already disabled.\"); }\n this._isEnabled = false;\n\n this._world?.[\"_disableSystem\"](this);\n }\n\n public onAttach(world: W): void\n {\n if (this._world) { throw new ReferenceException(\"The system is already attached to a world.\"); }\n this._world = world;\n }\n public onDetach(): void\n {\n if (!(this._world)) { throw new ReferenceException(\"The system isn't attached to any world.\"); }\n this._world = null;\n }\n\n public update(deltaTime: number): void { /* ... */ }\n\n public dispose(): void\n {\n if (this._world)\n {\n throw new RuntimeException(\"The system must be detached from the world before disposing it.\");\n }\n }\n}\n","import { ReferenceException, RuntimeException } from \"@byloth/core\";\n\nimport μObject from \"./core.js\";\nimport type World from \"./world.js\";\n\nexport default class Resource<W extends World = World> extends μObject\n{\n private _world: W | null;\n public get world(): W | null { return this._world; }\n\n public constructor()\n {\n super();\n\n this._world = null;\n }\n\n public onAttach(world: W): void\n {\n if (this._world) { throw new ReferenceException(\"The resource is already attached to a world.\"); }\n this._world = world;\n }\n public onDetach(): void\n {\n if (!(this._world)) { throw new ReferenceException(\"The resource isn't attached to any world.\"); }\n this._world = null;\n }\n\n public dispose(): void\n {\n if (this._world)\n {\n throw new RuntimeException(\"The resource must be detached from the world before disposing it.\");\n }\n }\n}\n","import { TimedPromise } from \"@byloth/core\";\nimport type {\n Callback,\n CallbackMap,\n Constructor,\n InternalsEventsMap,\n PromiseResolver,\n Publisher,\n WildcardEventsMap\n\n} from \"@byloth/core\";\n\nimport type System from \"../system.js\";\nimport type Resource from \"../resource.js\";\nimport type World from \"../world.js\";\nimport type { SignalEventsMap } from \"../types.js\";\n\ntype P = SignalEventsMap & InternalsEventsMap;\ntype S = P & WildcardEventsMap;\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport default class WorldContext<T extends CallbackMap<T> = { }>\n{\n private get _world(): World { return this._system.world!; }\n\n private readonly _system: System;\n private readonly _publisher: Publisher;\n\n private readonly _dependencies: Set<Resource>;\n public get dependencies(): ReadonlySet<Resource> { return this._dependencies; }\n\n private _onDispose?: (context: WorldContext) => void;\n\n public constructor(system: System, publisher: Publisher)\n {\n this._system = system;\n this._publisher = publisher;\n\n this._dependencies = new Set();\n }\n\n public emit<K extends keyof T>(event: K & string, ...args: Parameters<T[K]>): ReturnType<T[K]>[];\n public emit<K extends keyof P>(event: K & string, ...args: Parameters<P[K]>): ReturnType<P[K]>[];\n public emit(event: string, ...args: unknown[]): unknown[]\n {\n return this._publisher.publish(event, ...args);\n }\n\n public on<K extends keyof T>(event: K & string, callback: T[K]): Callback;\n public on<K extends keyof S>(event: K & string, callback: S[K]): Callback;\n public on(event: string, callback: Callback<unknown[], unknown>): Callback\n {\n return this._publisher.subscribe(event, callback);\n }\n\n public once<K extends keyof T>(event: K & string, callback: T[K]): Callback;\n public once<K extends keyof S>(event: K & string, callback: S[K]): Callback;\n public once(event: string, callback: Callback<unknown[], unknown>): Callback\n {\n const _callback = (...args: unknown[]): unknown =>\n {\n this._publisher.unsubscribe(event, _callback);\n\n return callback(...args);\n };\n\n return this._publisher.subscribe(event, _callback);\n }\n public async wait<K extends keyof T>(event: K & string, timeout?: number): Promise<Parameters<T[K]>>;\n public async wait<K extends keyof S>(event: K & string, timeout?: number): Promise<Parameters<S[K]>>;\n public async wait(event: string, timeout?: number): Promise<unknown[]>\n {\n let _callback: Callback<unknown[]>;\n\n const executor = (resolve: PromiseResolver<unknown[]>) =>\n {\n _callback = (...args) => { resolve(args); };\n\n this._publisher.subscribe(event, _callback);\n };\n\n try\n {\n if (timeout) { return await new TimedPromise(executor, timeout); }\n\n return await new Promise(executor);\n }\n finally\n {\n this._publisher.unsubscribe(event, _callback!);\n }\n }\n\n public off<K extends keyof T>(event: K & string, callback: T[K]): void;\n public off<K extends keyof S>(event: K & string, callback: S[K]): void;\n public off(event: string, callback: Callback<unknown[], unknown>): void\n {\n this._publisher.unsubscribe(event, callback);\n }\n\n public useResource<R extends Resource>(type: Constructor<R>): R\n {\n const dependency = this._world[\"_addDependency\"](this._system, type);\n this._dependencies.add(dependency);\n\n return dependency as R;\n }\n\n public releaseResource<R extends Resource>(type: Constructor<R>): void;\n public releaseResource<R extends Resource>(resource: R): void;\n public releaseResource<R extends Resource>(resource: Constructor<R> | R): void\n {\n const type = (typeof resource === \"function\") ? resource : resource.constructor as Constructor<Resource>;\n\n const dependency = this._world[\"_removeDependency\"](this._system, type);\n this._dependencies.delete(dependency);\n }\n\n public dispose(): void\n {\n if (this._onDispose)\n {\n this._onDispose(this);\n this._onDispose = undefined;\n }\n\n this._dependencies.clear();\n this._publisher.clear();\n }\n}\n","import { KeyException, MapView, SmartIterator, ValueException } from \"@byloth/core\";\nimport type { CallbackMap, Constructor, ReadonlyMapView } from \"@byloth/core\";\n\nimport type Entity from \"./entity.js\";\nimport type Component from \"./component.js\";\nimport type { Instances } from \"./types.js\";\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport default class QueryManager<T extends CallbackMap<T> = { }>\n{\n private readonly _typeKeys: Map<Constructor<Component>, Set<string>>;\n private readonly _keyTypes: Map<string, Constructor<Component>[]>;\n\n private readonly _views: Map<string, MapView<Entity, Component[]>>;\n\n private readonly _entities: ReadonlyMap<number, Entity>;\n\n public constructor(entities: ReadonlyMap<number, Entity>)\n {\n this._typeKeys = new Map();\n this._keyTypes = new Map();\n\n this._views = new Map();\n\n this._entities = entities;\n }\n\n private _onEntityComponentEnable(entity: Entity, component: Component)\n {\n const type = component.constructor as Constructor<Component>;\n const keys = this._typeKeys.get(type);\n if (!(keys)) { return; }\n\n for (const key of keys)\n {\n const entities = this._views.get(key)!;\n if (entities.has(entity)) { continue; }\n\n const types = this._keyTypes.get(key);\n if (!(types)) { continue; }\n\n const components: Component[] = [];\n\n let found = true;\n let index = 0;\n do\n {\n const _type = types[index];\n const _component = entity.components.get(_type);\n if (!(_component) || !(_component.isEnabled))\n {\n found = false;\n\n break;\n }\n\n components.push(_component);\n\n index += 1;\n }\n while (index < types.length);\n\n if (found) { entities.set(entity, components); }\n }\n }\n private _onEntityComponentDisable(entity: Entity, component: Component)\n {\n const type = component.constructor as Constructor<Component>;\n const keys = this._typeKeys.get(type);\n if (!(keys)) { return; }\n\n for (const key of keys)\n {\n const view = this._views.get(key);\n if (view) { view.delete(entity); }\n }\n }\n\n private _addComponentKeys(types: Constructor<Component>[], key: string): void\n {\n for (const type of types)\n {\n const view = this._typeKeys.get(type);\n if (view) { view.add(key); }\n else { this._typeKeys.set(type, new Set([key])); }\n }\n }\n private _addKeyComponents(key: string, types: Constructor<Component>[]): void\n {\n if (this._keyTypes.has(key)) { throw new KeyException(`The key \"${key}\" is already registered.`); }\n this._keyTypes.set(key, types);\n }\n\n public pickOne<C extends Constructor<Component>, R = InstanceType<C>>(type: C): R | undefined\n {\n const view = this._views.get(type.name) as MapView<number, R> | undefined;\n if (view)\n {\n const { value } = view.values()\n .next();\n\n return value;\n }\n\n for (const entity of this._entities.values())\n {\n if (!(entity.isEnabled)) { continue; }\n\n const component = entity.components.get(type);\n if (component?.isEnabled) { return component as R; }\n }\n\n return undefined;\n }\n\n public findFirst<C extends Constructor<Component>[], R extends Instances<C> = Instances<C>>(\n ...types: C\n ): R | undefined\n {\n if (!(types.length)) { throw new ValueException(\"At least one type must be provided.\"); }\n\n const key = types.map((type) => type.name)\n .sort()\n .join(\",\");\n\n const view = this._views.get(key) as MapView<number, R> | undefined;\n if (view)\n {\n const { value } = view.values()\n .next();\n\n return value;\n }\n\n const components: Component[] = [];\n\n for (const entity of this._entities.values())\n {\n if (!(entity.isEnabled)) { continue; }\n\n let found = true;\n let index = 0;\n do\n {\n const type = types[index];\n const component = entity.components.get(type);\n if (!(component) || !(component.isEnabled))\n {\n found = false;\n\n break;\n }\n\n components.push(component);\n\n index += 1;\n }\n while (index < types.length);\n\n if (found) { return components as R; }\n\n components.length = 0;\n }\n\n return undefined;\n }\n public findAll<C extends Constructor<Component>[], R extends Instances<C> = Instances<C>>(\n ...types: C\n ): SmartIterator<R>\n {\n if (!(types.length)) { throw new ValueException(\"At least one type must be provided.\"); }\n\n const key = types.map((type) => type.name)\n .sort()\n .join(\",\");\n\n const view = this._views.get(key) as MapView<number, R> | undefined;\n if (view) { return new SmartIterator(view.values()); }\n\n return new SmartIterator(this._entities.values())\n .filter((entity) => (entity.isEnabled))\n .map((entity) =>\n {\n const components: Component[] = [];\n\n let found = true;\n let index = 0;\n do\n {\n const type = types[index];\n const component = entity.components.get(type);\n if (!(component) || !(component.isEnabled))\n {\n found = false;\n\n break;\n }\n\n components.push(component);\n\n index += 1;\n }\n while (index < types.length);\n\n if (found) { return components as R; }\n\n return undefined;\n })\n .filter<R>((component) => component !== undefined);\n }\n\n public getView<C extends Constructor<Component>[], R extends Instances<C> = Instances<C>>(\n ...types: C\n ): ReadonlyMapView<Entity, R>\n {\n if (!(types.length)) { throw new ValueException(\"At least one type must be provided.\"); }\n\n const key = types.map((type) => type.name)\n .sort()\n .join(\",\");\n\n let view = this._views.get(key) as MapView<Entity, R> | undefined;\n if (view) { return view; }\n\n view = new MapView<Entity, R>();\n for (const entity of this._entities.values())\n {\n if (!(entity.isEnabled)) { continue; }\n\n const components: Component[] = [];\n\n let found = true;\n let index = 0;\n do\n {\n const type = types[index];\n const component = entity.components.get(type);\n if (!(component) || !(component.isEnabled))\n {\n found = false;\n\n break;\n }\n\n components.push(component);\n\n index += 1;\n }\n while (index < types.length);\n\n if (found) { view.set(entity, components as R); }\n }\n\n this._views.set(key, view);\n\n this._addComponentKeys(types, key);\n this._addKeyComponents(key, types);\n\n return view;\n }\n\n public dispose(): void\n {\n for (const view of this._views.values()) { view.clear(); }\n this._views.clear();\n\n this._keyTypes.clear();\n this._typeKeys.clear();\n }\n}\n","import { Publisher, ReferenceException } from \"@byloth/core\";\nimport type { CallbackMap, Constructor, InternalsEventsMap, ReadonlyMapView, SmartIterator } from \"@byloth/core\";\n\nimport type Entity from \"./entity.js\";\nimport type Component from \"./component.js\";\nimport type System from \"./system.js\";\nimport type Resource from \"./resource.js\";\n\nimport WorldContext from \"./contexts/world.js\";\nimport { AttachmentException, DependencyException } from \"./exceptions.js\";\nimport QueryManager from \"./query-manager.js\";\nimport type { Instances, SignalEventsMap } from \"./types.js\";\n\ntype P = SignalEventsMap & InternalsEventsMap;\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport default class World<T extends CallbackMap<T> = { }>\n{\n private readonly _entities: Map<number, Entity>;\n public get entities(): ReadonlyMap<number, Entity> { return this._entities; }\n\n private readonly _resources: Map<Constructor<Resource>, Resource>;\n public get resources(): ReadonlyMap<Constructor<Resource>, Resource> { return this._resources; }\n\n private readonly _systems: Map<Constructor<System>, System>;\n private readonly _enabledSystems: System[];\n public get systems(): ReadonlyMap<Constructor<System>, System> { return this._systems; }\n\n private readonly _contexts: Map<System, WorldContext<CallbackMap>>;\n private readonly _dependencies: Map<Resource, Set<System>>;\n\n private readonly _queryManager: QueryManager;\n private readonly _publisher: Publisher;\n\n private _onContextDispose = (context: WorldContext): void =>\n {\n const system = context[\"_system\"];\n\n for (const dependency of context.dependencies)\n {\n const dependants = this._dependencies.get(dependency)!;\n dependants.delete(system);\n\n if (dependants.size === 0) { this._dependencies.delete(dependency); }\n }\n\n this._contexts.delete(system);\n };\n\n public constructor()\n {\n this._entities = new Map();\n this._resources = new Map();\n\n this._systems = new Map();\n this._enabledSystems = [];\n\n this._contexts = new Map();\n this._dependencies = new Map();\n\n this._queryManager = new QueryManager(this._entities);\n this._publisher = new Publisher();\n }\n\n private _enableEntity(entity: Entity): void\n {\n for (const component of entity.components.values())\n {\n if (!(component.isEnabled)) { continue; }\n\n this._enableEntityComponent(entity, component);\n }\n }\n private _disableEntity(entity: Entity): void\n {\n for (const component of entity.components.values())\n {\n if (!(component.isEnabled)) { continue; }\n\n this._disableEntityComponent(entity, component);\n }\n }\n\n private _enableEntityComponent(entity: Entity, component: Component): void\n {\n this._queryManager[\"_onEntityComponentEnable\"](entity, component);\n }\n private _disableEntityComponent(entity: Entity, component: Component): void\n {\n this._queryManager[\"_onEntityComponentDisable\"](entity, component);\n }\n\n private _enableSystem(system: System): void\n {\n let left = 0;\n let right = this._enabledSystems.length;\n\n while (left < right)\n {\n const middle = Math.floor((left + right) / 2);\n const other = this._enabledSystems[middle];\n\n if (system.priority < other.priority) { right = middle; }\n else { left = middle + 1; }\n }\n\n this._enabledSystems.splice(left, 0, system);\n }\n private _disableSystem(system: System): void\n {\n const index = this._enabledSystems.indexOf(system);\n if (index === -1) { return; }\n\n this._enabledSystems.splice(index, 1);\n }\n\n private _addDependency(system: System, type: Constructor<Resource>): Resource\n {\n const dependency = this._resources.get(type);\n if (!(dependency)) { throw new DependencyException(\"The dependency doesn't exist in the world.\"); }\n\n const dependants = this._dependencies.get(dependency);\n if (dependants)\n {\n if (dependants.has(system))\n {\n throw new DependencyException(\"The dependant already depends on this resource.\");\n }\n\n dependants.add(system);\n }\n else { this._dependencies.set(dependency, new Set([system])); }\n\n return dependency;\n }\n private _removeDependency(system: System, type: Constructor<Resource>): Resource\n {\n const dependency = this._resources.get(type)!;\n const dependants = this._dependencies.get(dependency);\n if (!(dependants?.delete(system)))\n {\n throw new DependencyException(\"The dependant doesn't depend on this resource.\");\n }\n\n if (dependants.size === 0) { this._dependencies.delete(dependency); }\n\n return dependency;\n }\n\n public addEntity<E extends Entity>(entity: E): E\n {\n if (this._entities.has(entity.id)) { throw new ReferenceException(\"The entity already exists in the world.\"); }\n\n try\n {\n entity.onAttach(this);\n }\n catch (error)\n {\n throw new AttachmentException(\"It wasn't possible to attach this entity to the world.\", error);\n }\n\n this._entities.set(entity.id, entity);\n\n if (entity.isEnabled) { this._enableEntity(entity); }\n return entity;\n }\n\n public removeEntity<E extends Entity = Entity>(entityId: number): E;\n public removeEntity<E extends Entity>(entity: E): E;\n public removeEntity<E extends Entity>(entity: number | E): E\n {\n const entityId = (typeof entity === \"number\") ? entity : entity.id;\n\n const _entity = this._entities.get(entityId) as E | undefined;\n if (!(_entity)) { throw new ReferenceException(\"The entity doesn't exist in the world.\"); }\n\n if (_entity.isEnabled) { this._disableEntity(_entity); }\n this._entities.delete(_entity.id);\n\n try\n {\n _entity.onDetach();\n }\n catch (error)\n {\n // eslint-disable-next-line no-console\n console.warn(\"An error occurred while detaching this entity from the world.\\n\\nSuppressed\", error);\n }\n\n return _entity;\n }\n\n public getFirstComponent<C extends Constructor<Component>, R extends InstanceType<C> = InstanceType<C>>(\n type: C\n ): R | undefined\n {\n return this._queryManager.pickOne<C, R>(type);\n }\n public getFirstComponents<C extends Constructor<Component>[], R extends Instances<C> = Instances<C>>(\n ...types: C\n ): R | undefined\n {\n return this._queryManager.findFirst<C, R>(...types);\n }\n\n public findAllComponents<C extends Constructor<Component>[], R extends Instances<C> = Instances<C>>(\n ...types: C\n ): SmartIterator<R>\n {\n return this._queryManager.findAll<C, R>(...types);\n }\n\n public getComponentView<C extends Constructor<Component>[], R extends Instances<C> = Instances<C>>(\n ...types: C\n ): ReadonlyMapView<Entity, R>\n {\n return this._queryManager.getView<C, R>(...types);\n }\n\n public addResource<R extends Resource>(resource: R): R\n {\n const type = resource.constructor as Constructor<Resource>;\n if (this._resources.has(type)) { throw new ReferenceException(\"The resource already exists in the world.\"); }\n\n try\n {\n resource.onAttach(this);\n }\n catch (error)\n {\n throw new AttachmentException(\"It wasn't possible to attach this resource to the world.\", error);\n }\n\n this._resources.set(type, resource);\n\n return resource;\n }\n\n public removeResource<R extends Resource>(type: Constructor<R>): R;\n public removeResource<R extends Resource>(resource: R): R;\n public removeResource<R extends Resource>(resource: Constructor<R> | R): R\n {\n const type = (typeof resource === \"function\") ? resource : resource.constructor as Constructor<Resource>;\n\n const _resource = this._resources.get(type) as R | undefined;\n if (!(_resource)) { throw new ReferenceException(\"The resource doesn't exist in the world.\"); }\n\n if (this._dependencies.has(_resource))\n {\n throw new DependencyException(\n \"The resource has dependants and cannot be removed. Remove them first.\"\n );\n }\n\n this._resources.delete(_resource.constructor as Constructor<Resource>);\n\n try\n {\n _resource.onDetach();\n }\n catch (error)\n {\n // eslint-disable-next-line no-console\n console.warn(\"An error occurred while detaching this resource from the world.\\n\\nSuppressed\", error);\n }\n\n return _resource;\n }\n\n public addSystem<S extends System>(system: S): S\n {\n const type = system.constructor as Constructor<System>;\n if (this._systems.has(type)) { throw new ReferenceException(\"The system already exists in the world.\"); }\n\n try\n {\n system.onAttach(this);\n }\n catch (error)\n {\n throw new AttachmentException(\"It wasn't possible to attach this system to the world.\", error);\n }\n\n this._systems.set(type, system);\n if (system.isEnabled) { this._enableSystem(system); }\n\n return system;\n }\n\n public removeSystem<S extends System>(type: Constructor<S>): S;\n public removeSystem<S extends System>(system: S): S;\n public removeSystem<S extends System>(system: Constructor<S> | S): S\n {\n const type = (typeof system === \"function\") ? system : system.constructor as Constructor<System>;\n\n const _system = this._systems.get(type) as S | undefined;\n if (!(_system)) { throw new ReferenceException(\"The system doesn't exist in the world.\"); }\n\n const context = this._contexts.get(_system);\n if (context)\n {\n try\n {\n context.dispose();\n }\n catch (error)\n {\n // eslint-disable-next-line no-console\n console.warn(\"An error occurred while disposing the context of the system.\\n\\nSuppressed\", error);\n }\n\n this._contexts.delete(_system);\n }\n\n if (_system.isEnabled) { this._disableSystem(_system); }\n this._systems.delete(_system.constructor as Constructor<System>);\n\n try\n {\n _system.onDetach();\n }\n catch (error)\n {\n // eslint-disable-next-line no-console\n console.warn(\"An error occurred while detaching this system from the world.\\n\\nSuppressed\", error);\n }\n\n return _system;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n public getContext<U extends CallbackMap<U> = { }>(system: System): WorldContext<U & T>\n {\n let context = this._contexts.get(system);\n if (context) { return context; }\n\n context = new WorldContext(system, this._publisher.createScope());\n context[\"_onDispose\"] = this._onContextDispose;\n\n this._contexts.set(system, context);\n\n return context;\n }\n\n public emit<K extends keyof T>(event: K & string, ...args: Parameters<T[K]>): ReturnType<T[K]>[];\n public emit<K extends keyof P>(event: K & string, ...args: Parameters<P[K]>): ReturnType<P[K]>[];\n public emit(event: string, ...args: unknown[]): unknown[]\n {\n return this._publisher.publish(event, ...args);\n }\n\n public update(deltaTime: number): void\n {\n for (const system of this._enabledSystems)\n {\n system.update(deltaTime);\n }\n }\n\n public dispose(): void\n {\n this._queryManager.dispose();\n\n try\n {\n for (const system of this._systems.values())\n {\n system.onDetach();\n system.dispose();\n }\n }\n catch (error)\n {\n // eslint-disable-next-line no-console\n console.warn(\"An error occurred while disposing systems of the world.\\n\\nSuppressed\", error);\n }\n\n this._systems.clear();\n this._enabledSystems.length = 0;\n\n try\n {\n for (const resource of this._resources.values())\n {\n resource.onDetach();\n resource.dispose();\n }\n }\n catch (error)\n {\n // eslint-disable-next-line no-console\n console.warn(\"An error occurred while disposing resources of the world.\\n\\nSuppressed\", error);\n }\n\n this._resources.clear();\n\n try\n {\n for (const entity of this._entities.values())\n {\n entity.onDetach();\n entity.dispose();\n }\n }\n catch (error)\n {\n // eslint-disable-next-line no-console\n console.warn(\"An error occurred while disposing entities of the world.\\n\\nSuppressed\", error);\n }\n\n this._entities.clear();\n\n try\n {\n for (const context of this._contexts.values())\n {\n context.dispose();\n }\n }\n catch (error)\n {\n // eslint-disable-next-line no-console\n console.warn(\"An error occurred while disposing contexts of the world.\\n\\nSuppressed\", error);\n }\n\n this._contexts.clear();\n this._publisher.clear();\n }\n}\n","export const VERSION = \"1.0.24\";\n\nimport Entity from \"./entity.js\";\nimport Component from \"./component.js\";\nimport System from \"./system.js\";\nimport Resource from \"./resource.js\";\nexport { Entity, Component, System, Resource };\n\nimport World from \"./world.js\";\nexport { World };\n\nexport { EntityContext, WorldContext } from \"./contexts/index.js\";\nexport { AttachmentException, DependencyException } from \"./exceptions.js\";\n\nimport QueryManager from \"./query-manager.js\";\nexport { QueryManager };\n\nexport type { Instances, SignalEventsMap } from \"./types.js\";\n"],"names":["μObject","EntityContext","component","type","dependency","AttachmentException","RuntimeException","message","cause","name","DependencyException","ReferenceException","Entity","context","dependants","enabled","error","_component","world","Component","entity","System","a","b","priority","deltaTime","Resource","WorldContext","system","publisher","event","args","callback","_callback","timeout","executor","resolve","TimedPromise","resource","QueryManager","entities","keys","key","types","components","found","index","_type","view","KeyException","value","ValueException","SmartIterator","MapView","World","Publisher","left","right","middle","other","entityId","_entity","_resource","_system","VERSION"],"mappings":"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