@codehz/ecs 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,6 +9,7 @@
9
9
  - 🏗️ 模块化:清晰的架构,支持自定义系统和组件
10
10
  - 📦 轻量级:零依赖,易于集成
11
11
  - ⚡ 内存高效:连续内存布局,优化的迭代性能
12
+ - 🎣 生命周期钩子:支持组件和通配符关系的事件监听
12
13
 
13
14
  ## 安装
14
15
 
@@ -22,15 +23,15 @@ bun install
22
23
 
23
24
  ```typescript
24
25
  import { World } from "@codehz/ecs";
25
- import { createComponentId } from "@codehz/ecs";
26
+ import { component } from "@codehz/ecs";
26
27
 
27
28
  // 定义组件类型
28
29
  type Position = { x: number; y: number };
29
30
  type Velocity = { x: number; y: number };
30
31
 
31
32
  // 定义组件ID
32
- const PositionId = createComponentId<Position>(1);
33
- const VelocityId = createComponentId<Velocity>(2);
33
+ const PositionId = component<Position>(1);
34
+ const VelocityId = component<Velocity>(2);
34
35
 
35
36
  // 创建世界
36
37
  const world = new World();
@@ -58,20 +59,20 @@ ECS 支持在组件添加或移除时执行回调函数:
58
59
 
59
60
  ```typescript
60
61
  // 注册组件生命周期钩子
