iris-ecs 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +721 -0
  3. package/dist/actions.d.ts +43 -0
  4. package/dist/actions.d.ts.map +1 -0
  5. package/dist/actions.js +35 -0
  6. package/dist/actions.js.map +1 -0
  7. package/dist/archetype.d.ts +194 -0
  8. package/dist/archetype.d.ts.map +1 -0
  9. package/dist/archetype.js +412 -0
  10. package/dist/archetype.js.map +1 -0
  11. package/dist/component.d.ts +89 -0
  12. package/dist/component.d.ts.map +1 -0
  13. package/dist/component.js +237 -0
  14. package/dist/component.js.map +1 -0
  15. package/dist/encoding.d.ts +204 -0
  16. package/dist/encoding.d.ts.map +1 -0
  17. package/dist/encoding.js +215 -0
  18. package/dist/encoding.js.map +1 -0
  19. package/dist/entity.d.ts +129 -0
  20. package/dist/entity.d.ts.map +1 -0
  21. package/dist/entity.js +243 -0
  22. package/dist/entity.js.map +1 -0
  23. package/dist/event.d.ts +237 -0
  24. package/dist/event.d.ts.map +1 -0
  25. package/dist/event.js +293 -0
  26. package/dist/event.js.map +1 -0
  27. package/dist/filters.d.ts +121 -0
  28. package/dist/filters.d.ts.map +1 -0
  29. package/dist/filters.js +202 -0
  30. package/dist/filters.js.map +1 -0
  31. package/dist/index.d.ts +24 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +54 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/name.d.ts +70 -0
  36. package/dist/name.d.ts.map +1 -0
  37. package/dist/name.js +172 -0
  38. package/dist/name.js.map +1 -0
  39. package/dist/observer.d.ts +83 -0
  40. package/dist/observer.d.ts.map +1 -0
  41. package/dist/observer.js +62 -0
  42. package/dist/observer.js.map +1 -0
  43. package/dist/query.d.ts +198 -0
  44. package/dist/query.d.ts.map +1 -0
  45. package/dist/query.js +299 -0
  46. package/dist/query.js.map +1 -0
  47. package/dist/registry.d.ts +118 -0
  48. package/dist/registry.d.ts.map +1 -0
  49. package/dist/registry.js +112 -0
  50. package/dist/registry.js.map +1 -0
  51. package/dist/relation.d.ts +60 -0
  52. package/dist/relation.d.ts.map +1 -0
  53. package/dist/relation.js +171 -0
  54. package/dist/relation.js.map +1 -0
  55. package/dist/removal.d.ts +27 -0
  56. package/dist/removal.d.ts.map +1 -0
  57. package/dist/removal.js +66 -0
  58. package/dist/removal.js.map +1 -0
  59. package/dist/resource.d.ts +78 -0
  60. package/dist/resource.d.ts.map +1 -0
  61. package/dist/resource.js +86 -0
  62. package/dist/resource.js.map +1 -0
  63. package/dist/scheduler.d.ts +106 -0
  64. package/dist/scheduler.d.ts.map +1 -0
  65. package/dist/scheduler.js +204 -0
  66. package/dist/scheduler.js.map +1 -0
  67. package/dist/schema.d.ts +117 -0
  68. package/dist/schema.d.ts.map +1 -0
  69. package/dist/schema.js +113 -0
  70. package/dist/schema.js.map +1 -0
  71. package/dist/world.d.ts +172 -0
  72. package/dist/world.d.ts.map +1 -0
  73. package/dist/world.js +127 -0
  74. package/dist/world.js.map +1 -0
  75. package/package.json +52 -0
