From 102200541de663db6484195657128eca228ac8dc Mon Sep 17 00:00:00 2001 From: rowan Date: Wed, 12 Mar 2025 11:55:58 -0500 Subject: [PATCH] initial commit --- index.html | 17 + public/css/style.css | 13 + public/vendor/bitecs/index.js | 852 ++++++++++++++++++++++++++ public/vendor/bitecs/index.js.map | 7 + public/vendor/bitecs/index.min.js | 2 + public/vendor/bitecs/index.min.js.map | 7 + src/components/index.js | 157 +++++ src/index.js | 58 ++ src/mixins/index.js | 4 + src/render/index.js | 110 ++++ src/render/webgl.js | 298 +++++++++ src/types.js | 15 + 12 files changed, 1540 insertions(+) create mode 100644 index.html create mode 100644 public/css/style.css create mode 100644 public/vendor/bitecs/index.js create mode 100644 public/vendor/bitecs/index.js.map create mode 100644 public/vendor/bitecs/index.min.js create mode 100644 public/vendor/bitecs/index.min.js.map create mode 100644 src/components/index.js create mode 100644 src/index.js create mode 100644 src/mixins/index.js create mode 100644 src/render/index.js create mode 100644 src/render/webgl.js create mode 100644 src/types.js diff --git a/index.html b/index.html new file mode 100644 index 0000000..1b36e00 --- /dev/null +++ b/index.html @@ -0,0 +1,17 @@ + + + + + + + HTML 5 Boilerplate + + + +
+ +
+ + + + diff --git a/public/css/style.css b/public/css/style.css new file mode 100644 index 0000000..38e155a --- /dev/null +++ b/public/css/style.css @@ -0,0 +1,13 @@ +html, body { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} + +main canvas { + aspect-ratio: 16 / 9; + width: min(100%, 100vh * 16 / 9); + height: 100%; +} + diff --git a/public/vendor/bitecs/index.js b/public/vendor/bitecs/index.js new file mode 100644 index 0000000..43c6e15 --- /dev/null +++ b/public/vendor/bitecs/index.js @@ -0,0 +1,852 @@ +// src/core/utils/defineHiddenProperty.ts +var defineHiddenProperty = (obj, key, value) => Object.defineProperty(obj, key, { + value, + enumerable: false, + writable: true, + configurable: true +}); + +// src/core/EntityIndex.ts +var getId = (index, id) => id & index.entityMask; +var getVersion = (index, id) => id >>> index.versionShift & (1 << index.versionBits) - 1; +var incrementVersion = (index, id) => { + const currentVersion = getVersion(index, id); + const newVersion = currentVersion + 1 & (1 << index.versionBits) - 1; + return id & index.entityMask | newVersion << index.versionShift; +}; +var withVersioning = (versionBits) => ({ + versioning: true, + versionBits +}); +var createEntityIndex = (options) => { + const config = options ? typeof options === "function" ? options() : options : { versioning: false, versionBits: 8 }; + const versionBits = config.versionBits ?? 8; + const versioning = config.versioning ?? false; + const entityBits = 32 - versionBits; + const entityMask = (1 << entityBits) - 1; + const versionShift = entityBits; + const versionMask = (1 << versionBits) - 1 << versionShift; + return { + aliveCount: 0, + dense: [], + sparse: [], + maxId: 0, + versioning, + versionBits, + entityMask, + versionShift, + versionMask + }; +}; +var addEntityId = (index) => { + if (index.aliveCount < index.dense.length) { + const recycledId = index.dense[index.aliveCount]; + const entityId = recycledId; + index.sparse[entityId] = index.aliveCount; + index.aliveCount++; + return recycledId; + } + const id = ++index.maxId; + index.dense.push(id); + index.sparse[id] = index.aliveCount; + index.aliveCount++; + return id; +}; +var removeEntityId = (index, id) => { + const denseIndex = index.sparse[id]; + if (denseIndex === void 0 || denseIndex >= index.aliveCount) { + return; + } + const lastIndex = index.aliveCount - 1; + const lastId = index.dense[lastIndex]; + index.sparse[lastId] = denseIndex; + index.dense[denseIndex] = lastId; + index.sparse[id] = lastIndex; + index.dense[lastIndex] = id; + if (index.versioning) { + const newId = incrementVersion(index, id); + index.dense[lastIndex] = newId; + } + index.aliveCount--; +}; +var isEntityIdAlive = (index, id) => { + const entityId = getId(index, id); + const denseIndex = index.sparse[entityId]; + return denseIndex !== void 0 && denseIndex < index.aliveCount && index.dense[denseIndex] === id; +}; + +// src/core/World.ts +var $internal = Symbol.for("bitecs_internal"); +var createBaseWorld = (context, entityIndex) => defineHiddenProperty(context || {}, $internal, { + entityIndex: entityIndex || createEntityIndex(), + entityMasks: [[]], + entityComponents: /* @__PURE__ */ new Map(), + bitflag: 1, + componentMap: /* @__PURE__ */ new Map(), + componentCount: 0, + queries: /* @__PURE__ */ new Set(), + queriesHashMap: /* @__PURE__ */ new Map(), + notQueries: /* @__PURE__ */ new Set(), + dirtyQueries: /* @__PURE__ */ new Set(), + entitiesWithRelations: /* @__PURE__ */ new Set() +}); +function createWorld(...args) { + let entityIndex; + let context; + args.forEach((arg) => { + if (typeof arg === "object" && "add" in arg && "remove" in arg) { + entityIndex = arg; + } else if (typeof arg === "object") { + context = arg; + } + }); + return createBaseWorld(context, entityIndex); +} +var resetWorld = (world) => { + const ctx = world[$internal]; + ctx.entityIndex = createEntityIndex(); + ctx.entityMasks = [[]]; + ctx.entityComponents = /* @__PURE__ */ new Map(); + ctx.bitflag = 1; + ctx.componentMap = /* @__PURE__ */ new Map(); + ctx.componentCount = 0; + ctx.queries = /* @__PURE__ */ new Set(); + ctx.queriesHashMap = /* @__PURE__ */ new Map(); + ctx.notQueries = /* @__PURE__ */ new Set(); + ctx.dirtyQueries = /* @__PURE__ */ new Set(); + ctx.entitiesWithRelations = /* @__PURE__ */ new Set(); + return world; +}; +var deleteWorld = (world) => { + delete world[$internal]; +}; +var getWorldComponents = (world) => Object.keys(world[$internal].componentMap); +var getAllEntities = (world) => Array.from(world[$internal].entityComponents.keys()); + +// src/core/utils/SparseSet.ts +var createSparseSet = () => { + const dense = []; + const sparse = []; + const has = (val) => dense[sparse[val]] === val; + const add = (val) => { + if (has(val)) return; + sparse[val] = dense.push(val) - 1; + }; + const remove = (val) => { + if (!has(val)) return; + const index = sparse[val]; + const swapped = dense.pop(); + if (swapped !== val) { + dense[index] = swapped; + sparse[swapped] = index; + } + }; + const reset = () => { + dense.length = 0; + sparse.length = 0; + }; + return { + add, + remove, + has, + sparse, + dense, + reset + }; +}; +var SharedArrayBufferOrArrayBuffer = typeof SharedArrayBuffer !== "undefined" ? SharedArrayBuffer : ArrayBuffer; +var createUint32SparseSet = (initialCapacity = 1e3) => { + const sparse = []; + let length = 0; + let dense = new Uint32Array(new SharedArrayBufferOrArrayBuffer(initialCapacity * 4)); + const has = (val) => val < sparse.length && sparse[val] < length && dense[sparse[val]] === val; + const add = (val) => { + if (has(val)) return; + if (length >= dense.length) { + const newDense = new Uint32Array(new SharedArrayBufferOrArrayBuffer(dense.length * 2 * 4)); + newDense.set(dense); + dense = newDense; + } + dense[length] = val; + sparse[val] = length; + length++; + }; + const remove = (val) => { + if (!has(val)) return; + length--; + const index = sparse[val]; + const swapped = dense[length]; + dense[index] = swapped; + sparse[swapped] = index; + }; + const reset = () => { + length = 0; + sparse.length = 0; + }; + return { + add, + remove, + has, + sparse, + get dense() { + return new Uint32Array(dense.buffer, 0, length); + }, + reset + }; +}; + +// src/core/utils/Observer.ts +var createObservable = () => { + const observers = /* @__PURE__ */ new Set(); + const subscribe = (observer) => { + observers.add(observer); + return () => { + observers.delete(observer); + }; + }; + const notify = (entity, ...args) => { + return Array.from(observers).reduce((acc, listener) => { + const result = listener(entity, ...args); + return result && typeof result === "object" ? { ...acc, ...result } : acc; + }, {}); + }; + return { + subscribe, + notify + }; +}; + +// src/core/Query.ts +var $opType = Symbol.for("bitecs-opType"); +var $opTerms = Symbol.for("bitecs-opTerms"); +var Or = (...components) => ({ + [$opType]: "Or", + [$opTerms]: components +}); +var And = (...components) => ({ + [$opType]: "And", + [$opTerms]: components +}); +var Not = (...components) => ({ + [$opType]: "Not", + [$opTerms]: components +}); +var Any = Or; +var All = And; +var None = Not; +var onAdd = (...terms) => ({ + [$opType]: "add", + [$opTerms]: terms +}); +var onRemove = (...terms) => ({ + [$opType]: "remove", + [$opTerms]: terms +}); +var onSet = (component) => ({ + [$opType]: "set", + [$opTerms]: [component] +}); +var onGet = (component) => ({ + [$opType]: "get", + [$opTerms]: [component] +}); +function observe(world, hook, callback) { + const ctx = world[$internal]; + const { [$opType]: type, [$opTerms]: components } = hook; + if (type === "add" || type === "remove") { + const hash = queryHash(world, components); + let queryData = ctx.queriesHashMap.get(hash); + if (!queryData) { + queryData = registerQuery(world, components); + } + const observableKey = type === "add" ? "addObservable" : "removeObservable"; + return queryData[observableKey].subscribe(callback); + } else if (type === "set" || type === "get") { + if (components.length !== 1) { + throw new Error("Set and Get hooks can only observe a single component"); + } + const component = components[0]; + let componentData = ctx.componentMap.get(component); + if (!componentData) { + componentData = registerComponent(world, component); + } + const observableKey = type === "set" ? "setObservable" : "getObservable"; + return componentData[observableKey].subscribe(callback); + } + throw new Error(`Invalid hook type: ${type}`); +} +var queryHash = (world, terms) => { + const ctx = world[$internal]; + const getComponentId = (component) => { + if (!ctx.componentMap.has(component)) { + registerComponent(world, component); + } + return ctx.componentMap.get(component).id; + }; + const termToString = (term) => { + if ($opType in term) { + const componentIds = term[$opTerms].map(getComponentId); + const sortedComponentIds = componentIds.sort((a, b) => a - b); + const sortedType = term[$opType].toLowerCase(); + return `${sortedType}(${sortedComponentIds.join(",")})`; + } else { + return getComponentId(term).toString(); + } + }; + return terms.map(termToString).sort().join("-"); +}; +var registerQuery = (world, terms, options = {}) => { + const ctx = world[$internal]; + const hash = queryHash(world, terms); + const components = []; + const notComponents = []; + const orComponents = []; + const processComponents = (comps, targetArray) => { + comps.forEach((comp) => { + if (!ctx.componentMap.has(comp)) registerComponent(world, comp); + targetArray.push(comp); + }); + }; + terms.forEach((term) => { + if ($opType in term) { + if (term[$opType] === "Not") { + processComponents(term[$opTerms], notComponents); + } else if (term[$opType] === "Or") { + processComponents(term[$opTerms], orComponents); + } + } else { + if (!ctx.componentMap.has(term)) registerComponent(world, term); + components.push(term); + } + }); + const mapComponents = (c) => ctx.componentMap.get(c); + const allComponents = components.concat(notComponents.flat()).concat(orComponents.flat()).map(mapComponents); + const sparseSet = options.buffered ? createUint32SparseSet() : createSparseSet(); + const toRemove = createSparseSet(); + const generations = allComponents.map((c) => c.generationId).reduce((a, v) => { + if (a.includes(v)) return a; + a.push(v); + return a; + }, []); + const reduceBitflags = (a, c) => { + if (!a[c.generationId]) a[c.generationId] = 0; + a[c.generationId] |= c.bitflag; + return a; + }; + const masks = components.map(mapComponents).reduce(reduceBitflags, {}); + const notMasks = notComponents.map(mapComponents).reduce(reduceBitflags, {}); + const orMasks = orComponents.map(mapComponents).reduce(reduceBitflags, {}); + const hasMasks = allComponents.reduce(reduceBitflags, {}); + const addObservable = createObservable(); + const removeObservable = createObservable(); + const query2 = Object.assign(sparseSet, { + components, + notComponents, + orComponents, + allComponents, + masks, + notMasks, + orMasks, + hasMasks, + generations, + toRemove, + addObservable, + removeObservable, + queues: {} + }); + ctx.queries.add(query2); + ctx.queriesHashMap.set(hash, query2); + allComponents.forEach((c) => { + c.queries.add(query2); + }); + if (notComponents.length) ctx.notQueries.add(query2); + const entityIndex = ctx.entityIndex; + for (let i = 0; i < entityIndex.aliveCount; i++) { + const eid = entityIndex.dense[i]; + if (hasComponent(world, eid, Prefab)) continue; + const match = queryCheckEntity(world, query2, eid); + if (match) { + queryAddEntity(query2, eid); + } + } + return query2; +}; +function innerQuery(world, terms, options = {}) { + const ctx = world[$internal]; + const hash = queryHash(world, terms); + let queryData = ctx.queriesHashMap.get(hash); + if (!queryData) { + queryData = registerQuery(world, terms, options); + } else if (options.buffered && !("buffer" in queryData.dense)) { + queryData = registerQuery(world, terms, { buffered: true }); + } + return queryData.dense; +} +function query(world, terms) { + commitRemovals(world); + return innerQuery(world, terms); +} +function queryCheckEntity(world, query2, eid) { + const ctx = world[$internal]; + const { masks, notMasks, orMasks, generations } = query2; + for (let i = 0; i < generations.length; i++) { + const generationId = generations[i]; + const qMask = masks[generationId]; + const qNotMask = notMasks[generationId]; + const qOrMask = orMasks[generationId]; + const eMask = ctx.entityMasks[generationId][eid]; + if (qNotMask && (eMask & qNotMask) !== 0) { + return false; + } + if (qMask && (eMask & qMask) !== qMask) { + return false; + } + if (qOrMask && (eMask & qOrMask) === 0) { + return false; + } + } + return true; +} +var queryAddEntity = (query2, eid) => { + query2.toRemove.remove(eid); + query2.addObservable.notify(eid); + query2.add(eid); +}; +var queryCommitRemovals = (query2) => { + for (let i = 0; i < query2.toRemove.dense.length; i++) { + const eid = query2.toRemove.dense[i]; + query2.remove(eid); + } + query2.toRemove.reset(); +}; +var commitRemovals = (world) => { + const ctx = world[$internal]; + if (!ctx.dirtyQueries.size) return; + ctx.dirtyQueries.forEach(queryCommitRemovals); + ctx.dirtyQueries.clear(); +}; +var queryRemoveEntity = (world, query2, eid) => { + const ctx = world[$internal]; + const has = query2.has(eid); + if (!has || query2.toRemove.has(eid)) return; + query2.toRemove.add(eid); + ctx.dirtyQueries.add(query2); + query2.removeObservable.notify(eid); +}; +var removeQuery = (world, terms) => { + const ctx = world[$internal]; + const hash = queryHash(world, terms); + const query2 = ctx.queriesHashMap.get(hash); + if (query2) { + ctx.queries.delete(query2); + ctx.queriesHashMap.delete(hash); + } +}; + +// src/core/Relation.ts +var $relation = Symbol.for("bitecs-relation"); +var $pairTarget = Symbol.for("bitecs-pairTarget"); +var $isPairComponent = Symbol.for("bitecs-isPairComponent"); +var $relationData = Symbol.for("bitecs-relationData"); +var createBaseRelation = () => { + const data = { + pairsMap: /* @__PURE__ */ new Map(), + initStore: void 0, + exclusiveRelation: false, + autoRemoveSubject: false, + onTargetRemoved: void 0 + }; + const relation = (target) => { + if (target === void 0) throw Error("Relation target is undefined"); + const normalizedTarget = target === "*" ? Wildcard : target; + if (!data.pairsMap.has(normalizedTarget)) { + const component = data.initStore ? data.initStore(target) : {}; + defineHiddenProperty(component, $relation, relation); + defineHiddenProperty(component, $pairTarget, normalizedTarget); + defineHiddenProperty(component, $isPairComponent, true); + data.pairsMap.set(normalizedTarget, component); + } + return data.pairsMap.get(normalizedTarget); + }; + defineHiddenProperty(relation, $relationData, data); + return relation; +}; +var withStore = (createStore) => (relation) => { + const ctx = relation[$relationData]; + ctx.initStore = createStore; + return relation; +}; +var makeExclusive = (relation) => { + const ctx = relation[$relationData]; + ctx.exclusiveRelation = true; + return relation; +}; +var withAutoRemoveSubject = (relation) => { + const ctx = relation[$relationData]; + ctx.autoRemoveSubject = true; + return relation; +}; +var withOnTargetRemoved = (onRemove2) => (relation) => { + const ctx = relation[$relationData]; + ctx.onTargetRemoved = onRemove2; + return relation; +}; +var Pair = (relation, target) => { + if (relation === void 0) throw Error("Relation is undefined"); + return relation(target); +}; +var getRelationTargets = (world, eid, relation) => { + const components = getEntityComponents(world, eid); + const targets = []; + for (const c of components) { + if (c[$relation] === relation && c[$pairTarget] !== Wildcard && !isRelation(c[$pairTarget])) { + targets.push(c[$pairTarget]); + } + } + return targets; +}; +function createRelation(...args) { + if (args.length === 1 && typeof args[0] === "object") { + const { store, exclusive, autoRemoveSubject, onTargetRemoved } = args[0]; + const modifiers = [ + store && withStore(store), + exclusive && makeExclusive, + autoRemoveSubject && withAutoRemoveSubject, + onTargetRemoved && withOnTargetRemoved(onTargetRemoved) + ].filter(Boolean); + return modifiers.reduce((acc, modifier) => modifier(acc), createBaseRelation()); + } else { + const modifiers = args; + return modifiers.reduce((acc, modifier) => modifier(acc), createBaseRelation()); + } +} +var $wildcard = Symbol.for("bitecs-wildcard"); +function createWildcardRelation() { + const relation = createBaseRelation(); + Object.defineProperty(relation, $wildcard, { + value: true, + enumerable: false, + writable: false, + configurable: false + }); + return relation; +} +function getWildcard() { + const GLOBAL_WILDCARD = Symbol.for("bitecs-global-wildcard"); + if (!globalThis[GLOBAL_WILDCARD]) { + globalThis[GLOBAL_WILDCARD] = createWildcardRelation(); + } + return globalThis[GLOBAL_WILDCARD]; +} +var Wildcard = getWildcard(); +function createIsARelation() { + return createBaseRelation(); +} +function getIsA() { + const GLOBAL_ISA = Symbol.for("bitecs-global-isa"); + if (!globalThis[GLOBAL_ISA]) { + globalThis[GLOBAL_ISA] = createIsARelation(); + } + return globalThis[GLOBAL_ISA]; +} +var IsA = getIsA(); +function isWildcard(relation) { + if (!relation) return false; + const symbols = Object.getOwnPropertySymbols(relation); + return symbols.includes($wildcard); +} +function isRelation(component) { + if (!component) return false; + const symbols = Object.getOwnPropertySymbols(component); + return symbols.includes($relationData); +} + +// src/core/Component.ts +var registerComponent = (world, component) => { + if (!component) { + throw new Error(`bitECS - Cannot register null or undefined component`); + } + const ctx = world[$internal]; + const queries = /* @__PURE__ */ new Set(); + const data = { + id: ctx.componentCount++, + generationId: ctx.entityMasks.length - 1, + bitflag: ctx.bitflag, + ref: component, + queries, + setObservable: createObservable(), + getObservable: createObservable() + }; + ctx.componentMap.set(component, data); + ctx.bitflag *= 2; + if (ctx.bitflag >= 2 ** 31) { + ctx.bitflag = 1; + ctx.entityMasks.push([]); + } + return data; +}; +var registerComponents = (world, components) => { + components.forEach((component) => registerComponent(world, component)); +}; +var hasComponent = (world, eid, component) => { + const ctx = world[$internal]; + const registeredComponent = ctx.componentMap.get(component); + if (!registeredComponent) return false; + const { generationId, bitflag } = registeredComponent; + const mask = ctx.entityMasks[generationId][eid]; + return (mask & bitflag) === bitflag; +}; +var getComponentData = (world, eid, component) => { + const ctx = world[$internal]; + const componentData = ctx.componentMap.get(component); + if (!componentData) { + return void 0; + } + if (!hasComponent(world, eid, component)) { + return void 0; + } + return componentData.getObservable.notify(eid); +}; +var set = (component, data) => ({ + component, + data +}); +var recursivelyInherit = (ctx, world, baseEid, inheritedEid, visited = /* @__PURE__ */ new Set()) => { + if (visited.has(inheritedEid)) return; + visited.add(inheritedEid); + addComponent(world, baseEid, IsA(inheritedEid)); + for (const component of getEntityComponents(world, inheritedEid)) { + if (component === Prefab) continue; + if (!hasComponent(world, baseEid, component)) { + addComponent(world, baseEid, component); + const componentData = ctx.componentMap.get(component); + if (componentData?.setObservable) { + const data = getComponentData(world, inheritedEid, component); + componentData.setObservable.notify(baseEid, data); + } + } + } + for (const parentEid of getRelationTargets(world, inheritedEid, IsA)) { + recursivelyInherit(ctx, world, baseEid, parentEid, visited); + } +}; +var addComponent = (world, eid, ...components) => { + if (!entityExists(world, eid)) { + throw new Error(`Cannot add component - entity ${eid} does not exist in the world.`); + } + const ctx = world[$internal]; + components.forEach((componentOrSet) => { + const component = "component" in componentOrSet ? componentOrSet.component : componentOrSet; + const data = "data" in componentOrSet ? componentOrSet.data : void 0; + if (!ctx.componentMap.has(component)) registerComponent(world, component); + const componentData = ctx.componentMap.get(component); + if (data !== void 0) { + componentData.setObservable.notify(eid, data); + } + if (hasComponent(world, eid, component)) return; + const { generationId, bitflag, queries } = componentData; + ctx.entityMasks[generationId][eid] |= bitflag; + if (!hasComponent(world, eid, Prefab)) { + queries.forEach((queryData) => { + queryData.toRemove.remove(eid); + const match = queryCheckEntity(world, queryData, eid); + if (match) queryAddEntity(queryData, eid); + else queryRemoveEntity(world, queryData, eid); + }); + } + ctx.entityComponents.get(eid).add(component); + if (component[$isPairComponent]) { + const relation = component[$relation]; + const target = component[$pairTarget]; + addComponent(world, eid, Pair(relation, Wildcard)); + addComponent(world, eid, Pair(Wildcard, target)); + if (typeof target === "number") { + addComponent(world, target, Pair(Wildcard, eid)); + addComponent(world, target, Pair(Wildcard, relation)); + ctx.entitiesWithRelations.add(target); + ctx.entitiesWithRelations.add(eid); + } + ctx.entitiesWithRelations.add(target); + const relationData = relation[$relationData]; + if (relationData.exclusiveRelation === true && target !== Wildcard) { + const oldTarget = getRelationTargets(world, eid, relation)[0]; + if (oldTarget !== void 0 && oldTarget !== null && oldTarget !== target) { + removeComponent(world, eid, relation(oldTarget)); + } + } + if (relation === IsA) { + const inheritedTargets = getRelationTargets(world, eid, IsA); + for (const inherited of inheritedTargets) { + recursivelyInherit(ctx, world, eid, inherited); + } + } + } + }); +}; +var addComponents = addComponent; +var removeComponent = (world, eid, ...components) => { + const ctx = world[$internal]; + if (!entityExists(world, eid)) { + throw new Error(`Cannot remove component - entity ${eid} does not exist in the world.`); + } + components.forEach((component) => { + if (!hasComponent(world, eid, component)) return; + const componentNode = ctx.componentMap.get(component); + const { generationId, bitflag, queries } = componentNode; + ctx.entityMasks[generationId][eid] &= ~bitflag; + queries.forEach((queryData) => { + queryData.toRemove.remove(eid); + const match = queryCheckEntity(world, queryData, eid); + if (match) queryAddEntity(queryData, eid); + else queryRemoveEntity(world, queryData, eid); + }); + ctx.entityComponents.get(eid).delete(component); + if (component[$isPairComponent]) { + const target = component[$pairTarget]; + removeComponent(world, eid, Pair(Wildcard, target)); + const relation = component[$relation]; + const otherTargets = getRelationTargets(world, eid, relation); + if (otherTargets.length === 0) { + removeComponent(world, eid, Pair(relation, Wildcard)); + } + } + }); +}; +var removeComponents = removeComponent; + +// src/core/Entity.ts +var Prefab = {}; +var addPrefab = (world) => { + const eid = addEntity(world); + addComponent(world, eid, Prefab); + return eid; +}; +var addEntity = (world) => { + const ctx = world[$internal]; + const eid = addEntityId(ctx.entityIndex); + ctx.notQueries.forEach((q) => { + const match = queryCheckEntity(world, q, eid); + if (match) queryAddEntity(q, eid); + }); + ctx.entityComponents.set(eid, /* @__PURE__ */ new Set()); + return eid; +}; +var removeEntity = (world, eid) => { + const ctx = world[$internal]; + if (!isEntityIdAlive(ctx.entityIndex, eid)) return; + const removalQueue = [eid]; + const processedEntities = /* @__PURE__ */ new Set(); + while (removalQueue.length > 0) { + const currentEid = removalQueue.shift(); + if (processedEntities.has(currentEid)) continue; + processedEntities.add(currentEid); + const componentRemovalQueue = []; + if (ctx.entitiesWithRelations.has(currentEid)) { + for (const subject of innerQuery(world, [Wildcard(currentEid)])) { + if (!entityExists(world, subject)) { + continue; + } + for (const component of ctx.entityComponents.get(subject)) { + if (!component[$isPairComponent]) { + continue; + } + const relation = component[$relation]; + const relationData = relation[$relationData]; + componentRemovalQueue.push(() => removeComponent(world, subject, Pair(Wildcard, currentEid))); + if (component[$pairTarget] === currentEid) { + componentRemovalQueue.push(() => removeComponent(world, subject, component)); + if (relationData.autoRemoveSubject) { + removalQueue.push(subject); + } + if (relationData.onTargetRemoved) { + componentRemovalQueue.push(() => relationData.onTargetRemoved(world, subject, currentEid)); + } + } + } + } + ctx.entitiesWithRelations.delete(currentEid); + } + for (const removeOperation of componentRemovalQueue) { + removeOperation(); + } + for (const eid2 of removalQueue) { + removeEntity(world, eid2); + } + for (const query2 of ctx.queries) { + queryRemoveEntity(world, query2, currentEid); + } + removeEntityId(ctx.entityIndex, currentEid); + ctx.entityComponents.delete(currentEid); + for (let i = 0; i < ctx.entityMasks.length; i++) { + ctx.entityMasks[i][currentEid] = 0; + } + } +}; +var getEntityComponents = (world, eid) => { + const ctx = world[$internal]; + if (eid === void 0) throw new Error(`getEntityComponents: entity id is undefined.`); + if (!isEntityIdAlive(ctx.entityIndex, eid)) + throw new Error(`getEntityComponents: entity ${eid} does not exist in the world.`); + return Array.from(ctx.entityComponents.get(eid)); +}; +var entityExists = (world, eid) => isEntityIdAlive(world[$internal].entityIndex, eid); + +// src/core/utils/pipe.ts +var pipe = (...functions) => { + return (...args) => functions.reduce((result, fn) => [fn(...result)], args)[0]; +}; +export { + $internal, + All, + And, + Any, + IsA, + None, + Not, + Or, + Pair, + Prefab, + Wildcard, + addComponent, + addComponents, + addEntity, + addPrefab, + commitRemovals, + createEntityIndex, + createRelation, + createWorld, + deleteWorld, + entityExists, + getAllEntities, + getComponentData, + getEntityComponents, + getId, + getRelationTargets, + getVersion, + getWorldComponents, + hasComponent, + innerQuery, + isRelation, + isWildcard, + observe, + onAdd, + onGet, + onRemove, + onSet, + pipe, + query, + registerComponent, + registerComponents, + registerQuery, + removeComponent, + removeComponents, + removeEntity, + removeQuery, + resetWorld, + set, + withAutoRemoveSubject, + withOnTargetRemoved, + withStore, + withVersioning +}; +//# sourceMappingURL=index.mjs.map diff --git a/public/vendor/bitecs/index.js.map b/public/vendor/bitecs/index.js.map new file mode 100644 index 0000000..331a995 --- /dev/null +++ b/public/vendor/bitecs/index.js.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "sources": ["../../src/core/utils/defineHiddenProperty.ts", "../../src/core/EntityIndex.ts", "../../src/core/World.ts", "../../src/core/utils/SparseSet.ts", "../../src/core/utils/Observer.ts", "../../src/core/Query.ts", "../../src/core/Relation.ts", "../../src/core/Component.ts", "../../src/core/Entity.ts", "../../src/core/utils/pipe.ts"], + "sourcesContent": ["export const defineHiddenProperty = (obj:any,key:any,value:any) => Object.defineProperty(obj, key, {\n value,\n enumerable: false,\n writable: true,\n configurable: true,\n})\n\nexport const defineHiddenProperties = (obj:any,kv:any) => {\n const descriptors = {\n enumerable: false,\n writable: true,\n configurable: true,\n }\n Object.defineProperties(obj, Reflect.ownKeys(kv).reduce((a,k) => Object.assign(a, {[k]: {value: kv[k], ...descriptors}}), {}))\n}", "/**\n * Represents the structure for managing entity IDs.\n */\nexport type EntityIndex = {\n /** The number of currently alive entities. */\n aliveCount: number\n /** Array of entity IDs, densely packed. */\n dense: number[]\n /** Sparse array mapping entity IDs to their index in the dense array. */\n sparse: number[]\n /** The highest entity ID that has been assigned. */\n maxId: number\n /** Flag indicating if versioning is enabled. */\n versioning: boolean\n /** Number of bits used for versioning. */\n versionBits: number\n /** Bit mask for entity ID. */\n entityMask: number\n /** Bit shift for version. */\n versionShift: number\n /** Bit mask for version. */\n versionMask: number\n}\n\n/**\n * Extracts the entity ID from a versioned entity ID by stripping off the version.\n * @param {EntityIndex} index - The EntityIndex containing the masks.\n * @param {number} id - The versioned entity ID.\n * @returns {number} The entity ID without the version.\n */\nexport const getId = (index: EntityIndex, id: number): number => id & index.entityMask;\n\n/**\n * Extracts the version from an entity ID.\n * @param {EntityIndex} index - The EntityIndex containing the masks and shifts.\n * @param {number} id - The entity ID.\n * @returns {number} The version.\n */\nexport const getVersion = (index: EntityIndex, id: number): number => \n (id >>> index.versionShift) & ((1 << index.versionBits) - 1);\n\n/**\n * Increments the version of an entity ID.\n * @param {EntityIndex} index - The EntityIndex containing the masks and shifts.\n * @param {number} id - The entity ID.\n * @returns {number} The new entity ID with incremented version.\n */\nexport const incrementVersion = (index: EntityIndex, id: number): number => {\n const currentVersion = getVersion(index, id);\n const newVersion = (currentVersion + 1) & ((1 << index.versionBits) - 1);\n return (id & index.entityMask) | (newVersion << index.versionShift);\n}\n\n/**\n * Creates configuration options for entity ID recycling with versioning.\n * @param {number} [versionBits] - Optional number of bits to use for version numbers. Defaults to 8 if not specified.\n * @returns {object} Configuration object with versioning enabled and specified version bits.\n */\nexport const withVersioning = (versionBits?: number) => ({\n versioning: true,\n versionBits\n})\n\n/**\n * Creates and initializes a new EntityIndex.\n * @param {object|function} [options] - Optional configuration object from withVersioning() or withVersioning function.\n * @param {boolean} options.versioning - Flag to enable versioning for recycled IDs.\n * @param {number} options.versionBits - Number of bits to use for versioning (default: 8).\n * @returns {EntityIndex} A new EntityIndex object.\n */\nexport const createEntityIndex = (options?: ReturnType | typeof withVersioning): EntityIndex => {\n const config = options \n ? typeof options === 'function' \n ? options()\n : options\n : { versioning: false, versionBits: 8 }\n\n const versionBits = config.versionBits ?? 8\n const versioning = config.versioning ?? false\n \n const entityBits = 32 - versionBits\n const entityMask = (1 << entityBits) - 1\n const versionShift = entityBits\n const versionMask = ((1 << versionBits) - 1) << versionShift\n\n return {\n aliveCount: 0,\n dense: [],\n sparse: [],\n maxId: 0,\n versioning,\n versionBits,\n entityMask,\n versionShift,\n versionMask\n }\n}\n\n/**\n * Adds a new entity ID to the index or recycles an existing one.\n * @param {EntityIndex} index - The EntityIndex to add to.\n * @returns {number} The new or recycled entity ID.\n */\nexport const addEntityId = (index: EntityIndex): number => {\n if (index.aliveCount < index.dense.length) {\n // Recycle id\n const recycledId = index.dense[index.aliveCount];\n const entityId = recycledId;\n index.sparse[entityId] = index.aliveCount;\n index.aliveCount++;\n return recycledId;\n }\n\n // Create new id\n const id = ++index.maxId;\n index.dense.push(id);\n index.sparse[id] = index.aliveCount;\n index.aliveCount++;\n\n return id;\n}\n\n/**\n * Removes an entity ID from the index.\n * @param {EntityIndex} index - The EntityIndex to remove from.\n * @param {number} id - The entity ID to remove.\n */\nexport const removeEntityId = (index: EntityIndex, id: number): void => {\n const denseIndex = index.sparse[id];\n if (denseIndex === undefined || denseIndex >= index.aliveCount) {\n // Entity is not alive or doesn't exist, nothing to be done\n return;\n }\n\n const lastIndex = index.aliveCount - 1;\n const lastId = index.dense[lastIndex];\n\n // Swap with the last element\n index.sparse[lastId] = denseIndex;\n index.dense[denseIndex] = lastId;\n\n // Update the removed entity's record\n index.sparse[id] = lastIndex; // Set to lastIndex instead of undefined\n index.dense[lastIndex] = id; // Keep the original id, don't strip version\n\n // Version the ID if enabled\n if (index.versioning) {\n const newId = incrementVersion(index, id);\n index.dense[lastIndex] = newId;\n }\n\n index.aliveCount--;\n}\n\n/**\n * Checks if an entity ID is currently alive in the index.\n * @param {EntityIndex} index - The EntityIndex to check.\n * @param {number} id - The entity ID to check.\n * @returns {boolean} True if the entity ID is alive, false otherwise.\n */\nexport const isEntityIdAlive = (index: EntityIndex, id: number): boolean => {\n const entityId = getId(index, id);\n const denseIndex = index.sparse[entityId];\n return denseIndex !== undefined && denseIndex < index.aliveCount && index.dense[denseIndex] === id;\n}\n", "import { defineHiddenProperty } from './utils/defineHiddenProperty'\nimport { createEntityIndex, EntityIndex } from './EntityIndex'\nimport { ComponentRef, ComponentData } from './Component'\nimport { Query } from './Query'\nimport { EntityId } from './Entity'\n\nexport const $internal = Symbol.for('bitecs_internal')\n\nexport type WorldContext = {\n entityIndex: EntityIndex\n entityMasks: number[][]\n entityComponents: Map>\n bitflag: number\n componentMap: Map\n componentCount: number\n queries: Set\n queriesHashMap: Map\n notQueries: Set\n dirtyQueries: Set\n entitiesWithRelations: Set\n}\n\nexport type InternalWorld = {\n [$internal]: WorldContext\n}\n\nexport type World = { [K in keyof T]: T[K] }\n\nconst createBaseWorld = (context?: T, entityIndex?: EntityIndex): World => \n defineHiddenProperty(context || {} as T, $internal, {\n entityIndex: entityIndex || createEntityIndex(),\n entityMasks: [[]],\n entityComponents: new Map(),\n bitflag: 1,\n componentMap: new Map(),\n componentCount: 0,\n queries: new Set(),\n queriesHashMap: new Map(),\n notQueries: new Set(),\n dirtyQueries: new Set(),\n entitiesWithRelations: new Set(),\n}) as World\n\n/**\n * Creates a new world with various configurations.\n * @template T\n * @param {...Array} args - EntityIndex, context object, or both.\n * @returns {World} The created world.\n */\n\n// TODO: middleware\n\nexport function createWorld(\n ...args: Array\n): World {\n let entityIndex: EntityIndex | undefined\n let context: T | undefined\n\n args.forEach(arg => {\n if (typeof arg === 'object' && 'add' in arg && 'remove' in arg) {\n entityIndex = arg as EntityIndex\n } else if (typeof arg === 'object') {\n context = arg as T\n }\n })\n\n return createBaseWorld(context, entityIndex)\n}\n\n/**\n * Resets a world.\n *\n * @param {World} world\n * @returns {object}\n */\nexport const resetWorld = (world: World) => {\n const ctx = (world as InternalWorld)[$internal]\n ctx.entityIndex = createEntityIndex()\n ctx.entityMasks = [[]]\n ctx.entityComponents = new Map()\n ctx.bitflag = 1\n ctx.componentMap = new Map()\n ctx.componentCount = 0\n ctx.queries = new Set()\n ctx.queriesHashMap = new Map()\n ctx.notQueries = new Set()\n ctx.dirtyQueries = new Set()\n ctx.entitiesWithRelations = new Set()\n return world\n}\n\n/**\n * Deletes a world by removing its internal data.\n *\n * @param {World} world - The world to be deleted.\n */\nexport const deleteWorld = (world: World) => {\n delete (world as any)[$internal];\n}\n\n/**\n * Returns all components registered to a world\n *\n * @param {World} world\n * @returns Array\n */\nexport const getWorldComponents = (world: World) =>\n Object.keys((world as InternalWorld)[$internal].componentMap)\n\n/**\n * Returns all existing entities in a world\n *\n * @param {World} world\n * @returns Array\n */\nexport const getAllEntities = (world: World): readonly EntityId[] => Array.from((world as InternalWorld)[$internal].entityComponents.keys())\n", "export type SparseSet = {\n add: (val: number) => void\n remove: (val: number) => void\n has: (val: number) => boolean\n sparse: number[]\n dense: number[] | Uint32Array\n reset: () => void\n}\n\nexport const createSparseSet = (): SparseSet => {\n\tconst dense: number[] = []\n\tconst sparse: number[] = []\n\n\tconst has = (val: number) => dense[sparse[val]] === val\n\n\tconst add = (val: number) => {\n\t\tif (has(val)) return\n\t\tsparse[val] = dense.push(val) - 1\n\t}\n\n\tconst remove = (val: number) => {\n\t\tif (!has(val)) return\n\t\tconst index = sparse[val]\n\t\tconst swapped = dense.pop()!\n\t\tif (swapped !== val) {\n\t\t\tdense[index] = swapped\n\t\t\tsparse[swapped] = index\n\t\t}\n\t}\n\n\tconst reset = () => {\n\t\tdense.length = 0\n\t\tsparse.length = 0\n\t}\n\n\treturn {\n\t\tadd,\n\t\tremove,\n\t\thas,\n\t\tsparse,\n\t\tdense,\n\t\treset,\n\t}\n}\n\nconst SharedArrayBufferOrArrayBuffer = typeof SharedArrayBuffer !== 'undefined' ? SharedArrayBuffer : ArrayBuffer\n\nexport const createUint32SparseSet = (initialCapacity: number = 1000): SparseSet => {\n\tconst sparse: number[] = []\n\tlet length = 0\n\tlet dense: Uint32Array = new Uint32Array(new SharedArrayBufferOrArrayBuffer(initialCapacity * 4))\n\n\tconst has = (val: number) => val < sparse.length && sparse[val] < length && dense[sparse[val]] === val\n\n\tconst add = (val: number) => {\n\t\tif (has(val)) return\n\t\tif (length >= dense.length) {\n\t\t\tconst newDense = new Uint32Array(new SharedArrayBufferOrArrayBuffer(dense.length * 2 * 4))\n\t\t\tnewDense.set(dense)\n\t\t\tdense = newDense\n\t\t}\n\t\tdense[length] = val\n\t\tsparse[val] = length\n\t\tlength++\n\t}\n\n\tconst remove = (val: number) => {\n\t\tif (!has(val)) return\n\t\tlength--\n\t\tconst index = sparse[val]\n\t\tconst swapped = dense[length]\n\t\tdense[index] = swapped\n\t\tsparse[swapped] = index\n\t}\n\n\tconst reset = () => {\n\t\tlength = 0\n\t\tsparse.length = 0\n\t}\n\n\treturn {\n\t\tadd,\n\t\tremove,\n\t\thas,\n\t\tsparse,\n\t\tget dense() {\n\t\t\treturn new Uint32Array(dense.buffer, 0, length)\n\t\t},\n\t\treset,\n\t}\n}", "import { EntityId } from \"../Entity\"\n\nexport type Observer = (entity: EntityId, ...args: any[]) => void | object\n\nexport interface Observable {\n subscribe: (observer: Observer) => () => void\n notify: (entity: EntityId, ...args: any[]) => void | object\n}\n\nexport const createObservable = (): Observable => {\n const observers = new Set()\n\n const subscribe = (observer: Observer) => {\n observers.add(observer)\n return () => {\n observers.delete(observer)\n }\n }\n const notify = (entity: EntityId, ...args: any[]) => {\n return Array.from(observers).reduce((acc, listener) => {\n const result = listener(entity, ...args)\n return result && typeof result === 'object' ? { ...acc, ...result } : acc\n }, {})\n }\n\n return {\n subscribe,\n notify\n }\n}\n", "import { createSparseSet, createUint32SparseSet, type SparseSet } from './utils/SparseSet'\nimport { hasComponent, registerComponent } from './Component'\nimport { ComponentRef, ComponentData } from './Component'\nimport { World } from \"./World\"\nimport { InternalWorld } from './World'\nimport { $internal } from './World'\nimport { createObservable } from './utils/Observer'\nimport { EntityId, Prefab } from './Entity'\n\n/**\n * @typedef {Uint32Array | readonly number[]} QueryResult\n * @description The result of a query, either as a Uint32Array or a readonly array of numbers.\n */\nexport type QueryResult = Uint32Array | readonly EntityId[]\n\n/**\n * @typedef {Object} Query\n * @description Represents a query in the ECS.\n * @property {ComponentRef[]} allComponents - All components in the query.\n * @property {ComponentRef[]} orComponents - Components in an OR relationship.\n * @property {ComponentRef[]} notComponents - Components that should not be present.\n * @property {Object.} masks - Bitmasks for each component generation.\n * @property {Object.} orMasks - OR bitmasks for each component generation.\n * @property {Object.} notMasks - NOT bitmasks for each component generation.\n * @property {Object.} hasMasks - HAS bitmasks for each component generation.\n * @property {number[]} generations - Component generations.\n * @property {SparseSet} toRemove - Set of entities to be removed.\n * @property {ReturnType} addObservable - Observable for entity additions.\n * @property {ReturnType} removeObservable - Observable for entity removals.\n */\nexport type Query = SparseSet & {\n\tallComponents: ComponentRef[]\n\torComponents: ComponentRef[]\n\tnotComponents: ComponentRef[]\n\tmasks: Record\n\torMasks: Record\n\tnotMasks: Record\n\thasMasks: Record\n\tgenerations: number[]\n\ttoRemove: SparseSet\n\taddObservable: ReturnType\n\tremoveObservable: ReturnType\n\tqueues: Record\n}\n\n/**\n * @typedef {'Or' | 'And' | 'Not'} QueryOperatorType\n * @description Types of query operators.\n */\nexport type QueryOperatorType = 'Or' | 'And' | 'Not'\n/**\n * Symbol for query operator type.\n * @type {Symbol}\n */\nexport const $opType = Symbol.for('bitecs-opType')\n\n/**\n * Symbol for query operator terms.\n * @type {Symbol}\n */\nexport const $opTerms = Symbol.for('bitecs-opTerms')\n\n/**\n * @typedef {Object} OpReturnType\n * @property {symbol} [$opType] - The type of the operator.\n * @property {symbol} [$opTerms] - The components involved in the operation.\n */\nexport type OpReturnType = {\n\t[$opType]: string\n\t[$opTerms]: ComponentRef[]\n}\n\n/**\n * @typedef {Function} QueryOperator\n * @description A function that creates a query operator.\n * @param {...ComponentRef} components - The components to apply the operator to.\n * @returns {OpReturnType} The result of the operator.\n */\nexport type QueryOperator = (...components: ComponentRef[]) => OpReturnType\n\n/**\n * @typedef {ComponentRef | QueryOperator} QueryTerm\n * @description A term in a query, either a component reference or a query operator.\n */\nexport type QueryTerm = ComponentRef | QueryOperator\n\n\n// Aliases\nexport type OrOp = QueryOperator\nexport type AndOp = QueryOperator\nexport type NotOp = QueryOperator\nexport type AnyOp = OrOp\nexport type AllOp = AndOp\nexport type NoneOp = NotOp\n\n/**\n * @function Or\n * @description Creates an 'Or' query operator.\n * @param {...ComponentRef} components - The components to apply the 'Or' operator to.\n * @returns {OpReturnType} The 'Or' operator configuration.\n */\nexport const Or: OrOp = (...components: ComponentRef[]) => ({\n\t[$opType]: 'Or',\n\t[$opTerms]: components\n})\n\n/**\n * @function And\n * @description Creates an 'And' query operator.\n * @param {...ComponentRef} components - The components to apply the 'And' operator to.\n * @returns {OpReturnType} The 'And' operator configuration.\n */\nexport const And: AndOp = (...components: ComponentRef[]) => ({\n\t[$opType]: 'And',\n\t[$opTerms]: components\n})\n\n/**\n * @function Not\n * @description Creates a 'Not' query operator.\n * @param {...ComponentRef} components - The components to apply the 'Not' operator to.\n * @returns {OpReturnType} The 'Not' operator configuration.\n */\nexport const Not: NotOp = (...components: ComponentRef[]) => ({\n\t[$opType]: 'Not',\n\t[$opTerms]: components\n})\n\nexport const Any: AnyOp = Or\nexport const All: AllOp = And\nexport const None: NoneOp = Not\n\n/**\n * @typedef {Function} ObservableHook\n * @description A function that creates an observable hook for queries.\n * @param {...QueryTerm} terms - The query terms to observe.\n * @returns {{type: 'add' | 'remove' | 'set', terms: QueryTerm[]}} The observable hook configuration.\n */\nexport type ObservableHookDef = (...terms: QueryTerm[]) => {\n\t[$opType]: 'add' | 'remove' | 'set' | 'get'\n\t[$opTerms]: QueryTerm[]\n}\n\nexport type ObservableHook = ReturnType\n\n/**\n * @function onAdd\n * @description Creates an 'add' observable hook.\n * @param {...QueryTerm} terms - The query terms to observe for addition.\n * @returns {OpReturnType} The 'add' observable hook configuration.\n */\nexport const onAdd: ObservableHookDef = (...terms: QueryTerm[]) => ({\n\t[$opType]: 'add',\n\t[$opTerms]: terms\n})\n\n/**\n * @function onRemove\n * @description Creates a 'remove' observable hook.\n * @param {...QueryTerm} terms - The query terms to observe for removal.\n * @returns {OpReturnType} The 'remove' observable hook configuration.\n */\nexport const onRemove: ObservableHookDef = (...terms: QueryTerm[]) => ({\n\t[$opType]: 'remove',\n\t[$opTerms]: terms\n})\n\n/**\n * @function onSet\n * @description Creates a 'set' observable hook.\n * @param {...QueryTerm} terms - The query terms to observe for setting.\n * @returns {OpReturnType} The 'set' observable hook configuration.\n */\nexport const onSet: ObservableHookDef = (component: ComponentRef) => ({\n\t[$opType]: 'set',\n\t[$opTerms]: [component]\n})\n\n/**\n * @function onGet\n * @description Creates a 'get' observable hook.\n * @param {...QueryTerm} terms - The query terms to observe for getting.\n * @returns {OpReturnType} The 'get' observable hook configuration.\n */\nexport const onGet: ObservableHookDef = (component: ComponentRef) => ({\n\t[$opType]: 'get',\n\t[$opTerms]: [component]\n})\n\n/**\n * @function observe\n * @description Observes changes in entities based on specified components.\n * @param {World} world - The world object.\n * @param {ObservableHook} hook - The observable hook.\n * @param {function(number): any} callback - The callback function to execute when changes occur.\n * @returns {function(): void} A function to unsubscribe from the observation.\n */\nexport function observe(world: World, hook: ObservableHook, callback: (eid: EntityId, ...args: any[]) => any): () => void {\n\tconst ctx = (world as InternalWorld)[$internal]\n\tconst { [$opType]: type, [$opTerms]: components } = hook\n\n\tif (type === 'add' || type === 'remove') {\n\t\tconst hash = queryHash(world, components)\n\t\tlet queryData = ctx.queriesHashMap.get(hash)!\n\n\t\tif (!queryData) {\n\t\t\tqueryData = registerQuery(world, components)\n\t\t}\n\n\t\tconst observableKey = type === 'add' ? 'addObservable' : 'removeObservable'\n\t\treturn queryData[observableKey].subscribe(callback)\n\t} else if (type === 'set' || type === 'get') {\n\t\tif (components.length !== 1) {\n\t\t\tthrow new Error('Set and Get hooks can only observe a single component')\n\t\t}\n\t\tconst component = components[0]\n\t\tlet componentData = ctx.componentMap.get(component)\n\t\tif (!componentData) {\n\t\t\tcomponentData = registerComponent(world, component)\n\t\t}\n\t\tconst observableKey = type === 'set' ? 'setObservable' : 'getObservable'\n\t\treturn componentData[observableKey].subscribe(callback)\n\t}\n\n\tthrow new Error(`Invalid hook type: ${type}`)\n}\n\n/**\n * @function queryHash\n * @description Generates a hash for a query based on its terms.\n * @param {World} world - The world object.\n * @param {QueryTerm[]} terms - The query terms.\n * @returns {string} The generated hash.\n */\nexport const queryHash = (world: World, terms: QueryTerm[]): string => {\n\tconst ctx = (world as InternalWorld)[$internal]\n\n\tconst getComponentId = (component: ComponentRef): number => {\n\t\tif (!ctx.componentMap.has(component)) {\n\t\t\tregisterComponent(world, component)\n\t\t}\n\t\treturn ctx.componentMap.get(component)!.id\n\t}\n\tconst termToString = (term: QueryTerm): string => {\n\t\tif ($opType in term) {\n\t\t\tconst componentIds = term[$opTerms].map(getComponentId)\n\t\t\tconst sortedComponentIds = componentIds.sort((a, b) => a - b)\n\t\t\tconst sortedType = term[$opType].toLowerCase()\n\t\t\treturn `${sortedType}(${sortedComponentIds.join(',')})`\n\t\t} else {\n\t\t\treturn getComponentId(term).toString()\n\t\t}\n\t}\n\n\treturn terms\n\t\t.map(termToString)\n\t\t.sort()\n\t\t.join('-')\n}\n\n/**\n * @function registerQuery\n * @description Registers a new query in the world.\n * @param {World} world - The world object.\n * @param {QueryTerm[]} terms - The query terms.\n * @param {Object} [options] - Additional options.\n * @param {boolean} [options.buffered] - Whether the query should be buffered.\n * @returns {Query} The registered query.\n */\nexport const registerQuery = (world: World, terms: QueryTerm[], options: { buffered?: boolean } = {}): Query => {\n\tconst ctx = (world as InternalWorld)[$internal]\n\tconst hash = queryHash(world, terms)\n\t// if (ctx.queriesHashMap.has(hash)) {\n\t// \treturn ctx.queriesHashMap.get(hash)!\n\t// }\n\tconst components: ComponentRef[] = []\n\tconst notComponents: ComponentRef[] = []\n\tconst orComponents: ComponentRef[] = []\n\n\tconst processComponents = (comps: ComponentRef[], targetArray: ComponentRef[]) => {\n\t\tcomps.forEach((comp: ComponentRef) => {\n\t\t\tif (!ctx.componentMap.has(comp)) registerComponent(world, comp)\n\t\t\ttargetArray.push(comp)\n\t\t})\n\t}\n\n\tterms.forEach((term: QueryTerm) => {\n\t\tif ($opType in term) {\n\t\t\tif (term[$opType] === 'Not') {\n\t\t\t\tprocessComponents(term[$opTerms], notComponents)\n\t\t\t} else if (term[$opType] === 'Or') {\n\t\t\t\tprocessComponents(term[$opTerms], orComponents)\n\t\t\t}\n\t\t} else {\n\t\t\tif (!ctx.componentMap.has(term)) registerComponent(world, term)\n\t\t\tcomponents.push(term)\n\t\t}\n\t})\n\n\tconst mapComponents = (c: ComponentRef) => ctx.componentMap.get(c)!\n\tconst allComponents = components.concat(notComponents.flat()).concat(orComponents.flat()).map(mapComponents)\n\n\tconst sparseSet = options.buffered ? createUint32SparseSet() : createSparseSet()\n\n\tconst toRemove = createSparseSet()\n\n\tconst generations = allComponents\n\t\t.map((c) => c.generationId)\n\t\t.reduce((a, v) => {\n\t\t\tif (a.includes(v)) return a\n\t\t\ta.push(v)\n\t\t\treturn a\n\t\t}, [] as number[])\n\n\tconst reduceBitflags = (a: { [key: number]: number }, c: ComponentData) => {\n\t\tif (!a[c.generationId]) a[c.generationId] = 0\n\t\ta[c.generationId] |= c.bitflag\n\t\treturn a\n\t}\n\n\tconst masks = components.map(mapComponents).reduce(reduceBitflags, {})\n\tconst notMasks = notComponents.map(mapComponents).reduce(reduceBitflags, {})\n\tconst orMasks = orComponents.map(mapComponents).reduce(reduceBitflags, {})\n\tconst hasMasks = allComponents.reduce(reduceBitflags, {})\n\n\tconst addObservable = createObservable()\n\tconst removeObservable = createObservable()\n\n\tconst query = Object.assign(sparseSet, {\n\t\tcomponents,\n\t\tnotComponents,\n\t\torComponents,\n\t\tallComponents,\n\t\tmasks,\n\t\tnotMasks,\n\t\torMasks,\n\t\thasMasks,\n\t\tgenerations,\n\t\ttoRemove,\n\t\taddObservable,\n\t\tremoveObservable,\n\t\tqueues: {},\n\t}) as Query\n\n\tctx.queries.add(query)\n\n\tctx.queriesHashMap.set(hash, query)\n\n\tallComponents.forEach((c) => {\n\t\tc.queries.add(query)\n\t})\n\n\tif (notComponents.length) ctx.notQueries.add(query)\n\n\tconst entityIndex = ctx.entityIndex\n\tfor (let i = 0; i < entityIndex.aliveCount; i++) {\n\t\tconst eid = entityIndex.dense[i]\n\t\tif (hasComponent(world, eid, Prefab)) continue\n\t\tconst match = queryCheckEntity(world, query, eid)\n\t\tif (match) {\n\t\t\tqueryAddEntity(query, eid)\n\t\t}\n\t}\n\n\treturn query\n}\n\n/**\n * @function innerQuery\n * @description Performs an internal query operation.\n * @param {World} world - The world object.\n * @param {QueryTerm[]} terms - The query terms.\n * @param {Object} [options] - Additional options.\n * @param {boolean} [options.buffered] - Whether the query should be buffered.\n * @returns {QueryResult} The result of the query.\n */\nexport function innerQuery(world: World, terms: QueryTerm[], options: { buffered?: boolean } = {}): QueryResult {\n\tconst ctx = (world as InternalWorld)[$internal]\n\tconst hash = queryHash(world, terms)\n\tlet queryData = ctx.queriesHashMap.get(hash)\n\tif (!queryData) {\n\t\tqueryData = registerQuery(world, terms, options)\n\t} else if (options.buffered && !('buffer' in queryData.dense)) {\n\t\tqueryData = registerQuery(world, terms, { buffered: true })\n\t}\n\treturn queryData.dense\n}\n\n/**\n * @function query\n * @description Performs a query operation.\n * @param {World} world - The world object.\n * @param {QueryTerm[]} terms - The query terms.\n * @returns {readonly EntityId[]} The result of the query as a readonly array of entity IDs.\n */\nexport function query(world: World, terms: QueryTerm[]): readonly EntityId[] {\n\tcommitRemovals(world)\n\treturn innerQuery(world, terms) as EntityId[]\n}\n\n/**\n * @function bufferQuery\n * @description Performs a buffered query operation.\n * @param {World} world - The world object.\n * @param {QueryTerm[]} terms - The query terms.\n * @returns {Uint32Array} The result of the query as a Uint32Array.\n */\nexport function bufferQuery(world: World, terms: QueryTerm[]): Uint32Array {\n\tcommitRemovals(world)\n\treturn innerQuery(world, terms, { buffered: true }) as Uint32Array\n}\n\n/**\n * @function queryCheckEntity\n * @description Checks if an entity matches a query.\n * @param {World} world - The world object.\n * @param {Query} query - The query to check against.\n * @param {number} eid - The entity ID to check.\n * @returns {boolean} True if the entity matches the query, false otherwise.\n */\nexport function queryCheckEntity(world: World, query: Query, eid: EntityId): boolean {\n\tconst ctx = (world as InternalWorld)[$internal]\n\tconst { masks, notMasks, orMasks, generations } = query\n\n\tfor (let i = 0; i < generations.length; i++) {\n\t\tconst generationId = generations[i]\n\t\tconst qMask = masks[generationId]\n\t\tconst qNotMask = notMasks[generationId]\n\t\tconst qOrMask = orMasks[generationId]\n\t\tconst eMask = ctx.entityMasks[generationId][eid]\n\n\t\tif (qNotMask && (eMask & qNotMask) !== 0) {\n\t\t\treturn false\n\t\t}\n\n\t\tif (qMask && (eMask & qMask) !== qMask) {\n\t\t\treturn false\n\t\t}\n\n\t\tif (qOrMask && (eMask & qOrMask) === 0) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\n/**\n * @function queryCheckComponent\n * @description Checks if a component matches a query.\n * @param {Query} query - The query to check against.\n * @param {ComponentData} c - The component data to check.\n * @returns {boolean} True if the component matches the query, false otherwise.\n */\nexport const queryCheckComponent = (query: Query, c: ComponentData) => {\n\tconst { generationId, bitflag } = c\n\tconst { hasMasks } = query\n\tconst mask = hasMasks[generationId]\n\treturn (mask & bitflag) === bitflag\n}\n\n/**\n * @function queryAddEntity\n * @description Adds an entity to a query.\n * @param {Query} query - The query to add the entity to.\n * @param {number} eid - The entity ID to add.\n */\nexport const queryAddEntity = (query: Query, eid: EntityId) => {\n\tquery.toRemove.remove(eid)\n\n\tquery.addObservable.notify(eid)\n\n\tquery.add(eid)\n}\n\n/**\n * @function queryCommitRemovals\n * @description Commits removals for a query.\n * @param {Query} query - The query to commit removals for.\n */\nconst queryCommitRemovals = (query: Query) => {\n\tfor (let i = 0; i < query.toRemove.dense.length; i++) {\n\t\tconst eid = query.toRemove.dense[i]\n\n\t\tquery.remove(eid)\n\t}\n\tquery.toRemove.reset()\n}\n\n/**\n * @function commitRemovals\n * @description Commits all pending removals for queries in the world.\n * @param {World} world - The world object.\n */\nexport const commitRemovals = (world: World) => {\n\tconst ctx = (world as InternalWorld)[$internal]\n\tif (!ctx.dirtyQueries.size) return\n\tctx.dirtyQueries.forEach(queryCommitRemovals)\n\tctx.dirtyQueries.clear()\n}\n\n/**\n * @function queryRemoveEntity\n * @description Removes an entity from a query.\n * @param {World} world - The world object.\n * @param {Query} query - The query to remove the entity from.\n * @param {number} eid - The entity ID to remove.\n */\nexport const queryRemoveEntity = (world: World, query: Query, eid: EntityId) => {\n\tconst ctx = (world as InternalWorld)[$internal]\n\tconst has = query.has(eid)\n\tif (!has || query.toRemove.has(eid)) return\n\tquery.toRemove.add(eid)\n\tctx.dirtyQueries.add(query)\n\tquery.removeObservable.notify(eid)\n}\n\n/**\n * @function removeQuery\n * @description Removes a query from the world.\n * @param {World} world - The world object.\n * @param {QueryTerm[]} terms - The query terms of the query to remove.\n */\nexport const removeQuery = (world: World, terms: QueryTerm[]) => {\n\tconst ctx = (world as InternalWorld)[$internal]\n\tconst hash = queryHash(world, terms)\n\tconst query = ctx.queriesHashMap.get(hash)\n\tif (query) {\n\t\tctx.queries.delete(query)\n\t\tctx.queriesHashMap.delete(hash)\n\t}\n}\n", "import { getEntityComponents, World } from '.'\nimport { EntityId } from './Entity'\nimport { defineHiddenProperty } from './utils/defineHiddenProperty'\n\n/**\n * Callback function type for when a target is removed from a relation.\n * @callback OnTargetRemovedCallback\n * @param {number} subject - The subject entity ID.\n * @param {number} target - The target entity ID.\n */\nexport type OnTargetRemovedCallback = (subject: EntityId, target: EntityId) => void\n\n/**\n * Possible types for a relation target.\n * @typedef {number | '*' | typeof Wildcard} RelationTarget\n */\nexport type RelationTarget = number | '*' | typeof Wildcard\n/**\n * Symbol for accessing the relation of a component.\n * @type {Symbol}\n */\nexport const $relation = Symbol.for('bitecs-relation')\n\n/**\n * Symbol for accessing the pair target of a component.\n * @type {Symbol}\n */\nexport const $pairTarget = Symbol.for('bitecs-pairTarget')\n\n/**\n * Symbol for checking if a component is a pair component.\n * @type {Symbol}\n */\nexport const $isPairComponent = Symbol.for('bitecs-isPairComponent')\n\n/**\n * Symbol for accessing the relation data of a component.\n * @type {Symbol}\n */\nexport const $relationData = Symbol.for('bitecs-relationData')\n\n/**\n * Interface for relation data.\n * @interface RelationData\n * @template T\n */\ntype RelationData = {\n pairsMap: Map, T>\n initStore: (eid: EntityId) => T\n exclusiveRelation: boolean\n autoRemoveSubject: boolean\n onTargetRemoved: OnTargetRemovedCallback\n}\n\n/**\n * Type definition for a Relation function.\n * @template T\n * @typedef {function} Relation\n * @param {RelationTarget} target - The target of the relation.\n * @returns {T} The relation component.\n */\nexport type Relation = (target: RelationTarget) => T\n\n/**\n * Creates a base relation.\n * @template T\n * @returns {Relation} The created base relation.\n */\nconst createBaseRelation = (): Relation => {\n const data = {\n pairsMap: new Map(),\n initStore: undefined,\n exclusiveRelation: false,\n autoRemoveSubject: false,\n onTargetRemoved: undefined\n }\n const relation = (target: RelationTarget): T => {\n if (target === undefined) throw Error('Relation target is undefined')\n const normalizedTarget = target === '*' ? Wildcard : target\n if (!data.pairsMap.has(normalizedTarget)) {\n const component = data.initStore ? data.initStore(target) : {} as T\n defineHiddenProperty(component, $relation, relation)\n defineHiddenProperty(component, $pairTarget, normalizedTarget)\n defineHiddenProperty(component, $isPairComponent, true)\n data.pairsMap.set(normalizedTarget, component)\n }\n\n return data.pairsMap.get(normalizedTarget)!\n }\n\n defineHiddenProperty(relation, $relationData, data)\n\n return relation as Relation\n}\n\n/**\n * Adds a store to a relation.\n * @template T\n * @param {function(): T} createStore - Function to create the store.\n * @returns {function(Relation): Relation} A function that modifies the relation.\n */\nexport const withStore = (createStore: (eid: EntityId) => T) => (relation: Relation): Relation => {\n const ctx = relation[$relationData] as RelationData\n ctx.initStore = createStore\n return relation\n}\n\n/**\n * Makes a relation exclusive.\n * @template T\n * @param {Relation} relation - The relation to make exclusive.\n * @returns {Relation} The modified relation.\n */\nexport const makeExclusive = (relation: Relation): Relation => {\n const ctx = relation[$relationData] as RelationData\n ctx.exclusiveRelation = true\n return relation\n}\n\n/**\n * Adds auto-remove subject behavior to a relation.\n * @template T\n * @param {Relation} relation - The relation to modify.\n * @returns {Relation} The modified relation.\n */\nexport const withAutoRemoveSubject = (relation: Relation): Relation => {\n const ctx = relation[$relationData] as RelationData\n ctx.autoRemoveSubject = true\n return relation\n}\n\n/**\n * Adds an onTargetRemoved callback to a relation.\n * @template T\n * @param {OnTargetRemovedCallback} onRemove - The callback to add.\n * @returns {function(Relation): Relation} A function that modifies the relation.\n */\nexport const withOnTargetRemoved = (onRemove: OnTargetRemovedCallback) => (relation: Relation): Relation => {\n const ctx = relation[$relationData] as RelationData\n ctx.onTargetRemoved = onRemove\n return relation\n}\n\n// TODO: withSetter\n/**\n * Adds validation to a relation.\n * @template T\n * @param {function(T): boolean} validateFn - The validation function.\n * @returns {function(Relation): Relation} A function that modifies the relation.\n */\nconst withValidation = (validateFn: (value: T) => boolean) => (relation: Relation): Relation => {\n const originalRelation = relation\n return ((target: RelationTarget): T => {\n const component = originalRelation(target)\n if (!validateFn(component)) {\n throw new Error('Validation failed for relation component')\n }\n return component\n }) as Relation\n}\n\n/**\n * Creates a pair from a relation and a target.\n * @template T\n * @param {Relation} relation - The relation.\n * @param {RelationTarget} target - The target.\n * @returns {T} The created pair.\n * @throws {Error} If the relation is undefined.\n */\nexport const Pair = (relation: Relation, target: RelationTarget): T => {\n if (relation === undefined) throw Error('Relation is undefined')\n return relation(target)\n}\n\n/**\n * Gets the relation targets for an entity.\n * @param {World} world - The world object.\n * @param {Relation} relation - The relation to get targets for.\n * @param {number} eid - The entity ID.\n * @returns {Array} An array of relation targets.\n */\nexport const getRelationTargets = (world: World, eid: EntityId, relation: Relation): number[] => {\n\tconst components = getEntityComponents(world, eid)\n\tconst targets = []\n\tfor (const c of components) {\n\t\tif (c[$relation] === relation && c[$pairTarget] !== Wildcard && !isRelation(c[$pairTarget])) {\n\t\t\ttargets.push(c[$pairTarget])\n\t\t}\n\t}\n\treturn targets\n}\n\n/**\n * Creates a new relation.\n * @template T\n * @param {...Array): Relation>} modifiers - Modifier functions for the relation.\n * @returns {Relation} The created relation.\n */\nexport function createRelation(...modifiers: Array<(relation: Relation) => Relation>): Relation\n\n/**\n * Creates a new relation with options.\n * @template T\n * @param {Object} options - Options for creating the relation.\n * @param {function(): T} [options.store] - Function to create the store.\n * @param {boolean} [options.exclusive] - Whether the relation is exclusive.\n * @param {boolean} [options.autoRemoveSubject] - Whether to auto-remove the subject.\n * @param {OnTargetRemovedCallback} [options.onTargetRemoved] - Callback for when a target is removed.\n * @returns {Relation} The created relation.\n */\nexport function createRelation(options: {\n store?: () => T\n exclusive?: boolean\n autoRemoveSubject?: boolean\n onTargetRemoved?: OnTargetRemovedCallback\n}): Relation\nexport function createRelation(\n ...args: Array<(relation: Relation) => Relation> | [{\n store?: () => T\n exclusive?: boolean\n autoRemoveSubject?: boolean\n onTargetRemoved?: OnTargetRemovedCallback\n }]\n): Relation {\n if (args.length === 1 && typeof args[0] === 'object') {\n const { store, exclusive, autoRemoveSubject, onTargetRemoved } = args[0]\n const modifiers = [\n store && withStore(store),\n exclusive && makeExclusive,\n autoRemoveSubject && withAutoRemoveSubject,\n onTargetRemoved && withOnTargetRemoved(onTargetRemoved)\n ].filter(Boolean) as Array<(relation: Relation) => Relation>\n return modifiers.reduce((acc, modifier) => modifier(acc), createBaseRelation())\n } else {\n const modifiers = args as Array<(relation: Relation) => Relation>\n return modifiers.reduce((acc, modifier) => modifier(acc), createBaseRelation())\n }\n}\n\n/**\n * Symbol used to mark a relation as a wildcard relation\n */\nexport const $wildcard = Symbol.for('bitecs-wildcard')\n\n/**\n * Creates a wildcard relation that matches any target.\n * @template T\n * @returns {Relation} The created wildcard relation.\n */\nexport function createWildcardRelation(): Relation {\n const relation = createBaseRelation()\n Object.defineProperty(relation, $wildcard, {\n value: true,\n enumerable: false,\n writable: false,\n configurable: false\n })\n return relation\n}\n\n/**\n * Gets the singleton wildcard instance.\n * @returns {Relation} The global wildcard relation instance.\n */\nexport function getWildcard(): Relation {\n const GLOBAL_WILDCARD = Symbol.for('bitecs-global-wildcard')\n \n if (!(globalThis as any)[GLOBAL_WILDCARD]) {\n (globalThis as any)[GLOBAL_WILDCARD] = createWildcardRelation()\n }\n \n return (globalThis as any)[GLOBAL_WILDCARD]\n}\n\n/**\n * Wildcard relation.\n * @type {Relation}\n */\nexport const Wildcard = getWildcard()\n\n/**\n * Creates an IsA relation.\n * @template T\n * @returns {Relation} The created IsA relation.\n */\nexport function createIsARelation(): Relation {\n return createBaseRelation()\n}\n\n/**\n * Gets the singleton IsA instance.\n * @returns {Relation} The global IsA relation instance.\n */\nexport function getIsA(): Relation {\n const GLOBAL_ISA = Symbol.for('bitecs-global-isa')\n \n if (!(globalThis as any)[GLOBAL_ISA]) {\n (globalThis as any)[GLOBAL_ISA] = createIsARelation()\n }\n \n return (globalThis as any)[GLOBAL_ISA]\n}\n\n/**\n * IsA relation.\n * @type {Relation}\n */\nexport const IsA = getIsA()\n\n/**\n * Checks if a relation is a wildcard relation.\n * @param {any} relation - The relation to check.\n * @returns {boolean} True if the relation is a wildcard relation, false otherwise.\n */\nexport function isWildcard(relation: any): boolean {\n if (!relation) return false\n const symbols = Object.getOwnPropertySymbols(relation)\n return symbols.includes($wildcard)\n}\n\n/**\n * Checks if a component is a relation.\n * @param {any} component - The component to check.\n * @returns {boolean} True if the component is a relation, false otherwise.\n */\nexport function isRelation(component: any): boolean {\n if (!component) return false\n const symbols = Object.getOwnPropertySymbols(component)\n return symbols.includes($relationData)\n}\n", "import { entityExists, EntityId, getEntityComponents, Prefab } from './Entity'\nimport { queryAddEntity, queryCheckEntity, queryRemoveEntity } from './Query'\nimport { Query } from './Query'\nimport {\n\tIsA,\n\tPair,\n\tWildcard,\n\tgetRelationTargets,\n\t$relationData,\n\t$isPairComponent,\n\t$pairTarget,\n\t$relation\n} from './Relation'\nimport { createObservable, Observable } from './utils/Observer'\nimport { $internal, InternalWorld, World, WorldContext } from './World'\n\n/**\n * Represents a reference to a component.\n * @typedef {any} ComponentRef\n */\nexport type ComponentRef = any\n\n/**\n * Represents the data associated with a component.\n * @interface ComponentData\n * @property {number} id - The unique identifier for the component.\n * @property {number} generationId - The generation ID of the component.\n * @property {number} bitflag - The bitflag used for component masking.\n * @property {ComponentRef} ref - Reference to the component.\n * @property {Set} queries - Set of queries associated with the component.\n * @property {Observable} setObservable - Observable for component changes.\n */\nexport interface ComponentData {\n\tid: number\n\tgenerationId: number\n\tbitflag: number\n\tref: ComponentRef\n\tqueries: Set\n\tsetObservable: Observable\n\tgetObservable: Observable\n}\n\n/**\n * Registers a component with the world.\n * @param {World} world - The world object.\n * @param {ComponentRef} component - The component to register.\n * @returns {ComponentData} The registered component data.\n * @throws {Error} If the component is null or undefined.\n */\nexport const registerComponent = (world: World, component: ComponentRef) => {\n\tif (!component) {\n\t\tthrow new Error(`bitECS - Cannot register null or undefined component`)\n\t}\n\n\tconst ctx = (world as InternalWorld)[$internal]\n\tconst queries = new Set()\n\n\tconst data: ComponentData = {\n\t\tid: ctx.componentCount++,\n\t\tgenerationId: ctx.entityMasks.length - 1,\n\t\tbitflag: ctx.bitflag,\n\t\tref: component,\n\t\tqueries,\n\t\tsetObservable: createObservable(),\n\t\tgetObservable: createObservable(),\n\t}\n\n\tctx.componentMap.set(component, data)\n\n\tctx.bitflag *= 2\n\tif (ctx.bitflag >= 2 ** 31) {\n\t\tctx.bitflag = 1\n\t\tctx.entityMasks.push([])\n\t}\n\n\treturn data\n}\n\n/**\n * Registers multiple components with the world.\n * @param {World} world - The world object.\n * @param {ComponentRef[]} components - Array of components to register.\n */\nexport const registerComponents = (world: World, components: ComponentRef[]) => {\n\tcomponents.forEach((component) => registerComponent(world, component))\n}\n\n/**\n * Checks if an entity has a specific component.\n * @param {World} world - The world object.\n * @param {number} eid - The entity ID.\n * @param {ComponentRef} component - The component to check for.\n * @returns {boolean} True if the entity has the component, false otherwise.\n */\nexport const hasComponent = (world: World, eid: EntityId, component: ComponentRef): boolean => {\n\tconst ctx = (world as InternalWorld)[$internal]\n\tconst registeredComponent = ctx.componentMap.get(component)\n\tif (!registeredComponent) return false\n\n\tconst { generationId, bitflag } = registeredComponent\n\tconst mask = ctx.entityMasks[generationId][eid]\n\n\treturn (mask & bitflag) === bitflag\n}\n/**\n * Retrieves the data associated with a component for a specific entity.\n * @param {World} world - The world object.\n * @param {EntityId} eid - The entity ID.\n * @param {ComponentRef} component - The component to retrieve data for.\n * @returns {any} The component data, or undefined if the component is not found or the entity doesn't have the component.\n */\nexport const getComponentData = (world: World, eid: EntityId, component: ComponentRef): any => {\n\tconst ctx = (world as InternalWorld)[$internal]\n\tconst componentData = ctx.componentMap.get(component)\n\n\tif (!componentData) {\n\t\treturn undefined\n\t}\n\n\tif (!hasComponent(world, eid, component)) {\n\t\treturn undefined\n\t}\n\n\t// Notify observers that this component is being accessed\n\treturn componentData.getObservable.notify(eid)\n}\n\n/**\n * Helper function to set component data.\n * @param {ComponentRef} component - The component to set.\n * @param {any} data - The data to set for the component.\n * @returns {{ component: ComponentRef, data: any }} An object containing the component and its data.\n */\nexport const set = (component: T, data: any): { component: T, data: any } => ({\n\tcomponent,\n\tdata\n})\n\n/**\n * Recursvely inherits components from one entity to another.\n * @param {World} world - The world object.\n * @param {number} baseEid - The ID of the entity inheriting components.\n * @param {number} inheritedEid - The ID of the entity being inherited from.\n * @param {boolean} isFirstSuper - Whether this is the first super in the inheritance chain.\n */\nconst recursivelyInherit = (ctx: WorldContext, world: World, baseEid: EntityId, inheritedEid: EntityId, visited = new Set()): void => {\n\t// Guard against circular inheritance\n\tif (visited.has(inheritedEid)) return\n\tvisited.add(inheritedEid)\n\t\n\t// Add IsA relation first\n\taddComponent(world, baseEid, IsA(inheritedEid))\n\t\n\t// Copy components and their data from this level\n\t// This needs to happen before recursing to ancestors so closer ancestors take precedence\n\tfor (const component of getEntityComponents(world, inheritedEid)) {\n\t\t// TODO: inherit reference vs copy\n\t\tif (component === Prefab) continue\n\t\t\n\t\t// Only add component if entity doesn't already have it\n\t\t// This ensures closer ancestors take precedence\n\t\tif (!hasComponent(world, baseEid, component)) {\n\t\t\taddComponent(world, baseEid, component)\n\t\t\t\n\t\t\tconst componentData = ctx.componentMap.get(component)\n\t\t\tif (componentData?.setObservable) {\n\t\t\t\tconst data = getComponentData(world, inheritedEid, component)\n\t\t\t\tcomponentData.setObservable.notify(baseEid, data)\n\t\t\t}\n\t\t}\n\t}\n\t\n\t// Then recursively inherit from ancestors\n\t// This ensures more distant ancestors don't override closer ones\n\tfor (const parentEid of getRelationTargets(world, inheritedEid, IsA)) {\n\t\trecursivelyInherit(ctx, world, baseEid, parentEid, visited)\n\t}\n}\n\n/**\n * Represents a component with data to be set on an entity.\n */\ntype ComponentSetter = { component: ComponentRef; data: T }\n\n/**\n * Adds one or more components to an entity.\n * @param {World} world - The world object.\n * @param {EntityId} eid - The entity ID.\n * @param {...(ComponentRef | ComponentSetter)} components - Components to add or set.\n * @throws {Error} If the entity does not exist in the world.\n */\nexport const addComponent = (world: World, eid: EntityId, ...components: (ComponentRef | ComponentSetter)[]): void => {\n\tif (!entityExists(world, eid)) {\n\t\tthrow new Error(`Cannot add component - entity ${eid} does not exist in the world.`)\n\t}\n\t\n\tconst ctx = (world as InternalWorld)[$internal]\n\t\n\tcomponents.forEach(componentOrSet => {\n\t\tconst component = 'component' in componentOrSet ? componentOrSet.component : componentOrSet\n\t\tconst data = 'data' in componentOrSet ? componentOrSet.data : undefined\n\n\t\tif (!ctx.componentMap.has(component)) registerComponent(world, component)\n\n\t\tconst componentData = ctx.componentMap.get(component)!\n\t\tif (data !== undefined) {\n\t\t\tcomponentData.setObservable.notify(eid, data)\n\t\t}\n\n\t\tif (hasComponent(world, eid, component)) return\n\n\t\tconst { generationId, bitflag, queries } = componentData\n\n\t\tctx.entityMasks[generationId][eid] |= bitflag\n\n\t\tif (!hasComponent(world, eid, Prefab)) {\n\t\t\tqueries.forEach((queryData: Query) => {\n\t\t\t\tqueryData.toRemove.remove(eid)\n\t\t\t\tconst match = queryCheckEntity(world, queryData, eid)\n\n\t\t\t\tif (match) queryAddEntity(queryData, eid)\n\t\t\t\telse queryRemoveEntity(world, queryData, eid)\n\t\t\t})\n\t\t}\n\t\tctx.entityComponents.get(eid)!.add(component)\n\t\tif (component[$isPairComponent]) {\n\t\t\tconst relation = component[$relation]\n\t\t\tconst target = component[$pairTarget]\n\n\t\t\t// Add both Wildcard pairs for relation and target\n\t\t\taddComponent(world, eid, Pair(relation, Wildcard))\n\t\t\taddComponent(world, eid, Pair(Wildcard, target))\n\n\t\t\t// For non-Wildcard targets, add Wildcard pair to track relation targets\n\t\t\tif (typeof target === 'number') {\n\t\t\t\t// Add Wildcard pair for target being a relation target\n\t\t\t\taddComponent(world, target, Pair(Wildcard, eid))\n\t\t\t\taddComponent(world, target, Pair(Wildcard, relation))\n\t\t\t\t// Track entities with relations for autoRemoveSubject\n\t\t\t\tctx.entitiesWithRelations.add(target)\n\t\t\t\tctx.entitiesWithRelations.add(eid)\n\t\t\t}\n\n\t\t\t// add target to a set to make autoRemoveSubject checks faster\n\t\t\tctx.entitiesWithRelations.add(target)\n\n\t\t\tconst relationData = relation[$relationData]\n\t\t\tif (relationData.exclusiveRelation === true && target !== Wildcard) {\n\t\t\t\tconst oldTarget = getRelationTargets(world, eid, relation)[0]\n\t\t\t\tif (oldTarget !== undefined && oldTarget !== null && oldTarget !== target) {\n\t\t\t\t\tremoveComponent(world, eid, relation(oldTarget))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (relation === IsA) {\n\t\t\t\tconst inheritedTargets = getRelationTargets(world, eid, IsA)\n\t\t\t\tfor (const inherited of inheritedTargets) {\n\t\t\t\t\trecursivelyInherit(ctx, world, eid, inherited)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n}\n\n/**\n * Alias for addComponent.\n */\nexport const addComponents = addComponent\n\n/**\n * Removes one or more components from an entity.\n * @param {World} world - The world object.\n * @param {number} eid - The entity ID.\n * @param {...ComponentRef} components - Components to remove.\n * @throws {Error} If the entity does not exist in the world.\n */\nexport const removeComponent = (world: World, eid: EntityId, ...components: ComponentRef[]) => {\n\tconst ctx = (world as InternalWorld)[$internal]\n\tif (!entityExists(world, eid)) {\n\t\tthrow new Error(`Cannot remove component - entity ${eid} does not exist in the world.`)\n\t}\n\n\tcomponents.forEach(component => {\n\t\tif (!hasComponent(world, eid, component)) return\n\n\t\tconst componentNode = ctx.componentMap.get(component)!\n\t\tconst { generationId, bitflag, queries } = componentNode\n\n\t\tctx.entityMasks[generationId][eid] &= ~bitflag\n\n\t\tqueries.forEach((queryData: Query) => {\n\t\t\tqueryData.toRemove.remove(eid)\n\n\t\t\tconst match = queryCheckEntity(world, queryData, eid)\n\n\t\t\tif (match) queryAddEntity(queryData, eid)\n\t\t\telse queryRemoveEntity(world, queryData, eid)\n\t\t})\n\n\t\tctx.entityComponents.get(eid)!.delete(component)\n\n\t\tif (component[$isPairComponent]) {\n\t\t\tconst target = component[$pairTarget]\n\t\t\tremoveComponent(world, eid, Pair(Wildcard, target))\n\n\t\t\tconst relation = component[$relation]\n\t\t\tconst otherTargets = getRelationTargets(world, eid, relation)\n\t\t\tif (otherTargets.length === 0) {\n\t\t\t\tremoveComponent(world, eid, Pair(relation, Wildcard))\n\t\t\t}\n\t\t}\n\t})\n}\n\n/**\n * Alias for removeComponent.\n */\nexport const removeComponents = removeComponent\n", "import { addComponent, removeComponent } from './Component'\nimport {\n\tinnerQuery,\n\tqueryAddEntity,\n\tqueryCheckEntity,\n\tqueryRemoveEntity,\n} from './Query'\nimport { Pair, Wildcard, $isPairComponent, $relation, $pairTarget, $relationData } from './Relation'\nimport { World } from \"./World\"\nimport { InternalWorld } from './World'\nimport { addEntityId, isEntityIdAlive, removeEntityId } from './EntityIndex'\nimport { $internal } from './World'\nimport { ComponentRef } from './Component'\n\nexport type EntityId = number\n\nexport const Prefab = {}\nexport const addPrefab = (world: World): EntityId => {\n\tconst eid = addEntity(world)\n\n\taddComponent(world, eid, Prefab)\n\n\treturn eid\n}\n\n/**\n * Adds a new entity to the specified world.\n *\n * @param {World} world\n * @returns {number} eid\n */\nexport const addEntity = (world: World): EntityId => {\n\tconst ctx = (world as InternalWorld)[$internal]\n\tconst eid = addEntityId(ctx.entityIndex)\n\n\tctx.notQueries.forEach((q) => {\n\t\tconst match = queryCheckEntity(world, q, eid)\n\t\tif (match) queryAddEntity(q, eid)\n\t})\n\n\tctx.entityComponents.set(eid, new Set())\n\n\treturn eid\n}\n\n/**\n * Removes an existing entity from the specified world.\n *\n * @param {World} world\n * @param {number} eid\n */\n\nexport const removeEntity = (world: World, eid: EntityId) => {\n\tconst ctx = (world as InternalWorld)[$internal]\n\t// Check if entity is already removed\n\tif (!isEntityIdAlive(ctx.entityIndex, eid)) return\n\n\t// Remove relation components from entities that have a relation to this one, breadth-first\n\t// e.g. addComponent(world, child, ChildOf(parent))\n\t// when parent is removed, we need to remove the child\n\tconst removalQueue = [eid]\n\tconst processedEntities = new Set()\n while (removalQueue.length > 0) {\n \n\t\tconst currentEid = removalQueue.shift()!\n if (processedEntities.has(currentEid)) continue\n processedEntities.add(currentEid)\n\n const componentRemovalQueue = []\n\n\t\tif (ctx.entitiesWithRelations.has(currentEid)) {\n\t\t\tfor (const subject of innerQuery(world, [Wildcard(currentEid)])) {\n\t\t\t\tif (!entityExists(world, subject)) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tfor (const component of ctx.entityComponents.get(subject)!) {\n\t\t\t\t\tif (!component[$isPairComponent]) {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\n\t\t\t\t\tconst relation = component[$relation]\n\t\t\t\t\tconst relationData = relation[$relationData]\n\t\t\t\t\tcomponentRemovalQueue.push(() => removeComponent(world, subject, Pair(Wildcard, currentEid)))\n\n\t\t\t\t\tif (component[$pairTarget] === currentEid) {\n\t\t\t\t\t\tcomponentRemovalQueue.push(() => removeComponent(world, subject, component))\n\t\t\t\t\t\tif (relationData.autoRemoveSubject) {\n\t\t\t\t\t\t\tremovalQueue.push(subject)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (relationData.onTargetRemoved) {\n\t\t\t\t\t\t\tcomponentRemovalQueue.push(() => relationData.onTargetRemoved(world, subject, currentEid))\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tctx.entitiesWithRelations.delete(currentEid)\n\t\t}\n\n for (const removeOperation of componentRemovalQueue) {\n removeOperation()\n }\n\n\t\tfor (const eid of removalQueue) {\n\t\t\tremoveEntity(world, eid)\n\t\t}\n\n\t\t// Remove entity from all queries\n\t\tfor (const query of ctx.queries) {\n\t\t\tqueryRemoveEntity(world, query, currentEid)\n\t\t}\n\n\t\t// Free the entity ID\n\t\tremoveEntityId(ctx.entityIndex, currentEid)\n\n\t\t// Remove all entity state from world\n\t\tctx.entityComponents.delete(currentEid)\n\n\t\t// Clear entity bitmasks\n\t\tfor (let i = 0; i < ctx.entityMasks.length; i++) {\n\t\t\tctx.entityMasks[i][currentEid] = 0\n\t\t}\n\t}\n}\n\n/**\n * Returns an array of components that an entity possesses.\n *\n * @param {*} world\n * @param {*} eid\n */\nexport const getEntityComponents = (world: World, eid: EntityId): ComponentRef[] => {\n\tconst ctx = (world as InternalWorld)[$internal]\n\tif (eid === undefined) throw new Error(`getEntityComponents: entity id is undefined.`)\n\tif (!isEntityIdAlive(ctx.entityIndex, eid))\n\t\tthrow new Error(`getEntityComponents: entity ${eid} does not exist in the world.`)\n\treturn Array.from(ctx.entityComponents.get(eid)!)\n}\n\n/**\n * Checks the existence of an entity in a world\n *\n * @param {World} world\n * @param {number} eid\n */\nexport const entityExists = (world: World, eid: EntityId) => isEntityIdAlive((world as InternalWorld)[$internal].entityIndex, eid)\n", "type Func = (...args: any) => any\nexport const pipe = \n (...functions: [T, ...U[], R]): ((...args: Parameters) => ReturnType) => {\n return (...args: Parameters): ReturnType => \n functions.reduce((result, fn) => [fn(...result)], args as any)[0]\n}\n"], + "mappings": "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", + "names": ["query", "query", "query", "onRemove", "eid", "query"] +} diff --git a/public/vendor/bitecs/index.min.js b/public/vendor/bitecs/index.min.js new file mode 100644 index 0000000..cc20f49 --- /dev/null +++ b/public/vendor/bitecs/index.min.js @@ -0,0 +1,2 @@ +var S=(e,t,n)=>Object.defineProperty(e,t,{value:n,enumerable:!1,writable:!0,configurable:!0});var X=(e,t)=>t&e.entityMask,Y=(e,t)=>t>>>e.versionShift&(1<{let o=Y(e,t)+1&(1<({versioning:!0,versionBits:e}),U=e=>{let t=e?typeof e=="function"?e():e:{versioning:!1,versionBits:8},n=t.versionBits??8,o=t.versioning??!1,s=32-n,r=(1<{if(e.aliveCount{let n=e.sparse[t];if(n===void 0||n>=e.aliveCount)return;let o=e.aliveCount-1,s=e.dense[o];if(e.sparse[s]=n,e.dense[n]=s,e.sparse[t]=o,e.dense[o]=t,e.versioning){let r=Te(e,t);e.dense[o]=r}e.aliveCount--},V=(e,t)=>{let n=X(e,t),o=e.sparse[n];return o!==void 0&&oS(e||{},m,{entityIndex:t||U(),entityMasks:[[]],entityComponents:new Map,bitflag:1,componentMap:new Map,componentCount:0,queries:new Set,queriesHashMap:new Map,notQueries:new Set,dirtyQueries:new Set,entitiesWithRelations:new Set});function Ie(...e){let t,n;return e.forEach(o=>{typeof o=="object"&&"add"in o&&"remove"in o?t=o:typeof o=="object"&&(n=o)}),he(n,t)}var Oe=e=>{let t=e[m];return t.entityIndex=U(),t.entityMasks=[[]],t.entityComponents=new Map,t.bitflag=1,t.componentMap=new Map,t.componentCount=0,t.queries=new Set,t.queriesHashMap=new Map,t.notQueries=new Set,t.dirtyQueries=new Set,t.entitiesWithRelations=new Set,e},Ee=e=>{delete e[m]},We=e=>Object.keys(e[m].componentMap),Se=e=>Array.from(e[m].entityComponents.keys());var z=()=>{let e=[],t=[],n=i=>e[t[i]]===i;return{add:i=>{n(i)||(t[i]=e.push(i)-1)},remove:i=>{if(!n(i))return;let a=t[i],p=e.pop();p!==i&&(e[a]=p,t[p]=a)},has:n,sparse:t,dense:e,reset:()=>{e.length=0,t.length=0}}},te=typeof SharedArrayBuffer<"u"?SharedArrayBuffer:ArrayBuffer,ne=(e=1e3)=>{let t=[],n=0,o=new Uint32Array(new te(e*4)),s=p=>p{if(!s(p)){if(n>=o.length){let l=new Uint32Array(new te(o.length*2*4));l.set(o),o=l}o[n]=p,t[p]=n,n++}},remove:p=>{if(!s(p))return;n--;let l=t[p],u=o[n];o[l]=u,t[u]=l},has:s,sparse:t,get dense(){return new Uint32Array(o.buffer,0,n)},reset:()=>{n=0,t.length=0}}};var A=()=>{let e=new Set;return{subscribe:o=>(e.add(o),()=>{e.delete(o)}),notify:(o,...s)=>Array.from(e).reduce((r,i)=>{let a=i(o,...s);return a&&typeof a=="object"?{...r,...a}:r},{})}};var R=Symbol.for("bitecs-opType"),g=Symbol.for("bitecs-opTerms"),oe=(...e)=>({[R]:"Or",[g]:e}),re=(...e)=>({[R]:"And",[g]:e}),se=(...e)=>({[R]:"Not",[g]:e}),Me=oe,Qe=re,ke=se,Ae=(...e)=>({[R]:"add",[g]:e}),De=(...e)=>({[R]:"remove",[g]:e}),$e=e=>({[R]:"set",[g]:[e]}),je=e=>({[R]:"get",[g]:[e]});function qe(e,t,n){let o=e[m],{[R]:s,[g]:r}=t;if(s==="add"||s==="remove"){let i=L(e,r),a=o.queriesHashMap.get(i);return a||(a=K(e,r)),a[s==="add"?"addObservable":"removeObservable"].subscribe(n)}else if(s==="set"||s==="get"){if(r.length!==1)throw new Error("Set and Get hooks can only observe a single component");let i=r[0],a=o.componentMap.get(i);return a||(a=I(e,i)),a[s==="set"?"setObservable":"getObservable"].subscribe(n)}throw new Error(`Invalid hook type: ${s}`)}var L=(e,t)=>{let n=e[m],o=r=>(n.componentMap.has(r)||I(e,r),n.componentMap.get(r).id),s=r=>{if(R in r){let a=r[g].map(o).sort((l,u)=>l-u);return`${r[R].toLowerCase()}(${a.join(",")})`}else return o(r).toString()};return t.map(s).sort().join("-")},K=(e,t,n={})=>{let o=e[m],s=L(e,t),r=[],i=[],a=[],p=(c,b)=>{c.forEach(N=>{o.componentMap.has(N)||I(e,N),b.push(N)})};t.forEach(c=>{R in c?c[R]==="Not"?p(c[g],i):c[R]==="Or"&&p(c[g],a):(o.componentMap.has(c)||I(e,c),r.push(c))});let l=c=>o.componentMap.get(c),u=r.concat(i.flat()).concat(a.flat()).map(l),f=n.buffered?ne():z(),d=z(),k=u.map(c=>c.generationId).reduce((c,b)=>(c.includes(b)||c.push(b),c),[]),x=(c,b)=>(c[b.generationId]||(c[b.generationId]=0),c[b.generationId]|=b.bitflag,c),_=r.map(l).reduce(x,{}),be=i.map(l).reduce(x,{}),Re=a.map(l).reduce(x,{}),xe=u.reduce(x,{}),ge=A(),ve=A(),W=Object.assign(f,{components:r,notComponents:i,orComponents:a,allComponents:u,masks:_,notMasks:be,orMasks:Re,hasMasks:xe,generations:k,toRemove:d,addObservable:ge,removeObservable:ve,queues:{}});o.queries.add(W),o.queriesHashMap.set(s,W),u.forEach(c=>{c.queries.add(W)}),i.length&&o.notQueries.add(W);let J=o.entityIndex;for(let c=0;c{e.toRemove.remove(t),e.addObservable.notify(t),e.add(t)},He=e=>{for(let t=0;t{let t=e[m];t.dirtyQueries.size&&(t.dirtyQueries.forEach(He),t.dirtyQueries.clear())},H=(e,t,n)=>{let o=e[m];!t.has(n)||t.toRemove.has(n)||(t.toRemove.add(n),o.dirtyQueries.add(t),t.removeObservable.notify(n))},we=(e,t)=>{let n=e[m],o=L(e,t),s=n.queriesHashMap.get(o);s&&(n.queries.delete(s),n.queriesHashMap.delete(o))};var Q=Symbol.for("bitecs-relation"),h=Symbol.for("bitecs-pairTarget"),j=Symbol.for("bitecs-isPairComponent"),v=Symbol.for("bitecs-relationData"),F=()=>{let e={pairsMap:new Map,initStore:void 0,exclusiveRelation:!1,autoRemoveSubject:!1,onTargetRemoved:void 0},t=n=>{if(n===void 0)throw Error("Relation target is undefined");let o=n==="*"?y:n;if(!e.pairsMap.has(o)){let s=e.initStore?e.initStore(n):{};S(s,Q,t),S(s,h,o),S(s,j,!0),e.pairsMap.set(o,s)}return e.pairsMap.get(o)};return S(t,v,e),t},ie=e=>t=>{let n=t[v];return n.initStore=e,t},Be=e=>{let t=e[v];return t.exclusiveRelation=!0,e},pe=e=>{let t=e[v];return t.autoRemoveSubject=!0,e},ce=e=>t=>{let n=t[v];return n.onTargetRemoved=e,t};var T=(e,t)=>{if(e===void 0)throw Error("Relation is undefined");return e(t)},q=(e,t,n)=>{let o=w(e,t),s=[];for(let r of o)r[Q]===n&&r[h]!==y&&!me(r[h])&&s.push(r[h]);return s};function Ne(...e){if(e.length===1&&typeof e[0]=="object"){let{store:t,exclusive:n,autoRemoveSubject:o,onTargetRemoved:s}=e[0];return[t&&ie(t),n&&Be,o&&pe,s&&ce(s)].filter(Boolean).reduce((i,a)=>a(i),F())}else return e.reduce((n,o)=>o(n),F())}var le=Symbol.for("bitecs-wildcard");function Ue(){let e=F();return Object.defineProperty(e,le,{value:!0,enumerable:!1,writable:!1,configurable:!1}),e}function Ve(){let e=Symbol.for("bitecs-global-wildcard");return globalThis[e]||(globalThis[e]=Ue()),globalThis[e]}var y=Ve();function Ke(){return F()}function Le(){let e=Symbol.for("bitecs-global-isa");return globalThis[e]||(globalThis[e]=Ke()),globalThis[e]}var P=Le();function Ge(e){return e?Object.getOwnPropertySymbols(e).includes(le):!1}function me(e){return e?Object.getOwnPropertySymbols(e).includes(v):!1}var I=(e,t)=>{if(!t)throw new Error("bitECS - Cannot register null or undefined component");let n=e[m],o=new Set,s={id:n.componentCount++,generationId:n.entityMasks.length-1,bitflag:n.bitflag,ref:t,queries:o,setObservable:A(),getObservable:A()};return n.componentMap.set(t,s),n.bitflag*=2,n.bitflag>=2**31&&(n.bitflag=1,n.entityMasks.push([])),s},Fe=(e,t)=>{t.forEach(n=>I(e,n))},O=(e,t,n)=>{let o=e[m],s=o.componentMap.get(n);if(!s)return!1;let{generationId:r,bitflag:i}=s;return(o.entityMasks[r][t]&i)===i},ue=(e,t,n)=>{let s=e[m].componentMap.get(n);if(s&&O(e,t,n))return s.getObservable.notify(t)},_e=(e,t)=>({component:e,data:t}),fe=(e,t,n,o,s=new Set)=>{if(!s.has(o)){s.add(o),C(t,n,P(o));for(let r of w(t,o))if(r!==M&&!O(t,n,r)){C(t,n,r);let i=e.componentMap.get(r);if(i?.setObservable){let a=ue(t,o,r);i.setObservable.notify(n,a)}}for(let r of q(t,o,P))fe(e,t,n,r,s)}},C=(e,t,...n)=>{if(!B(e,t))throw new Error(`Cannot add component - entity ${t} does not exist in the world.`);let o=e[m];n.forEach(s=>{let r="component"in s?s.component:s,i="data"in s?s.data:void 0;o.componentMap.has(r)||I(e,r);let a=o.componentMap.get(r);if(i!==void 0&&a.setObservable.notify(t,i),O(e,t,r))return;let{generationId:p,bitflag:l,queries:u}=a;if(o.entityMasks[p][t]|=l,O(e,t,M)||u.forEach(f=>{f.toRemove.remove(t),D(e,f,t)?$(f,t):H(e,f,t)}),o.entityComponents.get(t).add(r),r[j]){let f=r[Q],d=r[h];if(C(e,t,T(f,y)),C(e,t,T(y,d)),typeof d=="number"&&(C(e,d,T(y,t)),C(e,d,T(y,f)),o.entitiesWithRelations.add(d),o.entitiesWithRelations.add(t)),o.entitiesWithRelations.add(d),f[v].exclusiveRelation===!0&&d!==y){let x=q(e,t,f)[0];x!=null&&x!==d&&E(e,t,f(x))}if(f===P){let x=q(e,t,P);for(let _ of x)fe(o,e,t,_)}}})},ze=C,E=(e,t,...n)=>{let o=e[m];if(!B(e,t))throw new Error(`Cannot remove component - entity ${t} does not exist in the world.`);n.forEach(s=>{if(!O(e,t,s))return;let r=o.componentMap.get(s),{generationId:i,bitflag:a,queries:p}=r;if(o.entityMasks[i][t]&=~a,p.forEach(l=>{l.toRemove.remove(t),D(e,l,t)?$(l,t):H(e,l,t)}),o.entityComponents.get(t).delete(s),s[j]){let l=s[h];E(e,t,T(y,l));let u=s[Q];q(e,t,u).length===0&&E(e,t,T(u,y))}})},Je=E;var M={},Xe=e=>{let t=de(e);return C(e,t,M),t},de=e=>{let t=e[m],n=Z(t.entityIndex);return t.notQueries.forEach(o=>{D(e,o,n)&&$(o,n)}),t.entityComponents.set(n,new Set),n},ye=(e,t)=>{let n=e[m];if(!V(n.entityIndex,t))return;let o=[t],s=new Set;for(;o.length>0;){let r=o.shift();if(s.has(r))continue;s.add(r);let i=[];if(n.entitiesWithRelations.has(r)){for(let a of G(e,[y(r)]))if(B(e,a))for(let p of n.entityComponents.get(a)){if(!p[j])continue;let u=p[Q][v];i.push(()=>E(e,a,T(y,r))),p[h]===r&&(i.push(()=>E(e,a,p)),u.autoRemoveSubject&&o.push(a),u.onTargetRemoved&&i.push(()=>u.onTargetRemoved(e,a,r)))}n.entitiesWithRelations.delete(r)}for(let a of i)a();for(let a of o)ye(e,a);for(let a of n.queries)H(e,a,r);ee(n.entityIndex,r),n.entityComponents.delete(r);for(let a=0;a{let n=e[m];if(t===void 0)throw new Error("getEntityComponents: entity id is undefined.");if(!V(n.entityIndex,t))throw new Error(`getEntityComponents: entity ${t} does not exist in the world.`);return Array.from(n.entityComponents.get(t))},B=(e,t)=>V(e[m].entityIndex,t);var Ye=(...e)=>(...t)=>e.reduce((n,o)=>[o(...n)],t)[0];export{m as $internal,Qe as All,re as And,Me as Any,P as IsA,ke as None,se as Not,oe as Or,T as Pair,M as Prefab,y as Wildcard,C as addComponent,ze as addComponents,de as addEntity,Xe as addPrefab,ae as commitRemovals,U as createEntityIndex,Ne as createRelation,Ie as createWorld,Ee as deleteWorld,B as entityExists,Se as getAllEntities,ue as getComponentData,w as getEntityComponents,X as getId,q as getRelationTargets,Y as getVersion,We as getWorldComponents,O as hasComponent,G as innerQuery,me as isRelation,Ge as isWildcard,qe as observe,Ae as onAdd,je as onGet,De as onRemove,$e as onSet,Ye as pipe,Pe as query,I as registerComponent,Fe as registerComponents,K as registerQuery,E as removeComponent,Je as removeComponents,ye as removeEntity,we as removeQuery,Oe as resetWorld,_e as set,pe as withAutoRemoveSubject,ce as withOnTargetRemoved,ie as withStore,Ce as withVersioning}; +//# sourceMappingURL=index.min.mjs.map diff --git a/public/vendor/bitecs/index.min.js.map b/public/vendor/bitecs/index.min.js.map new file mode 100644 index 0000000..24be6b4 --- /dev/null +++ b/public/vendor/bitecs/index.min.js.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "sources": ["../../src/core/utils/defineHiddenProperty.ts", "../../src/core/EntityIndex.ts", "../../src/core/World.ts", "../../src/core/utils/SparseSet.ts", "../../src/core/utils/Observer.ts", "../../src/core/Query.ts", "../../src/core/Relation.ts", "../../src/core/Component.ts", "../../src/core/Entity.ts", "../../src/core/utils/pipe.ts"], + "sourcesContent": ["export const defineHiddenProperty = (obj:any,key:any,value:any) => Object.defineProperty(obj, key, {\n value,\n enumerable: false,\n writable: true,\n configurable: true,\n})\n\nexport const defineHiddenProperties = (obj:any,kv:any) => {\n const descriptors = {\n enumerable: false,\n writable: true,\n configurable: true,\n }\n Object.defineProperties(obj, Reflect.ownKeys(kv).reduce((a,k) => Object.assign(a, {[k]: {value: kv[k], ...descriptors}}), {}))\n}", "/**\n * Represents the structure for managing entity IDs.\n */\nexport type EntityIndex = {\n /** The number of currently alive entities. */\n aliveCount: number\n /** Array of entity IDs, densely packed. */\n dense: number[]\n /** Sparse array mapping entity IDs to their index in the dense array. */\n sparse: number[]\n /** The highest entity ID that has been assigned. */\n maxId: number\n /** Flag indicating if versioning is enabled. */\n versioning: boolean\n /** Number of bits used for versioning. */\n versionBits: number\n /** Bit mask for entity ID. */\n entityMask: number\n /** Bit shift for version. */\n versionShift: number\n /** Bit mask for version. */\n versionMask: number\n}\n\n/**\n * Extracts the entity ID from a versioned entity ID by stripping off the version.\n * @param {EntityIndex} index - The EntityIndex containing the masks.\n * @param {number} id - The versioned entity ID.\n * @returns {number} The entity ID without the version.\n */\nexport const getId = (index: EntityIndex, id: number): number => id & index.entityMask;\n\n/**\n * Extracts the version from an entity ID.\n * @param {EntityIndex} index - The EntityIndex containing the masks and shifts.\n * @param {number} id - The entity ID.\n * @returns {number} The version.\n */\nexport const getVersion = (index: EntityIndex, id: number): number => \n (id >>> index.versionShift) & ((1 << index.versionBits) - 1);\n\n/**\n * Increments the version of an entity ID.\n * @param {EntityIndex} index - The EntityIndex containing the masks and shifts.\n * @param {number} id - The entity ID.\n * @returns {number} The new entity ID with incremented version.\n */\nexport const incrementVersion = (index: EntityIndex, id: number): number => {\n const currentVersion = getVersion(index, id);\n const newVersion = (currentVersion + 1) & ((1 << index.versionBits) - 1);\n return (id & index.entityMask) | (newVersion << index.versionShift);\n}\n\n/**\n * Creates configuration options for entity ID recycling with versioning.\n * @param {number} [versionBits] - Optional number of bits to use for version numbers. Defaults to 8 if not specified.\n * @returns {object} Configuration object with versioning enabled and specified version bits.\n */\nexport const withVersioning = (versionBits?: number) => ({\n versioning: true,\n versionBits\n})\n\n/**\n * Creates and initializes a new EntityIndex.\n * @param {object|function} [options] - Optional configuration object from withVersioning() or withVersioning function.\n * @param {boolean} options.versioning - Flag to enable versioning for recycled IDs.\n * @param {number} options.versionBits - Number of bits to use for versioning (default: 8).\n * @returns {EntityIndex} A new EntityIndex object.\n */\nexport const createEntityIndex = (options?: ReturnType | typeof withVersioning): EntityIndex => {\n const config = options \n ? typeof options === 'function' \n ? options()\n : options\n : { versioning: false, versionBits: 8 }\n\n const versionBits = config.versionBits ?? 8\n const versioning = config.versioning ?? false\n \n const entityBits = 32 - versionBits\n const entityMask = (1 << entityBits) - 1\n const versionShift = entityBits\n const versionMask = ((1 << versionBits) - 1) << versionShift\n\n return {\n aliveCount: 0,\n dense: [],\n sparse: [],\n maxId: 0,\n versioning,\n versionBits,\n entityMask,\n versionShift,\n versionMask\n }\n}\n\n/**\n * Adds a new entity ID to the index or recycles an existing one.\n * @param {EntityIndex} index - The EntityIndex to add to.\n * @returns {number} The new or recycled entity ID.\n */\nexport const addEntityId = (index: EntityIndex): number => {\n if (index.aliveCount < index.dense.length) {\n // Recycle id\n const recycledId = index.dense[index.aliveCount];\n const entityId = recycledId;\n index.sparse[entityId] = index.aliveCount;\n index.aliveCount++;\n return recycledId;\n }\n\n // Create new id\n const id = ++index.maxId;\n index.dense.push(id);\n index.sparse[id] = index.aliveCount;\n index.aliveCount++;\n\n return id;\n}\n\n/**\n * Removes an entity ID from the index.\n * @param {EntityIndex} index - The EntityIndex to remove from.\n * @param {number} id - The entity ID to remove.\n */\nexport const removeEntityId = (index: EntityIndex, id: number): void => {\n const denseIndex = index.sparse[id];\n if (denseIndex === undefined || denseIndex >= index.aliveCount) {\n // Entity is not alive or doesn't exist, nothing to be done\n return;\n }\n\n const lastIndex = index.aliveCount - 1;\n const lastId = index.dense[lastIndex];\n\n // Swap with the last element\n index.sparse[lastId] = denseIndex;\n index.dense[denseIndex] = lastId;\n\n // Update the removed entity's record\n index.sparse[id] = lastIndex; // Set to lastIndex instead of undefined\n index.dense[lastIndex] = id; // Keep the original id, don't strip version\n\n // Version the ID if enabled\n if (index.versioning) {\n const newId = incrementVersion(index, id);\n index.dense[lastIndex] = newId;\n }\n\n index.aliveCount--;\n}\n\n/**\n * Checks if an entity ID is currently alive in the index.\n * @param {EntityIndex} index - The EntityIndex to check.\n * @param {number} id - The entity ID to check.\n * @returns {boolean} True if the entity ID is alive, false otherwise.\n */\nexport const isEntityIdAlive = (index: EntityIndex, id: number): boolean => {\n const entityId = getId(index, id);\n const denseIndex = index.sparse[entityId];\n return denseIndex !== undefined && denseIndex < index.aliveCount && index.dense[denseIndex] === id;\n}\n", "import { defineHiddenProperty } from './utils/defineHiddenProperty'\nimport { createEntityIndex, EntityIndex } from './EntityIndex'\nimport { ComponentRef, ComponentData } from './Component'\nimport { Query } from './Query'\nimport { EntityId } from './Entity'\n\nexport const $internal = Symbol.for('bitecs_internal')\n\nexport type WorldContext = {\n entityIndex: EntityIndex\n entityMasks: number[][]\n entityComponents: Map>\n bitflag: number\n componentMap: Map\n componentCount: number\n queries: Set\n queriesHashMap: Map\n notQueries: Set\n dirtyQueries: Set\n entitiesWithRelations: Set\n}\n\nexport type InternalWorld = {\n [$internal]: WorldContext\n}\n\nexport type World = { [K in keyof T]: T[K] }\n\nconst createBaseWorld = (context?: T, entityIndex?: EntityIndex): World => \n defineHiddenProperty(context || {} as T, $internal, {\n entityIndex: entityIndex || createEntityIndex(),\n entityMasks: [[]],\n entityComponents: new Map(),\n bitflag: 1,\n componentMap: new Map(),\n componentCount: 0,\n queries: new Set(),\n queriesHashMap: new Map(),\n notQueries: new Set(),\n dirtyQueries: new Set(),\n entitiesWithRelations: new Set(),\n}) as World\n\n/**\n * Creates a new world with various configurations.\n * @template T\n * @param {...Array} args - EntityIndex, context object, or both.\n * @returns {World} The created world.\n */\n\n// TODO: middleware\n\nexport function createWorld(\n ...args: Array\n): World {\n let entityIndex: EntityIndex | undefined\n let context: T | undefined\n\n args.forEach(arg => {\n if (typeof arg === 'object' && 'add' in arg && 'remove' in arg) {\n entityIndex = arg as EntityIndex\n } else if (typeof arg === 'object') {\n context = arg as T\n }\n })\n\n return createBaseWorld(context, entityIndex)\n}\n\n/**\n * Resets a world.\n *\n * @param {World} world\n * @returns {object}\n */\nexport const resetWorld = (world: World) => {\n const ctx = (world as InternalWorld)[$internal]\n ctx.entityIndex = createEntityIndex()\n ctx.entityMasks = [[]]\n ctx.entityComponents = new Map()\n ctx.bitflag = 1\n ctx.componentMap = new Map()\n ctx.componentCount = 0\n ctx.queries = new Set()\n ctx.queriesHashMap = new Map()\n ctx.notQueries = new Set()\n ctx.dirtyQueries = new Set()\n ctx.entitiesWithRelations = new Set()\n return world\n}\n\n/**\n * Deletes a world by removing its internal data.\n *\n * @param {World} world - The world to be deleted.\n */\nexport const deleteWorld = (world: World) => {\n delete (world as any)[$internal];\n}\n\n/**\n * Returns all components registered to a world\n *\n * @param {World} world\n * @returns Array\n */\nexport const getWorldComponents = (world: World) =>\n Object.keys((world as InternalWorld)[$internal].componentMap)\n\n/**\n * Returns all existing entities in a world\n *\n * @param {World} world\n * @returns Array\n */\nexport const getAllEntities = (world: World): readonly EntityId[] => Array.from((world as InternalWorld)[$internal].entityComponents.keys())\n", "export type SparseSet = {\n add: (val: number) => void\n remove: (val: number) => void\n has: (val: number) => boolean\n sparse: number[]\n dense: number[] | Uint32Array\n reset: () => void\n}\n\nexport const createSparseSet = (): SparseSet => {\n\tconst dense: number[] = []\n\tconst sparse: number[] = []\n\n\tconst has = (val: number) => dense[sparse[val]] === val\n\n\tconst add = (val: number) => {\n\t\tif (has(val)) return\n\t\tsparse[val] = dense.push(val) - 1\n\t}\n\n\tconst remove = (val: number) => {\n\t\tif (!has(val)) return\n\t\tconst index = sparse[val]\n\t\tconst swapped = dense.pop()!\n\t\tif (swapped !== val) {\n\t\t\tdense[index] = swapped\n\t\t\tsparse[swapped] = index\n\t\t}\n\t}\n\n\tconst reset = () => {\n\t\tdense.length = 0\n\t\tsparse.length = 0\n\t}\n\n\treturn {\n\t\tadd,\n\t\tremove,\n\t\thas,\n\t\tsparse,\n\t\tdense,\n\t\treset,\n\t}\n}\n\nconst SharedArrayBufferOrArrayBuffer = typeof SharedArrayBuffer !== 'undefined' ? SharedArrayBuffer : ArrayBuffer\n\nexport const createUint32SparseSet = (initialCapacity: number = 1000): SparseSet => {\n\tconst sparse: number[] = []\n\tlet length = 0\n\tlet dense: Uint32Array = new Uint32Array(new SharedArrayBufferOrArrayBuffer(initialCapacity * 4))\n\n\tconst has = (val: number) => val < sparse.length && sparse[val] < length && dense[sparse[val]] === val\n\n\tconst add = (val: number) => {\n\t\tif (has(val)) return\n\t\tif (length >= dense.length) {\n\t\t\tconst newDense = new Uint32Array(new SharedArrayBufferOrArrayBuffer(dense.length * 2 * 4))\n\t\t\tnewDense.set(dense)\n\t\t\tdense = newDense\n\t\t}\n\t\tdense[length] = val\n\t\tsparse[val] = length\n\t\tlength++\n\t}\n\n\tconst remove = (val: number) => {\n\t\tif (!has(val)) return\n\t\tlength--\n\t\tconst index = sparse[val]\n\t\tconst swapped = dense[length]\n\t\tdense[index] = swapped\n\t\tsparse[swapped] = index\n\t}\n\n\tconst reset = () => {\n\t\tlength = 0\n\t\tsparse.length = 0\n\t}\n\n\treturn {\n\t\tadd,\n\t\tremove,\n\t\thas,\n\t\tsparse,\n\t\tget dense() {\n\t\t\treturn new Uint32Array(dense.buffer, 0, length)\n\t\t},\n\t\treset,\n\t}\n}", "import { EntityId } from \"../Entity\"\n\nexport type Observer = (entity: EntityId, ...args: any[]) => void | object\n\nexport interface Observable {\n subscribe: (observer: Observer) => () => void\n notify: (entity: EntityId, ...args: any[]) => void | object\n}\n\nexport const createObservable = (): Observable => {\n const observers = new Set()\n\n const subscribe = (observer: Observer) => {\n observers.add(observer)\n return () => {\n observers.delete(observer)\n }\n }\n const notify = (entity: EntityId, ...args: any[]) => {\n return Array.from(observers).reduce((acc, listener) => {\n const result = listener(entity, ...args)\n return result && typeof result === 'object' ? { ...acc, ...result } : acc\n }, {})\n }\n\n return {\n subscribe,\n notify\n }\n}\n", "import { createSparseSet, createUint32SparseSet, type SparseSet } from './utils/SparseSet'\nimport { hasComponent, registerComponent } from './Component'\nimport { ComponentRef, ComponentData } from './Component'\nimport { World } from \"./World\"\nimport { InternalWorld } from './World'\nimport { $internal } from './World'\nimport { createObservable } from './utils/Observer'\nimport { EntityId, Prefab } from './Entity'\n\n/**\n * @typedef {Uint32Array | readonly number[]} QueryResult\n * @description The result of a query, either as a Uint32Array or a readonly array of numbers.\n */\nexport type QueryResult = Uint32Array | readonly EntityId[]\n\n/**\n * @typedef {Object} Query\n * @description Represents a query in the ECS.\n * @property {ComponentRef[]} allComponents - All components in the query.\n * @property {ComponentRef[]} orComponents - Components in an OR relationship.\n * @property {ComponentRef[]} notComponents - Components that should not be present.\n * @property {Object.} masks - Bitmasks for each component generation.\n * @property {Object.} orMasks - OR bitmasks for each component generation.\n * @property {Object.} notMasks - NOT bitmasks for each component generation.\n * @property {Object.} hasMasks - HAS bitmasks for each component generation.\n * @property {number[]} generations - Component generations.\n * @property {SparseSet} toRemove - Set of entities to be removed.\n * @property {ReturnType} addObservable - Observable for entity additions.\n * @property {ReturnType} removeObservable - Observable for entity removals.\n */\nexport type Query = SparseSet & {\n\tallComponents: ComponentRef[]\n\torComponents: ComponentRef[]\n\tnotComponents: ComponentRef[]\n\tmasks: Record\n\torMasks: Record\n\tnotMasks: Record\n\thasMasks: Record\n\tgenerations: number[]\n\ttoRemove: SparseSet\n\taddObservable: ReturnType\n\tremoveObservable: ReturnType\n\tqueues: Record\n}\n\n/**\n * @typedef {'Or' | 'And' | 'Not'} QueryOperatorType\n * @description Types of query operators.\n */\nexport type QueryOperatorType = 'Or' | 'And' | 'Not'\n/**\n * Symbol for query operator type.\n * @type {Symbol}\n */\nexport const $opType = Symbol.for('bitecs-opType')\n\n/**\n * Symbol for query operator terms.\n * @type {Symbol}\n */\nexport const $opTerms = Symbol.for('bitecs-opTerms')\n\n/**\n * @typedef {Object} OpReturnType\n * @property {symbol} [$opType] - The type of the operator.\n * @property {symbol} [$opTerms] - The components involved in the operation.\n */\nexport type OpReturnType = {\n\t[$opType]: string\n\t[$opTerms]: ComponentRef[]\n}\n\n/**\n * @typedef {Function} QueryOperator\n * @description A function that creates a query operator.\n * @param {...ComponentRef} components - The components to apply the operator to.\n * @returns {OpReturnType} The result of the operator.\n */\nexport type QueryOperator = (...components: ComponentRef[]) => OpReturnType\n\n/**\n * @typedef {ComponentRef | QueryOperator} QueryTerm\n * @description A term in a query, either a component reference or a query operator.\n */\nexport type QueryTerm = ComponentRef | QueryOperator\n\n\n// Aliases\nexport type OrOp = QueryOperator\nexport type AndOp = QueryOperator\nexport type NotOp = QueryOperator\nexport type AnyOp = OrOp\nexport type AllOp = AndOp\nexport type NoneOp = NotOp\n\n/**\n * @function Or\n * @description Creates an 'Or' query operator.\n * @param {...ComponentRef} components - The components to apply the 'Or' operator to.\n * @returns {OpReturnType} The 'Or' operator configuration.\n */\nexport const Or: OrOp = (...components: ComponentRef[]) => ({\n\t[$opType]: 'Or',\n\t[$opTerms]: components\n})\n\n/**\n * @function And\n * @description Creates an 'And' query operator.\n * @param {...ComponentRef} components - The components to apply the 'And' operator to.\n * @returns {OpReturnType} The 'And' operator configuration.\n */\nexport const And: AndOp = (...components: ComponentRef[]) => ({\n\t[$opType]: 'And',\n\t[$opTerms]: components\n})\n\n/**\n * @function Not\n * @description Creates a 'Not' query operator.\n * @param {...ComponentRef} components - The components to apply the 'Not' operator to.\n * @returns {OpReturnType} The 'Not' operator configuration.\n */\nexport const Not: NotOp = (...components: ComponentRef[]) => ({\n\t[$opType]: 'Not',\n\t[$opTerms]: components\n})\n\nexport const Any: AnyOp = Or\nexport const All: AllOp = And\nexport const None: NoneOp = Not\n\n/**\n * @typedef {Function} ObservableHook\n * @description A function that creates an observable hook for queries.\n * @param {...QueryTerm} terms - The query terms to observe.\n * @returns {{type: 'add' | 'remove' | 'set', terms: QueryTerm[]}} The observable hook configuration.\n */\nexport type ObservableHookDef = (...terms: QueryTerm[]) => {\n\t[$opType]: 'add' | 'remove' | 'set' | 'get'\n\t[$opTerms]: QueryTerm[]\n}\n\nexport type ObservableHook = ReturnType\n\n/**\n * @function onAdd\n * @description Creates an 'add' observable hook.\n * @param {...QueryTerm} terms - The query terms to observe for addition.\n * @returns {OpReturnType} The 'add' observable hook configuration.\n */\nexport const onAdd: ObservableHookDef = (...terms: QueryTerm[]) => ({\n\t[$opType]: 'add',\n\t[$opTerms]: terms\n})\n\n/**\n * @function onRemove\n * @description Creates a 'remove' observable hook.\n * @param {...QueryTerm} terms - The query terms to observe for removal.\n * @returns {OpReturnType} The 'remove' observable hook configuration.\n */\nexport const onRemove: ObservableHookDef = (...terms: QueryTerm[]) => ({\n\t[$opType]: 'remove',\n\t[$opTerms]: terms\n})\n\n/**\n * @function onSet\n * @description Creates a 'set' observable hook.\n * @param {...QueryTerm} terms - The query terms to observe for setting.\n * @returns {OpReturnType} The 'set' observable hook configuration.\n */\nexport const onSet: ObservableHookDef = (component: ComponentRef) => ({\n\t[$opType]: 'set',\n\t[$opTerms]: [component]\n})\n\n/**\n * @function onGet\n * @description Creates a 'get' observable hook.\n * @param {...QueryTerm} terms - The query terms to observe for getting.\n * @returns {OpReturnType} The 'get' observable hook configuration.\n */\nexport const onGet: ObservableHookDef = (component: ComponentRef) => ({\n\t[$opType]: 'get',\n\t[$opTerms]: [component]\n})\n\n/**\n * @function observe\n * @description Observes changes in entities based on specified components.\n * @param {World} world - The world object.\n * @param {ObservableHook} hook - The observable hook.\n * @param {function(number): any} callback - The callback function to execute when changes occur.\n * @returns {function(): void} A function to unsubscribe from the observation.\n */\nexport function observe(world: World, hook: ObservableHook, callback: (eid: EntityId, ...args: any[]) => any): () => void {\n\tconst ctx = (world as InternalWorld)[$internal]\n\tconst { [$opType]: type, [$opTerms]: components } = hook\n\n\tif (type === 'add' || type === 'remove') {\n\t\tconst hash = queryHash(world, components)\n\t\tlet queryData = ctx.queriesHashMap.get(hash)!\n\n\t\tif (!queryData) {\n\t\t\tqueryData = registerQuery(world, components)\n\t\t}\n\n\t\tconst observableKey = type === 'add' ? 'addObservable' : 'removeObservable'\n\t\treturn queryData[observableKey].subscribe(callback)\n\t} else if (type === 'set' || type === 'get') {\n\t\tif (components.length !== 1) {\n\t\t\tthrow new Error('Set and Get hooks can only observe a single component')\n\t\t}\n\t\tconst component = components[0]\n\t\tlet componentData = ctx.componentMap.get(component)\n\t\tif (!componentData) {\n\t\t\tcomponentData = registerComponent(world, component)\n\t\t}\n\t\tconst observableKey = type === 'set' ? 'setObservable' : 'getObservable'\n\t\treturn componentData[observableKey].subscribe(callback)\n\t}\n\n\tthrow new Error(`Invalid hook type: ${type}`)\n}\n\n/**\n * @function queryHash\n * @description Generates a hash for a query based on its terms.\n * @param {World} world - The world object.\n * @param {QueryTerm[]} terms - The query terms.\n * @returns {string} The generated hash.\n */\nexport const queryHash = (world: World, terms: QueryTerm[]): string => {\n\tconst ctx = (world as InternalWorld)[$internal]\n\n\tconst getComponentId = (component: ComponentRef): number => {\n\t\tif (!ctx.componentMap.has(component)) {\n\t\t\tregisterComponent(world, component)\n\t\t}\n\t\treturn ctx.componentMap.get(component)!.id\n\t}\n\tconst termToString = (term: QueryTerm): string => {\n\t\tif ($opType in term) {\n\t\t\tconst componentIds = term[$opTerms].map(getComponentId)\n\t\t\tconst sortedComponentIds = componentIds.sort((a, b) => a - b)\n\t\t\tconst sortedType = term[$opType].toLowerCase()\n\t\t\treturn `${sortedType}(${sortedComponentIds.join(',')})`\n\t\t} else {\n\t\t\treturn getComponentId(term).toString()\n\t\t}\n\t}\n\n\treturn terms\n\t\t.map(termToString)\n\t\t.sort()\n\t\t.join('-')\n}\n\n/**\n * @function registerQuery\n * @description Registers a new query in the world.\n * @param {World} world - The world object.\n * @param {QueryTerm[]} terms - The query terms.\n * @param {Object} [options] - Additional options.\n * @param {boolean} [options.buffered] - Whether the query should be buffered.\n * @returns {Query} The registered query.\n */\nexport const registerQuery = (world: World, terms: QueryTerm[], options: { buffered?: boolean } = {}): Query => {\n\tconst ctx = (world as InternalWorld)[$internal]\n\tconst hash = queryHash(world, terms)\n\t// if (ctx.queriesHashMap.has(hash)) {\n\t// \treturn ctx.queriesHashMap.get(hash)!\n\t// }\n\tconst components: ComponentRef[] = []\n\tconst notComponents: ComponentRef[] = []\n\tconst orComponents: ComponentRef[] = []\n\n\tconst processComponents = (comps: ComponentRef[], targetArray: ComponentRef[]) => {\n\t\tcomps.forEach((comp: ComponentRef) => {\n\t\t\tif (!ctx.componentMap.has(comp)) registerComponent(world, comp)\n\t\t\ttargetArray.push(comp)\n\t\t})\n\t}\n\n\tterms.forEach((term: QueryTerm) => {\n\t\tif ($opType in term) {\n\t\t\tif (term[$opType] === 'Not') {\n\t\t\t\tprocessComponents(term[$opTerms], notComponents)\n\t\t\t} else if (term[$opType] === 'Or') {\n\t\t\t\tprocessComponents(term[$opTerms], orComponents)\n\t\t\t}\n\t\t} else {\n\t\t\tif (!ctx.componentMap.has(term)) registerComponent(world, term)\n\t\t\tcomponents.push(term)\n\t\t}\n\t})\n\n\tconst mapComponents = (c: ComponentRef) => ctx.componentMap.get(c)!\n\tconst allComponents = components.concat(notComponents.flat()).concat(orComponents.flat()).map(mapComponents)\n\n\tconst sparseSet = options.buffered ? createUint32SparseSet() : createSparseSet()\n\n\tconst toRemove = createSparseSet()\n\n\tconst generations = allComponents\n\t\t.map((c) => c.generationId)\n\t\t.reduce((a, v) => {\n\t\t\tif (a.includes(v)) return a\n\t\t\ta.push(v)\n\t\t\treturn a\n\t\t}, [] as number[])\n\n\tconst reduceBitflags = (a: { [key: number]: number }, c: ComponentData) => {\n\t\tif (!a[c.generationId]) a[c.generationId] = 0\n\t\ta[c.generationId] |= c.bitflag\n\t\treturn a\n\t}\n\n\tconst masks = components.map(mapComponents).reduce(reduceBitflags, {})\n\tconst notMasks = notComponents.map(mapComponents).reduce(reduceBitflags, {})\n\tconst orMasks = orComponents.map(mapComponents).reduce(reduceBitflags, {})\n\tconst hasMasks = allComponents.reduce(reduceBitflags, {})\n\n\tconst addObservable = createObservable()\n\tconst removeObservable = createObservable()\n\n\tconst query = Object.assign(sparseSet, {\n\t\tcomponents,\n\t\tnotComponents,\n\t\torComponents,\n\t\tallComponents,\n\t\tmasks,\n\t\tnotMasks,\n\t\torMasks,\n\t\thasMasks,\n\t\tgenerations,\n\t\ttoRemove,\n\t\taddObservable,\n\t\tremoveObservable,\n\t\tqueues: {},\n\t}) as Query\n\n\tctx.queries.add(query)\n\n\tctx.queriesHashMap.set(hash, query)\n\n\tallComponents.forEach((c) => {\n\t\tc.queries.add(query)\n\t})\n\n\tif (notComponents.length) ctx.notQueries.add(query)\n\n\tconst entityIndex = ctx.entityIndex\n\tfor (let i = 0; i < entityIndex.aliveCount; i++) {\n\t\tconst eid = entityIndex.dense[i]\n\t\tif (hasComponent(world, eid, Prefab)) continue\n\t\tconst match = queryCheckEntity(world, query, eid)\n\t\tif (match) {\n\t\t\tqueryAddEntity(query, eid)\n\t\t}\n\t}\n\n\treturn query\n}\n\n/**\n * @function innerQuery\n * @description Performs an internal query operation.\n * @param {World} world - The world object.\n * @param {QueryTerm[]} terms - The query terms.\n * @param {Object} [options] - Additional options.\n * @param {boolean} [options.buffered] - Whether the query should be buffered.\n * @returns {QueryResult} The result of the query.\n */\nexport function innerQuery(world: World, terms: QueryTerm[], options: { buffered?: boolean } = {}): QueryResult {\n\tconst ctx = (world as InternalWorld)[$internal]\n\tconst hash = queryHash(world, terms)\n\tlet queryData = ctx.queriesHashMap.get(hash)\n\tif (!queryData) {\n\t\tqueryData = registerQuery(world, terms, options)\n\t} else if (options.buffered && !('buffer' in queryData.dense)) {\n\t\tqueryData = registerQuery(world, terms, { buffered: true })\n\t}\n\treturn queryData.dense\n}\n\n/**\n * @function query\n * @description Performs a query operation.\n * @param {World} world - The world object.\n * @param {QueryTerm[]} terms - The query terms.\n * @returns {readonly EntityId[]} The result of the query as a readonly array of entity IDs.\n */\nexport function query(world: World, terms: QueryTerm[]): readonly EntityId[] {\n\tcommitRemovals(world)\n\treturn innerQuery(world, terms) as EntityId[]\n}\n\n/**\n * @function bufferQuery\n * @description Performs a buffered query operation.\n * @param {World} world - The world object.\n * @param {QueryTerm[]} terms - The query terms.\n * @returns {Uint32Array} The result of the query as a Uint32Array.\n */\nexport function bufferQuery(world: World, terms: QueryTerm[]): Uint32Array {\n\tcommitRemovals(world)\n\treturn innerQuery(world, terms, { buffered: true }) as Uint32Array\n}\n\n/**\n * @function queryCheckEntity\n * @description Checks if an entity matches a query.\n * @param {World} world - The world object.\n * @param {Query} query - The query to check against.\n * @param {number} eid - The entity ID to check.\n * @returns {boolean} True if the entity matches the query, false otherwise.\n */\nexport function queryCheckEntity(world: World, query: Query, eid: EntityId): boolean {\n\tconst ctx = (world as InternalWorld)[$internal]\n\tconst { masks, notMasks, orMasks, generations } = query\n\n\tfor (let i = 0; i < generations.length; i++) {\n\t\tconst generationId = generations[i]\n\t\tconst qMask = masks[generationId]\n\t\tconst qNotMask = notMasks[generationId]\n\t\tconst qOrMask = orMasks[generationId]\n\t\tconst eMask = ctx.entityMasks[generationId][eid]\n\n\t\tif (qNotMask && (eMask & qNotMask) !== 0) {\n\t\t\treturn false\n\t\t}\n\n\t\tif (qMask && (eMask & qMask) !== qMask) {\n\t\t\treturn false\n\t\t}\n\n\t\tif (qOrMask && (eMask & qOrMask) === 0) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\treturn true\n}\n\n/**\n * @function queryCheckComponent\n * @description Checks if a component matches a query.\n * @param {Query} query - The query to check against.\n * @param {ComponentData} c - The component data to check.\n * @returns {boolean} True if the component matches the query, false otherwise.\n */\nexport const queryCheckComponent = (query: Query, c: ComponentData) => {\n\tconst { generationId, bitflag } = c\n\tconst { hasMasks } = query\n\tconst mask = hasMasks[generationId]\n\treturn (mask & bitflag) === bitflag\n}\n\n/**\n * @function queryAddEntity\n * @description Adds an entity to a query.\n * @param {Query} query - The query to add the entity to.\n * @param {number} eid - The entity ID to add.\n */\nexport const queryAddEntity = (query: Query, eid: EntityId) => {\n\tquery.toRemove.remove(eid)\n\n\tquery.addObservable.notify(eid)\n\n\tquery.add(eid)\n}\n\n/**\n * @function queryCommitRemovals\n * @description Commits removals for a query.\n * @param {Query} query - The query to commit removals for.\n */\nconst queryCommitRemovals = (query: Query) => {\n\tfor (let i = 0; i < query.toRemove.dense.length; i++) {\n\t\tconst eid = query.toRemove.dense[i]\n\n\t\tquery.remove(eid)\n\t}\n\tquery.toRemove.reset()\n}\n\n/**\n * @function commitRemovals\n * @description Commits all pending removals for queries in the world.\n * @param {World} world - The world object.\n */\nexport const commitRemovals = (world: World) => {\n\tconst ctx = (world as InternalWorld)[$internal]\n\tif (!ctx.dirtyQueries.size) return\n\tctx.dirtyQueries.forEach(queryCommitRemovals)\n\tctx.dirtyQueries.clear()\n}\n\n/**\n * @function queryRemoveEntity\n * @description Removes an entity from a query.\n * @param {World} world - The world object.\n * @param {Query} query - The query to remove the entity from.\n * @param {number} eid - The entity ID to remove.\n */\nexport const queryRemoveEntity = (world: World, query: Query, eid: EntityId) => {\n\tconst ctx = (world as InternalWorld)[$internal]\n\tconst has = query.has(eid)\n\tif (!has || query.toRemove.has(eid)) return\n\tquery.toRemove.add(eid)\n\tctx.dirtyQueries.add(query)\n\tquery.removeObservable.notify(eid)\n}\n\n/**\n * @function removeQuery\n * @description Removes a query from the world.\n * @param {World} world - The world object.\n * @param {QueryTerm[]} terms - The query terms of the query to remove.\n */\nexport const removeQuery = (world: World, terms: QueryTerm[]) => {\n\tconst ctx = (world as InternalWorld)[$internal]\n\tconst hash = queryHash(world, terms)\n\tconst query = ctx.queriesHashMap.get(hash)\n\tif (query) {\n\t\tctx.queries.delete(query)\n\t\tctx.queriesHashMap.delete(hash)\n\t}\n}\n", "import { getEntityComponents, World } from '.'\nimport { EntityId } from './Entity'\nimport { defineHiddenProperty } from './utils/defineHiddenProperty'\n\n/**\n * Callback function type for when a target is removed from a relation.\n * @callback OnTargetRemovedCallback\n * @param {number} subject - The subject entity ID.\n * @param {number} target - The target entity ID.\n */\nexport type OnTargetRemovedCallback = (subject: EntityId, target: EntityId) => void\n\n/**\n * Possible types for a relation target.\n * @typedef {number | '*' | typeof Wildcard} RelationTarget\n */\nexport type RelationTarget = number | '*' | typeof Wildcard\n/**\n * Symbol for accessing the relation of a component.\n * @type {Symbol}\n */\nexport const $relation = Symbol.for('bitecs-relation')\n\n/**\n * Symbol for accessing the pair target of a component.\n * @type {Symbol}\n */\nexport const $pairTarget = Symbol.for('bitecs-pairTarget')\n\n/**\n * Symbol for checking if a component is a pair component.\n * @type {Symbol}\n */\nexport const $isPairComponent = Symbol.for('bitecs-isPairComponent')\n\n/**\n * Symbol for accessing the relation data of a component.\n * @type {Symbol}\n */\nexport const $relationData = Symbol.for('bitecs-relationData')\n\n/**\n * Interface for relation data.\n * @interface RelationData\n * @template T\n */\ntype RelationData = {\n pairsMap: Map, T>\n initStore: (eid: EntityId) => T\n exclusiveRelation: boolean\n autoRemoveSubject: boolean\n onTargetRemoved: OnTargetRemovedCallback\n}\n\n/**\n * Type definition for a Relation function.\n * @template T\n * @typedef {function} Relation\n * @param {RelationTarget} target - The target of the relation.\n * @returns {T} The relation component.\n */\nexport type Relation = (target: RelationTarget) => T\n\n/**\n * Creates a base relation.\n * @template T\n * @returns {Relation} The created base relation.\n */\nconst createBaseRelation = (): Relation => {\n const data = {\n pairsMap: new Map(),\n initStore: undefined,\n exclusiveRelation: false,\n autoRemoveSubject: false,\n onTargetRemoved: undefined\n }\n const relation = (target: RelationTarget): T => {\n if (target === undefined) throw Error('Relation target is undefined')\n const normalizedTarget = target === '*' ? Wildcard : target\n if (!data.pairsMap.has(normalizedTarget)) {\n const component = data.initStore ? data.initStore(target) : {} as T\n defineHiddenProperty(component, $relation, relation)\n defineHiddenProperty(component, $pairTarget, normalizedTarget)\n defineHiddenProperty(component, $isPairComponent, true)\n data.pairsMap.set(normalizedTarget, component)\n }\n\n return data.pairsMap.get(normalizedTarget)!\n }\n\n defineHiddenProperty(relation, $relationData, data)\n\n return relation as Relation\n}\n\n/**\n * Adds a store to a relation.\n * @template T\n * @param {function(): T} createStore - Function to create the store.\n * @returns {function(Relation): Relation} A function that modifies the relation.\n */\nexport const withStore = (createStore: (eid: EntityId) => T) => (relation: Relation): Relation => {\n const ctx = relation[$relationData] as RelationData\n ctx.initStore = createStore\n return relation\n}\n\n/**\n * Makes a relation exclusive.\n * @template T\n * @param {Relation} relation - The relation to make exclusive.\n * @returns {Relation} The modified relation.\n */\nexport const makeExclusive = (relation: Relation): Relation => {\n const ctx = relation[$relationData] as RelationData\n ctx.exclusiveRelation = true\n return relation\n}\n\n/**\n * Adds auto-remove subject behavior to a relation.\n * @template T\n * @param {Relation} relation - The relation to modify.\n * @returns {Relation} The modified relation.\n */\nexport const withAutoRemoveSubject = (relation: Relation): Relation => {\n const ctx = relation[$relationData] as RelationData\n ctx.autoRemoveSubject = true\n return relation\n}\n\n/**\n * Adds an onTargetRemoved callback to a relation.\n * @template T\n * @param {OnTargetRemovedCallback} onRemove - The callback to add.\n * @returns {function(Relation): Relation} A function that modifies the relation.\n */\nexport const withOnTargetRemoved = (onRemove: OnTargetRemovedCallback) => (relation: Relation): Relation => {\n const ctx = relation[$relationData] as RelationData\n ctx.onTargetRemoved = onRemove\n return relation\n}\n\n// TODO: withSetter\n/**\n * Adds validation to a relation.\n * @template T\n * @param {function(T): boolean} validateFn - The validation function.\n * @returns {function(Relation): Relation} A function that modifies the relation.\n */\nconst withValidation = (validateFn: (value: T) => boolean) => (relation: Relation): Relation => {\n const originalRelation = relation\n return ((target: RelationTarget): T => {\n const component = originalRelation(target)\n if (!validateFn(component)) {\n throw new Error('Validation failed for relation component')\n }\n return component\n }) as Relation\n}\n\n/**\n * Creates a pair from a relation and a target.\n * @template T\n * @param {Relation} relation - The relation.\n * @param {RelationTarget} target - The target.\n * @returns {T} The created pair.\n * @throws {Error} If the relation is undefined.\n */\nexport const Pair = (relation: Relation, target: RelationTarget): T => {\n if (relation === undefined) throw Error('Relation is undefined')\n return relation(target)\n}\n\n/**\n * Gets the relation targets for an entity.\n * @param {World} world - The world object.\n * @param {Relation} relation - The relation to get targets for.\n * @param {number} eid - The entity ID.\n * @returns {Array} An array of relation targets.\n */\nexport const getRelationTargets = (world: World, eid: EntityId, relation: Relation): number[] => {\n\tconst components = getEntityComponents(world, eid)\n\tconst targets = []\n\tfor (const c of components) {\n\t\tif (c[$relation] === relation && c[$pairTarget] !== Wildcard && !isRelation(c[$pairTarget])) {\n\t\t\ttargets.push(c[$pairTarget])\n\t\t}\n\t}\n\treturn targets\n}\n\n/**\n * Creates a new relation.\n * @template T\n * @param {...Array): Relation>} modifiers - Modifier functions for the relation.\n * @returns {Relation} The created relation.\n */\nexport function createRelation(...modifiers: Array<(relation: Relation) => Relation>): Relation\n\n/**\n * Creates a new relation with options.\n * @template T\n * @param {Object} options - Options for creating the relation.\n * @param {function(): T} [options.store] - Function to create the store.\n * @param {boolean} [options.exclusive] - Whether the relation is exclusive.\n * @param {boolean} [options.autoRemoveSubject] - Whether to auto-remove the subject.\n * @param {OnTargetRemovedCallback} [options.onTargetRemoved] - Callback for when a target is removed.\n * @returns {Relation} The created relation.\n */\nexport function createRelation(options: {\n store?: () => T\n exclusive?: boolean\n autoRemoveSubject?: boolean\n onTargetRemoved?: OnTargetRemovedCallback\n}): Relation\nexport function createRelation(\n ...args: Array<(relation: Relation) => Relation> | [{\n store?: () => T\n exclusive?: boolean\n autoRemoveSubject?: boolean\n onTargetRemoved?: OnTargetRemovedCallback\n }]\n): Relation {\n if (args.length === 1 && typeof args[0] === 'object') {\n const { store, exclusive, autoRemoveSubject, onTargetRemoved } = args[0]\n const modifiers = [\n store && withStore(store),\n exclusive && makeExclusive,\n autoRemoveSubject && withAutoRemoveSubject,\n onTargetRemoved && withOnTargetRemoved(onTargetRemoved)\n ].filter(Boolean) as Array<(relation: Relation) => Relation>\n return modifiers.reduce((acc, modifier) => modifier(acc), createBaseRelation())\n } else {\n const modifiers = args as Array<(relation: Relation) => Relation>\n return modifiers.reduce((acc, modifier) => modifier(acc), createBaseRelation())\n }\n}\n\n/**\n * Symbol used to mark a relation as a wildcard relation\n */\nexport const $wildcard = Symbol.for('bitecs-wildcard')\n\n/**\n * Creates a wildcard relation that matches any target.\n * @template T\n * @returns {Relation} The created wildcard relation.\n */\nexport function createWildcardRelation(): Relation {\n const relation = createBaseRelation()\n Object.defineProperty(relation, $wildcard, {\n value: true,\n enumerable: false,\n writable: false,\n configurable: false\n })\n return relation\n}\n\n/**\n * Gets the singleton wildcard instance.\n * @returns {Relation} The global wildcard relation instance.\n */\nexport function getWildcard(): Relation {\n const GLOBAL_WILDCARD = Symbol.for('bitecs-global-wildcard')\n \n if (!(globalThis as any)[GLOBAL_WILDCARD]) {\n (globalThis as any)[GLOBAL_WILDCARD] = createWildcardRelation()\n }\n \n return (globalThis as any)[GLOBAL_WILDCARD]\n}\n\n/**\n * Wildcard relation.\n * @type {Relation}\n */\nexport const Wildcard = getWildcard()\n\n/**\n * Creates an IsA relation.\n * @template T\n * @returns {Relation} The created IsA relation.\n */\nexport function createIsARelation(): Relation {\n return createBaseRelation()\n}\n\n/**\n * Gets the singleton IsA instance.\n * @returns {Relation} The global IsA relation instance.\n */\nexport function getIsA(): Relation {\n const GLOBAL_ISA = Symbol.for('bitecs-global-isa')\n \n if (!(globalThis as any)[GLOBAL_ISA]) {\n (globalThis as any)[GLOBAL_ISA] = createIsARelation()\n }\n \n return (globalThis as any)[GLOBAL_ISA]\n}\n\n/**\n * IsA relation.\n * @type {Relation}\n */\nexport const IsA = getIsA()\n\n/**\n * Checks if a relation is a wildcard relation.\n * @param {any} relation - The relation to check.\n * @returns {boolean} True if the relation is a wildcard relation, false otherwise.\n */\nexport function isWildcard(relation: any): boolean {\n if (!relation) return false\n const symbols = Object.getOwnPropertySymbols(relation)\n return symbols.includes($wildcard)\n}\n\n/**\n * Checks if a component is a relation.\n * @param {any} component - The component to check.\n * @returns {boolean} True if the component is a relation, false otherwise.\n */\nexport function isRelation(component: any): boolean {\n if (!component) return false\n const symbols = Object.getOwnPropertySymbols(component)\n return symbols.includes($relationData)\n}\n", "import { entityExists, EntityId, getEntityComponents, Prefab } from './Entity'\nimport { queryAddEntity, queryCheckEntity, queryRemoveEntity } from './Query'\nimport { Query } from './Query'\nimport {\n\tIsA,\n\tPair,\n\tWildcard,\n\tgetRelationTargets,\n\t$relationData,\n\t$isPairComponent,\n\t$pairTarget,\n\t$relation\n} from './Relation'\nimport { createObservable, Observable } from './utils/Observer'\nimport { $internal, InternalWorld, World, WorldContext } from './World'\n\n/**\n * Represents a reference to a component.\n * @typedef {any} ComponentRef\n */\nexport type ComponentRef = any\n\n/**\n * Represents the data associated with a component.\n * @interface ComponentData\n * @property {number} id - The unique identifier for the component.\n * @property {number} generationId - The generation ID of the component.\n * @property {number} bitflag - The bitflag used for component masking.\n * @property {ComponentRef} ref - Reference to the component.\n * @property {Set} queries - Set of queries associated with the component.\n * @property {Observable} setObservable - Observable for component changes.\n */\nexport interface ComponentData {\n\tid: number\n\tgenerationId: number\n\tbitflag: number\n\tref: ComponentRef\n\tqueries: Set\n\tsetObservable: Observable\n\tgetObservable: Observable\n}\n\n/**\n * Registers a component with the world.\n * @param {World} world - The world object.\n * @param {ComponentRef} component - The component to register.\n * @returns {ComponentData} The registered component data.\n * @throws {Error} If the component is null or undefined.\n */\nexport const registerComponent = (world: World, component: ComponentRef) => {\n\tif (!component) {\n\t\tthrow new Error(`bitECS - Cannot register null or undefined component`)\n\t}\n\n\tconst ctx = (world as InternalWorld)[$internal]\n\tconst queries = new Set()\n\n\tconst data: ComponentData = {\n\t\tid: ctx.componentCount++,\n\t\tgenerationId: ctx.entityMasks.length - 1,\n\t\tbitflag: ctx.bitflag,\n\t\tref: component,\n\t\tqueries,\n\t\tsetObservable: createObservable(),\n\t\tgetObservable: createObservable(),\n\t}\n\n\tctx.componentMap.set(component, data)\n\n\tctx.bitflag *= 2\n\tif (ctx.bitflag >= 2 ** 31) {\n\t\tctx.bitflag = 1\n\t\tctx.entityMasks.push([])\n\t}\n\n\treturn data\n}\n\n/**\n * Registers multiple components with the world.\n * @param {World} world - The world object.\n * @param {ComponentRef[]} components - Array of components to register.\n */\nexport const registerComponents = (world: World, components: ComponentRef[]) => {\n\tcomponents.forEach((component) => registerComponent(world, component))\n}\n\n/**\n * Checks if an entity has a specific component.\n * @param {World} world - The world object.\n * @param {number} eid - The entity ID.\n * @param {ComponentRef} component - The component to check for.\n * @returns {boolean} True if the entity has the component, false otherwise.\n */\nexport const hasComponent = (world: World, eid: EntityId, component: ComponentRef): boolean => {\n\tconst ctx = (world as InternalWorld)[$internal]\n\tconst registeredComponent = ctx.componentMap.get(component)\n\tif (!registeredComponent) return false\n\n\tconst { generationId, bitflag } = registeredComponent\n\tconst mask = ctx.entityMasks[generationId][eid]\n\n\treturn (mask & bitflag) === bitflag\n}\n/**\n * Retrieves the data associated with a component for a specific entity.\n * @param {World} world - The world object.\n * @param {EntityId} eid - The entity ID.\n * @param {ComponentRef} component - The component to retrieve data for.\n * @returns {any} The component data, or undefined if the component is not found or the entity doesn't have the component.\n */\nexport const getComponentData = (world: World, eid: EntityId, component: ComponentRef): any => {\n\tconst ctx = (world as InternalWorld)[$internal]\n\tconst componentData = ctx.componentMap.get(component)\n\n\tif (!componentData) {\n\t\treturn undefined\n\t}\n\n\tif (!hasComponent(world, eid, component)) {\n\t\treturn undefined\n\t}\n\n\t// Notify observers that this component is being accessed\n\treturn componentData.getObservable.notify(eid)\n}\n\n/**\n * Helper function to set component data.\n * @param {ComponentRef} component - The component to set.\n * @param {any} data - The data to set for the component.\n * @returns {{ component: ComponentRef, data: any }} An object containing the component and its data.\n */\nexport const set = (component: T, data: any): { component: T, data: any } => ({\n\tcomponent,\n\tdata\n})\n\n/**\n * Recursvely inherits components from one entity to another.\n * @param {World} world - The world object.\n * @param {number} baseEid - The ID of the entity inheriting components.\n * @param {number} inheritedEid - The ID of the entity being inherited from.\n * @param {boolean} isFirstSuper - Whether this is the first super in the inheritance chain.\n */\nconst recursivelyInherit = (ctx: WorldContext, world: World, baseEid: EntityId, inheritedEid: EntityId, visited = new Set()): void => {\n\t// Guard against circular inheritance\n\tif (visited.has(inheritedEid)) return\n\tvisited.add(inheritedEid)\n\t\n\t// Add IsA relation first\n\taddComponent(world, baseEid, IsA(inheritedEid))\n\t\n\t// Copy components and their data from this level\n\t// This needs to happen before recursing to ancestors so closer ancestors take precedence\n\tfor (const component of getEntityComponents(world, inheritedEid)) {\n\t\t// TODO: inherit reference vs copy\n\t\tif (component === Prefab) continue\n\t\t\n\t\t// Only add component if entity doesn't already have it\n\t\t// This ensures closer ancestors take precedence\n\t\tif (!hasComponent(world, baseEid, component)) {\n\t\t\taddComponent(world, baseEid, component)\n\t\t\t\n\t\t\tconst componentData = ctx.componentMap.get(component)\n\t\t\tif (componentData?.setObservable) {\n\t\t\t\tconst data = getComponentData(world, inheritedEid, component)\n\t\t\t\tcomponentData.setObservable.notify(baseEid, data)\n\t\t\t}\n\t\t}\n\t}\n\t\n\t// Then recursively inherit from ancestors\n\t// This ensures more distant ancestors don't override closer ones\n\tfor (const parentEid of getRelationTargets(world, inheritedEid, IsA)) {\n\t\trecursivelyInherit(ctx, world, baseEid, parentEid, visited)\n\t}\n}\n\n/**\n * Represents a component with data to be set on an entity.\n */\ntype ComponentSetter = { component: ComponentRef; data: T }\n\n/**\n * Adds one or more components to an entity.\n * @param {World} world - The world object.\n * @param {EntityId} eid - The entity ID.\n * @param {...(ComponentRef | ComponentSetter)} components - Components to add or set.\n * @throws {Error} If the entity does not exist in the world.\n */\nexport const addComponent = (world: World, eid: EntityId, ...components: (ComponentRef | ComponentSetter)[]): void => {\n\tif (!entityExists(world, eid)) {\n\t\tthrow new Error(`Cannot add component - entity ${eid} does not exist in the world.`)\n\t}\n\t\n\tconst ctx = (world as InternalWorld)[$internal]\n\t\n\tcomponents.forEach(componentOrSet => {\n\t\tconst component = 'component' in componentOrSet ? componentOrSet.component : componentOrSet\n\t\tconst data = 'data' in componentOrSet ? componentOrSet.data : undefined\n\n\t\tif (!ctx.componentMap.has(component)) registerComponent(world, component)\n\n\t\tconst componentData = ctx.componentMap.get(component)!\n\t\tif (data !== undefined) {\n\t\t\tcomponentData.setObservable.notify(eid, data)\n\t\t}\n\n\t\tif (hasComponent(world, eid, component)) return\n\n\t\tconst { generationId, bitflag, queries } = componentData\n\n\t\tctx.entityMasks[generationId][eid] |= bitflag\n\n\t\tif (!hasComponent(world, eid, Prefab)) {\n\t\t\tqueries.forEach((queryData: Query) => {\n\t\t\t\tqueryData.toRemove.remove(eid)\n\t\t\t\tconst match = queryCheckEntity(world, queryData, eid)\n\n\t\t\t\tif (match) queryAddEntity(queryData, eid)\n\t\t\t\telse queryRemoveEntity(world, queryData, eid)\n\t\t\t})\n\t\t}\n\t\tctx.entityComponents.get(eid)!.add(component)\n\t\tif (component[$isPairComponent]) {\n\t\t\tconst relation = component[$relation]\n\t\t\tconst target = component[$pairTarget]\n\n\t\t\t// Add both Wildcard pairs for relation and target\n\t\t\taddComponent(world, eid, Pair(relation, Wildcard))\n\t\t\taddComponent(world, eid, Pair(Wildcard, target))\n\n\t\t\t// For non-Wildcard targets, add Wildcard pair to track relation targets\n\t\t\tif (typeof target === 'number') {\n\t\t\t\t// Add Wildcard pair for target being a relation target\n\t\t\t\taddComponent(world, target, Pair(Wildcard, eid))\n\t\t\t\taddComponent(world, target, Pair(Wildcard, relation))\n\t\t\t\t// Track entities with relations for autoRemoveSubject\n\t\t\t\tctx.entitiesWithRelations.add(target)\n\t\t\t\tctx.entitiesWithRelations.add(eid)\n\t\t\t}\n\n\t\t\t// add target to a set to make autoRemoveSubject checks faster\n\t\t\tctx.entitiesWithRelations.add(target)\n\n\t\t\tconst relationData = relation[$relationData]\n\t\t\tif (relationData.exclusiveRelation === true && target !== Wildcard) {\n\t\t\t\tconst oldTarget = getRelationTargets(world, eid, relation)[0]\n\t\t\t\tif (oldTarget !== undefined && oldTarget !== null && oldTarget !== target) {\n\t\t\t\t\tremoveComponent(world, eid, relation(oldTarget))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (relation === IsA) {\n\t\t\t\tconst inheritedTargets = getRelationTargets(world, eid, IsA)\n\t\t\t\tfor (const inherited of inheritedTargets) {\n\t\t\t\t\trecursivelyInherit(ctx, world, eid, inherited)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n}\n\n/**\n * Alias for addComponent.\n */\nexport const addComponents = addComponent\n\n/**\n * Removes one or more components from an entity.\n * @param {World} world - The world object.\n * @param {number} eid - The entity ID.\n * @param {...ComponentRef} components - Components to remove.\n * @throws {Error} If the entity does not exist in the world.\n */\nexport const removeComponent = (world: World, eid: EntityId, ...components: ComponentRef[]) => {\n\tconst ctx = (world as InternalWorld)[$internal]\n\tif (!entityExists(world, eid)) {\n\t\tthrow new Error(`Cannot remove component - entity ${eid} does not exist in the world.`)\n\t}\n\n\tcomponents.forEach(component => {\n\t\tif (!hasComponent(world, eid, component)) return\n\n\t\tconst componentNode = ctx.componentMap.get(component)!\n\t\tconst { generationId, bitflag, queries } = componentNode\n\n\t\tctx.entityMasks[generationId][eid] &= ~bitflag\n\n\t\tqueries.forEach((queryData: Query) => {\n\t\t\tqueryData.toRemove.remove(eid)\n\n\t\t\tconst match = queryCheckEntity(world, queryData, eid)\n\n\t\t\tif (match) queryAddEntity(queryData, eid)\n\t\t\telse queryRemoveEntity(world, queryData, eid)\n\t\t})\n\n\t\tctx.entityComponents.get(eid)!.delete(component)\n\n\t\tif (component[$isPairComponent]) {\n\t\t\tconst target = component[$pairTarget]\n\t\t\tremoveComponent(world, eid, Pair(Wildcard, target))\n\n\t\t\tconst relation = component[$relation]\n\t\t\tconst otherTargets = getRelationTargets(world, eid, relation)\n\t\t\tif (otherTargets.length === 0) {\n\t\t\t\tremoveComponent(world, eid, Pair(relation, Wildcard))\n\t\t\t}\n\t\t}\n\t})\n}\n\n/**\n * Alias for removeComponent.\n */\nexport const removeComponents = removeComponent\n", "import { addComponent, removeComponent } from './Component'\nimport {\n\tinnerQuery,\n\tqueryAddEntity,\n\tqueryCheckEntity,\n\tqueryRemoveEntity,\n} from './Query'\nimport { Pair, Wildcard, $isPairComponent, $relation, $pairTarget, $relationData } from './Relation'\nimport { World } from \"./World\"\nimport { InternalWorld } from './World'\nimport { addEntityId, isEntityIdAlive, removeEntityId } from './EntityIndex'\nimport { $internal } from './World'\nimport { ComponentRef } from './Component'\n\nexport type EntityId = number\n\nexport const Prefab = {}\nexport const addPrefab = (world: World): EntityId => {\n\tconst eid = addEntity(world)\n\n\taddComponent(world, eid, Prefab)\n\n\treturn eid\n}\n\n/**\n * Adds a new entity to the specified world.\n *\n * @param {World} world\n * @returns {number} eid\n */\nexport const addEntity = (world: World): EntityId => {\n\tconst ctx = (world as InternalWorld)[$internal]\n\tconst eid = addEntityId(ctx.entityIndex)\n\n\tctx.notQueries.forEach((q) => {\n\t\tconst match = queryCheckEntity(world, q, eid)\n\t\tif (match) queryAddEntity(q, eid)\n\t})\n\n\tctx.entityComponents.set(eid, new Set())\n\n\treturn eid\n}\n\n/**\n * Removes an existing entity from the specified world.\n *\n * @param {World} world\n * @param {number} eid\n */\n\nexport const removeEntity = (world: World, eid: EntityId) => {\n\tconst ctx = (world as InternalWorld)[$internal]\n\t// Check if entity is already removed\n\tif (!isEntityIdAlive(ctx.entityIndex, eid)) return\n\n\t// Remove relation components from entities that have a relation to this one, breadth-first\n\t// e.g. addComponent(world, child, ChildOf(parent))\n\t// when parent is removed, we need to remove the child\n\tconst removalQueue = [eid]\n\tconst processedEntities = new Set()\n while (removalQueue.length > 0) {\n \n\t\tconst currentEid = removalQueue.shift()!\n if (processedEntities.has(currentEid)) continue\n processedEntities.add(currentEid)\n\n const componentRemovalQueue = []\n\n\t\tif (ctx.entitiesWithRelations.has(currentEid)) {\n\t\t\tfor (const subject of innerQuery(world, [Wildcard(currentEid)])) {\n\t\t\t\tif (!entityExists(world, subject)) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tfor (const component of ctx.entityComponents.get(subject)!) {\n\t\t\t\t\tif (!component[$isPairComponent]) {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\n\t\t\t\t\tconst relation = component[$relation]\n\t\t\t\t\tconst relationData = relation[$relationData]\n\t\t\t\t\tcomponentRemovalQueue.push(() => removeComponent(world, subject, Pair(Wildcard, currentEid)))\n\n\t\t\t\t\tif (component[$pairTarget] === currentEid) {\n\t\t\t\t\t\tcomponentRemovalQueue.push(() => removeComponent(world, subject, component))\n\t\t\t\t\t\tif (relationData.autoRemoveSubject) {\n\t\t\t\t\t\t\tremovalQueue.push(subject)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (relationData.onTargetRemoved) {\n\t\t\t\t\t\t\tcomponentRemovalQueue.push(() => relationData.onTargetRemoved(world, subject, currentEid))\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tctx.entitiesWithRelations.delete(currentEid)\n\t\t}\n\n for (const removeOperation of componentRemovalQueue) {\n removeOperation()\n }\n\n\t\tfor (const eid of removalQueue) {\n\t\t\tremoveEntity(world, eid)\n\t\t}\n\n\t\t// Remove entity from all queries\n\t\tfor (const query of ctx.queries) {\n\t\t\tqueryRemoveEntity(world, query, currentEid)\n\t\t}\n\n\t\t// Free the entity ID\n\t\tremoveEntityId(ctx.entityIndex, currentEid)\n\n\t\t// Remove all entity state from world\n\t\tctx.entityComponents.delete(currentEid)\n\n\t\t// Clear entity bitmasks\n\t\tfor (let i = 0; i < ctx.entityMasks.length; i++) {\n\t\t\tctx.entityMasks[i][currentEid] = 0\n\t\t}\n\t}\n}\n\n/**\n * Returns an array of components that an entity possesses.\n *\n * @param {*} world\n * @param {*} eid\n */\nexport const getEntityComponents = (world: World, eid: EntityId): ComponentRef[] => {\n\tconst ctx = (world as InternalWorld)[$internal]\n\tif (eid === undefined) throw new Error(`getEntityComponents: entity id is undefined.`)\n\tif (!isEntityIdAlive(ctx.entityIndex, eid))\n\t\tthrow new Error(`getEntityComponents: entity ${eid} does not exist in the world.`)\n\treturn Array.from(ctx.entityComponents.get(eid)!)\n}\n\n/**\n * Checks the existence of an entity in a world\n *\n * @param {World} world\n * @param {number} eid\n */\nexport const entityExists = (world: World, eid: EntityId) => isEntityIdAlive((world as InternalWorld)[$internal].entityIndex, eid)\n", "type Func = (...args: any) => any\nexport const pipe = \n (...functions: [T, ...U[], R]): ((...args: Parameters) => ReturnType) => {\n return (...args: Parameters): ReturnType => \n functions.reduce((result, fn) => [fn(...result)], args as any)[0]\n}\n"], + "mappings": "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", + "names": ["defineHiddenProperty", "obj", "key", "value", "getId", "index", "id", "getVersion", "incrementVersion", "newVersion", "withVersioning", "versionBits", "createEntityIndex", "options", "config", "versioning", "entityBits", "entityMask", "versionShift", "versionMask", "addEntityId", "recycledId", "entityId", "removeEntityId", "denseIndex", "lastIndex", "lastId", "newId", "isEntityIdAlive", "$internal", "createBaseWorld", "context", "entityIndex", "defineHiddenProperty", "createEntityIndex", "createWorld", "args", "arg", "resetWorld", "world", "ctx", "deleteWorld", "getWorldComponents", "getAllEntities", "createSparseSet", "dense", "sparse", "has", "val", "index", "swapped", "SharedArrayBufferOrArrayBuffer", "createUint32SparseSet", "initialCapacity", "length", "newDense", "createObservable", "observers", "observer", "entity", "args", "acc", "listener", "result", "$opType", "$opTerms", "Or", "components", "And", "Not", "Any", "All", "None", "onAdd", "terms", "onRemove", "onSet", "component", "onGet", "observe", "world", "hook", "callback", "ctx", "$internal", "type", "hash", "queryHash", "queryData", "registerQuery", "componentData", "registerComponent", "getComponentId", "termToString", "term", "sortedComponentIds", "a", "b", "options", "notComponents", "orComponents", "processComponents", "comps", "targetArray", "comp", "mapComponents", "allComponents", "sparseSet", "createUint32SparseSet", "createSparseSet", "toRemove", "generations", "v", "reduceBitflags", "c", "masks", "notMasks", "orMasks", "hasMasks", "addObservable", "createObservable", "removeObservable", "query", "entityIndex", "i", "eid", "hasComponent", "Prefab", "queryCheckEntity", "queryAddEntity", "innerQuery", "commitRemovals", "queryCheckEntity", "world", "query", "eid", "ctx", "$internal", "masks", "notMasks", "orMasks", "generations", "i", "generationId", "qMask", "qNotMask", "qOrMask", "eMask", "queryAddEntity", "query", "eid", "queryCommitRemovals", "i", "commitRemovals", "world", "ctx", "$internal", "queryRemoveEntity", "removeQuery", "terms", "hash", "queryHash", "$relation", "$pairTarget", "$isPairComponent", "$relationData", "createBaseRelation", "data", "relation", "target", "normalizedTarget", "Wildcard", "component", "defineHiddenProperty", "withStore", "createStore", "ctx", "makeExclusive", "withAutoRemoveSubject", "withOnTargetRemoved", "onRemove", "Pair", "relation", "target", "getRelationTargets", "world", "eid", "components", "getEntityComponents", "targets", "c", "$relation", "$pairTarget", "Wildcard", "isRelation", "createRelation", "args", "store", "exclusive", "autoRemoveSubject", "onTargetRemoved", "withStore", "makeExclusive", "withAutoRemoveSubject", "withOnTargetRemoved", "acc", "modifier", "createBaseRelation", "$wildcard", "createWildcardRelation", "getWildcard", "GLOBAL_WILDCARD", "createIsARelation", "getIsA", "GLOBAL_ISA", "IsA", "isWildcard", "component", "$relationData", "registerComponent", "world", "component", "ctx", "$internal", "queries", "data", "createObservable", "registerComponents", "components", "hasComponent", "eid", "registeredComponent", "generationId", "bitflag", "getComponentData", "componentData", "set", "recursivelyInherit", "baseEid", "inheritedEid", "visited", "addComponent", "IsA", "getEntityComponents", "Prefab", "parentEid", "getRelationTargets", "entityExists", "componentOrSet", "queryData", "queryCheckEntity", "queryAddEntity", "queryRemoveEntity", "$isPairComponent", "relation", "$relation", "target", "$pairTarget", "Pair", "Wildcard", "$relationData", "oldTarget", "removeComponent", "inheritedTargets", "inherited", "addComponents", "componentNode", "removeComponents", "Prefab", "addPrefab", "world", "eid", "addEntity", "addComponent", "ctx", "$internal", "addEntityId", "q", "queryCheckEntity", "queryAddEntity", "removeEntity", "isEntityIdAlive", "removalQueue", "processedEntities", "currentEid", "componentRemovalQueue", "subject", "innerQuery", "Wildcard", "entityExists", "component", "$isPairComponent", "relationData", "$relation", "$relationData", "removeComponent", "Pair", "$pairTarget", "removeOperation", "query", "queryRemoveEntity", "removeEntityId", "i", "getEntityComponents", "pipe", "functions", "args", "result", "fn"] +} diff --git a/src/components/index.js b/src/components/index.js new file mode 100644 index 0000000..91d910a --- /dev/null +++ b/src/components/index.js @@ -0,0 +1,157 @@ +const DefaultSize = 512 + +export const Rgba8 = { + r: new Uint8Array(DefaultSize), + g: new Uint8Array(DefaultSize), + b: new Uint8Array(DefaultSize), + a: new Uint8Array(DefaultSize), +} + +export const Range = { + min: new Float32Array(DefaultSize), + max: new Float32Array(DefaultSize) +} + +export const UVector2 = { + x: new Uint32Array(DefaultSize), + y: new Uint32Array(DefaultSize) +} + +export const UVector3 = { + ...UVector2, + z: new Uint32Array(DefaultSize) +} + +export const Vector2 = { + x: new Float32Array(DefaultSize), + y: new Float32Array(DefaultSize), +} + +export const Vector3 = { + ...Vector2, + z: new Float32Array(DefaultSize) +} + +export const Quaternion = { + ...Vector3, + w: new Float32Array(DefaultSize) +} + +export const Transform = { + translation: Vector3, + rotation: Quaternion, + scale: Vector3 +} + +export const Viewport = { + position: UVector2, + size: UVector2, + depth: Range +} + +export const RenderTarget = [] + +class RenderGraph { + #nodes = new Map() + #edges = new Map() + + add(name, render, dependencies = []) { + this.node.set(name, render) + this.edges.set(name, dependencies) + } + + update(world) { + const executed = new Set() + const order = this.sort() + + if(!order) { + return + } + + for(const node of order) { + const render = this.nodes.get(node) + render(world) + executed.add(node) + } + } + + sort() { + const visited = new Set() + const stack = [] + const cycles = new Set() + + const visit = node => { + if(cycles.has(node)) { + return false + } + + if (visited.has(node)) { + return true + } + + visited.add(node) + cycles.add(node) + + for(const dep of this.dependentsFor(name)) { + if (!visit(dep)) { + return false + } + } + + cycles.delete(name) + stack.push(node) + } + + for(const node in this.nodes) { + if(!visited.has(node) && !visit(node)) { + return + } + } + + return stack.reverse() + } + + dependentsFor(name) { + return this.edges.values() + .filter(deps => deps.includes(name)) + } +} + +export const Camera = { + viewport: Viewport, + order: new Int32Array(DefaultSize), + clearColor: Rgba8, + renderTarget: RenderTarget +} + +export const Renderable = {} + +const Topology = Object.freeze({ + Points: 0, + Lines: 1, + LineStrip: 2, + LineLoop: 3, + Triangles: 4, + TriangleStrip: 5, + TriangleFan: 6 +}) + +export const VertexPositions = new Float32Array(1024) +export const Indices = new Uint16Array(1024) + +export const Mesh = { + topology: new Uint8Array(DefaultSize), + positions: new Uint32Array(DefaultSize), + indices: new Uint32Array(DefaultSize), + vao: new Uint32Array(DefaultSize), + drawMode: new Uint32Array(DefaultSize), + vertexCount: new Uint32Array(DefaultSize), + indexCount: new Uint32Array(DefaultSize) +} + +export const Sprite = { + data: [], + height: new Uint32Array(DefaultSize), + width: new Uint32Array(DefaultSize) +} + diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..3b33e76 --- /dev/null +++ b/src/index.js @@ -0,0 +1,58 @@ +import * as Components from './components/index.js' +const { Transform, Camera, Renderable, Sprite } = Components +import { Renderer2D } from './render/index.js' +import { addEntity, addComponent, createWorld, set, observe, onSet } from '../public/vendor/bitecs/index.js' + +const canvas = document.querySelector('main canvas') +const addComponents = (world, entity, components) => { + components.forEach(component => addComponent(world, entity, component)) +} + +const setData = (component, eid, data) => { + const entries = Object.entries(data) + if (Array.isArray(data) || ArrayBuffer.isView(data) || entries.length === 0) { + component[eid] = data + } else { + entries.forEach(([key, value]) => setData(component[key], eid, value)) + } +} + +if (canvas.getContext) { + const world = createWorld() + + Object.values(Components).forEach(component => { + observe(world, onSet(component), (eid, params) => { + setData(component, eid, params) + }) + }) + + const camera = addEntity(world) + addComponents(world, camera, [ + Transform, + set(Camera, { viewport: { position: { x: 16, y: 16 } } }) + ]) + + const obj = addEntity(world) + + const pixels = new Uint8ClampedArray(64 * 64 * 4) + for (let i = 0; i < pixels.length; i += 4) { + pixels[i + 0] = 255 + pixels[i + 3] = 255 + } + + addComponents(world, obj, [ + Renderable, + set(Transform, { translation: { x: 32, y: 32 } }), + set(Sprite, { + data: pixels, + width: 64, + height: 64 + }) + ]) + + const renderer = Renderer2D(canvas) + renderer(world) +} else { + // canvas not supported +} + diff --git a/src/mixins/index.js b/src/mixins/index.js new file mode 100644 index 0000000..92a761b --- /dev/null +++ b/src/mixins/index.js @@ -0,0 +1,4 @@ +export const mixin = (target, mixin) => { + Object.assign(target, mixin) +} + diff --git a/src/render/index.js b/src/render/index.js new file mode 100644 index 0000000..c3cdea4 --- /dev/null +++ b/src/render/index.js @@ -0,0 +1,110 @@ +import { query } from '/public/vendor/bitecs/index.js' +import { Transform, Camera, Renderable } from '/src/components/index.js' + +const vertSource = `#version 300 es +in vec2 a_position; +in vec4 a_color; + +uniform vec2 u_resolution; +uniform vec2 u_cameraPosition; +uniform float u_cameraZoom; + +out vec4 v_color; + +void main() { + vec2 position = (a_position - u_cameraPosition) * u_cameraZoom; + vec2 clipSpace = position / (u_resolution / 2.0) - 1.0; + gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); + v_color = a_color; +}` + +const fragSource = `#version 300 es +precision mediump float; +in vec4 v_color; +out vec4 outColor; + +void main() { + outColor = v_color; +}` + +const createMesh = (world, gl, entity, positions, indices, drawMode) => { + addComponent(world, Mesh, entity) + addComponent(world, VertexPositions, entity) + + VertexPositions.data.set(positions, entity * positions.length) + + if (indices) { + addComponent(world, Indices, entity) + Indices.data.set(indices, entity * indices.length) + } + + const vao = gl.createVertexArray() + gl.bindVertexArray(vao) + + const positionBuffer = gl.createBuffer() + gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer) + gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW) + gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0) + gl.enableVertexAttribArray(0) + + if (indices) { + const indexBuffer = gl.createBuffer() + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer) + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW) + } + + gl.bindVertexArray(null) + + MeshHandle.positionBuffer[entity] = positionBuffer + MeshHandle.indexBuffer[entity] = indexBuffer + MeshHandle.vao[entity] = vao + MeshHandle.drawMode[entity] = drawMode + MeshHandle.vertexCount[entity] = positions.length / 3 + MeshHandle.indexCount[entity] = indices ? indices.length : 0 +} + +export const Renderer2D = canvas => { + const gl = canvas.getContext('webgl2') + const program = Program.fromSource(gl, vertSource, fragSource) + const position = new Attribute(gl, program, 'a_position', new Buffer(), new BufferSchema(DataType.f32, { size: 2 })) + const color = new Attribute(gl, program, 'a_color', new Buffer(), new BufferSchema(DataType.f32, { size: 4 })) + const resolution = new Uniform(gl, program, 'u_resolution', 2, UniformType.Float) + const cameraPosition = new Uniform(gl, program, 'u_cameraPosition', 2, UniformType.Float) + + // TODO: make this a property of camera + const viewport = new Viewport(gl) + viewport.resize() + + // TODO: separate into window class + window.addEventListener('resize', () => { + canvas.width = window.innerWidth + canvas.height = window.innerHeight + resolution.set(canvas.width, canvas.height) + viewport.resize() + }) + + return world => { + viewport.clear() + + const cameras = query(world, [Transform, Camera]) + + // FIXME: Supporting only one camera for now + const camera = cameras[0] + const vx = Camera.viewport.position.x[camera] + const vy = Camera.viewport.position.y[camera] + const target = Camera.renderTarget[camera] || ctx + + cameraPosition.set(vx, vy) + + const renderable = query(world, [Renderable, Transform]) + + for (let i = 0; i < renderable.length; i++) { + const eid = renderable[i] + const x = Transform.translation.x[eid] - vx + const y = Transform.translation.y[eid] - vy + + //target.putImageData(new ImageData(Sprite.data[eid], Sprite.width[eid], Sprite.height[eid]), x, y) + } + } +} + diff --git a/src/render/webgl.js b/src/render/webgl.js new file mode 100644 index 0000000..fc352f8 --- /dev/null +++ b/src/render/webgl.js @@ -0,0 +1,298 @@ +class GLObject { + #gl + + constructor(gl) { + this.#gl = gl + } +} + +export class ShaderError extends Error { + constructor(message) { + super(message) + } +} + +export class Shader extends GLObject { + #gl + #shader + #type + + constructor(gl, type, source) { + super(gl) + const shader = gl.createShader(type) + gl.shaderSource(shader, source) + gl.compileShader(shader) + + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + gl.deleteShader(shader) + throw new ShaderError(gl.getShaderInfoLog(shader)) + } + + this.#shader = shader + this.#type = type + } + + static vertex(gl, source) { + return new Shader(gl, gl.VERTEX_SHADER, source) + } + + static fragment(gl, source) { + return new Shader(gl, gl.FRAGMENT_SHADER, source) + } + + attach(program) { + this.#gl.attachShader(program, this.#shader) + } +} + +export class ProgramError extends Error { + constructor(message) { + super(message) + } +} + +export class Program { + #program + + constructor(gl, vertexShader, fragmentShader) { + super(gl) + + const program = gl.createProgram() + + vertexShader.attach(program) + fragmentShader.attach(program) + + gl.linkProgram(program) + + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + gl.deleteProgram(program) + throw new ProgramError(gl.getProgramInfoLog(program)) + } + + this.#program = program + + } + + static fromSource(gl, vertexSource, fragmentSource) { + return new Program( + gl, + Shader.vertex(gl, vertexSource), + Shader.fragment(gl, fragmentSource) + ) + } +} + +export const DataType = { + i8: 5120, + u8: 5121, + i16: 5122, + u16: 5123, + f16: 5131, + f32: 5126, + i32: 5124, + u32: 5125 +} + +export class Buffer extends GLObject { + #buffer + #target + + constructor(gl, target = gl.ARRAY_BUFFER) { + super(gl) + + const buffer = gl.createBuffer() + + this.#buffer = buffer + this.#target = target + } + + get size() { + return this.#gl.getBufferParameter( + this.#target, + this.#gl.BUFFER_SIZE + ) + } + + get usage() { + return this.#gl.getBufferParameter( + this.#target, + this.#gl.BUFFER_USAGE + ) + } + + bind() { + this.#gl.bindBuffer(this.#target, this.#buffer) + } + + set(value, usage) { + if(!usage) { + console.warn('WARN: Buffer.set called without "usage" argument. Defaulting to DYNAMIC_DRAW') + usage = gl.DYNAMIC_DRAW + } + + this.#gl.bufferData( + this.#target, + value, + usage + ) + } +} + +export class BufferSchema { + type + #size + normalize + stride + offset + + constructor(type, { size = 4, normalize = false, stride = 0, offset = 0 } = {}) { + this.type = type + this.#size = size + this.normalize = normalize + this.stride = stride + this.offset = offset + } + + get size() { + return this.#size + } + + set size(value) { + if (value > 0 && value < 5) { + this.#size = value + } else { + throw new RangeError("BufferSchema size must be between 1 and 4") + } + } + + bind(gl, location) { + gl.vertexAttribPointer( + location, + this.size, + this.type, + this.normalize, + this.stride, + this.offset + ) + } +} + +export class Attribute extends GLObject { + #name + #buffer + #program + #location + #schema + + constructor(gl, program, name, buffer, schema) { + super(gl) + + this.#name = name + this.#buffer = buffer + this.#program = program + this.#schema = schema + this.#location = gl.getAttribLocation(program, name) + } + + get buffer() { + return this.#buffer + } + + get location() { + return this.#location + } + + bind() { + this.#gl.enableVertexAttribArray(this.#location) + this.#buffer.bind() + this.#schema.bind(this.#gl, this.#location) + } +} + +export const UniformType = { + Int: 'i', + IntVec: 'iv', + UInt: 'ui', + UIntVec: 'uiv', + Float: 'f', + FloatVec: 'fv' +} + +// TODO: clean this api up +export class Uniform extends GLObject { + #name + #program + #location + #length + #type + #fn + + constructor(gl, program, name, length, type) { + super(gl) + this.#name = name + this.#program = program + this.#location = gl.getUniformLocation(program, name) + this.#length = length + this.#type = type + this.#setFn(gl, length, type) + } + + #setFn(gl, length, type) { + this.#fn = gl[`uniform${length}${type}`].bind(gl) + } + + get length() { + return this.#length + } + + set length(value) { + this.#length = value + this.#setFn(this.#gl, value, this.#type) + } + + get type() { + return this.#type + } + + set type(value) { + this.#type = value + this.#setFn(this.#gl, this.#length, value) + } + + // TODO: add data validation + set(...args) { + this.#fn(this.#location, ...args) + } +} + +export class Viewport extends GLObject { + constructor(gl, clearColor = [0, 0, 0, 1]) { + super(gl) + this.clearColor = clearColor + } + + get clearColor() { + return this.#gl.getParameter(this.#gl.COLOR_CLEAR_VALUE) + } + + set clearColor(value) { + this.#gl.clearColor(...value) + } + + get MaxViewportDimensions() { + return this.#gl.getParameter(this.#gl.MAX_VIEWPORT_DIMS) + } + + get bounds() { + return this.#gl.getParameter(this.#gl.VIEWPORT) + } + + resize(x, y, width, height) { + this.#gl.viewport(x, y, width, height) + } + + clear() { + this.#gl.clear(this.#gl.COLOR_BUFFER_BIT) + } +} + diff --git a/src/types.js b/src/types.js new file mode 100644 index 0000000..3cc37a7 --- /dev/null +++ b/src/types.js @@ -0,0 +1,15 @@ +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Typed_arrays#typed_array_views +export const i8 = size => createStore(Int8Array, size) +export const u8 = size => createStore(Uint8Array, size) +export const u8c = size => createStore(Uint8ClampedArray, size) +export const i16 = size => createStore(Int16Array, size) +export const u16 = size => createStore(Uint16Array, size) +export const i32 = size => createStore(Int32Array, size) +export const u32 = size => createStore(Uint32Array, size) +export const f16 = size => createStore(Float16Array, size) +export const f32 = size => createStore(Float32Array, size) +export const f64 = size => createStore(Float64Array, size) +export const i64 = size => createStore(BigInt64Array, size) +export const u64 = size => createStore(BigUint64Array, size) + +const createStore = (type, size = 64) => new type(size)