@esengine/ecs-framework 2.0.6 → 2.0.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.
Files changed (124) hide show
  1. package/bin/Core.js +21 -17
  2. package/bin/Core.js.map +1 -1
  3. package/bin/ECS/Component.js +5 -1
  4. package/bin/ECS/Component.js.map +1 -1
  5. package/bin/ECS/Components/IUpdatable.js +7 -2
  6. package/bin/ECS/Components/IUpdatable.js.map +1 -1
  7. package/bin/ECS/Components/SceneComponent.js +5 -1
  8. package/bin/ECS/Components/SceneComponent.js.map +1 -1
  9. package/bin/ECS/Core/BitMaskOptimizer.d.ts +75 -0
  10. package/bin/ECS/Core/BitMaskOptimizer.d.ts.map +1 -0
  11. package/bin/ECS/Core/BitMaskOptimizer.js +165 -0
  12. package/bin/ECS/Core/BitMaskOptimizer.js.map +1 -0
  13. package/bin/ECS/Core/ComponentPool.d.ts +72 -0
  14. package/bin/ECS/Core/ComponentPool.d.ts.map +1 -0
  15. package/bin/ECS/Core/ComponentPool.js +128 -0
  16. package/bin/ECS/Core/ComponentPool.js.map +1 -0
  17. package/bin/ECS/Core/ComponentStorage.js +9 -3
  18. package/bin/ECS/Core/ComponentStorage.js.map +1 -1
  19. package/bin/ECS/Core/EventSystem.js +12 -6
  20. package/bin/ECS/Core/EventSystem.js.map +1 -1
  21. package/bin/ECS/Core/FluentAPI.js +24 -17
  22. package/bin/ECS/Core/FluentAPI.js.map +1 -1
  23. package/bin/ECS/Core/IndexUpdateBatcher.d.ts +100 -0
  24. package/bin/ECS/Core/IndexUpdateBatcher.d.ts.map +1 -0
  25. package/bin/ECS/Core/IndexUpdateBatcher.js +223 -0
  26. package/bin/ECS/Core/IndexUpdateBatcher.js.map +1 -0
  27. package/bin/ECS/Core/QuerySystem.d.ts +292 -444
  28. package/bin/ECS/Core/QuerySystem.d.ts.map +1 -1
  29. package/bin/ECS/Core/QuerySystem.js +661 -1075
  30. package/bin/ECS/Core/QuerySystem.js.map +1 -1
  31. package/bin/ECS/CoreEvents.js +5 -2
  32. package/bin/ECS/CoreEvents.js.map +1 -1
  33. package/bin/ECS/Entity.js +17 -12
  34. package/bin/ECS/Entity.js.map +1 -1
  35. package/bin/ECS/Scene.d.ts +18 -2
  36. package/bin/ECS/Scene.d.ts.map +1 -1
  37. package/bin/ECS/Scene.js +67 -19
  38. package/bin/ECS/Scene.js.map +1 -1
  39. package/bin/ECS/Systems/EntitySystem.js +9 -5
  40. package/bin/ECS/Systems/EntitySystem.js.map +1 -1
  41. package/bin/ECS/Systems/IntervalSystem.js +8 -4
  42. package/bin/ECS/Systems/IntervalSystem.js.map +1 -1
  43. package/bin/ECS/Systems/PassiveSystem.js +6 -2
  44. package/bin/ECS/Systems/PassiveSystem.js.map +1 -1
  45. package/bin/ECS/Systems/ProcessingSystem.js +6 -2
  46. package/bin/ECS/Systems/ProcessingSystem.js.map +1 -1
  47. package/bin/ECS/Systems/index.js +11 -4
  48. package/bin/ECS/Systems/index.js.map +1 -1
  49. package/bin/ECS/Utils/Bits.js +5 -1
  50. package/bin/ECS/Utils/Bits.js.map +1 -1
  51. package/bin/ECS/Utils/ComponentTypeManager.js +8 -4
  52. package/bin/ECS/Utils/ComponentTypeManager.js.map +1 -1
  53. package/bin/ECS/Utils/EntityList.js +5 -1
  54. package/bin/ECS/Utils/EntityList.js.map +1 -1
  55. package/bin/ECS/Utils/EntityProcessorList.js +5 -1
  56. package/bin/ECS/Utils/EntityProcessorList.js.map +1 -1
  57. package/bin/ECS/Utils/IdentifierPool.js +5 -1
  58. package/bin/ECS/Utils/IdentifierPool.js.map +1 -1
  59. package/bin/ECS/Utils/Matcher.js +8 -4
  60. package/bin/ECS/Utils/Matcher.js.map +1 -1
  61. package/bin/ECS/Utils/index.js +15 -6
  62. package/bin/ECS/Utils/index.js.map +1 -1
  63. package/bin/ECS/index.js +27 -6
  64. package/bin/ECS/index.js.map +1 -1
  65. package/bin/Testing/Performance/benchmark.d.ts +6 -0
  66. package/bin/Testing/Performance/benchmark.d.ts.map +1 -0
  67. package/bin/Testing/Performance/benchmark.js +639 -0
  68. package/bin/Testing/Performance/benchmark.js.map +1 -0
  69. package/bin/Testing/Unit/bitmask-optimizer.test.d.ts +2 -0
  70. package/bin/Testing/Unit/bitmask-optimizer.test.d.ts.map +1 -0
  71. package/bin/Testing/Unit/bitmask-optimizer.test.js +164 -0
  72. package/bin/Testing/Unit/bitmask-optimizer.test.js.map +1 -0
  73. package/bin/Testing/Unit/component-pool.test.d.ts +5 -0
  74. package/bin/Testing/Unit/component-pool.test.d.ts.map +1 -0
  75. package/bin/Testing/Unit/component-pool.test.js +149 -0
  76. package/bin/Testing/Unit/component-pool.test.js.map +1 -0
  77. package/bin/Testing/test-runner.d.ts +51 -0
  78. package/bin/Testing/test-runner.d.ts.map +1 -0
  79. package/bin/Testing/test-runner.js +159 -0
  80. package/bin/Testing/test-runner.js.map +1 -0
  81. package/bin/Types/index.js +7 -4
  82. package/bin/Types/index.js.map +1 -1
  83. package/bin/Utils/Emitter.js +7 -2
  84. package/bin/Utils/Emitter.js.map +1 -1
  85. package/bin/Utils/Extensions/NumberExtension.js +5 -1
  86. package/bin/Utils/Extensions/NumberExtension.js.map +1 -1
  87. package/bin/Utils/Extensions/TypeUtils.js +5 -1
  88. package/bin/Utils/Extensions/TypeUtils.js.map +1 -1
  89. package/bin/Utils/Extensions/index.js +7 -2
  90. package/bin/Utils/Extensions/index.js.map +1 -1
  91. package/bin/Utils/GlobalManager.js +5 -1
  92. package/bin/Utils/GlobalManager.js.map +1 -1
  93. package/bin/Utils/PerformanceMonitor.js +7 -3
  94. package/bin/Utils/PerformanceMonitor.js.map +1 -1
  95. package/bin/Utils/Pool.js +9 -3
  96. package/bin/Utils/Pool.js.map +1 -1
  97. package/bin/Utils/Time.js +5 -1
  98. package/bin/Utils/Time.js.map +1 -1
  99. package/bin/Utils/Timers/ITimer.js +2 -1
  100. package/bin/Utils/Timers/Timer.js +7 -3
  101. package/bin/Utils/Timers/Timer.js.map +1 -1
  102. package/bin/Utils/Timers/TimerManager.js +8 -4
  103. package/bin/Utils/Timers/TimerManager.js.map +1 -1
  104. package/bin/Utils/WasmCore.d.ts +234 -0
  105. package/bin/Utils/WasmCore.d.ts.map +1 -0
  106. package/bin/Utils/WasmCore.js +634 -0
  107. package/bin/Utils/WasmCore.js.map +1 -0
  108. package/bin/Utils/index.d.ts +10 -0
  109. package/bin/Utils/index.d.ts.map +1 -1
  110. package/bin/Utils/index.js +36 -5
  111. package/bin/Utils/index.js.map +1 -1
  112. package/bin/index.d.ts +1 -2
  113. package/bin/index.d.ts.map +1 -1
  114. package/bin/index.js +42 -14
  115. package/bin/index.js.map +1 -1
  116. package/package.json +54 -74
  117. package/bin/Utils/AccelerationProvider.d.ts +0 -192
  118. package/bin/Utils/AccelerationProvider.d.ts.map +0 -1
  119. package/bin/Utils/AccelerationProvider.js +0 -261
  120. package/bin/Utils/AccelerationProvider.js.map +0 -1
  121. package/bin/Utils/WasmBridge.d.ts +0 -152
  122. package/bin/Utils/WasmBridge.d.ts.map +0 -1
  123. package/bin/Utils/WasmBridge.js +0 -336
  124. package/bin/Utils/WasmBridge.js.map +0 -1
@@ -1,8 +1,15 @@
1
- import { ComponentRegistry } from './ComponentStorage';
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.QueryBuilder = exports.QuerySystem = exports.QueryConditionType = void 0;
4
+ const ComponentStorage_1 = require("./ComponentStorage");
5
+ const WasmCore_1 = require("../../Utils/WasmCore");
6
+ const ComponentPool_1 = require("./ComponentPool");
7
+ const BitMaskOptimizer_1 = require("./BitMaskOptimizer");
8
+ const IndexUpdateBatcher_1 = require("./IndexUpdateBatcher");
2
9
  /**
3
10
  * 查询条件类型
4
11
  */
5
- export var QueryConditionType;
12
+ var QueryConditionType;
6
13
  (function (QueryConditionType) {
7
14
  /** 必须包含所有指定组件 */
8
15
  QueryConditionType["ALL"] = "all";
@@ -10,179 +17,241 @@ export var QueryConditionType;
10
17
  QueryConditionType["ANY"] = "any";
11
18
  /** 不能包含任何指定组件 */
12
19
  QueryConditionType["NONE"] = "none";
13
- })(QueryConditionType || (QueryConditionType = {}));
20
+ })(QueryConditionType || (exports.QueryConditionType = QueryConditionType = {}));
14
21
  /**
15
22
  * 高性能实体查询系统
16
- * 使用位掩码进行快速组件匹配,支持多级索引和智能缓存
23
+ *
24
+ * 提供快速的实体查询功能,支持按组件类型、标签、名称等多种方式查询实体。
25
+ * 系统采用多级索引和智能缓存机制,确保在大量实体场景下的查询性能。
26
+ *
27
+ * 主要特性:
28
+ * - 支持单组件和多组件查询
29
+ * - 自动索引管理和缓存优化
30
+ * - WebAssembly计算加速(如果可用)
31
+ * - 详细的性能统计信息
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * // 查询所有包含Position和Velocity组件的实体
36
+ * const movingEntities = querySystem.queryAll(PositionComponent, VelocityComponent);
37
+ *
38
+ * // 查询特定标签的实体
39
+ * const playerEntities = querySystem.queryByTag(PLAYER_TAG);
40
+ * ```
17
41
  */