61
- world.registerComponentLifecycleHook(PositionId, {
62
+ world.registerLifecycleHook(PositionId, {
62
63
  onAdded: (entityId, componentType, component) => {
63
64
  console.log(`组件 ${componentType} 被添加到实体 ${entityId}`);
64
65
  },
65
66
  onRemoved: (entityId, componentType) => {
66
67
  console.log(`组件 ${componentType} 被从实体 ${entityId} 移除`);
67
- }
68
+ },
68
69
  });
69
70
 
70
71
  // 你也可以只注册其中一个钩子
71
- world.registerComponentLifecycleHook(VelocityId, {
72
+ world.registerLifecycleHook(VelocityId, {
72
73
  onRemoved: (entityId, componentType) => {
73
74
  console.log(`组件 ${componentType} 被从实体 ${entityId} 移除`);
74
- }
75
+ },
75
76
  });
76
77
 
77
78
  // 添加组件时会触发钩子
@@ -79,6 +80,45 @@ world.addComponent(entity, PositionId, { x: 0, y: 0 });
79
80
  world.flushCommands(); // 钩子在这里被调用
80
81
  ```
81
82
 
83
+ ### 通配符关系生命周期钩子
84
+
85
+ ECS 还支持通配符关系生命周期钩子,可以监听特定组件的所有关系变化:
86
+
87
+ ```typescript
88
+ import { World, component, relation } from "@codehz/ecs";
89
+
90
+ // 定义组件类型
91
+ type Position = { x: number; y: number };
92
+
93
+ // 定义组件ID
94
+ const PositionId = component<Position>(1);
95
+
96
+ // 创建世界
97
+ const world = new World();
98
+
99
+ // 创建实体
100
+ const entity = world.createEntity();
101
+
102
+ // 创建通配符关系ID,用于监听所有 Position 相关的关系
103
+ const wildcardPositionRelation = relation(PositionId, "*");
104
+
105
+ // 注册通配符关系钩子
106
+ world.registerLifecycleHook(wildcardPositionRelation, {
107
+ onAdded: (entityId, componentType, component) => {
108
+ console.log(`关系组件 ${componentType} 被添加到实体 ${entityId}`);
109
+ },
110
+ onRemoved: (entityId, componentType) => {
111
+ console.log(`关系组件 ${componentType} 被从实体 ${entityId} 移除`);
112
+ },
113
+ });
114
+
115
+ // 创建实体间的关系
116
+ const entity2 = world.createEntity();
117
+ const positionRelation = relation(PositionId, entity2);
118
+ world.addComponent(entity, positionRelation, { x: 10, y: 20 });
119
+ world.flushCommands(); // 通配符钩子会被触发
120
+ ```
121
+
82
122
  ### 运行示例
83
123
 
84
124
  ```bash
@@ -100,14 +140,14 @@ bun run examples/simple/demo.ts
100
140
  - `removeComponent(entity, componentId)`: 从实体移除组件
101
141
  - `createQuery(componentIds)`: 创建查询
102
142
  - `registerSystem(system)`: 注册系统
103
- - `registerComponentLifecycleHook(componentId, hook)`: 注册组件生命周期钩子
104
- - `unregisterComponentLifecycleHook(componentId, hook)`: 注销组件生命周期钩子
143
+ - `registerLifecycleHook(componentId, hook)`: 注册组件或通配符关系生命周期钩子
144
+ - `unregisterLifecycleHook(componentId, hook)`: 注销组件或通配符关系生命周期钩子
105
145
  - `update(deltaTime)`: 更新世界
106
146
  - `flushCommands()`: 应用命令缓冲区
107
147
 
108
148
  ### Entity
109
149
 
110
- - `createComponentId<T>(id)`: 创建类型安全的组件ID
150
+ - `component<T>(id)`: 分配类型安全的组件ID(上限:1022个)
111
151
 
112
152
  ### Query
113
153
 
package/entity.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  /**
2
- * Brand for EntityId to create nominal typing with component type information
2
+ * Unique symbol brand for associating component type information with EntityId
3
3
  */
4
- declare const __entityIdBrand: unique symbol;
4
+ declare const __componentTypeMarker: unique symbol;
5
5
  /**
6
- * Brand for wildcard relation IDs
6
+ * Unique symbol brand for tagging the kind of EntityId (e.g., 'component', 'entity-relation')
7
7
  */
8
- declare const __wildcardRelationBrand: unique symbol;
8
+ declare const __entityIdTypeTag: unique symbol;
9
9
  /**
10
10
  * Entity ID type for ECS architecture
11
11
  * Based on 52-bit integers within safe integer range
@@ -13,12 +13,15 @@ declare const __wildcardRelationBrand: unique symbol;
13
13
  * - Entity IDs: 1024+
14
14
  * - Relation IDs: negative numbers encoding component and entity associations
15
15
  */
16
- export type EntityId<T = void> = number & {
17
- readonly [__entityIdBrand]: T;
18
- };
19
- export type WildcardRelationId<T = void> = EntityId<T> & {
20
- readonly [__wildcardRelationBrand]: true;
16
+ export type EntityId<T = void, U = unknown> = number & {
17
+ readonly [__componentTypeMarker]: T;
18
+ readonly [__entityIdTypeTag]: U;
21
19
  };
20
+ export type ComponentId<T = void> = EntityId<T, "component">;
21
+ export type EntityRelationId<T = void> = EntityId<T, "entity-relation">;
22
+ export type ComponentRelationId<T = void> = EntityId<T, "component-relation">;
23
+ export type WildcardRelationId<T = void> = EntityId<T, "wildcard-relation">;
24
+ export type RelationId<T = void> = EntityRelationId<T> | ComponentRelationId<T> | WildcardRelationId<T>;
22
25
  /**
23
26
  * Constants for ID ranges
24
27
  */
@@ -33,8 +36,9 @@ export declare const WILDCARD_TARGET_ID = 0;
33
36
  /**
34
37
  * Create a component ID
35
38
  * @param id Component identifier (1-1023)
39
+ * @see component
36
40
  */
37
- export declare function createComponentId<T = void>(id: number): EntityId<T>;
41
+ export declare function createComponentId<T = void>(id: number): ComponentId<T>;
38
42
  /**
39
43
  * Create an entity ID
40
44
  * @param id Entity identifier (starting from 1024)
@@ -43,33 +47,37 @@ export declare function createEntityId(id: number): EntityId;
43
47
  /**
44
48
  * Type for relation ID based on component and target types
45
49
  */
46
- type RelationIdType<T, U> = U extends void ? EntityId<T> : T extends void ? EntityId<U> : EntityId<never>;
50
+ type RelationIdType<T, R> = R extends ComponentId<infer U> ? U extends void ? ComponentRelationId<T> : ComponentRelationId<T & U> : R extends EntityId<any> ? EntityRelationId<T> : never;
47
51
  /**
48
52
  * Create a relation ID by associating a component with another ID (entity or component)
49
53
  * @param componentId The component ID (0-1023)
50
54
  * @param targetId The target ID (entity, component, or '*' for wildcard)
51
55
  */
52
- export declare function createRelationId<T>(componentId: EntityId<T>, targetId: "*"): WildcardRelationId<T>;
53
- export declare function createRelationId<T, U>(componentId: EntityId<T>, targetId: EntityId<U>): RelationIdType<T, U>;
56
+ export declare function relation<T>(componentId: ComponentId<T>, targetId: "*"): WildcardRelationId<T>;
57
+ export declare function relation<T, R extends EntityId<any>>(componentId: ComponentId<T>, targetId: R): RelationIdType<T, R>;
54
58
  /**
55
59
  * Check if an ID is a component ID
56
60
  */
57
- export declare function isComponentId(id: EntityId<any>): boolean;
61
+ export declare function isComponentId<T>(id: EntityId<T>): id is ComponentId<T>;
58
62
  /**
59
63
  * Check if an ID is an entity ID
60
64
  */
61
- export declare function isEntityId(id: EntityId<any>): boolean;
65
+ export declare function isEntityId<T>(id: EntityId<T>): id is EntityId<T>;
62
66
  /**
63
67
  * Check if an ID is a relation ID
64
68
  */
65
- export declare function isRelationId(id: EntityId): boolean;
69
+ export declare function isRelationId<T>(id: EntityId<T>): id is RelationId<T>;
70
+ /**
71
+ * Check if an ID is a wildcard relation id
72
+ */
73
+ export declare function isWildcardRelationId<T>(id: EntityId<T>): id is WildcardRelationId<T>;
66
74
  /**
67
75
  * Decode a relation ID into component and target IDs
68
76
  * @param relationId The relation ID (must be negative)
69
77
  * @returns Object with componentId, targetId, and relation type
70
78
  */
71
- export declare function decodeRelationId(relationId: EntityId<any>): {
72
- componentId: EntityId<any>;
79
+ export declare function decodeRelationId(relationId: RelationId<any>): {
80
+ componentId: ComponentId<any>;
73
81
  targetId: EntityId<any>;
74
82
  type: "entity" | "component" | "wildcard";
75
83
  };
@@ -83,9 +91,13 @@ export declare function getIdType(id: EntityId<any>): "component" | "entity" | "
83
91
  * @returns Detailed type information including relation subtypes
84
92
  */
85
93
  export declare function getDetailedIdType(id: EntityId<any>): {
86
- type: "component" | "entity" | "entity-relation" | "component-relation" | "wildcard-relation" | "invalid";
87
- componentId?: EntityId<any>;
88
- targetId?: EntityId<any>;
94
+ type: "component" | "entity" | "invalid";
95
+ componentId?: never;
96
+ targetId?: never;
97
+ } | {
98
+ type: "entity-relation" | "component-relation" | "wildcard-relation";
99
+ componentId: ComponentId<any>;
100
+ targetId: EntityId<any>;
89
101
  };
90
102
  /**
91
103
  * Inspect an EntityId and return a human-readable string representation
@@ -122,13 +134,13 @@ export declare class EntityIdManager {
122
134
  * Component ID Manager for automatic allocation
123
135
  * Components are typically registered once and not recycled
124
136
  */
125
- export declare class ComponentIdManager {
137
+ export declare class ComponentIdAllocator {
126
138
  private nextId;
127
139
  /**
128
140
  * Allocate a new component ID
129
141
  * Increments counter sequentially from 1
130
142
  */
131
- allocate<T = void>(): EntityId<T>;
143
+ allocate<T = void>(): ComponentId<T>;
132
144
  /**
133
145
  * Get the next ID that would be allocated (for debugging)
134
146
  */
@@ -138,4 +150,8 @@ export declare class ComponentIdManager {
138
150
  */
139
151
  hasAvailableIds(): boolean;
140
152
  }
153
+ /**
154
+ * Allocate a new component ID from the global allocator
155
+ */
156
+ export declare function component<T>(): ComponentId<T>;
141
157
  export {};
package/index.js CHANGED
@@ -16,7 +16,7 @@ function createEntityId(id) {
16
16
  }
17
17
  return id;
18
18
  }
19
- function createRelationId(componentId, targetId) {
19
+ function relation(componentId, targetId) {
20
20
  if (!isComponentId(componentId)) {
21
21
  throw new Error("First argument must be a valid component ID");
22
22
  }
@@ -40,6 +40,14 @@ function isEntityId(id) {
40
40
  function isRelationId(id) {
41
41
  return id < 0;
42
42
  }
43
+ function isWildcardRelationId(id) {
44
+ if (!isRelationId(id)) {
45
+ return false;
46
+ }
47
+ const absId = -id;
48
+ const targetId = absId % RELATION_SHIFT;
49
+ return targetId === WILDCARD_TARGET_ID;
50
+ }
43
51
  function decodeRelationId(relationId) {
44
52
  if (!isRelationId(relationId)) {
45
53
  throw new Error("ID is not a relation ID");
@@ -178,7 +186,7 @@ class EntityIdManager {
178
186
  }
179
187
  }
180
188
 
181
- class ComponentIdManager {
189
+ class ComponentIdAllocator {
182
190
  nextId = 1;
183
191
  allocate() {
184
192
  if (this.nextId > COMPONENT_ID_MAX) {
@@ -195,6 +203,10 @@ class ComponentIdManager {
195
203
  return this.nextId <= COMPONENT_ID_MAX;
196
204
  }
197
205
  }
206
+ var globalComponentIdAllocator = new ComponentIdAllocator;
207
+ function component() {
208
+ return globalComponentIdAllocator.allocate();
209
+ }
198
210
  // src/utils.ts
199
211
  function getOrComputeCache(cache, key, compute) {
200
212
  let value = cache.get(key);
@@ -281,16 +293,16 @@ class Archetype {
281
293
  return;
282
294
  }
283
295
  }
284
- if (getIdType(componentType) === "wildcard-relation") {
296
+ if (isWildcardRelationId(componentType)) {
285
297
  const decoded = decodeRelationId(componentType);
286
298
  const componentId = decoded.componentId;
287
299
  const relations = [];
288
300
  for (const relType of this.componentTypes) {
289
- const relDecoded = decodeRelationId(relType);
290
- if (relDecoded.componentId === componentId && (getIdType(relType) === "entity-relation" || getIdType(relType) === "component-relation")) {
301
+ const relDetailed = getDetailedIdType(relType);
302
+ if ((relDetailed.type === "entity-relation" || relDetailed.type === "component-relation") && relDetailed.componentId === componentId) {
291
303
  const dataArray = this.componentData.get(relType);
292
304
  if (dataArray && dataArray[index] !== undefined) {
293
- relations.push([relDecoded.targetId, dataArray[index]]);
305
+ relations.push([relDetailed.targetId, dataArray[index]]);
294
306
  }
295
307
  }
296
308
  }
@@ -327,15 +339,14 @@ class Archetype {
327
339
  const cacheKey = componentTypes.map((id) => id.toString()).join(",");
328
340
  const componentDataSources = getOrComputeCache(this.componentDataSourcesCache, cacheKey, () => {
329
341
  return componentTypes.map((compType) => {
330
- if (getIdType(compType) === "wildcard-relation") {
331
- const decoded = decodeRelationId(compType);
332
- const componentId = decoded.componentId;
342
+ const detailedType = getDetailedIdType(compType);
343
+ if (detailedType.type === "wildcard-relation") {
344
+ const componentId = detailedType.componentId;
333
345
  const matchingRelations = this.componentTypes.filter((ct) => {
334
- const ctType = getIdType(ct);
335
- if (ctType !== "entity-relation" && ctType !== "component-relation")
346
+ const detailedCt = getDetailedIdType(ct);
347
+ if (detailedCt.type !== "entity-relation" && detailedCt.type !== "component-relation")
336
348
  return false;
337
- const decodedCt = decodeRelationId(ct);
338
- return decodedCt.componentId === componentId;
349
+ return detailedCt.componentId === componentId;
339
350
  });
340
351
  return matchingRelations;
341
352
  } else {
@@ -384,8 +395,8 @@ class CommandBuffer {
384
395
  constructor(executeEntityCommands) {
385
396
  this.executeEntityCommands = executeEntityCommands;
386
397
  }
387
- addComponent(entityId, componentType, component) {
388
- this.commands.push({ type: "addComponent", entityId, componentType, component });
398
+ addComponent(entityId, componentType, component2) {
399
+ this.commands.push({ type: "addComponent", entityId, componentType, component: component2 });
389
400
  }
390
401
  removeComponent(entityId, componentType) {
391
402
  this.commands.push({ type: "removeComponent", entityId, componentType });
@@ -541,8 +552,7 @@ class World {
541
552
  queries = [];
542
553
  commandBuffer;
543
554
  componentToArchetypes = new Map;
544
- componentLifecycleHooks = new Map;
545
- wildcardRelationLifecycleHooks = new Map;
555
+ lifecycleHooks = new Map;
546
556
  entityReverseIndex = new Map;
547
557
  constructor() {
548
558
  this.commandBuffer = new CommandBuffer((entityId, commands) => this.executeEntityCommands(entityId, commands));
@@ -598,7 +608,7 @@ class World {
598
608
  hasEntity(entityId) {
599
609
  return this.entityToArchetype.has(entityId);
600
610
  }
601
- addComponent(entityId, componentType, component) {
611
+ addComponent(entityId, componentType, component2) {
602
612
  if (!this.hasEntity(entityId)) {
603
613
  throw new Error(`Entity ${entityId} does not exist`);
604
614
  }
@@ -609,7 +619,7 @@ class World {
609
619
  if (detailedType.type === "wildcard-relation") {
610
620
  throw new Error(`Cannot directly add wildcard relation components: ${componentType}`);
611
621
  }
612
- this.commandBuffer.addComponent(entityId, componentType, component);
622
+ this.commandBuffer.addComponent(entityId, componentType, component2);
613
623
  }
614
624
  removeComponent(entityId, componentType) {
615
625
  if (!this.hasEntity(entityId)) {
@@ -648,33 +658,18 @@ class World {
648
658
  this.systems.splice(index, 1);
649
659
  }
650
660
  }
651
- registerComponentLifecycleHook(componentType, hook) {
652
- if (!this.componentLifecycleHooks.has(componentType)) {
653
- this.componentLifecycleHooks.set(componentType, new Set);
654
- }
655
- this.componentLifecycleHooks.get(componentType).add(hook);
656
- }
657
- unregisterComponentLifecycleHook(componentType, hook) {
658
- const hooks = this.componentLifecycleHooks.get(componentType);
659
- if (hooks) {
660
- hooks.delete(hook);
661
- if (hooks.size === 0) {
662
- this.componentLifecycleHooks.delete(componentType);
663
- }
664
- }
665
- }
666
- registerWildcardRelationLifecycleHook(baseComponentType, hook) {
667
- if (!this.wildcardRelationLifecycleHooks.has(baseComponentType)) {
668
- this.wildcardRelationLifecycleHooks.set(baseComponentType, new Set);
661
+ registerLifecycleHook(componentType, hook) {
662
+ if (!this.lifecycleHooks.has(componentType)) {
663
+ this.lifecycleHooks.set(componentType, new Set);
669
664
  }
670
- this.wildcardRelationLifecycleHooks.get(baseComponentType).add(hook);
665
+ this.lifecycleHooks.get(componentType).add(hook);
671
666
  }
672
- unregisterWildcardRelationLifecycleHook(baseComponentType, hook) {
673
- const hooks = this.wildcardRelationLifecycleHooks.get(baseComponentType);
667
+ unregisterLifecycleHook(componentType, hook) {
668
+ const hooks = this.lifecycleHooks.get(componentType);
674
669
  if (hooks) {
675
670
  hooks.delete(hook);
676
671
  if (hooks.size === 0) {
677
- this.wildcardRelationLifecycleHooks.delete(baseComponentType);
672
+ this.lifecycleHooks.delete(componentType);
678
673
  }
679
674
  }
680
675
  }
@@ -820,8 +815,8 @@ class World {
820
815
  for (const componentType of removes) {
821
816
  finalComponents.delete(componentType);
822
817
  }
823
- for (const [componentType, component] of adds) {
824
- finalComponents.set(componentType, component);
818
+ for (const [componentType, component2] of adds) {
819
+ finalComponents.set(componentType, component2);
825
820
  }
826
821
  const finalComponentTypes = Array.from(finalComponents.keys()).sort((a, b) => a - b);
827
822
  const currentComponentTypes = currentArchetype.componentTypes.sort((a, b) => a - b);
@@ -832,8 +827,8 @@ class World {
832
827
  newArchetype.addEntity(entityId, finalComponents);
833
828
  this.entityToArchetype.set(entityId, newArchetype);
834
829
  } else {
835
- for (const [componentType, component] of adds) {
836
- currentArchetype.setComponent(entityId, componentType, component);
830
+ for (const [componentType, component2] of adds) {
831
+ currentArchetype.setComponent(entityId, componentType, component2);
837
832
  }
838
833
  }
839
834
  for (const componentType of removes) {
@@ -845,7 +840,7 @@ class World {
845
840
  this.removeComponentReference(entityId, componentType, componentType);
846
841
  }
847
842
  }
848
- for (const [componentType, component] of adds) {
843
+ for (const [componentType, component2] of adds) {
849
844
  const detailedType = getDetailedIdType(componentType);
850
845
  if (detailedType.type === "entity-relation") {
851
846
  const targetEntityId = detailedType.targetId;
@@ -920,31 +915,32 @@ class World {
920
915
  }
921
916
  }
922
917
  executeComponentLifecycleHooks(entityId, addedComponents, removedComponents) {
923
- for (const [componentType, component] of addedComponents) {
924
- const hooks = this.componentLifecycleHooks.get(componentType);
925
- if (hooks) {
926
- for (const hook of hooks) {
918
+ for (const [componentType, component2] of addedComponents) {
919
+ const directHooks = this.lifecycleHooks.get(componentType);
920
+ if (directHooks) {
921
+ for (const hook of directHooks) {
927
922
  if (hook.onAdded) {
928
- hook.onAdded(entityId, componentType, component);
923
+ hook.onAdded(entityId, componentType, component2);
929
924
  }
930
925
  }
931
926
  }
932
927
  const detailedType = getDetailedIdType(componentType);
933
928
  if (detailedType.type === "entity-relation" || detailedType.type === "component-relation" || detailedType.type === "wildcard-relation") {
934
- const wildcardHooks = this.wildcardRelationLifecycleHooks.get(detailedType.componentId);
929
+ const wildcardRelationId = relation(detailedType.componentId, "*");
930
+ const wildcardHooks = this.lifecycleHooks.get(wildcardRelationId);
935
931
  if (wildcardHooks) {
936
932
  for (const hook of wildcardHooks) {
937
933
  if (hook.onAdded) {
938
- hook.onAdded(entityId, componentType, component);
934
+ hook.onAdded(entityId, componentType, component2);
939
935
  }
940
936
  }
941
937
  }
942
938
  }
943
939
  }
944
940
  for (const componentType of removedComponents) {
945
- const hooks = this.componentLifecycleHooks.get(componentType);
946
- if (hooks) {
947
- for (const hook of hooks) {
941
+ const directHooks = this.lifecycleHooks.get(componentType);
942
+ if (directHooks) {
943
+ for (const hook of directHooks) {
948
944
  if (hook.onRemoved) {
949
945
  hook.onRemoved(entityId, componentType);
950
946
  }
@@ -952,7 +948,8 @@ class World {
952
948
  }
953
949
  const detailedType = getDetailedIdType(componentType);
954
950
  if (detailedType.type === "entity-relation" || detailedType.type === "component-relation" || detailedType.type === "wildcard-relation") {
955
- const wildcardHooks = this.wildcardRelationLifecycleHooks.get(detailedType.componentId);
951
+ const wildcardRelationId = relation(detailedType.componentId, "*");
952
+ const wildcardHooks = this.lifecycleHooks.get(wildcardRelationId);
956
953
  if (wildcardHooks) {
957
954
  for (const hook of wildcardHooks) {
958
955
  if (hook.onRemoved) {
@@ -965,6 +962,8 @@ class World {
965
962
  }
966
963
  }
967
964
  export {
965
+ relation,
966
+ isWildcardRelationId,
968
967
  isRelationId,
969
968
  isEntityId,
970
969
  isComponentId,
@@ -972,9 +971,9 @@ export {
972
971
  getIdType,
973
972
  getDetailedIdType,
974
973
  decodeRelationId,
975
- createRelationId,
976
974
  createEntityId,
977
975
  createComponentId,
976
+ component,
978
977
  World,
979
978
  WILDCARD_TARGET_ID,
980
979
  RELATION_SHIFT,
@@ -982,7 +981,7 @@ export {
982
981
  INVALID_COMPONENT_ID,
983
982
  EntityIdManager,
984
983
  ENTITY_ID_START,
985
- ComponentIdManager,
984
+ ComponentIdAllocator,
986
985
  COMPONENT_ID_MAX,
987
986
  Archetype
988
987
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codehz/ecs",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "types": "./index.d.ts",
package/world.d.ts CHANGED
@@ -3,8 +3,8 @@ import { type Command } from "./command-buffer";
3
3
  import type { EntityId, WildcardRelationId } from "./entity";
4
4
  import { Query } from "./query";
5
5
  import type { QueryFilter } from "./query-filter";
6
- import type { ComponentTuple, LifecycleHook } from "./types";
7
6
  import type { System } from "./system";
7
+ import type { ComponentTuple, LifecycleHook } from "./types";
8
8
  /**
9
9
  * World class for ECS architecture
10
10
  * Manages entities, components, and systems
@@ -19,14 +19,9 @@ export declare class World<ExtraParams extends any[] = [deltaTime: number]> {
19
19
  private commandBuffer;
20
20
  private componentToArchetypes;
21
21
  /**
22
- * Hook storage for component lifecycle events
23
- */
24
- private componentLifecycleHooks;
25
- /**
26
- * Hook storage for wildcard relation lifecycle events
27
- * Maps base component type to set of wildcard relation hooks
22
+ * Hook storage for component and wildcard relation lifecycle events
28
23
  */
29
- private wildcardRelationLifecycleHooks;
24
+ private lifecycleHooks;
30
25
  /**
31
26
  * Reverse index tracking which entities use each entity as a component type
32
27
  * Maps entity ID to set of {sourceEntityId, componentType} pairs where componentType uses this entity
@@ -83,22 +78,13 @@ export declare class World<ExtraParams extends any[] = [deltaTime: number]> {
83
78
  */
84
79
  unregisterSystem(system: System<ExtraParams>): void;
85
80
  /**
86
- * Register a lifecycle hook for component events
87
- */
88
- registerComponentLifecycleHook<T>(componentType: EntityId<T>, hook: LifecycleHook<T>): void;
89
- /**
90
- * Unregister a lifecycle hook for component events
91
- */
92
- unregisterComponentLifecycleHook<T>(componentType: EntityId<T>, hook: LifecycleHook<T>): void;
93
- /**
94
- * Register a lifecycle hook for wildcard relation events
95
- * The hook will be triggered for any component that matches the wildcard relation pattern
81
+ * Register a lifecycle hook for component or wildcard relation events
96
82
  */
97
- registerWildcardRelationLifecycleHook<T>(baseComponentType: EntityId<T>, hook: LifecycleHook<T>): void;
83
+ registerLifecycleHook<T>(componentType: EntityId<T>, hook: LifecycleHook<T>): void;
98
84
  /**
99
- * Unregister a lifecycle hook for wildcard relation events
85
+ * Unregister a lifecycle hook for component or wildcard relation events
100
86
  */
101
- unregisterWildcardRelationLifecycleHook<T>(baseComponentType: EntityId<T>, hook: LifecycleHook<T>): void;
87
+ unregisterLifecycleHook<T>(componentType: EntityId<T>, hook: LifecycleHook<T>): void;
102
88
  /**
103
89
  * Update the world (run all systems)
104
90
  */