@codehz/ecs 0.8.2 → 0.10.0
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.en.md +26 -3
- package/README.md +41 -4
- package/dist/builder.d.mts +348 -83
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/dist/testing.d.mts +1 -1
- package/dist/testing.mjs +1 -1
- package/dist/world.mjs +1922 -1400
- package/dist/world.mjs.map +1 -1
- package/examples/debug-observability.ts +92 -0
- package/examples/inventory-system-relations.ts +1 -1
- package/examples/parent-child-hierarchy.ts +18 -38
- package/examples/spatial-grid.ts +1 -1
- package/package.json +1 -1
- package/skills/ecs/SKILL.md +4 -4
- package/src/__tests__/component/singleton.test.ts +116 -35
- package/src/__tests__/core/archetype.test.ts +155 -13
- package/src/__tests__/core/bitset.test.ts +12 -0
- package/src/__tests__/entity/entity.test.ts +33 -0
- package/src/__tests__/entity/id-system.test.ts +40 -0
- package/src/__tests__/perf/comprehensive.perf.test.ts +6 -9
- package/src/__tests__/perf/serialization.perf.test.ts +242 -0
- package/src/__tests__/perf/{dontfragment-wildcard.perf.test.ts → sparse-wildcard.perf.test.ts} +13 -16
- package/src/__tests__/query/caching.test.ts +62 -0
- package/src/__tests__/query/filter.test.ts +16 -22
- package/src/__tests__/query/perf.test.ts +3 -5
- package/src/__tests__/relations/hierarchy.test.ts +208 -0
- package/src/__tests__/relations/{dont-fragment → sparse}/basic.test.ts +64 -69
- package/src/__tests__/relations/{dont-fragment → sparse}/query-notification.test.ts +17 -9
- package/src/__tests__/serialization/bounds.test.ts +133 -1
- package/src/__tests__/world/commands.test.ts +337 -0
- package/src/__tests__/world/component-management.test.ts +6 -5
- package/src/__tests__/world/debug-stats.test.ts +206 -0
- package/src/__tests__/world/multi-component-hooks.test.ts +44 -0
- package/src/__tests__/world/serialize.test.ts +17 -0
- package/src/__tests__/world/wildcard-relation-hooks.test.ts +127 -0
- package/src/archetype/archetype.ts +96 -46
- package/src/archetype/helpers.ts +7 -29
- package/src/archetype/store.ts +35 -20
- package/src/commands/buffer.ts +5 -2
- package/src/commands/changeset.ts +0 -31
- package/src/component/registry.ts +64 -63
- package/src/entity/index.ts +6 -3
- package/src/index.ts +15 -0
- package/src/query/filter.ts +4 -10
- package/src/query/query.ts +12 -12
- package/src/storage/serialization.ts +29 -2
- package/src/types/index.ts +71 -0
- package/src/world/archetype-manager.ts +283 -0
- package/src/world/command-executor.ts +258 -0
- package/src/world/commands.ts +44 -56
- package/src/world/debug-stats.ts +147 -0
- package/src/world/hooks.ts +8 -0
- package/src/world/operations.ts +88 -0
- package/src/world/serialization.ts +32 -18
- package/src/world/singleton.ts +51 -0
- package/src/world/world.ts +429 -457
package/README.en.md
CHANGED
|
@@ -78,7 +78,7 @@ const ChildOf = component({ exclusive: true, name: "ChildOf" });
|
|
|
78
78
|
| `name` | `string` | Component name, used for serialization/debugging |
|
|
79
79
|
| `exclusive` | `boolean` | Relation components only: an entity can have at most one relation of the same base component |
|
|
80
80
|
| `cascadeDelete` | `boolean` | Entity relations only: when the target entity is deleted, the **entire referencing entity** is deleted. Differs from default behavior (default only cleans up the relation component, the entity survives). Supports transitive cascading. |
|
|
81
|
-
| `
|
|
81
|
+
| `sparse` | `boolean` | Relation components only: relations with different target entities are stored in the same Archetype, preventing excessive fragmentation (legacy `dontFragment` alias remains fully supported) |
|
|
82
82
|
| `merge` | `(prev, next) => T` | Merge strategy when `set()` is called multiple times on the same component within a single sync batch |
|
|
83
83
|
|
|
84
84
|
### Lifecycle Hooks
|
|
@@ -274,7 +274,7 @@ component<T>();
|
|
|
274
274
|
// With a name
|
|
275
275
|
component<T>("Name");
|
|
276
276
|
// With options
|
|
277
|
-
component<T>({ name?: string, exclusive?: boolean, cascadeDelete?: boolean, dontFragment?: boolean, merge?: (prev, next) => T });
|
|
277
|
+
component<T>({ name?: string, exclusive?: boolean, cascadeDelete?: boolean, sparse?: boolean, dontFragment?: boolean /* legacy alias, fully compatible */, merge?: (prev, next) => T });
|
|
278
278
|
```
|
|
279
279
|
|
|
280
280
|
### relation()
|
|
@@ -288,6 +288,29 @@ relation(componentId, "*");
|
|
|
288
288
|
relation(componentId, otherComponentId);
|
|
289
289
|
```
|
|
290
290
|
|
|
291
|
+
### Relation & Hierarchy Companion Tools (New)
|
|
292
|
+
|
|
293
|
+
To stop users from repeatedly hand-writing `buildChildrenByParent` + recursive descent for parent-child hierarchies and inventory systems, we now ship first-class helpers:
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
const ChildOf = component<void>({ exclusive: true, sparse: true });
|
|
297
|
+
const world = new World();
|
|
298
|
+
// ... build hierarchy ...
|
|
299
|
+
|
|
300
|
+
// Recommended usage (standalone functions removed to simplify API surface)
|
|
301
|
+
const kids = world.getChildren(parent, ChildOf);
|
|
302
|
+
const p = world.getParent(child, ChildOf);
|
|
303
|
+
|
|
304
|
+
for (const { entity, depth } of world.iterateDescendants(root, ChildOf)) { ... }
|
|
305
|
+
|
|
306
|
+
const items = world.getRelationTargets(player, InInventory);
|
|
307
|
+
const owners = world.getRelationSources(sword, InInventory);
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
The same functionality is also available as methods on `World` instances. All helpers are fully compatible with data-bearing relations, exclusive/non-exclusive, and post-`sync()` semantics.
|
|
311
|
+
|
|
312
|
+
See `src/relations/hierarchy.ts` and the new test suite for details.
|
|
313
|
+
|
|
291
314
|
### Component / Entity ID Rules
|
|
292
315
|
|
|
293
316
|
- Component ID: `1` – `1023`
|
|
@@ -391,7 +414,7 @@ src/
|
|
|
391
414
|
│ ├── component-registry.ts # Component registry
|
|
392
415
|
│ ├── component-entity-store.ts # Singleton component storage
|
|
393
416
|
│ ├── component-type-utils.ts # Component type utilities
|
|
394
|
-
│ ├──
|
|
417
|
+
│ ├── store.ts # SparseStore (internal sparse storage)
|
|
395
418
|
│ ├── entity.ts # Entity/component/relation type exports (aggregate)
|
|
396
419
|
│ ├── entity-types.ts # Entity ID type definitions & constants
|
|
397
420
|
│ ├── entity-relation.ts # Relation ID encoding/decoding
|
package/README.md
CHANGED
|
@@ -78,7 +78,7 @@ const ChildOf = component({ exclusive: true, name: "ChildOf" });
|
|
|
78
78
|
| `name` | `string` | 组件名称,用于序列化/调试 |
|
|
79
79
|
| `exclusive` | `boolean` | 仅关系组件:同一实体对同一基础组件最多只能有一个关系 |
|
|
80
80
|
| `cascadeDelete` | `boolean` | 仅实体关系:删除目标实体时,持有该关系的**整个实体**也会被删除。区别于默认行为(默认仅清理关系组件,实体保留)。支持传递级联。 |
|
|
81
|
-
| `
|
|
81
|
+
| `sparse` | `boolean` | 仅关系组件:不同目标实体的关系存放在同一 Archetype,防止因目标不同而过度碎片化(旧别名 `dontFragment` 仍完全兼容) |
|
|
82
82
|
| `merge` | `(prev, next) => T` | 在同一 sync 批次中对同一组件反复 `set()` 时的合并策略 |
|
|
83
83
|
|
|
84
84
|
### 生命周期钩子
|
|
@@ -222,7 +222,7 @@ bun run examples/inventory-system-relations.ts
|
|
|
222
222
|
| `spawnMany(count, configure)` | 批量创建多个实体 |
|
|
223
223
|
| `exists(entity)` | 检查实体是否存在 |
|
|
224
224
|
| `set(entity, componentId, data?)` | 添加/更新组件(缓冲,`sync()` 后生效)。对 `void` 组件可不传 data |
|
|
225
|
-
| `
|
|
225
|
+
| `singleton(componentId)` | 获取单例组件句柄,推荐用 `world.singleton(Config).set(value)` |
|
|
226
226
|
| `get(entity, componentId?)` | 获取组件数据。**若组件不存在会抛出异常**,请先用 `has()` 检查或使用 `getOptional()` |
|
|
227
227
|
| `getOptional(entity, componentId?)` | 安全获取组件,返回 `{ value: T } \| undefined` |
|
|
228
228
|
| `has(entity, componentId?)` | 检查组件是否存在 |
|
|
@@ -236,6 +236,18 @@ bun run examples/inventory-system-relations.ts
|
|
|
236
236
|
| `serialize()` | 序列化世界状态为快照对象 |
|
|
237
237
|
| `sync()` | 执行所有延迟命令 |
|
|
238
238
|
|
|
239
|
+
单例组件推荐写法:
|
|
240
|
+
|
|
241
|
+
```ts
|
|
242
|
+
const config = world.singleton(GlobalConfig);
|
|
243
|
+
config.set({ debug: true });
|
|
244
|
+
world.sync();
|
|
245
|
+
|
|
246
|
+
if (config.has()) {
|
|
247
|
+
console.log(config.get());
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
239
251
|
### Query
|
|
240
252
|
|
|
241
253
|
查询通过 `world.createQuery()` 创建,应**跨帧复用**以获得最佳性能。
|
|
@@ -274,7 +286,7 @@ component<T>();
|
|
|
274
286
|
// 指定名称
|
|
275
287
|
component<T>("Name");
|
|
276
288
|
// 带选项
|
|
277
|
-
component<T>({ name?: string, exclusive?: boolean, cascadeDelete?: boolean,
|
|
289
|
+
component<T>({ name?: string, exclusive?: boolean, cascadeDelete?: boolean, sparse?: boolean, dontFragment?: boolean /* 旧别名,完全兼容 */, merge?: (prev, next) => T });
|
|
278
290
|
```
|
|
279
291
|
|
|
280
292
|
### relation()
|
|
@@ -288,6 +300,31 @@ relation(componentId, "*");
|
|
|
288
300
|
relation(componentId, otherComponentId);
|
|
289
301
|
```
|
|
290
302
|
|
|
303
|
+
### 关系/层级配套工具(新)
|
|
304
|
+
|
|
305
|
+
为避免用户在父子层级(`ChildOf`)和库存系统(`InInventory`)中反复手写 `buildChildrenByParent` + 递归遍历逻辑,我们提供了配套工具:
|
|
306
|
+
|
|
307
|
+
```typescript
|
|
308
|
+
const ChildOf = component<void>({ exclusive: true, sparse: true });
|
|
309
|
+
const world = new World();
|
|
310
|
+
// ... 创建层级 ...
|
|
311
|
+
|
|
312
|
+
// 推荐直接在 World 实例上使用(API 表面已简化)
|
|
313
|
+
const kids = world.getChildren(parent, ChildOf);
|
|
314
|
+
const p = world.getParent(child, ChildOf);
|
|
315
|
+
|
|
316
|
+
for (const { entity, depth, parent } of world.iterateDescendants(root, ChildOf)) {
|
|
317
|
+
// ...
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const items = world.getRelationTargets(player, InInventory);
|
|
321
|
+
const owners = world.getRelationSources(sword, InInventory);
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
这些工具全部在 `world` 实例方法上也有对应(`world.getChildren(...)` 等),并完整支持数据负载关系、独占/非独占、删除后一致性。
|
|
325
|
+
|
|
326
|
+
详见 `src/relations/hierarchy.ts` 和新增的测试。
|
|
327
|
+
|
|
291
328
|
### 组件 / 实体 ID 规则
|
|
292
329
|
|
|
293
330
|
- 组件 ID:`1` ~ `1023`
|
|
@@ -391,7 +428,7 @@ src/
|
|
|
391
428
|
│ ├── component-registry.ts # 组件注册表
|
|
392
429
|
│ ├── component-entity-store.ts # 单例组件存储
|
|
393
430
|
│ ├── component-type-utils.ts # 组件类型工具
|
|
394
|
-
│ ├──
|
|
431
|
+
│ ├── store.ts # SparseStore (内部稀疏存储)
|
|
395
432
|
│ ├── entity.ts # 实体/组件/关系类型导出(聚合)
|
|
396
433
|
│ ├── entity-types.ts # 实体 ID 类型定义与常量
|
|
397
434
|
│ ├── entity-relation.ts # 关系 ID 编码/解码
|