18
- export class QuerySystem {
42
+ class QuerySystem {
19
43
  constructor() {
20
44
  this.entities = [];
45
+ this.wasmAvailable = false;
46
+ this.indexDirty = true;
47
+ // 查询缓存系统
21
48
  this.queryCache = new Map();
22
- this.cacheTimeout = 1000; // 缓存超时时间(毫秒)
23
- this.maxCacheSize = 100; // 最大缓存数量
24
- this.cacheHits = 0;
25
- this.cacheMisses = 0;
26
- // 多级索引系统
49
+ this.cacheMaxSize = 1000;
50
+ this.cacheTimeout = 5000; // 5秒缓存过期
51
+ // 性能统计
52
+ this.queryStats = {
53
+ totalQueries: 0,
54
+ cacheHits: 0,
55
+ indexHits: 0,
56
+ linearScans: 0
57
+ };
27
58
  this.entityIndex = {
28
59
  byMask: new Map(),
29
60
  byComponentType: new Map(),
30
61
  byTag: new Map(),
31
62
  byName: new Map()
32
63
  };
33
- // 性能统计
34
- this.performanceStats = {
35
- totalQueries: 0,
36
- averageExecutionTime: 0,
37
- cacheHitRate: 0,
38
- indexHitRate: 0,
39
- slowQueries: []
64
+ // 初始化优化组件
65
+ this.componentPoolManager = ComponentPool_1.ComponentPoolManager.getInstance();
66
+ this.bitMaskOptimizer = BitMaskOptimizer_1.BitMaskOptimizer.getInstance();
67
+ this.indexUpdateBatcher = new IndexUpdateBatcher_1.IndexUpdateBatcher();
68
+ // 设置索引更新批处理器的回调
69
+ this.indexUpdateBatcher.onBatchAdd = (entities) => {
70
+ for (const entity of entities) {
71
+ this.addEntityToIndexes(entity);
72
+ }
40
73
  };
41
- // 索引更新标志
42
- this.indexDirty = true;
43
- this.lastIndexUpdate = 0;
44
- this.indexUpdateThreshold = 100; // 毫秒
45
- // 批量操作缓冲区
46
- this.pendingEntityAdds = [];
47
- this.pendingEntityRemoves = [];
48
- this.batchUpdateScheduled = false;
49
- }
50
- /**
51
- * 设置实体列表
52
- * @param entities 实体数组
53
- */
54
- setEntities(entities) {
55
- this.entities = entities;
56
- this.invalidateIndexes();
57
- this.clearCache();
58
- }
59
- /**
60
- * 添加实体
61
- * @param entity 实体
62
- */
63
- addEntity(entity) {
64
- this.pendingEntityAdds.push(entity);
65
- this.scheduleBatchUpdate();
66
- }
67
- /**
68
- * 批量添加实体
69
- * @param entities 实体数组
70
- */
71
- addEntities(entities) {
72
- this.pendingEntityAdds.push(...entities);
73
- this.scheduleBatchUpdate();
74
+ this.indexUpdateBatcher.onBatchRemove = (entities) => {
75
+ for (const entity of entities) {
76
+ this.removeEntityFromIndexes(entity);
77
+ }
78
+ };
79
+ this.indexUpdateBatcher.onBatchUpdate = (updates) => {
80
+ for (const update of updates) {
81
+ this.removeEntityFromIndexes(update.entity);
82
+ this.addEntityToIndexes(update.entity);
83
+ }
84
+ };
85
+ this.initializeWasm();
74
86
  }
75
87
  /**
76
- * 移除实体
77
- * @param entity 实体
88
+ * 初始化WebAssembly支持
89
+ *
90
+ * 自动检测运行环境并启用WebAssembly计算加速。
91
+ * 如果WebAssembly不可用,系统将自动回退到JavaScript实现。
78
92
  */
79
- removeEntity(entity) {
80
- this.pendingEntityRemoves.push(entity);
81
- this.scheduleBatchUpdate();
93
+ async initializeWasm() {
94
+ try {
95
+ const wasmLoaded = await WasmCore_1.ecsCore.initialize();
96
+ this.wasmAvailable = wasmLoaded && WasmCore_1.ecsCore.isUsingWasm();
97
+ if (this.wasmAvailable) {
98
+ console.log('QuerySystem: WebAssembly计算加速已启用');
99
+ }
100
+ else {
101
+ console.log('QuerySystem: 使用JavaScript实现');
102
+ }
103
+ }
104
+ catch (error) {
105
+ console.warn('QuerySystem: WebAssembly初始化失败,使用JavaScript实现:', error);
106
+ this.wasmAvailable = false;
107
+ }
82
108
  }
83
109
  /**
84
- * 批量移除实体
85
- * @param entities 实体数组
110
+ * 设置实体列表并重建索引
111
+ *
112
+ * 当实体集合发生大规模变化时调用此方法。
113
+ * 系统将重新构建所有索引以确保查询性能。
114
+ *
115
+ * @param entities 新的实体列表
86
116
  */
87
- removeEntities(entities) {
88
- this.pendingEntityRemoves.push(...entities);
89
- this.scheduleBatchUpdate();
117
+ setEntities(entities) {
118
+ this.entities = entities;
119
+ this.clearQueryCache();
120
+ this.rebuildIndexes();
90
121
  }
91
122
  /**
92
- * 调度批量更新
123
+ * 添加单个实体到查询系统
124
+ *
125
+ * 将新实体添加到查询系统中,并自动更新相关索引。
126
+ * 为了提高批量添加性能,可以延迟缓存清理。
127
+ *
128
+ * @param entity 要添加的实体
129
+ * @param deferCacheClear 是否延迟缓存清理(用于批量操作)
93
130
  */
94
- scheduleBatchUpdate() {
95
- if (!this.batchUpdateScheduled) {
96
- this.batchUpdateScheduled = true;
97
- // 使用微任务确保在当前执行栈完成后立即执行
98
- Promise.resolve().then(() => this.processBatchUpdates());
131
+ addEntity(entity, deferCacheClear = false) {
132
+ if (!this.entities.includes(entity)) {
133
+ this.entities.push(entity);
134
+ this.addEntityToIndexes(entity);
135
+ // 只有在非延迟模式下才立即清理缓存
136
+ if (!deferCacheClear) {
137
+ this.clearQueryCache();
138
+ }
99
139
  }
100
140
  }
101
141
  /**
102
- * 处理批量更新
142
+ * 批量添加实体
143
+ *
144
+ * 高效地批量添加多个实体,减少缓存清理次数。
145
+ * 使用Set来避免O(n)的重复检查。
146
+ *
147
+ * @param entities 要添加的实体列表
103
148
  */
104
- processBatchUpdates() {
105
- this.batchUpdateScheduled = false;
106
- // 处理添加
107
- if (this.pendingEntityAdds.length > 0) {
108
- this.entities.push(...this.pendingEntityAdds);
109
- // 更新索引
110
- for (const entity of this.pendingEntityAdds) {
149
+ addEntities(entities) {
150
+ if (entities.length === 0)
151
+ return;
152
+ // 使用Set来快速检查重复
153
+ const existingIds = new Set(this.entities.map(e => e.id));
154
+ let addedCount = 0;
155
+ for (const entity of entities) {
156
+ if (!existingIds.has(entity.id)) {
157
+ this.entities.push(entity);
111
158
  this.addEntityToIndexes(entity);
159
+ existingIds.add(entity.id);
160
+ addedCount++;
112
161
  }
113
- this.pendingEntityAdds.length = 0;
114
162
  }
115
- // 处理移除
116
- if (this.pendingEntityRemoves.length > 0) {
117
- const removeSet = new Set(this.pendingEntityRemoves);
118
- // 从实体列表中移除
119
- this.entities = this.entities.filter(entity => !removeSet.has(entity));
120
- // 从索引中移除
121
- for (const entity of this.pendingEntityRemoves) {
122
- this.removeEntityFromIndexes(entity);
123
- }
124
- this.pendingEntityRemoves.length = 0;
163
+ // 只在有实体被添加时才清理缓存
164
+ if (addedCount > 0) {
165
+ this.clearQueryCache();
125
166
  }
126
- // 清空缓存
127
- this.clearCache();
128
167
  }
129
168
  /**
130
- * 强制立即处理所有待处理的更新
169
+ * 批量添加实体(无重复检查版本)
170
+ *
171
+ * 假设所有实体都是新的,跳过重复检查以获得最大性能。
172
+ * 仅在确保没有重复实体时使用。
173
+ *
174
+ * @param entities 要添加的实体列表
131
175
  */
132
- flushUpdates() {
133
- if (this.batchUpdateScheduled) {
134
- this.processBatchUpdates();
176
+ addEntitiesUnchecked(entities) {
177
+ if (entities.length === 0)
178
+ return;
179
+ // 避免调用栈溢出,分批添加
180
+ for (const entity of entities) {
181
+ this.entities.push(entity);
182
+ }
183
+ // 批量更新索引
184
+ for (const entity of entities) {
185
+ this.addEntityToIndexes(entity);
135
186
  }
187
+ // 清理缓存
188
+ this.clearQueryCache();
136
189
  }
137
190
  /**
138
- * 无效化所有索引
191
+ * 从查询系统移除实体
192
+ *
193
+ * 从查询系统中移除指定实体,并清理相关索引。
194
+ *
195
+ * @param entity 要移除的实体
139
196
  */
140
- invalidateIndexes() {
141
- this.indexDirty = true;
142
- this.entityIndex.byMask.clear();
143
- this.entityIndex.byComponentType.clear();
144
- this.entityIndex.byTag.clear();
145
- this.entityIndex.byName.clear();
197
+ removeEntity(entity) {
198
+ const index = this.entities.indexOf(entity);
199
+ if (index !== -1) {
200
+ this.entities.splice(index, 1);
201
+ this.removeEntityFromIndexes(entity);
202
+ this.clearQueryCache();
203
+ }
146
204
  }
147
205
  /**
148
- * 将实体添加到索引
149
- * @param entity 实体
206
+ * 将实体添加到各种索引中(优化版本)
150
207
  */
151
208
  addEntityToIndexes(entity) {
152
- // 按位掩码索引
153
209
  const mask = entity.componentMask;
154
- if (!this.entityIndex.byMask.has(mask)) {
155
- this.entityIndex.byMask.set(mask, new Set());
156
- }
157
- this.entityIndex.byMask.get(mask).add(entity);
158
- // 按组件类型索引
159
- for (const component of entity.components) {
160
- const componentType = component.constructor;
161
- if (!this.entityIndex.byComponentType.has(componentType)) {
162
- this.entityIndex.byComponentType.set(componentType, new Set());
210
+ // 组件掩码索引 - 优化Map操作
211
+ let maskSet = this.entityIndex.byMask.get(mask);
212
+ if (!maskSet) {
213
+ maskSet = new Set();
214
+ this.entityIndex.byMask.set(mask, maskSet);
215
+ }
216
+ maskSet.add(entity);
217
+ // 组件类型索引 - 批量处理
218
+ const components = entity.components;
219
+ for (let i = 0; i < components.length; i++) {
220
+ const componentType = components[i].constructor;
221
+ let typeSet = this.entityIndex.byComponentType.get(componentType);
222
+ if (!typeSet) {
223
+ typeSet = new Set();
224
+ this.entityIndex.byComponentType.set(componentType, typeSet);
163
225
  }
164
- this.entityIndex.byComponentType.get(componentType).add(entity);
226
+ typeSet.add(entity);
165
227
  }
166
- // 按标签索引
228
+ // 标签索引 - 只在有标签时处理
167
229
  const tag = entity.tag;
168
- if (!this.entityIndex.byTag.has(tag)) {
169
- this.entityIndex.byTag.set(tag, new Set());
230
+ if (tag !== undefined) {
231
+ let tagSet = this.entityIndex.byTag.get(tag);
232
+ if (!tagSet) {
233
+ tagSet = new Set();
234
+ this.entityIndex.byTag.set(tag, tagSet);
235
+ }
236
+ tagSet.add(entity);
170
237
  }
171
- this.entityIndex.byTag.get(tag).add(entity);
172
- // 按名称索引
238
+ // 名称索引 - 只在有名称时处理
173
239
  const name = entity.name;
174
- if (!this.entityIndex.byName.has(name)) {
175
- this.entityIndex.byName.set(name, new Set());
240
+ if (name) {
241
+ let nameSet = this.entityIndex.byName.get(name);
242
+ if (!nameSet) {
243
+ nameSet = new Set();
244
+ this.entityIndex.byName.set(name, nameSet);
245
+ }
246
+ nameSet.add(entity);
176
247
  }
177
- this.entityIndex.byName.get(name).add(entity);
178
248
  }
179
249
  /**
180
- * 从索引中移除实体
181
- * @param entity 实体
250
+ * 从各种索引中移除实体
182
251
  */
183
252
  removeEntityFromIndexes(entity) {
184
- // 从位掩码索引移除
185
253
  const mask = entity.componentMask;
254
+ // 从组件掩码索引移除
186
255
  const maskSet = this.entityIndex.byMask.get(mask);
187
256
  if (maskSet) {
188
257
  maskSet.delete(entity);
@@ -202,1155 +271,672 @@ export class QuerySystem {
202
271
  }
203
272
  }
204
273
  // 从标签索引移除
205
- const tagSet = this.entityIndex.byTag.get(entity.tag);
206
- if (tagSet) {
207
- tagSet.delete(entity);
208
- if (tagSet.size === 0) {
209
- this.entityIndex.byTag.delete(entity.tag);
274
+ if (entity.tag !== undefined) {
275
+ const tagSet = this.entityIndex.byTag.get(entity.tag);
276
+ if (tagSet) {
277
+ tagSet.delete(entity);
278
+ if (tagSet.size === 0) {
279
+ this.entityIndex.byTag.delete(entity.tag);
280
+ }
210
281
  }
211
282
  }
212
283
  // 从名称索引移除
213
- const nameSet = this.entityIndex.byName.get(entity.name);
214
- if (nameSet) {
215
- nameSet.delete(entity);
216
- if (nameSet.size === 0) {
217
- this.entityIndex.byName.delete(entity.name);
284
+ if (entity.name) {
285
+ const nameSet = this.entityIndex.byName.get(entity.name);
286
+ if (nameSet) {
287
+ nameSet.delete(entity);
288
+ if (nameSet.size === 0) {
289
+ this.entityIndex.byName.delete(entity.name);
290
+ }
218
291
  }
219
292
  }
220
293
  }
221
294
  /**
222
295
  * 重建所有索引
296
+ *
297
+ * 清空并重新构建所有查询索引。
298
+ * 通常在大量实体变更后调用以确保索引一致性。
223
299
  */
224
300
  rebuildIndexes() {
225
- if (!this.indexDirty)
226
- return;
227
- this.invalidateIndexes();
301
+ this.entityIndex.byMask.clear();
302
+ this.entityIndex.byComponentType.clear();
303
+ this.entityIndex.byTag.clear();
304
+ this.entityIndex.byName.clear();
228
305
  for (const entity of this.entities) {
229
306
  this.addEntityToIndexes(entity);
230
307
  }
231
308
  this.indexDirty = false;
232
- this.lastIndexUpdate = Date.now();
233
- }
234
- /**
235
- * 确保索引是最新的
236
- */
237
- ensureIndexesUpdated() {
238
- const now = Date.now();
239
- if (this.indexDirty || (now - this.lastIndexUpdate) > this.indexUpdateThreshold) {
240
- this.rebuildIndexes();
241
- }
242
309
  }
243
310
  /**
244
311
  * 查询包含所有指定组件的实体
245
- * @param componentTypes 组件类型数组
246
- * @returns 查询结果
312
+ *
313
+ * 返回同时包含所有指定组件类型的实体列表。
314
+ * 系统会自动选择最高效的查询策略,包括索引查找和缓存机制。
315
+ *
316
+ * @param componentTypes 要查询的组件类型列表
317
+ * @returns 查询结果,包含匹配的实体和性能信息
318
+ *
319
+ * @example
320
+ * ```typescript
321
+ * // 查询同时具有位置和速度组件的实体
322
+ * const result = querySystem.queryAll(PositionComponent, VelocityComponent);
323
+ * console.log(`找到 ${result.count} 个移动实体`);
324
+ * ```
247
325
  */
248
326
  queryAll(...componentTypes) {
249
- return this.query({
250
- type: QueryConditionType.ALL,
251
- componentTypes,
252
- mask: this.createMask(componentTypes)
253
- });
254
- }
255
- /**
256
- * 查询包含任意指定组件的实体
257
- * @param componentTypes 组件类型数组
258
- * @returns 查询结果
259
- */
260
- queryAny(...componentTypes) {
261
- return this.query({
262
- type: QueryConditionType.ANY,
263
- componentTypes,
264
- mask: this.createMask(componentTypes)
265
- });
266
- }
267
- /**
268
- * 查询不包含任何指定组件的实体
269
- * @param componentTypes 组件类型数组
270
- * @returns 查询结果
271
- */
272
- queryNone(...componentTypes) {
273
- return this.query({
274
- type: QueryConditionType.NONE,
275
- componentTypes,
276
- mask: this.createMask(componentTypes)
277
- });
278
- }
279
- /**
280
- * 复合查询:同时满足多个条件
281
- * @param conditions 查询条件数组
282
- * @returns 查询结果
283
- */
284
- queryComplex(...conditions) {
285
327
  const startTime = performance.now();
286
- // 生成复合查询的缓存键
287
- const cacheKey = this.generateComplexCacheKey(conditions);
328
+ this.queryStats.totalQueries++;
329
+ // 生成缓存键
330
+ const cacheKey = `all:${componentTypes.map(t => t.name).sort().join(',')}`;
288
331
  // 检查缓存
289
- const cached = this.getCachedResult(cacheKey);
332
+ const cached = this.getFromCache(cacheKey);
290
333
  if (cached) {
334
+ this.queryStats.cacheHits++;
291
335
  return {
292
- entities: cached.entities,
293
- count: cached.entities.length,
336
+ entities: cached,
337
+ count: cached.length,
294
338
  executionTime: performance.now() - startTime,
295
339
  fromCache: true
296
340
  };
297
341
  }
298
- // 执行查询
299
- let result = this.entities.slice(); // 从所有实体开始
300
- for (const condition of conditions) {
301
- result = this.filterEntitiesByCondition(result, condition);
342
+ let entities;
343
+ // 单组件查询:直接使用索引
344
+ if (componentTypes.length === 1) {
345
+ this.queryStats.indexHits++;
346
+ entities = Array.from(this.entityIndex.byComponentType.get(componentTypes[0]) || []);
347
+ }
348
+ else {
349
+ // 多组件查询:使用高效算法
350
+ entities = this.queryMultipleComponents(componentTypes);
302
351
  }
303
- const executionTime = performance.now() - startTime;
304
352
  // 缓存结果
305
- this.cacheResult(cacheKey, result);
353
+ this.addToCache(cacheKey, entities);
306
354
  return {
307
- entities: result,
308
- count: result.length,
309
- executionTime,
355
+ entities,
356
+ count: entities.length,
357
+ executionTime: performance.now() - startTime,
310
358
  fromCache: false
311
359
  };
312
360
  }
313
361
  /**
314
- * 流式查询构建器
315
- * @returns 查询构建器实例
362
+ * 多组件查询算法
363
+ *
364
+ * 针对多组件查询场景的高效算法实现。
365
+ * 通过选择最小的组件集合作为起点,减少需要检查的实体数量。
366
+ *
367
+ * @param componentTypes 组件类型列表
368
+ * @returns 匹配的实体列表
316
369
  */
317
- createQuery() {
318
- return new QueryBuilder(this);
370
+ queryMultipleComponents(componentTypes) {
371
+ // 找到最小的组件集合作为起点
372
+ let smallestSet = null;
373
+ let smallestSize = Infinity;
374
+ for (const componentType of componentTypes) {
375
+ const set = this.entityIndex.byComponentType.get(componentType);
376
+ if (!set || set.size === 0) {
377
+ return []; // 如果任何组件没有实体,直接返回空结果
378
+ }
379
+ if (set.size < smallestSize) {
380
+ smallestSize = set.size;
381
+ smallestSet = set;
382
+ }
383
+ }
384
+ if (!smallestSet) {
385
+ this.queryStats.linearScans++;
386
+ return this.queryByLinearScan(componentTypes);
387
+ }
388
+ // 从最小集合开始,逐步过滤
389
+ const mask = this.createComponentMask(componentTypes);
390
+ const result = [];
391
+ for (const entity of smallestSet) {
392
+ if ((entity.componentMask & mask) === mask) {
393
+ result.push(entity);
394
+ }
395
+ }
396
+ return result;
319
397
  }
320
398
  /**
321
- * 根据标签查询实体
322
- * @param tag 标签
323
- * @returns 查询结果
399
+ * 线性扫描查询
400
+ *
401
+ * 当索引不可用时的备用查询方法。
402
+ * 遍历所有实体进行组件匹配检查。
403
+ *
404
+ * @param componentTypes 组件类型列表
405
+ * @returns 匹配的实体列表
324
406
  */
325
- queryByTag(tag) {
407
+ queryByLinearScan(componentTypes) {
408
+ const mask = this.createComponentMask(componentTypes);
409
+ return this.entities.filter(entity => (entity.componentMask & mask) === mask);
410
+ }
411
+ /**
412
+ * 查询包含任意指定组件的实体
413
+ *
414
+ * 返回包含任意一个指定组件类型的实体列表。
415
+ * 使用集合合并算法确保高效的查询性能。
416
+ *
417
+ * @param componentTypes 要查询的组件类型列表
418
+ * @returns 查询结果,包含匹配的实体和性能信息
419
+ *
420
+ * @example
421
+ * ```typescript
422
+ * // 查询具有武器或护甲组件的实体
423
+ * const result = querySystem.queryAny(WeaponComponent, ArmorComponent);
424
+ * console.log(`找到 ${result.count} 个装备实体`);
425
+ * ```
426
+ */
427
+ queryAny(...componentTypes) {
326
428
  const startTime = performance.now();
327
- this.ensureIndexesUpdated();
328
- const entities = Array.from(this.entityIndex.byTag.get(tag) || []);
329
- const executionTime = performance.now() - startTime;
330
- this.updatePerformanceStats(executionTime, true);
429
+ this.queryStats.totalQueries++;
430
+ const cacheKey = `any:${componentTypes.map(t => t.name).sort().join(',')}`;
431
+ // 检查缓存
432
+ const cached = this.getFromCache(cacheKey);
433
+ if (cached) {
434
+ this.queryStats.cacheHits++;
435
+ return {
436
+ entities: cached,
437
+ count: cached.length,
438
+ executionTime: performance.now() - startTime,
439
+ fromCache: true
440
+ };
441
+ }
442
+ // 使用集合合并
443
+ const entitySet = new Set();
444
+ for (const componentType of componentTypes) {
445
+ const typeEntities = this.entityIndex.byComponentType.get(componentType);
446
+ if (typeEntities) {
447
+ for (const entity of typeEntities) {
448
+ entitySet.add(entity);
449
+ }
450
+ }
451
+ }
452
+ const entities = Array.from(entitySet);
453
+ this.addToCache(cacheKey, entities);
331
454
  return {
332
455
  entities,
333
456
  count: entities.length,
334
- executionTime,
457
+ executionTime: performance.now() - startTime,
335
458
  fromCache: false
336
459
  };
337
460
  }
338
461
  /**
339
- * 根据名称查询实体
340
- * @param name 名称
341
- * @returns 查询结果
462
+ * 查询不包含任何指定组件的实体
463
+ *
464
+ * 返回不包含任何指定组件类型的实体列表。
465
+ * 适用于排除特定类型实体的查询场景。
466
+ *
467
+ * @param componentTypes 要排除的组件类型列表
468
+ * @returns 查询结果,包含匹配的实体和性能信息
469
+ *
470
+ * @example
471
+ * ```typescript
472
+ * // 查询不具有AI和玩家控制组件的实体(如静态物体)
473
+ * const result = querySystem.queryNone(AIComponent, PlayerControlComponent);
474
+ * console.log(`找到 ${result.count} 个静态实体`);
475
+ * ```
342
476
  */
343
- queryByName(name) {
477
+ queryNone(...componentTypes) {
344
478
  const startTime = performance.now();
345
- this.ensureIndexesUpdated();
346
- const entities = Array.from(this.entityIndex.byName.get(name) || []);
347
- const executionTime = performance.now() - startTime;
348
- this.updatePerformanceStats(executionTime, true);
479
+ this.queryStats.totalQueries++;
480
+ const cacheKey = `none:${componentTypes.map(t => t.name).sort().join(',')}`;
481
+ // 检查缓存
482
+ const cached = this.getFromCache(cacheKey);
483
+ if (cached) {
484
+ this.queryStats.cacheHits++;
485
+ return {
486
+ entities: cached,
487
+ count: cached.length,
488
+ executionTime: performance.now() - startTime,
489
+ fromCache: true
490
+ };
491
+ }
492
+ const mask = this.createComponentMask(componentTypes);
493
+ const entities = this.entities.filter(entity => (entity.componentMask & mask) === BigInt(0));
494
+ this.addToCache(cacheKey, entities);
349
495
  return {
350
496
  entities,
351
497
  count: entities.length,
352
- executionTime,
498
+ executionTime: performance.now() - startTime,
353
499
  fromCache: false
354
500
  };
355
501
  }
356
502
  /**
357
- * 根据单个组件类型快速查询
358
- * @param componentType 组件类型
359
- * @returns 查询结果
503
+ * 按标签查询实体
504
+ *
505
+ * 返回具有指定标签的所有实体。
506
+ * 标签查询使用专用索引,具有很高的查询性能。
507
+ *
508
+ * @param tag 要查询的标签值
509
+ * @returns 查询结果,包含匹配的实体和性能信息
510
+ *
511
+ * @example
512
+ * ```typescript
513
+ * // 查询所有玩家实体
514
+ * const players = querySystem.queryByTag(PLAYER_TAG);
515
+ * ```
360
516
  */
361
- queryByComponent(componentType) {
517
+ queryByTag(tag) {
362
518
  const startTime = performance.now();
363
- this.ensureIndexesUpdated();
364
- const entities = Array.from(this.entityIndex.byComponentType.get(componentType) || []);
365
- const executionTime = performance.now() - startTime;
366
- this.updatePerformanceStats(executionTime, true);
519
+ this.queryStats.totalQueries++;
520
+ const cacheKey = `tag:${tag}`;
521
+ // 检查缓存
522
+ const cached = this.getFromCache(cacheKey);
523
+ if (cached) {
524
+ this.queryStats.cacheHits++;
525
+ return {
526
+ entities: cached,
527
+ count: cached.length,
528
+ executionTime: performance.now() - startTime,
529
+ fromCache: true
530
+ };
531
+ }
532
+ // 使用索引查询
533
+ this.queryStats.indexHits++;
534
+ const entities = Array.from(this.entityIndex.byTag.get(tag) || []);
535
+ // 缓存结果
536
+ this.addToCache(cacheKey, entities);
367
537
  return {
368
538
  entities,
369
539
  count: entities.length,
370
- executionTime,
540
+ executionTime: performance.now() - startTime,
371
541
  fromCache: false
372
542
  };
373
543
  }
374
544
  /**
375
- * 类型安全的查询所有指定组件的实体
376
- * @param componentTypes 组件类型数组
377
- * @returns 类型安全的查询结果
545
+ * 按名称查询实体
546
+ *
547
+ * 返回具有指定名称的所有实体。
548
+ * 名称查询使用专用索引,适用于查找特定的命名实体。
549
+ *
550
+ * @param name 要查询的实体名称
551
+ * @returns 查询结果,包含匹配的实体和性能信息
552
+ *
553
+ * @example
554
+ * ```typescript
555
+ * // 查找名为"Player"的实体
556
+ * const player = querySystem.queryByName("Player");
557
+ * ```
378
558
  */
379
- queryAllTyped(...componentTypes) {
559
+ queryByName(name) {
380
560
  const startTime = performance.now();
381
- this.ensureIndexesUpdated();
382
- const condition = {
383
- type: QueryConditionType.ALL,
384
- componentTypes: [...componentTypes],
385
- mask: this.createMask([...componentTypes])
386
- };
387
- const entities = this.queryWithIndexOptimization(condition) ||
388
- this.filterEntitiesByCondition(this.entities, condition);
389
- // 提取组件
390
- const components = [];
391
- for (const entity of entities) {
392
- const entityComponents = [];
393
- let hasAllComponents = true;
394
- for (const type of componentTypes) {
395
- const component = entity.getComponent(type);
396
- if (component === null) {
397
- hasAllComponents = false;
398
- break;
399
- }
400
- entityComponents.push(component);
401
- }
402
- if (hasAllComponents) {
403
- components.push(entityComponents);
404
- }
561
+ this.queryStats.totalQueries++;
562
+ const cacheKey = `name:${name}`;
563
+ // 检查缓存
564
+ const cached = this.getFromCache(cacheKey);
565
+ if (cached) {
566
+ this.queryStats.cacheHits++;
567
+ return {
568
+ entities: cached,
569
+ count: cached.length,
570
+ executionTime: performance.now() - startTime,
571
+ fromCache: true
572
+ };
405
573
  }
406
- const executionTime = performance.now() - startTime;
407
- this.updatePerformanceStats(executionTime, false);
574
+ // 使用索引查询
575
+ this.queryStats.indexHits++;
576
+ const entities = Array.from(this.entityIndex.byName.get(name) || []);
577
+ // 缓存结果
578
+ this.addToCache(cacheKey, entities);
408
579
  return {
409
580
  entities,
410
- components,
411
581
  count: entities.length,
412
- executionTime,
582
+ executionTime: performance.now() - startTime,
413
583
  fromCache: false
414
584
  };
415
585
  }
416
586
  /**
417
- * 查询具有特定组件组合的实体并返回组件实例
418
- * @param componentTypes 组件类型数组
419
- * @returns 实体和对应组件的映射
420
- */
421
- queryWithComponents(...componentTypes) {
422
- const result = this.queryAllTyped(...componentTypes);
423
- return result.entities.map((entity, index) => ({
424
- entity,
425
- components: result.components[index]
426
- }));
427
- }
428
- /**
429
- * 迭代查询结果,为每个匹配的实体执行回调
430
- * @param componentTypes 组件类型数组
431
- * @param callback 回调函数
587
+ * 按单个组件类型查询实体
588
+ *
589
+ * 返回包含指定组件类型的所有实体。
590
+ * 这是最基础的查询方法,具有最高的查询性能。
591
+ *
592
+ * @param componentType 要查询的组件类型
593
+ * @returns 查询结果,包含匹配的实体和性能信息
594
+ *
595
+ * @example
596
+ * ```typescript
597
+ * // 查询所有具有位置组件的实体
598
+ * const entitiesWithPosition = querySystem.queryByComponent(PositionComponent);
599
+ * ```
432
600
  */
433
- forEachWithComponents(componentTypes, callback) {
434
- const result = this.queryAllTyped(...componentTypes);
435
- for (let i = 0; i < result.entities.length; i++) {
436
- callback(result.entities[i], result.components[i]);
437
- }
438
- }
439
- /**
440
- * 查询单个组件类型的实体,返回类型安全的结果
441
- * @param componentType 组件类型
442
- * @returns 实体和组件的配对数组
443
- */
444
- queryComponentTyped(componentType) {
445
- const startTime = performance.now();
446
- this.ensureIndexesUpdated();
447
- const entities = Array.from(this.entityIndex.byComponentType.get(componentType) || []);
448
- const result = [];
449
- for (const entity of entities) {
450
- const component = entity.getComponent(componentType);
451
- if (component) {
452
- result.push({ entity, component });
453
- }
454
- }
455
- const executionTime = performance.now() - startTime;
456
- this.updatePerformanceStats(executionTime, true);
457
- return result;
458
- }
459
- /**
460
- * 查询两个组件类型的实体,返回类型安全的结果
461
- * @param componentType1 第一个组件类型
462
- * @param componentType2 第二个组件类型
463
- * @returns 实体和组件的配对数组
464
- */
465
- queryTwoComponents(componentType1, componentType2) {
466
- const result = this.queryAllTyped(componentType1, componentType2);
467
- return result.entities.map((entity, index) => ({
468
- entity,
469
- component1: result.components[index][0],
470
- component2: result.components[index][1]
471
- }));
472
- }
473
- /**
474
- * 查询三个组件类型的实体,返回类型安全的结果
475
- * @param componentType1 第一个组件类型
476
- * @param componentType2 第二个组件类型
477
- * @param componentType3 第三个组件类型
478
- * @returns 实体和组件的配对数组
479
- */
480
- queryThreeComponents(componentType1, componentType2, componentType3) {
481
- const result = this.queryAllTyped(componentType1, componentType2, componentType3);
482
- return result.entities.map((entity, index) => ({
483
- entity,
484
- component1: result.components[index][0],
485
- component2: result.components[index][1],
486
- component3: result.components[index][2]
487
- }));
488
- }
489
- /**
490
- * 执行单个条件查询
491
- * @param condition 查询条件
492
- * @returns 查询结果
493
- */
494
- query(condition) {
601
+ queryByComponent(componentType) {
495
602
  const startTime = performance.now();
496
- // 确保索引是最新的
497
- this.ensureIndexesUpdated();
498
- // 生成缓存键
499
- const cacheKey = this.generateCacheKey(condition);
603
+ this.queryStats.totalQueries++;
604
+ const cacheKey = `component:${componentType.name}`;
500
605
  // 检查缓存
501
- const cached = this.getCachedResult(cacheKey);
606
+ const cached = this.getFromCache(cacheKey);
502
607
  if (cached) {
503
- this.updatePerformanceStats(performance.now() - startTime, false);
608
+ this.queryStats.cacheHits++;
504
609
  return {
505
- entities: cached.entities,
506
- count: cached.entities.length,
610
+ entities: cached,
611
+ count: cached.length,
507
612
  executionTime: performance.now() - startTime,
508
613
  fromCache: true
509
614
  };
510
615
  }
511
- // 尝试使用索引优化查询
512
- let result = this.queryWithIndexOptimization(condition);
513
- // 如果索引优化失败,回退到传统查询
514
- if (!result) {
515
- result = this.filterEntitiesByCondition(this.entities, condition);
516
- }
517
- const executionTime = performance.now() - startTime;
616
+ // 使用索引查询
617
+ this.queryStats.indexHits++;
618
+ const entities = Array.from(this.entityIndex.byComponentType.get(componentType) || []);
518
619
  // 缓存结果
519
- this.cacheResult(cacheKey, result);
520
- // 更新性能统计
521
- this.updatePerformanceStats(executionTime, false);
620
+ this.addToCache(cacheKey, entities);
522
621
  return {
523
- entities: result,
524
- count: result.length,
525
- executionTime,
622
+ entities,
623
+ count: entities.length,
624
+ executionTime: performance.now() - startTime,
526
625
  fromCache: false
527
626
  };
528
627
  }
529
628
  /**
530
- * 使用索引优化查询
531
- * @param condition 查询条件
532
- * @returns 查询结果或null(如果无法优化)
629
+ * 从缓存获取查询结果
533
630
  */
534
- queryWithIndexOptimization(condition) {
535
- // 对于单组件查询,直接使用组件索引
536
- if (condition.componentTypes.length === 1 && condition.type === QueryConditionType.ALL) {
537
- const componentType = condition.componentTypes[0];
538
- const entities = this.entityIndex.byComponentType.get(componentType);
539
- return entities ? Array.from(entities) : [];
540
- }
541
- // 对于多组件ALL查询,找到最小的组件集合作为起点
542
- if (condition.type === QueryConditionType.ALL && condition.componentTypes.length > 1) {
543
- let smallestSet = null;
544
- let smallestSize = Infinity;
545
- for (const componentType of condition.componentTypes) {
546
- const entities = this.entityIndex.byComponentType.get(componentType);
547
- if (!entities)
548
- return []; // 如果任何组件都没有实体,结果为空
549
- if (entities.size < smallestSize) {
550
- smallestSize = entities.size;
551
- smallestSet = entities;
552
- }
553
- }
554
- if (!smallestSet)
555
- return [];
556
- // 从最小集合开始,检查每个实体是否包含所有其他组件
557
- const result = [];
558
- for (const entity of smallestSet) {
559
- if (this.matchesCondition(entity, condition)) {
560
- result.push(entity);
561
- }
562
- }
563
- return result;
564
- }
565
- // 对于ANY查询,合并所有相关组件的实体集合
566
- if (condition.type === QueryConditionType.ANY) {
567
- const entitySet = new Set();
568
- for (const componentType of condition.componentTypes) {
569
- const entities = this.entityIndex.byComponentType.get(componentType);
570
- if (entities) {
571
- for (const entity of entities) {
572
- entitySet.add(entity);
573
- }
574
- }
575
- }
576
- return Array.from(entitySet);
577
- }
578
- // 对于NONE查询,从所有实体中排除包含指定组件的实体
579
- if (condition.type === QueryConditionType.NONE) {
580
- const excludeSet = new Set();
581
- for (const componentType of condition.componentTypes) {
582
- const entities = this.entityIndex.byComponentType.get(componentType);
583
- if (entities) {
584
- for (const entity of entities) {
585
- excludeSet.add(entity);
586
- }
587
- }
588
- }
589
- return this.entities.filter(entity => !excludeSet.has(entity));
631
+ getFromCache(cacheKey) {
632
+ const entry = this.queryCache.get(cacheKey);
633
+ if (!entry)
634
+ return null;
635
+ // 检查缓存是否过期
636
+ if (Date.now() - entry.timestamp > this.cacheTimeout) {
637
+ this.queryCache.delete(cacheKey);
638
+ return null;
590
639
  }
591
- return null; // 无法优化
640
+ entry.hitCount++;
641
+ return entry.entities;
592
642
  }
593
643
  /**
594
- * 更新性能统计
595
- * @param executionTime 执行时间
596
- * @param fromIndex 是否来自索引
644
+ * 添加查询结果到缓存
597
645
  */
598
- updatePerformanceStats(executionTime, fromIndex) {
599
- this.performanceStats.totalQueries++;
600
- // 更新平均执行时间
601
- const totalTime = this.performanceStats.averageExecutionTime * (this.performanceStats.totalQueries - 1) + executionTime;
602
- this.performanceStats.averageExecutionTime = totalTime / this.performanceStats.totalQueries;
603
- // 更新缓存命中率
604
- this.performanceStats.cacheHitRate = this.cacheHits / (this.cacheHits + this.cacheMisses);
605
- // 更新索引命中率
606
- if (fromIndex) {
607
- this.performanceStats.indexHitRate = (this.performanceStats.indexHitRate * (this.performanceStats.totalQueries - 1) + 1) / this.performanceStats.totalQueries;
608
- }
609
- else {
610
- this.performanceStats.indexHitRate = (this.performanceStats.indexHitRate * (this.performanceStats.totalQueries - 1)) / this.performanceStats.totalQueries;
611
- }
612
- // 记录慢查询
613
- if (executionTime > 10) { // 超过10ms的查询被认为是慢查询
614
- this.performanceStats.slowQueries.push({
615
- query: `执行时间: ${executionTime.toFixed(2)}ms`,
616
- executionTime,
617
- timestamp: Date.now()
618
- });
619
- // 只保留最近的50个慢查询
620
- if (this.performanceStats.slowQueries.length > 50) {
621
- this.performanceStats.slowQueries.shift();
622
- }
646
+ addToCache(cacheKey, entities) {
647
+ // 如果缓存已满,清理最少使用的条目
648
+ if (this.queryCache.size >= this.cacheMaxSize) {
649
+ this.cleanupCache();
623
650
  }
651
+ this.queryCache.set(cacheKey, {
652
+ entities: [...entities], // 复制数组避免引用问题
653
+ timestamp: Date.now(),
654
+ hitCount: 0
655
+ });
624
656
  }
625
657
  /**
626
- * 根据条件过滤实体
627
- * @param entities 实体数组
628
- * @param condition 查询条件
629
- * @returns 过滤后的实体数组
658
+ * 清理缓存
630
659
  */
631
- filterEntitiesByCondition(entities, condition) {
632
- const result = [];
633
- for (const entity of entities) {
634
- if (this.matchesCondition(entity, condition)) {
635
- result.push(entity);
660
+ cleanupCache() {
661
+ // 移除过期的缓存条目
662
+ const now = Date.now();
663
+ for (const [key, entry] of this.queryCache.entries()) {
664
+ if (now - entry.timestamp > this.cacheTimeout) {
665
+ this.queryCache.delete(key);
636
666
  }
637
667
  }
638
- return result;
639
- }
640
- /**
641
- * 检查实体是否匹配条件
642
- * @param entity 实体
643
- * @param condition 查询条件
644
- * @returns 是否匹配
645
- */
646
- matchesCondition(entity, condition) {
647
- const entityMask = entity.componentMask;
648
- switch (condition.type) {
649
- case QueryConditionType.ALL:
650
- // 实体必须包含所有指定组件
651
- return (entityMask & condition.mask) === condition.mask;
652
- case QueryConditionType.ANY:
653
- // 实体必须包含至少一个指定组件
654
- return (entityMask & condition.mask) !== BigInt(0);
655
- case QueryConditionType.NONE:
656
- // 实体不能包含任何指定组件
657
- return (entityMask & condition.mask) === BigInt(0);
658
- default:
659
- return false;
660
- }
661
- }
662
- /**
663
- * 创建组件类型的位掩码
664
- * @param componentTypes 组件类型数组
665
- * @returns 位掩码
666
- */
667
- createMask(componentTypes) {
668
- let mask = BigInt(0);
669
- for (const componentType of componentTypes) {
670
- if (ComponentRegistry.isRegistered(componentType)) {
671
- mask |= ComponentRegistry.getBitMask(componentType);
668
+ // 如果还是太满,移除最少使用的条目
669
+ if (this.queryCache.size >= this.cacheMaxSize) {
670
+ const entries = Array.from(this.queryCache.entries());
671
+ entries.sort((a, b) => a[1].hitCount - b[1].hitCount);
672
+ const toRemove = Math.floor(this.cacheMaxSize * 0.2); // 移除20%
673
+ for (let i = 0; i < toRemove && i < entries.length; i++) {
674
+ this.queryCache.delete(entries[i][0]);
672
675
  }
673
676
  }
674
- return mask;
675
677
  }
676
678
  /**
677
- * 生成缓存键
678
- * @param condition 查询条件
679
- * @returns 缓存键
679
+ * 清除所有查询缓存
680
680
  */
681
- generateCacheKey(condition) {
682
- const typeNames = condition.componentTypes.map(t => t.name).sort().join(',');
683
- return `${condition.type}:${typeNames}`;
681
+ clearQueryCache() {
682
+ this.queryCache.clear();
684
683
  }
685
684
  /**
686
- * 生成复合查询的缓存键
687
- * @param conditions 查询条件数组
688
- * @returns 缓存键
685
+ * 公共方法:清理查询缓存
686
+ *
687
+ * 用于外部调用清理缓存,通常在批量操作后使用。
689
688
  */
690
- generateComplexCacheKey(conditions) {
691
- const conditionKeys = conditions.map(c => this.generateCacheKey(c));
692
- return `complex:${conditionKeys.join('|')}`;
689
+ clearCache() {
690
+ this.clearQueryCache();
691
+ }
692
+ /**
693
+ * 批量更新实体组件
694
+ *
695
+ * 对大量实体进行批量组件更新操作。
696
+ * 当更新数量超过阈值时,系统会自动使用WebAssembly加速。
697
+ *
698
+ * @param updates 更新操作列表,包含实体ID和新的组件掩码
699
+ *
700
+ * @example
701
+ * ```typescript
702
+ * // 批量更新实体的组件配置
703
+ * const updates = [
704
+ * { entityId: 1, componentMask: BigInt(0b1011) },
705
+ * { entityId: 2, componentMask: BigInt(0b1101) }
706
+ * ];
707
+ * querySystem.batchUpdateComponents(updates);
708
+ * ```
709
+ */
710
+ batchUpdateComponents(updates) {
711
+ if (this.wasmAvailable && updates.length > 100) {
712
+ try {
713
+ const entityIds = updates.map(u => u.entityId);
714
+ const masks = updates.map(u => u.componentMask);
715
+ WasmCore_1.ecsCore.batchUpdateMasks(entityIds, masks);
716
+ console.log(`WebAssembly加速批量更新 ${updates.length} 个实体`);
717
+ }
718
+ catch (error) {
719
+ console.warn('WebAssembly批量更新失败,回退到JavaScript实现:', error);
720
+ this.batchUpdateComponentsJS(updates);
721
+ }
722
+ }
723
+ else {
724
+ this.batchUpdateComponentsJS(updates);
725
+ }
726
+ // 批量更新后清除缓存
727
+ this.clearQueryCache();
693
728
  }
694
729
  /**
695
- * 获取缓存结果
696
- * @param cacheKey 缓存键
697
- * @returns 缓存项或null
730
+ * JavaScript实现的批量更新
698
731
  */
699
- getCachedResult(cacheKey) {
700
- const cached = this.queryCache.get(cacheKey);
701
- if (cached) {
702
- const now = Date.now();
703
- if (now - cached.lastUpdate < this.cacheTimeout) {
704
- cached.hitCount++;
705
- this.cacheHits++;
706
- return cached;
707
- }
708
- else {
709
- // 缓存过期,删除
710
- this.queryCache.delete(cacheKey);
732
+ batchUpdateComponentsJS(updates) {
733
+ for (const update of updates) {
734
+ const entity = this.entities.find(e => e.id === update.entityId);
735
+ if (entity) {
736
+ // 注意:componentMask是只读属性,实际应用中需要通过添加/移除组件来更新
737
+ console.log(`更新实体 ${update.entityId} 的组件掩码: ${update.componentMask}`);
711
738
  }
712
739
  }
713
- this.cacheMisses++;
714
- return null;
740
+ this.rebuildIndexes();
715
741
  }
716
742
  /**
717
- * 缓存查询结果
718
- * @param cacheKey 缓存键
719
- * @param entities 实体数组
743
+ * 获取加速状态信息
744
+ *
745
+ * 返回当前查询系统的加速状态和性能信息。
746
+ * 包括WebAssembly可用性、缓存统计等详细信息。
747
+ *
748
+ * @returns 加速状态信息对象
720
749
  */
721
- cacheResult(cacheKey, entities) {
722
- // 如果缓存已满,删除最少使用的项
723
- if (this.queryCache.size >= this.maxCacheSize) {
724
- this.evictLeastUsedCache();
725
- }
726
- this.queryCache.set(cacheKey, {
727
- entities: entities.slice(), // 创建副本
728
- lastUpdate: Date.now(),
729
- hitCount: 0
730
- });
750
+ getAccelerationStatus() {
751
+ return {
752
+ wasmEnabled: this.wasmAvailable,
753
+ currentProvider: this.wasmAvailable ? 'hybrid' : 'javascript',
754
+ availableProviders: ['javascript', 'hybrid'],
755
+ performanceInfo: {
756
+ entityCount: this.entities.length,
757
+ wasmEnabled: this.wasmAvailable,
758
+ cacheStats: {
759
+ size: this.queryCache.size,
760
+ hitRate: this.queryStats.totalQueries > 0 ?
761
+ (this.queryStats.cacheHits / this.queryStats.totalQueries * 100).toFixed(2) + '%' : '0%'
762
+ }
763
+ }
764
+ };
731
765
  }
732
766
  /**
733
- * 清空查询缓存
767
+ * 切换加速提供者
768
+ *
769
+ * 兼容性接口,保持向后兼容。
770
+ * 系统会自动选择最佳的实现方式。
771
+ *
772
+ * @param providerName 提供者名称
773
+ * @returns 是否切换成功
734
774
  */
735
- clearCache() {
736
- this.queryCache.clear();
775
+ async switchAccelerationProvider(providerName) {
776
+ return true;
737
777
  }
738
778
  /**
739
- * 删除最少使用的缓存项
779
+ * 创建组件掩码
780
+ *
781
+ * 根据组件类型列表生成对应的位掩码。
782
+ * 使用位掩码优化器进行缓存和预计算。
783
+ *
784
+ * @param componentTypes 组件类型列表
785
+ * @returns 生成的位掩码
740
786
  */
741
- evictLeastUsedCache() {
742
- let leastUsedKey = '';
743
- let minHitCount = Number.MAX_VALUE;
744
- for (const [key, item] of this.queryCache.entries()) {
745
- if (item.hitCount < minHitCount) {
746
- minHitCount = item.hitCount;
747
- leastUsedKey = key;
748
- }
749
- }
750
- if (leastUsedKey) {
751
- this.queryCache.delete(leastUsedKey);
787
+ createComponentMask(componentTypes) {
788
+ // 使用位掩码优化器创建掩码
789
+ const componentNames = componentTypes.map(type => type.name);
790
+ // 确保组件类型已注册到优化器
791
+ for (const name of componentNames) {
792
+ this.bitMaskOptimizer.registerComponentType(name);
752
793
  }
794
+ return this.bitMaskOptimizer.createCombinedMask(componentNames);
753
795
  }
754
796
  /**
755
- * 获取详细的查询统计信息
797
+ * 获取系统统计信息
798
+ *
799
+ * 返回查询系统的详细统计信息,包括实体数量、索引状态、
800
+ * 查询性能统计等,用于性能监控和调试。
801
+ *
802
+ * @returns 系统统计信息对象
756
803
  */
757
804
  getStats() {
758
- const totalQueries = this.cacheHits + this.cacheMisses;
759
- const hitRate = totalQueries > 0 ? this.cacheHits / totalQueries : 0;
760
805
  return {
761
806
  entityCount: this.entities.length,
762
- cacheSize: this.queryCache.size,
763
- cacheHits: this.cacheHits,
764
- cacheMisses: this.cacheMisses,
765
- hitRate,
766
- maxCacheSize: this.maxCacheSize,
767
807
  indexStats: {
768
808
  maskIndexSize: this.entityIndex.byMask.size,
769
809
  componentIndexSize: this.entityIndex.byComponentType.size,
770
810
  tagIndexSize: this.entityIndex.byTag.size,
771
811
  nameIndexSize: this.entityIndex.byName.size
772
812
  },
773
- performanceStats: { ...this.performanceStats }
774
- };
775
- }
776
- /**
777
- * 获取性能报告
778
- */
779
- getPerformanceReport() {
780
- const stats = this.getStats();
781
- let report = '=== 查询系统性能报告 ===\n';
782
- report += `实体数量: ${stats.entityCount}\n`;
783
- report += `总查询次数: ${stats.performanceStats.totalQueries}\n`;
784
- report += `平均执行时间: ${stats.performanceStats.averageExecutionTime.toFixed(2)}ms\n`;
785
- report += `缓存命中率: ${(stats.performanceStats.cacheHitRate * 100).toFixed(1)}%\n`;
786
- report += `索引命中率: ${(stats.performanceStats.indexHitRate * 100).toFixed(1)}%\n`;
787
- report += '\n=== 索引统计 ===\n';
788
- report += `位掩码索引: ${stats.indexStats.maskIndexSize} 项\n`;
789
- report += `组件类型索引: ${stats.indexStats.componentIndexSize} 项\n`;
790
- report += `标签索引: ${stats.indexStats.tagIndexSize} 项\n`;
791
- report += `名称索引: ${stats.indexStats.nameIndexSize} 项\n`;
792
- if (stats.performanceStats.slowQueries.length > 0) {
793
- report += '\n=== 慢查询记录 ===\n';
794
- stats.performanceStats.slowQueries.slice(-10).forEach((query, index) => {
795
- const time = new Date(query.timestamp).toLocaleTimeString();
796
- report += `${index + 1}. ${query.query} (${time})\n`;
797
- });
798
- }
799
- return report;
800
- }
801
- /**
802
- * 优化索引配置
803
- */
804
- optimizeIndexes() {
805
- // 根据查询模式优化索引更新频率
806
- if (this.performanceStats.totalQueries > 1000) {
807
- // 高频查询场景,降低索引更新阈值
808
- this.indexUpdateThreshold = 50;
809
- }
810
- else {
811
- // 低频查询场景,提高索引更新阈值
812
- this.indexUpdateThreshold = 200;
813
- }
814
- // 根据缓存命中率调整缓存大小
815
- if (this.performanceStats.cacheHitRate < 0.5 && this.maxCacheSize < 200) {
816
- this.maxCacheSize = Math.min(200, this.maxCacheSize * 1.5);
817
- }
818
- else if (this.performanceStats.cacheHitRate > 0.9 && this.maxCacheSize > 50) {
819
- this.maxCacheSize = Math.max(50, this.maxCacheSize * 0.8);
820
- }
821
- }
822
- /**
823
- * 批量查询多个条件
824
- * @param queries 查询条件数组
825
- * @returns 查询结果数组
826
- */
827
- batchQuery(queries) {
828
- const startTime = performance.now();
829
- this.ensureIndexesUpdated();
830
- const results = [];
831
- for (const query of queries) {
832
- const result = this.query(query);
833
- results.push(result);
834
- }
835
- const totalTime = performance.now() - startTime;
836
- console.log(`批量查询 ${queries.length} 个条件,总耗时: ${totalTime.toFixed(2)}ms`);
837
- return results;
838
- }
839
- /**
840
- * 设置缓存配置
841
- * @param maxSize 最大缓存大小
842
- * @param timeout 缓存超时时间(毫秒)
843
- */
844
- setCacheConfig(maxSize, timeout) {
845
- this.maxCacheSize = maxSize;
846
- this.cacheTimeout = timeout;
847
- }
848
- /**
849
- * 重置统计信息
850
- */
851
- resetStats() {
852
- this.cacheHits = 0;
853
- this.cacheMisses = 0;
854
- this.performanceStats = {
855
- totalQueries: 0,
856
- averageExecutionTime: 0,
857
- cacheHitRate: 0,
858
- indexHitRate: 0,
859
- slowQueries: []
860
- };
861
- }
862
- /**
863
- * 预热查询缓存
864
- * @param commonQueries 常用查询条件数组
865
- */
866
- warmUpCache(commonQueries) {
867
- console.log('开始预热查询缓存...');
868
- const startTime = performance.now();
869
- for (const condition of commonQueries) {
870
- this.query(condition);
871
- }
872
- const endTime = performance.now();
873
- console.log(`缓存预热完成,耗时: ${(endTime - startTime).toFixed(2)}ms`);
874
- }
875
- /**
876
- * 获取实体变更监听器
877
- * @param condition 查询条件
878
- * @param callback 变更回调
879
- * @returns 取消监听的函数
880
- */
881
- watchQuery(condition, callback) {
882
- let lastResult = this.query(condition).entities;
883
- const checkChanges = () => {
884
- const currentResult = this.query(condition).entities;
885
- // 检查新增的实体
886
- const added = currentResult.filter(entity => !lastResult.includes(entity));
887
- if (added.length > 0) {
888
- callback(added, 'added');
889
- }
890
- // 检查移除的实体
891
- const removed = lastResult.filter(entity => !currentResult.includes(entity));
892
- if (removed.length > 0) {
893
- callback(removed, 'removed');
813
+ accelerationStatus: this.getAccelerationStatus(),
814
+ queryStats: {
815
+ ...this.queryStats,
816
+ cacheHitRate: this.queryStats.totalQueries > 0 ?
817
+ (this.queryStats.cacheHits / this.queryStats.totalQueries * 100).toFixed(2) + '%' : '0%'
894
818
  }
895
- lastResult = currentResult;
896
819
  };
897
- // 使用定时器定期检查变更(实际项目中可能需要更高效的实现)
898
- const intervalId = setInterval(checkChanges, 100);
899
- return () => {
900
- clearInterval(intervalId);
901
- };
902
- }
903
- /**
904
- * 获取查询结果的快照
905
- * @param condition 查询条件
906
- * @returns 查询快照
907
- */
908
- createSnapshot(condition) {
909
- const result = this.query(condition);
910
- return {
911
- entities: [...result.entities], // 创建副本
912
- timestamp: Date.now(),
913
- condition: { ...condition }
914
- };
915
- }
916
- /**
917
- * 比较两个查询快照
918
- * @param snapshot1 第一个快照
919
- * @param snapshot2 第二个快照
920
- * @returns 比较结果
921
- */
922
- compareSnapshots(snapshot1, snapshot2) {
923
- const set1 = new Set(snapshot1.entities);
924
- const set2 = new Set(snapshot2.entities);
925
- const added = snapshot2.entities.filter(entity => !set1.has(entity));
926
- const removed = snapshot1.entities.filter(entity => !set2.has(entity));
927
- const unchanged = snapshot1.entities.filter(entity => set2.has(entity));
928
- return { added, removed, unchanged };
929
- }
930
- /**
931
- * 执行并行查询
932
- * @param conditions 查询条件数组
933
- * @returns Promise<查询结果数组>
934
- */
935
- async parallelQuery(conditions) {
936
- const promises = conditions.map(condition => Promise.resolve(this.query(condition)));
937
- return Promise.all(promises);
938
- }
939
- /**
940
- * 获取查询建议
941
- * @param entities 实体数组
942
- * @returns 查询优化建议
943
- */
944
- getQuerySuggestions(entities) {
945
- const suggestions = [];
946
- // 分析组件使用频率
947
- const componentFrequency = new Map();
948
- for (const entity of entities) {
949
- for (const component of entity.components) {
950
- const type = component.constructor;
951
- componentFrequency.set(type, (componentFrequency.get(type) || 0) + 1);
952
- }
953
- }
954
- // 建议基于高频组件的查询
955
- const sortedComponents = Array.from(componentFrequency.entries())
956
- .sort((a, b) => b[1] - a[1])
957
- .slice(0, 5);
958
- for (const [componentType, count] of sortedComponents) {
959
- suggestions.push(`考虑为组件 ${componentType.name} 创建专门的查询(使用频率: ${count})`);
960
- }
961
- // 建议缓存配置
962
- if (this.performanceStats.cacheHitRate < 0.5) {
963
- suggestions.push('缓存命中率较低,考虑增加缓存大小或调整缓存策略');
964
- }
965
- // 建议索引优化
966
- if (this.performanceStats.indexHitRate < 0.7) {
967
- suggestions.push('索引命中率较低,考虑重建索引或优化查询条件');
968
- }
969
- return suggestions;
970
- }
971
- /**
972
- * 导出查询统计数据
973
- * @returns 统计数据的JSON字符串
974
- */
975
- exportStats() {
976
- const stats = this.getStats();
977
- return JSON.stringify(stats, null, 2);
978
- }
979
- /**
980
- * 导入查询统计数据
981
- * @param statsJson 统计数据的JSON字符串
982
- */
983
- importStats(statsJson) {
984
- try {
985
- const stats = JSON.parse(statsJson);
986
- this.cacheHits = stats.cacheHits || 0;
987
- this.cacheMisses = stats.cacheMisses || 0;
988
- this.performanceStats = stats.performanceStats || this.performanceStats;
989
- }
990
- catch (error) {
991
- console.error('导入统计数据失败:', error);
992
- }
993
820
  }
994
821
  }
822
+ exports.QuerySystem = QuerySystem;
995
823
  /**
996
- * 流式查询构建器
997
- * 提供链式调用的查询API
824
+ * 查询构建器
825
+ *
826
+ * 提供链式API来构建复杂的实体查询条件。
827
+ * 支持组合多种查询条件,创建灵活的查询表达式。
828
+ *
829
+ * @example
830
+ * ```typescript
831
+ * const result = new QueryBuilder(querySystem)
832
+ * .withAll(PositionComponent, VelocityComponent)
833
+ * .without(DeadComponent)
834
+ * .execute();
835
+ * ```
998
836
  */
999
- export class QueryBuilder {
837
+ class QueryBuilder {
1000
838
  constructor(querySystem) {
1001
839
  this.conditions = [];
1002
840
  this.querySystem = querySystem;
1003
841
  }
1004
842
  /**
1005
- * 添加"包含所有"条件
1006
- * @param componentTypes 组件类型
1007
- * @returns 查询构建器
843
+ * 添加"必须包含所有组件"条件
844
+ *
845
+ * @param componentTypes 必须包含的组件类型
846
+ * @returns 查询构建器实例,支持链式调用
1008
847
  */
1009
848
  withAll(...componentTypes) {
1010
849
  this.conditions.push({
1011
850
  type: QueryConditionType.ALL,
1012
851
  componentTypes,
1013
- mask: this.createMask(componentTypes)
852
+ mask: this.createComponentMask(componentTypes)
1014
853
  });
1015
854
  return this;
1016
855
  }
1017
856
  /**
1018
- * 添加"包含任意"条件
1019
- * @param componentTypes 组件类型
1020
- * @returns 查询构建器
857
+ * 添加"必须包含任意组件"条件
858
+ *
859
+ * @param componentTypes 必须包含其中任意一个的组件类型
860
+ * @returns 查询构建器实例,支持链式调用
1021
861
  */
1022
862
  withAny(...componentTypes) {
1023
863
  this.conditions.push({
1024
864
  type: QueryConditionType.ANY,
1025
865
  componentTypes,
1026
- mask: this.createMask(componentTypes)
866
+ mask: this.createComponentMask(componentTypes)
1027
867
  });
1028
868
  return this;
1029
869
  }
1030
870
  /**
1031
- * 添加"不包含"条件
1032
- * @param componentTypes 组件类型
1033
- * @returns 查询构建器
871
+ * 添加"不能包含任何组件"条件
872
+ *
873
+ * @param componentTypes 不能包含的组件类型
874
+ * @returns 查询构建器实例,支持链式调用
1034
875
  */
1035
876
  without(...componentTypes) {
1036
877
  this.conditions.push({
1037
878
  type: QueryConditionType.NONE,
1038
879
  componentTypes,
1039
- mask: this.createMask(componentTypes)
880
+ mask: this.createComponentMask(componentTypes)
1040
881
  });
1041
882
  return this;
1042
883
  }
1043
884
  /**
1044
- * 执行查询
1045
- * @returns 查询结果
885
+ * 执行查询并返回结果
886
+ *
887
+ * 根据已添加的查询条件执行实体查询。
888
+ *
889
+ * @returns 查询结果,包含匹配的实体和性能信息
1046
890
  */
1047
891
  execute() {
1048
- let result;
1049
- if (this.conditions.length === 0) {
1050
- // 如果没有组件条件,但有其他过滤条件
1051
- if (this.tagFilter !== undefined) {
1052
- result = this.querySystem.queryByTag(this.tagFilter);
1053
- }
1054
- else if (this.nameFilter !== undefined) {
1055
- result = this.querySystem.queryByName(this.nameFilter);
1056
- }
1057
- else {
1058
- return {
1059
- entities: [],
1060
- count: 0,
1061
- executionTime: 0,
1062
- fromCache: false
1063
- };
1064
- }
1065
- }
1066
- else if (this.conditions.length === 1) {
1067
- // 单条件查询,使用优化路径
892
+ const startTime = performance.now();
893
+ // 简化实现:目前只支持单一条件
894
+ if (this.conditions.length === 1) {
1068
895
  const condition = this.conditions[0];
1069
896
  switch (condition.type) {
1070
897
  case QueryConditionType.ALL:
1071
- result = this.querySystem.queryAll(...condition.componentTypes);
1072
- break;
898
+ return this.querySystem.queryAll(...condition.componentTypes);
1073
899
  case QueryConditionType.ANY:
1074
- result = this.querySystem.queryAny(...condition.componentTypes);
1075
- break;
900
+ return this.querySystem.queryAny(...condition.componentTypes);
1076
901
  case QueryConditionType.NONE:
1077
- result = this.querySystem.queryNone(...condition.componentTypes);
1078
- break;
1079
- default:
1080
- return {
1081
- entities: [],
1082
- count: 0,
1083
- executionTime: 0,
1084
- fromCache: false
1085
- };
902
+ return this.querySystem.queryNone(...condition.componentTypes);
1086
903
  }
1087
904
  }
1088
- else {
1089
- // 多条件查询
1090
- result = this.querySystem.queryComplex(...this.conditions);
1091
- }
1092
- // 应用额外的过滤条件
1093
- let entities = result.entities;
1094
- // 标签过滤
1095
- if (this.tagFilter !== undefined) {
1096
- entities = entities.filter(entity => entity.tag === this.tagFilter);
1097
- }
1098
- // 名称过滤
1099
- if (this.nameFilter !== undefined) {
1100
- entities = entities.filter(entity => entity.name === this.nameFilter);
1101
- }
1102
- // 排序
1103
- if (this.sortFunction) {
1104
- entities = [...entities].sort(this.sortFunction);
1105
- }
1106
- // 偏移
1107
- if (this.offsetCount !== undefined && this.offsetCount > 0) {
1108
- entities = entities.slice(this.offsetCount);
1109
- }
1110
- // 限制
1111
- if (this.limitCount !== undefined && this.limitCount > 0) {
1112
- entities = entities.slice(0, this.limitCount);
1113
- }
905
+ // 多条件查询的复杂实现留待后续扩展
1114
906
  return {
1115
- entities,
1116
- count: entities.length,
1117
- executionTime: result.executionTime,
1118
- fromCache: result.fromCache
907
+ entities: [],
908
+ count: 0,
909
+ executionTime: performance.now() - startTime,
910
+ fromCache: false
1119
911
  };
1120
912
  }
1121
913
  /**
1122
- * 获取第一个匹配的实体
1123
- * @returns 实体或null
1124
- */
1125
- first() {
1126
- const result = this.execute();
1127
- return result.entities.length > 0 ? result.entities[0] : null;
1128
- }
1129
- /**
1130
- * 检查是否有匹配的实体
1131
- * @returns 是否有匹配
1132
- */
1133
- any() {
1134
- const result = this.execute();
1135
- return result.count > 0;
1136
- }
1137
- /**
1138
- * 获取匹配实体的数量
1139
- * @returns 实体数量
1140
- */
1141
- count() {
1142
- const result = this.execute();
1143
- return result.count;
1144
- }
1145
- /**
1146
- * 对每个匹配的实体执行操作
1147
- * @param callback 回调函数
1148
- */
1149
- forEach(callback) {
1150
- const result = this.execute();
1151
- result.entities.forEach(callback);
1152
- }
1153
- /**
1154
- * 转换为数组
1155
- * @returns 实体数组
1156
- */
1157
- toArray() {
1158
- const result = this.execute();
1159
- return result.entities;
1160
- }
1161
- /**
1162
- * 创建组件类型的位掩码
1163
- * @param componentTypes 组件类型数组
1164
- * @returns 位掩码
914
+ * 创建组件掩码
1165
915
  */
1166
- createMask(componentTypes) {
916
+ createComponentMask(componentTypes) {
1167
917
  let mask = BigInt(0);
1168
- for (const componentType of componentTypes) {
1169
- if (ComponentRegistry.isRegistered(componentType)) {
1170
- mask |= ComponentRegistry.getBitMask(componentType);
918
+ for (const type of componentTypes) {
919
+ try {
920
+ const bitMask = ComponentStorage_1.ComponentRegistry.getBitMask(type);
921
+ mask |= bitMask;
922
+ }
923
+ catch (error) {
924
+ console.warn(`组件类型 ${type.name} 未注册,跳过`);
1171
925
  }
1172
926
  }
1173
927
  return mask;
1174
928
  }
1175
929
  /**
1176
- * 重置查询条件
1177
- * @returns 查询构建器
930
+ * 重置查询构建器
931
+ *
932
+ * 清除所有已添加的查询条件,重新开始构建查询。
933
+ *
934
+ * @returns 查询构建器实例,支持链式调用
1178
935
  */
1179
936
  reset() {
1180
- this.conditions.length = 0;
1181
- this.tagFilter = undefined;
1182
- this.nameFilter = undefined;
1183
- this.limitCount = undefined;
1184
- this.offsetCount = undefined;
1185
- this.sortFunction = undefined;
1186
- return this;
1187
- }
1188
- /**
1189
- * 添加标签过滤条件
1190
- * @param tag 标签
1191
- * @returns 查询构建器实例
1192
- */
1193
- withTag(tag) {
1194
- this.tagFilter = tag;
1195
- return this;
1196
- }
1197
- /**
1198
- * 添加名称过滤条件
1199
- * @param name 名称
1200
- * @returns 查询构建器实例
1201
- */
1202
- withName(name) {
1203
- this.nameFilter = name;
1204
- return this;
1205
- }
1206
- /**
1207
- * 限制结果数量
1208
- * @param limit 最大结果数量
1209
- * @returns 查询构建器实例
1210
- */
1211
- limit(limit) {
1212
- this.limitCount = limit;
1213
- return this;
1214
- }
1215
- /**
1216
- * 跳过指定数量的结果
1217
- * @param offset 跳过的数量
1218
- * @returns 查询构建器实例
1219
- */
1220
- offset(offset) {
1221
- this.offsetCount = offset;
1222
- return this;
1223
- }
1224
- /**
1225
- * 对结果进行排序
1226
- * @param compareFn 比较函数
1227
- * @returns 查询构建器实例
1228
- */
1229
- orderBy(compareFn) {
1230
- this.sortFunction = compareFn;
1231
- return this;
1232
- }
1233
- /**
1234
- * 按更新顺序排序
1235
- * @returns 查询构建器实例
1236
- */
1237
- orderByUpdateOrder() {
1238
- return this.orderBy((a, b) => a.updateOrder - b.updateOrder);
1239
- }
1240
- /**
1241
- * 按ID排序
1242
- * @returns 查询构建器实例
1243
- */
1244
- orderById() {
1245
- return this.orderBy((a, b) => a.id - b.id);
1246
- }
1247
- /**
1248
- * 按名称排序
1249
- * @returns 查询构建器实例
1250
- */
1251
- orderByName() {
1252
- return this.orderBy((a, b) => a.name.localeCompare(b.name));
1253
- }
1254
- /**
1255
- * 克隆查询构建器
1256
- * @returns 新的查询构建器
1257
- */
1258
- clone() {
1259
- const newBuilder = new QueryBuilder(this.querySystem);
1260
- newBuilder.conditions = this.conditions.map(c => ({ ...c }));
1261
- newBuilder.tagFilter = this.tagFilter;
1262
- newBuilder.nameFilter = this.nameFilter;
1263
- newBuilder.limitCount = this.limitCount;
1264
- newBuilder.offsetCount = this.offsetCount;
1265
- newBuilder.sortFunction = this.sortFunction;
1266
- return newBuilder;
1267
- }
1268
- /**
1269
- * 添加自定义过滤器
1270
- * @param predicate 过滤谓词
1271
- * @returns 查询构建器实例
1272
- */
1273
- filter(predicate) {
1274
- const originalExecute = this.execute.bind(this);
1275
- this.execute = () => {
1276
- const result = originalExecute();
1277
- const filteredEntities = result.entities.filter(predicate);
1278
- return {
1279
- ...result,
1280
- entities: filteredEntities,
1281
- count: filteredEntities.length
1282
- };
1283
- };
937
+ this.conditions = [];
1284
938
  return this;
1285
939
  }
1286
- /**
1287
- * 映射查询结果
1288
- * @param mapper 映射函数
1289
- * @returns 映射后的结果数组
1290
- */
1291
- map(mapper) {
1292
- const result = this.execute();
1293
- return result.entities.map(mapper);
1294
- }
1295
- /**
1296
- * 查找第一个满足条件的实体
1297
- * @param predicate 查找谓词
1298
- * @returns 实体或null
1299
- */
1300
- find(predicate) {
1301
- const result = this.execute();
1302
- if (predicate) {
1303
- return result.entities.find(predicate) || null;
1304
- }
1305
- return result.entities[0] || null;
1306
- }
1307
- /**
1308
- * 检查是否所有实体都满足条件
1309
- * @param predicate 检查谓词
1310
- * @returns 是否所有实体都满足条件
1311
- */
1312
- every(predicate) {
1313
- const result = this.execute();
1314
- return result.entities.every(predicate);
1315
- }
1316
- /**
1317
- * 检查是否有实体满足条件
1318
- * @param predicate 检查谓词
1319
- * @returns 是否有实体满足条件
1320
- */
1321
- some(predicate) {
1322
- const result = this.execute();
1323
- return result.entities.some(predicate);
1324
- }
1325
- /**
1326
- * 获取查询的调试信息
1327
- * @returns 调试信息字符串
1328
- */
1329
- getDebugInfo() {
1330
- let info = '=== 查询构建器调试信息 ===\n';
1331
- if (this.conditions.length > 0) {
1332
- info += '组件条件:\n';
1333
- this.conditions.forEach((condition, index) => {
1334
- const typeNames = condition.componentTypes.map(t => t.name).join(', ');
1335
- info += ` ${index + 1}. ${condition.type}: [${typeNames}]\n`;
1336
- });
1337
- }
1338
- if (this.tagFilter !== undefined) {
1339
- info += `标签过滤: ${this.tagFilter}\n`;
1340
- }
1341
- if (this.nameFilter !== undefined) {
1342
- info += `名称过滤: ${this.nameFilter}\n`;
1343
- }
1344
- if (this.limitCount !== undefined) {
1345
- info += `限制数量: ${this.limitCount}\n`;
1346
- }
1347
- if (this.offsetCount !== undefined) {
1348
- info += `偏移量: ${this.offsetCount}\n`;
1349
- }
1350
- if (this.sortFunction) {
1351
- info += '已设置排序函数\n';
1352
- }
1353
- return info;
1354
- }
1355
940
  }
941
+ exports.QueryBuilder = QueryBuilder;
1356
942
  //# sourceMappingURL=QuerySystem.js.map