@@ -0,0 +1,202 @@
1
+ import { ensureEntity } from "./entity.js";
2
+ import { fireObserverEvent, registerObserverCallback, unregisterObserverCallback } from "./observer.js";
3
+ // ============================================================================
4
+ // Filter Hashing
5
+ // ============================================================================
6
+ /**
7
+ * Generates a unique hash string for filter terms.
8
+ *
9
+ * @param terms - Filter terms containing include/exclude type arrays
10
+ * @returns Deterministic hash string (e.g., "+1:5:12|-3:7")
11
+ *
12
+ * @example
13
+ * const hash = hashFilterTerms({ include: [5, 1, 12], exclude: [7, 3] });
14
+ * // Returns "+1:5:12|-3:7" (sorted for consistency)
15
+ */
16
+ export function hashFilterTerms(terms) {
17
+ // Sort to ensure same terms always produce same hash regardless of input order
18
+ const includeHash = terms.include.toSorted((a, b) => a - b).join(":");
19
+ const excludeHash = terms.exclude.toSorted((a, b) => a - b).join(":");
20
+ return `+${includeHash}|-${excludeHash}`;
21
+ }
22
+ // ============================================================================
23
+ // Archetype Matching
24
+ // ============================================================================
25
+ /**
26
+ * Tests whether an archetype satisfies the given filter terms.
27
+ *
28
+ * @param archetype - Archetype to test against filter
29
+ * @param terms - Filter terms with include/exclude type constraints
30
+ * @returns True if archetype contains ALL included types and NONE of excluded types
31
+ *
32
+ * @example
33
+ * const matches = matchesFilterTerms(archetype, {
34
+ * include: [PositionType, VelocityType],
35
+ * exclude: [DisabledType]
36
+ * });
37
+ */
38
+ export function matchesFilterTerms(archetype, terms) {
39
+ // Verify ALL required types are present
40
+ for (let i = 0; i < terms.include.length; i++) {
41
+ const typeId = terms.include[i];
42
+ if (!archetype.typesSet.has(typeId)) {
43
+ return false;
44
+ }
45
+ }
46
+ // Verify NONE of excluded types are present
47
+ for (let i = 0; i < terms.exclude.length; i++) {
48
+ const typeId = terms.exclude[i];
49
+ if (archetype.typesSet.has(typeId)) {
50
+ return false;
51
+ }
52
+ }
53
+ return true;
54
+ }
55
+ /**
56
+ * Finds all archetypes matching filter terms using rarest-type optimization.
57
+ *
58
+ * Uses the "rarest type first" strategy: starts with the type that appears in
59
+ * the fewest archetypes, then filters that smaller set. This minimizes the
60
+ * number of archetypes we need to check.
61
+ *
62
+ * @param world - World instance containing archetype registry
63
+ * @param terms - Filter terms with include/exclude type constraints
64
+ * @returns Array of archetypes that match all filter criteria
65
+ *
66
+ * @example
67
+ * const archetypes = findMatchingArchetypes(world, {
68
+ * include: [PositionType, VelocityType],
69
+ * exclude: []
70
+ * });
71
+ */
72
+ export function findMatchingArchetypes(world, terms) {
73
+ // Empty include list is a degenerate case - return no matches
74
+ if (terms.include.length === 0) {
75
+ return [];
76
+ }
77
+ // Find the rarest type (appears in fewest archetypes) for optimal iteration
78
+ let rarestId = terms.include[0];
79
+ let minCount = Number.POSITIVE_INFINITY;
80
+ for (let i = 0; i < terms.include.length; i++) {
81
+ const typeId = terms.include[i];
82
+ const meta = ensureEntity(world, typeId);
83
+ const count = meta.records.length;
84
+ if (count === 0) {
85
+ // If any required type has zero archetypes, no matches are possible
86
+ return [];
87
+ }
88
+ if (count < minCount) {
89
+ rarestId = typeId;
90
+ minCount = count;
91
+ }
92
+ }
93
+ // Only iterate archetypes containing the rarest type, then filter further
94
+ const rarestMeta = ensureEntity(world, rarestId);
95
+ const archetypes = rarestMeta.records;
96
+ const matches = [];
97
+ for (let a = 0; a < archetypes.length; a++) {
98
+ const archetype = archetypes[a];
99
+ if (matchesFilterTerms(archetype, terms)) {
100
+ matches.push(archetype);
101
+ }
102
+ }
103
+ return matches;
104
+ }
105
+ // ============================================================================
106
+ // Filter Registry
107
+ // ============================================================================
108
+ /**
109
+ * Destroys a filter and cleans up its observer callbacks.
110
+ * Called when a filter's archetype cache becomes empty.
111
+ */
112
+ function destroyFilter(world, filterId) {
113
+ const filter = world.filters.byId.get(filterId);
114
+ // Unregister callbacks to prevent memory leaks and stale references
115
+ unregisterObserverCallback(world, "archetypeCreated", filter.onArchetypeCreate);
116
+ unregisterObserverCallback(world, "archetypeDestroyed", filter.onArchetypeDelete);
117
+ fireObserverEvent(world, "filterDestroyed", filter);
118
+ world.filters.byId.delete(filterId);
119
+ }
120
+ /**
121
+ * Gets or creates a filter with observer-based cache invalidation.
122
+ *
123
+ * Filters are cached by their terms hash. When created, observers are registered
124
+ * to automatically update the cached archetype list as archetypes are created
125
+ * or destroyed.
126
+ *
127
+ * @param world - World instance containing filter registry
128
+ * @param terms - Filter terms defining which archetypes to match
129
+ * @returns FilterMeta with cached matching archetypes
130
+ *
131
+ * @example
132
+ * const filter = ensureFilter(world, {
133
+ * include: [PositionType, VelocityType],
134
+ * exclude: [DisabledType]
135
+ * });
136
+ * // filter.archetypes contains all matching archetypes
137
+ */
138
+ export function ensureFilter(world, terms) {
139
+ const filterId = hashFilterTerms(terms);
140
+ let filterMeta = world.filters.byId.get(filterId);
141
+ if (!filterMeta) {
142
+ // Create new filter with observer callbacks that close over terms and filterMeta
143
+ filterMeta = {
144
+ terms,
145
+ archetypes: findMatchingArchetypes(world, terms),
146
+ // Called when a new archetype is created - add to cache if it matches
147
+ onArchetypeCreate: (archetype) => {
148
+ if (!matchesFilterTerms(archetype, terms)) {
149
+ return;
150
+ }
151
+ filterMeta.archetypes.push(archetype);
152
+ },
153
+ // Called when an archetype is destroyed - remove from cache, cleanup if empty
154
+ onArchetypeDelete: (archetype) => {
155
+ const idx = filterMeta.archetypes.indexOf(archetype);
156
+ if (idx !== -1) {
157
+ filterMeta.archetypes.splice(idx, 1);
158
+ }
159
+ // Auto-cleanup: destroy filter when it has no matching archetypes
160
+ if (filterMeta.archetypes.length === 0) {
161
+ destroyFilter(world, filterId);
162
+ }
163
+ },
164
+ };
165
+ world.filters.byId.set(filterId, filterMeta);
166
+ // Register observers to keep archetype cache in sync
167
+ registerObserverCallback(world, "archetypeCreated", filterMeta.onArchetypeCreate);
168
+ registerObserverCallback(world, "archetypeDestroyed", filterMeta.onArchetypeDelete);
169
+ fireObserverEvent(world, "filterCreated", filterMeta);
170
+ }
171
+ return filterMeta;
172
+ }
173
+ // ============================================================================
174
+ // Filter Iteration
175
+ // ============================================================================
176
+ /**
177
+ * Iterates all entities matching a filter in reverse order.
178
+ *
179
+ * Reverse iteration allows safe entity deletion during iteration without
180
+ * skipping entities or invalidating indices.
181
+ *
182
+ * @param filter - Filter metadata containing cached matching archetypes
183
+ * @returns Generator yielding entity IDs from all matching archetypes
184
+ *
185
+ * @example
186
+ * for (const entity of iterateFilterEntities(filter)) {
187
+ * // Safe to delete entity here due to reverse iteration
188
+ * destroyEntity(world, entity);
189
+ * }
190
+ */
191
+ export function* iterateFilterEntities(filter) {
192
+ const archetypes = filter.archetypes;
193
+ for (let a = 0; a < archetypes.length; a++) {
194
+ const archetype = archetypes[a];
195
+ const entities = archetype.entities;
196
+ // Reverse iteration enables safe deletion during traversal
197
+ for (let i = entities.length - 1; i >= 0; i--) {
198
+ yield entities[i];
199
+ }
200
+ }
201
+ }
202
+ //# sourceMappingURL=filters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filters.js","sourceRoot":"","sources":["../src/filters.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export { createWorld, resetWorld } from "./world.js";
2
+ export { createEntity, destroyEntity, isEntityAlive } from "./entity.js";
3
+ export { addComponent, emitComponentChanged, getComponentValue, hasComponent, removeComponent, setComponentValue, } from "./component.js";
4
+ export { defineComponent, defineRelation, defineTag, Wildcard } from "./registry.js";
5
+ export { getPairRelation, getPairTarget, getRelationTargets, pair } from "./relation.js";
6
+ export { addResource, getResourceValue, hasResource, removeResource, setResourceValue, } from "./resource.js";
7
+ export { getName, lookupByName, Name, removeName, setName } from "./name.js";
8
+ export { added, changed, destroyQuery, ensureQuery, fetchEntities, fetchEntitiesWithQuery, fetchFirstEntity, not, } from "./query.js";
9
+ export { addSystem, buildSchedule, executeSchedule, executeScheduleAsync, } from "./scheduler.js";
10
+ export type { ActionGetter, ActionInitializer, Actions } from "./actions.js";
11
+ export type { Component, Entity, EntityId, Pair, Relation, RelationTargetId, Tag } from "./encoding.js";
12
+ export type { Event, EventSchema } from "./event.js";
13
+ export type { FilterTerms } from "./filters.js";
14
+ export type { AddedModifier, ChangedModifier, ModifierType, NotModifier, QueryMeta, QueryModifier } from "./query.js";
15
+ export type { ScheduleId, SystemMeta, SystemOptions, SystemRunner } from "./scheduler.js";
16
+ export type { InferSchemaRecord, Schema, SchemaRecord } from "./schema.js";
17
+ export type { World } from "./world.js";
18
+ export { clearEvents, countEvents, defineEvent, EVENT_EXPIRY_TICKS, emitEvent, fetchEvents, fetchLastEvent, hasEvents, } from "./event.js";
19
+ export { removed } from "./removal.js";
20
+ export type { EventPayloads, EventType, Observer, ObserverMeta } from "./observer.js";
21
+ export { registerObserverCallback, unregisterObserverCallback } from "./observer.js";
22
+ export { Type } from "./schema.js";
23
+ export { defineActions } from "./actions.js";
24
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAMrD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAMzE,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AAMxB,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAMrF,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAMzF,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,gBAAgB,GACjB,MAAM,eAAe,CAAC;AAMvB,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAM7E,OAAO,EACL,KAAK,EACL,OAAO,EACP,YAAY,EACZ,WAAW,EACX,aAAa,EACb,sBAAsB,EACtB,gBAAgB,EAChB,GAAG,GACJ,MAAM,YAAY,CAAC;AAMpB,OAAO,EACL,SAAS,EACT,aAAa,EACb,eAAe,EACf,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AAMxB,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC7E,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,gBAAgB,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACxG,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACrD,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACtH,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC1F,YAAY,EAAE,iBAAiB,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3E,YAAY,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAMxC,OAAO,EACL,WAAW,EACX,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,SAAS,EACT,WAAW,EACX,cAAc,EACd,SAAS,GACV,MAAM,YAAY,CAAC;AAMpB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAMvC,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACtF,OAAO,EAAE,wBAAwB,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAMrF,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAMnC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,54 @@
1
+ // ============================================================================
2
+ // World Operations
3
+ // ============================================================================
4
+ export { createWorld, resetWorld } from "./world.js";
5
+ // ============================================================================
6
+ // Entity Operations
7
+ // ============================================================================
8
+ export { createEntity, destroyEntity, isEntityAlive } from "./entity.js";
9
+ // ============================================================================
10
+ // Component Operations
11
+ // ============================================================================
12
+ export { addComponent, emitComponentChanged, getComponentValue, hasComponent, removeComponent, setComponentValue, } from "./component.js";
13
+ // ============================================================================
14
+ // Registry Operations
15
+ // ============================================================================
16
+ export { defineComponent, defineRelation, defineTag, Wildcard } from "./registry.js";
17
+ // ============================================================================
18
+ // Relation Operations
19
+ // ============================================================================
20
+ export { getPairRelation, getPairTarget, getRelationTargets, pair } from "./relation.js";
21
+ // ============================================================================
22
+ // Resource Operations
23
+ // ============================================================================
24
+ export { addResource, getResourceValue, hasResource, removeResource, setResourceValue, } from "./resource.js";
25
+ // ============================================================================
26
+ // Name System
27
+ // ============================================================================
28
+ export { getName, lookupByName, Name, removeName, setName } from "./name.js";
29
+ // ============================================================================
30
+ // Query Operations
31
+ // ============================================================================
32
+ export { added, changed, destroyQuery, ensureQuery, fetchEntities, fetchEntitiesWithQuery, fetchFirstEntity, not, } from "./query.js";
33
+ // ============================================================================
34
+ // System Operations
35
+ // ============================================================================
36
+ export { addSystem, buildSchedule, executeSchedule, executeScheduleAsync, } from "./scheduler.js";
37
+ // ============================================================================
38
+ // Event System
39
+ // ============================================================================
40
+ export { clearEvents, countEvents, defineEvent, EVENT_EXPIRY_TICKS, emitEvent, fetchEvents, fetchLastEvent, hasEvents, } from "./event.js";
41
+ // ============================================================================
42
+ // Removal Detection
43
+ // ============================================================================
44
+ export { removed } from "./removal.js";
45
+ export { registerObserverCallback, unregisterObserverCallback } from "./observer.js";
46
+ // ============================================================================
47
+ // Schema Factories
48
+ // ============================================================================
49
+ export { Type } from "./schema.js";
50
+ // ============================================================================
51
+ // Actions
52
+ // ============================================================================
53
+ export { defineActions } from "./actions.js";
54
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAErD,+EAA+E;AAC/E,oBAAoB;AACpB,+EAA+E;AAE/E,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEzE,+EAA+E;AAC/E,uBAAuB;AACvB,+EAA+E;AAE/E,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,eAAe,EACf,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AAExB,+EAA+E;AAC/E,sBAAsB;AACtB,+EAA+E;AAE/E,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAErF,+EAA+E;AAC/E,sBAAsB;AACtB,+EAA+E;AAE/E,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAEzF,+EAA+E;AAC/E,sBAAsB;AACtB,+EAA+E;AAE/E,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,gBAAgB,GACjB,MAAM,eAAe,CAAC;AAEvB,+EAA+E;AAC/E,cAAc;AACd,+EAA+E;AAE/E,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7E,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E,OAAO,EACL,KAAK,EACL,OAAO,EACP,YAAY,EACZ,WAAW,EACX,aAAa,EACb,sBAAsB,EACtB,gBAAgB,EAChB,GAAG,GACJ,MAAM,YAAY,CAAC;AAEpB,+EAA+E;AAC/E,oBAAoB;AACpB,+EAA+E;AAE/E,OAAO,EACL,SAAS,EACT,aAAa,EACb,eAAe,EACf,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AAexB,+EAA+E;AAC/E,eAAe;AACf,+EAA+E;AAE/E,OAAO,EACL,WAAW,EACX,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,SAAS,EACT,WAAW,EACX,cAAc,EACd,SAAS,GACV,MAAM,YAAY,CAAC;AAEpB,+EAA+E;AAC/E,oBAAoB;AACpB,+EAA+E;AAE/E,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAOvC,OAAO,EAAE,wBAAwB,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAErF,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAEnC,+EAA+E;AAC/E,UAAU;AACV,+EAA+E;AAE/E,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
package/dist/name.d.ts ADDED
@@ -0,0 +1,70 @@
1
+ import type { EntityId } from "./encoding.js";
2
+ import type { World } from "./world.js";
3
+ /**
4
+ * Name component for entity identification.
5
+ *
6
+ * Stores a single string value that must be unique within the world.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * addComponent(world, entity, Name, { value: "player-1" });
11
+ * const name = getComponentValue(world, entity, Name, "value");
12
+ * ```
13
+ */
14
+ export declare const Name: import("./encoding.js").Component<{
15
+ value: import("./schema.js").Schema<string>;
16
+ }>;
17
+ /**
18
+ * Initializes the name system for a world by setting up the dual-index registry
19
+ * and observer callbacks that keep name mappings synchronized with entity lifecycle.
20
+ * Called automatically by createWorld().
21
+ * @internal
22
+ */
23
+ export declare function initNameSystem(world: World): void;
24
+ /**
25
+ * Gets the name of an entity.
26
+ * @param world - World instance
27
+ * @param entityId - Entity to get name from
28
+ * @returns Entity name or undefined if not named
29
+ * @example
30
+ * ```ts
31
+ * const name = getName(world, entity);
32
+ * ```
33
+ */
34
+ export declare function getName(world: World, entityId: EntityId): string | undefined;
35
+ /**
36
+ * Sets or updates the name of an entity.
37
+ * @param world - World instance
38
+ * @param entityId - Entity to name
39
+ * @param name - Name to assign (must be unique and non-empty)
40
+ * @throws Error if name is empty or already exists
41
+ * @example
42
+ * ```ts
43
+ * setName(world, player, "player-1");
44
+ * ```
45
+ */
46
+ export declare function setName(world: World, entityId: EntityId, name: string): void;
47
+ /**
48
+ * Removes the name from an entity.
49
+ * @param world - World instance
50
+ * @param entityId - Entity to remove name from
51
+ * @example
52
+ * ```ts
53
+ * removeName(world, entity);
54
+ * ```
55
+ */
56
+ export declare function removeName(world: World, entityId: EntityId): void;
57
+ /**
58
+ * Looks up an entity by name, optionally validating required components.
59
+ * @param world - World instance
60
+ * @param name - Name to look up
61
+ * @param components - Optional components to validate presence
62
+ * @returns Entity ID or undefined if not found or missing required components
63
+ * @example
64
+ * ```ts
65
+ * const player = lookupByName(world, "player-1");
66
+ * const player = lookupByName(world, "player-1", Position, Health);
67
+ * ```
68
+ */
69
+ export declare function lookupByName(world: World, name: string, ...components: EntityId[]): EntityId | undefined;
70
+ //# sourceMappingURL=name.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"name.d.ts","sourceRoot":"","sources":["../src/name.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAK9C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAMxC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,IAAI;;EAAoD,CAAC;AActE;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CA0EjD;AAMD;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,CAE5E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAO5E;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAMjE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,QAAQ,EAAE,GAAG,QAAQ,GAAG,SAAS,CAexG"}
package/dist/name.js ADDED
@@ -0,0 +1,172 @@
1
+ import { addComponent, getComponentValue, hasComponent, removeComponent, setComponentValue } from "./component.js";
2
+ import { registerObserverCallback } from "./observer.js";
3
+ import { defineComponent } from "./registry.js";
4
+ import { addResource, getResourceValue } from "./resource.js";
5
+ import { Type } from "./schema.js";
6
+ // ============================================================================
7
+ // Component Definitions
8
+ // ============================================================================
9
+ /**
10
+ * Name component for entity identification.
11
+ *
12
+ * Stores a single string value that must be unique within the world.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * addComponent(world, entity, Name, { value: "player-1" });
17
+ * const name = getComponentValue(world, entity, Name, "value");
18
+ * ```
19
+ */
20
+ export const Name = defineComponent("Name", { value: Type.string() });
21
+ /**
22
+ * Dual-index registry for O(1) lookups in both directions. Stored as a world resource.
23
+ */
24
+ const NameRegistry = defineComponent("NameRegistry", {
25
+ nameToEntity: Type.object(),
26
+ entityToName: Type.object(),
27
+ });
28
+ // ============================================================================
29
+ // Initialization
30
+ // ============================================================================
31
+ /**
32
+ * Initializes the name system for a world by setting up the dual-index registry
33
+ * and observer callbacks that keep name mappings synchronized with entity lifecycle.
34
+ * Called automatically by createWorld().
35
+ * @internal
36
+ */
37
+ export function initNameSystem(world) {
38
+ addResource(world, NameRegistry, {
39
+ nameToEntity: new Map(),
40
+ entityToName: new Map(),
41
+ });
42
+ // Clean up registry when Name component is removed from an entity
43
+ registerObserverCallback(world, "componentRemoved", (componentId, entityId) => {
44
+ if (componentId !== Name) {
45
+ return;
46
+ }
47
+ const nameToEntity = getResourceValue(world, NameRegistry, "nameToEntity");
48
+ const entityToName = getResourceValue(world, NameRegistry, "entityToName");
49
+ const name = entityToName.get(entityId);
50
+ nameToEntity.delete(name);
51
+ entityToName.delete(entityId);
52
+ });
53
+ // Sync registry when Name component is added or its value changes.
54
+ // Validates uniqueness and non-empty constraints before updating mappings.
55
+ registerObserverCallback(world, "componentChanged", (componentId, entityId) => {
56
+ if (componentId !== Name) {
57
+ return;
58
+ }
59
+ const nameToEntity = getResourceValue(world, NameRegistry, "nameToEntity");
60
+ const entityToName = getResourceValue(world, NameRegistry, "entityToName");
61
+ const previous = entityToName.get(entityId);
62
+ const current = getComponentValue(world, entityId, Name, "value");
63
+ if (previous === current) {
64
+ return;
65
+ }
66
+ if (!current) {
67
+ throw new Error("Name cannot be empty");
68
+ }
69
+ if (nameToEntity.has(current)) {
70
+ throw new Error(`Name "${current}" already exists`);
71
+ }
72
+ // Remove old mapping if renaming an entity
73
+ if (previous !== undefined) {
74
+ nameToEntity.delete(previous);
75
+ }
76
+ nameToEntity.set(current, entityId);
77
+ entityToName.set(entityId, current);
78
+ });
79
+ // Clean up registry when a named entity is destroyed
80
+ registerObserverCallback(world, "entityDestroyed", (entityId) => {
81
+ const nameToEntity = getResourceValue(world, NameRegistry, "nameToEntity");
82
+ const entityToName = getResourceValue(world, NameRegistry, "entityToName");
83
+ const name = entityToName.get(entityId);
84
+ if (name === undefined) {
85
+ return;
86
+ }
87
+ nameToEntity.delete(name);
88
+ entityToName.delete(entityId);
89
+ });
90
+ // Recreate fresh registry when world is reset
91
+ registerObserverCallback(world, "worldReset", () => {
92
+ addResource(world, NameRegistry, {
93
+ nameToEntity: new Map(),
94
+ entityToName: new Map(),
95
+ });
96
+ });
97
+ }
98
+ // ============================================================================
99
+ // Public API
100
+ // ============================================================================
101
+ /**
102
+ * Gets the name of an entity.
103
+ * @param world - World instance
104
+ * @param entityId - Entity to get name from
105
+ * @returns Entity name or undefined if not named
106
+ * @example
107
+ * ```ts
108
+ * const name = getName(world, entity);
109
+ * ```
110
+ */
111
+ export function getName(world, entityId) {
112
+ return getComponentValue(world, entityId, Name, "value");
113
+ }
114
+ /**
115
+ * Sets or updates the name of an entity.
116
+ * @param world - World instance
117
+ * @param entityId - Entity to name
118
+ * @param name - Name to assign (must be unique and non-empty)
119
+ * @throws Error if name is empty or already exists
120
+ * @example
121
+ * ```ts
122
+ * setName(world, player, "player-1");
123
+ * ```
124
+ */
125
+ export function setName(world, entityId, name) {
126
+ if (!hasComponent(world, entityId, Name)) {
127
+ addComponent(world, entityId, Name, { value: name });
128
+ return;
129
+ }
130
+ setComponentValue(world, entityId, Name, "value", name);
131
+ }
132
+ /**
133
+ * Removes the name from an entity.
134
+ * @param world - World instance
135
+ * @param entityId - Entity to remove name from
136
+ * @example
137
+ * ```ts
138
+ * removeName(world, entity);
139
+ * ```
140
+ */
141
+ export function removeName(world, entityId) {
142
+ if (!hasComponent(world, entityId, Name)) {
143
+ return;
144
+ }
145
+ removeComponent(world, entityId, Name);
146
+ }
147
+ /**
148
+ * Looks up an entity by name, optionally validating required components.
149
+ * @param world - World instance
150
+ * @param name - Name to look up
151
+ * @param components - Optional components to validate presence
152
+ * @returns Entity ID or undefined if not found or missing required components
153
+ * @example
154
+ * ```ts
155
+ * const player = lookupByName(world, "player-1");
156
+ * const player = lookupByName(world, "player-1", Position, Health);
157
+ * ```
158
+ */
159
+ export function lookupByName(world, name, ...components) {
160
+ const nameToEntity = getResourceValue(world, NameRegistry, "nameToEntity");
161
+ const entityId = nameToEntity.get(name);
162
+ if (!entityId) {
163
+ return;
164
+ }
165
+ for (const component of components) {
166
+ if (!hasComponent(world, entityId, component)) {
167
+ return;
168
+ }
169
+ }
170
+ return entityId;
171
+ }
172
+ //# sourceMappingURL=name.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"name.js","sourceRoot":"","sources":["../src/name.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ import type { Archetype } from "./archetype.js";
2
+ import type { Entity, EntityId } from "./encoding.js";
3
+ import type { FilterMeta } from "./filters.js";
4
+ import type { World } from "./world.js";
5
+ /**
6
+ * Event payload type mapping.
7
+ *
8
+ * Maps event names to argument tuples for type-safe observer callbacks.
9
+ */
10
+ export type EventPayloads = {
11
+ archetypeCreated: [archetype: Archetype];
12
+ archetypeDestroyed: [archetype: Archetype];
13
+ filterCreated: [filter: FilterMeta];
14
+ filterDestroyed: [filter: FilterMeta];
15
+ entityCreated: [entityId: Entity];
16
+ entityDestroyed: [entityId: EntityId];
17
+ componentAdded: [componentId: EntityId, entityId: EntityId];
18
+ componentRemoved: [componentId: EntityId, entityId: EntityId];
19
+ componentChanged: [componentId: EntityId, entityId: EntityId];
20
+ worldReset: [world: World];
21
+ };
22
+ /**
23
+ * Event type keys.
24
+ */
25
+ export type EventType = keyof EventPayloads;
26
+ /**
27
+ * Observer callback function.
28
+ */
29
+ export type Observer<T extends EventType> = (...args: EventPayloads[T]) => void;
30
+ /**
31
+ * Observer metadata for single event type.
32
+ */
33
+ export type ObserverMeta<T extends EventType> = {
34
+ /**
35
+ * Callbacks fired on event.
36
+ */
37
+ callbacks: Observer<T>[];
38
+ };
39
+ /**
40
+ * Registers a callback to be invoked when an event of the specified type is fired.
41
+ *
42
+ * @param world - The world instance containing observer state
43
+ * @param eventType - The event type to listen for
44
+ * @param callback - Function to invoke when the event fires
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * registerObserverCallback(world, "onAdd", (entity, componentId, value) => {
49
+ * console.log(`Component ${componentId} added to entity ${entity}`);
50
+ * });
51
+ * ```
52
+ */
53
+ export declare function registerObserverCallback<T extends EventType>(world: World, eventType: T, callback: Observer<T>): void;
54
+ /**
55
+ * Removes a previously registered callback for the specified event type.
56
+ *
57
+ * @param world - The world instance containing observer state
58
+ * @param eventType - The event type to stop listening for
59
+ * @param callback - The exact callback reference to remove
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * const handler = (entity, componentId, value) => { ... };
64
+ * registerObserverCallback(world, "onAdd", handler);
65
+ * // Later:
66
+ * unregisterObserverCallback(world, "onAdd", handler);
67
+ * ```
68
+ */
69
+ export declare function unregisterObserverCallback<T extends EventType>(world: World, eventType: T, callback: Observer<T>): void;
70
+ /**
71
+ * Dispatches an event to all registered callbacks for the specified event type.
72
+ *
73
+ * @param world - The world instance containing observer state
74
+ * @param eventType - The event type to dispatch
75
+ * @param args - Arguments to pass to each callback (varies by event type)
76
+ *
77
+ * @example
78
+ * ```ts
79
+ * fireObserverEvent(world, "onAdd", entity, componentId, componentValue);
80
+ * ```
81
+ */
82
+ export declare function fireObserverEvent<T extends EventType>(world: World, eventType: T, ...args: EventPayloads[T]): void;
83
+ //# sourceMappingURL=observer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observer.d.ts","sourceRoot":"","sources":["../src/observer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAMxC;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,gBAAgB,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACzC,kBAAkB,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAC3C,aAAa,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACpC,eAAe,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACtC,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAClC,eAAe,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACtC,cAAc,EAAE,CAAC,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC5D,gBAAgB,EAAE,CAAC,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC9D,gBAAgB,EAAE,CAAC,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC9D,UAAU,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;CAC5B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC;AAE5C;;GAEG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,SAAS,IAAI,CAAC,GAAG,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;AAEhF;;GAEG;AACH,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,SAAS,IAAI;IAC9C;;OAEG;IACH,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;CAC1B,CAAC;AAMF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,SAAS,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAErH;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,SAAS,SAAS,EAC5D,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,CAAC,EACZ,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,GACpB,IAAI,CAON;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI,CAOlH"}