@codehz/ecs 0.1.5 → 0.1.7

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
@@ -176,7 +176,7 @@ bun run examples/simple/demo.ts
176
176
  - `delete(entity, componentId)`: 从实体移除组件
177
177
  - `setExclusive(componentId)`: 将组件标记为独占关系
178
178
  - `createQuery(componentIds)`: 创建查询
179
- - `registerSystem(system)`: 注册系统
179
+ - `registerSystem(system, dependencies?)`: 注册系统
180
180
  - `registerLifecycleHook(componentId, hook)`: 注册组件或通配符关系生命周期钩子
181
181
  - `unregisterLifecycleHook(componentId, hook)`: 注销组件或通配符关系生命周期钩子
182
182
  - `update(...params)`: 更新世界(参数取决于泛型配置)
@@ -289,7 +289,7 @@ class MovementSystem implements System<[deltaTime: number]> {
289
289
  }
290
290
  ```
291
291
 
292
- 系统支持依赖关系排序,确保正确的执行顺序。依赖关系通过系统的 `dependencies` 属性指定:
292
+ 系统支持依赖关系排序,确保正确的执行顺序。依赖关系可以通过系统的 `dependencies` 属性指定:
293
293
 
294
294
  ```typescript
295
295
  class InputSystem implements System<[deltaTime: number]> {
@@ -314,7 +314,7 @@ class MovementSystem implements System<[deltaTime: number]> {
314
314
  // 注册系统
315
315
  const inputSystem = new InputSystem();
316
316
  world.registerSystem(inputSystem);
317
- world.registerSystem(new MovementSystem(inputSystem));
317
+ world.registerSystem(new MovementSystem(inputSystem), [inputSystem]); // 也可以在注册时指定额外依赖
318
318
  ```
319
319
 
320
320
  系统将按照拓扑排序执行,依赖系统始终在被依赖系统之前运行。
package/index.js CHANGED
@@ -280,8 +280,9 @@ class Archetype {
280
280
  const removedData = new Map;
281
281
  for (const componentType of this.componentTypes) {
282
282
  const dataArray = this.getComponentData(componentType);
283
- removedData.set(componentType, dataArray[index] === MISSING_COMPONENT ? undefined : dataArray[index]);
283
+ removedData.set(componentType, dataArray[index]);
284
284
  }
285
+ this.entityToIndex.delete(entityId);
285
286
  const lastIndex = this.entities.length - 1;
286
287
  if (index !== lastIndex) {
287
288
  const lastEntity = this.entities[lastIndex];
@@ -289,11 +290,13 @@ class Archetype {
289
290
  this.entityToIndex.set(lastEntity, index);
290
291
  for (const componentType of this.componentTypes) {
291
292
  const dataArray = this.getComponentData(componentType);
292
- [dataArray[index], dataArray[lastIndex]] = [dataArray[lastIndex], dataArray[index]];
293
+ dataArray[index] = dataArray[lastIndex];
293
294
  }
294
295
  }
295
296
  this.entities.pop();
296
- this.entityToIndex.delete(entityId);
297
+ for (const componentType of this.componentTypes) {
298
+ this.getComponentData(componentType).pop();
299
+ }
297
300
  return removedData;
298
301
  }
299
302
  exists(entityId) {
@@ -436,14 +439,13 @@ class ComponentChangeset {
436
439
  }
437
440
  }
438
441
  applyTo(existingComponents) {
439
- const finalComponents = new Map(existingComponents);
440
442
  for (const componentType of this.removes) {
441
- finalComponents.delete(componentType);
443
+ existingComponents.delete(componentType);
442
444
  }
443
445
  for (const [componentType, component2] of this.adds) {
444
- finalComponents.set(componentType, component2);
446
+ existingComponents.set(componentType, component2);
445
447
  }
446
- return finalComponents;
448
+ return existingComponents;
447
449
  }
448
450
  }
449
451
 
@@ -615,12 +617,14 @@ class Query {
615
617
  // src/system-scheduler.ts
616
618
  class SystemScheduler {
617
619
  systems = new Set;
620
+ systemDependencies = new Map;
618
621
  cachedExecutionOrder = null;
619
- addSystem(system) {
622
+ addSystem(system, additionalDeps = []) {
620
623
  this.systems.add(system);
621
624
  for (const dep of system.dependencies || []) {
622
625
  this.systems.add(dep);
623
626
  }
627
+ this.systemDependencies.set(system, new Set([...additionalDeps, ...system.dependencies || []]));
624
628
  this.cachedExecutionOrder = null;
625
629
  }
626
630
  getExecutionOrder() {
@@ -637,7 +641,7 @@ class SystemScheduler {
637
641
  throw new Error("Circular dependency detected in system scheduling");
638
642
  }
639
643
  visiting.add(system);
640
- for (const dep of system.dependencies || []) {
644
+ for (const dep of this.systemDependencies.get(system) || []) {
641
645
  visit(dep);
642
646
  }
643
647
  visiting.delete(system);
@@ -734,8 +738,7 @@ class World {
734
738
  currentComponents.set(archetypeComponentType, componentData);
735
739
  }
736
740
  }
737
- const newComponentTypes = Array.from(currentComponents.keys()).sort((a, b) => a - b);
738
- const newArchetype = this.ensureArchetype(newComponentTypes);
741
+ const newArchetype = this.ensureArchetype(currentComponents.keys());
739
742
  sourceArchetype.removeEntity(sourceEntityId);
740
743
  if (sourceArchetype.getEntities().length === 0) {
741
744
  this.cleanupEmptyArchetype(sourceArchetype);
@@ -800,8 +803,8 @@ class World {
800
803
  }
801
804
  return archetype.get(entityId, componentType);
802
805
  }
803
- registerSystem(system) {
804
- this.systemScheduler.addSystem(system);
806
+ registerSystem(system, additionalDeps = []) {
807
+ this.systemScheduler.addSystem(system, additionalDeps);
805
808
  }
806
809
  registerLifecycleHook(componentType, hook) {
807
810
  if (!this.lifecycleHooks.has(componentType)) {
@@ -1000,7 +1003,7 @@ class World {
1000
1003
  const currentComponentTypes = currentArchetype.componentTypes;
1001
1004
  const needsArchetypeChange = finalComponents.size !== currentComponentTypes.length || !currentComponentTypes.every((type) => finalComponents.has(type));
1002
1005
  if (needsArchetypeChange) {
1003
- const newArchetype = this.ensureArchetype(finalComponents.keys().toArray());
1006
+ const newArchetype = this.ensureArchetype(finalComponents.keys());
1004
1007
  currentArchetype.removeEntity(entityId);
1005
1008
  newArchetype.addEntity(entityId, finalComponents);
1006
1009
  this.entityToArchetype.set(entityId, newArchetype);
@@ -1031,7 +1034,7 @@ class World {
1031
1034
  return changeset;
1032
1035
  }
1033
1036
  ensureArchetype(componentTypes) {
1034
- const sortedTypes = componentTypes.toSorted((a, b) => a - b);
1037
+ const sortedTypes = Array.from(componentTypes).sort((a, b) => a - b);
1035
1038
  const hashKey = this.createArchetypeSignature(sortedTypes);
1036
1039
  return getOrCreateWithSideEffect(this.archetypeBySignature, hashKey, () => {
1037
1040
  const newArchetype = new Archetype(sortedTypes);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codehz/ecs",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "types": "./index.d.ts",
@@ -4,12 +4,14 @@ import type { System } from "./system";
4
4
  */
5
5
  export declare class SystemScheduler<UpdateParams extends any[] = [deltaTime: number]> {
6
6
  private systems;
7
+ private systemDependencies;
7
8
  private cachedExecutionOrder;
8
9
  /**
9
10
  * Add a system with optional dependencies
10
11
  * @param system The system to add
12
+ * @param additionalDeps Additional dependencies for the system
11
13
  */
12
- addSystem(system: System<UpdateParams>): void;
14
+ addSystem(system: System<UpdateParams>, additionalDeps?: System<UpdateParams>[]): void;
13
15
  /**
14
16
  * Get the execution order of systems based on dependencies
15
17
  * Uses topological sort
package/world.d.ts CHANGED
@@ -94,7 +94,7 @@ export declare class World<UpdateParams extends any[] = []> {
94
94
  /**
95
95
  * Register a system with optional dependencies
96
96
  */
97
- registerSystem(system: System<UpdateParams>): void;
97
+ registerSystem(system: System<UpdateParams>, additionalDeps?: System<UpdateParams>[]): void;
98
98
  /**
99
99
  * Register a lifecycle hook for component or wildcard relation events
100
100
  */