@cjhd/cj-ecs 1.0.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/.cj-ecs.md +12 -0
- package/assets/common/component/MoveComponent.ts +292 -0
- package/assets/common/component/MoveComponent.ts.meta +9 -0
- package/assets/common/component/NodeComponent.ts +315 -0
- package/assets/common/component/NodeComponent.ts.meta +9 -0
- package/assets/common/component.meta +12 -0
- package/assets/common/system/MoveSystem.ts +108 -0
- package/assets/common/system/MoveSystem.ts.meta +9 -0
- package/assets/common/system.meta +12 -0
- package/assets/common.meta +12 -0
- package/assets/ecs/EcsComponent.ts +244 -0
- package/assets/ecs/EcsComponent.ts.meta +9 -0
- package/assets/ecs/EcsDirty.ts +459 -0
- package/assets/ecs/EcsDirty.ts.meta +9 -0
- package/assets/ecs/EcsEntity.ts +430 -0
- package/assets/ecs/EcsEntity.ts.meta +9 -0
- package/assets/ecs/EcsSingleton.ts +6 -0
- package/assets/ecs/EcsSingleton.ts.meta +9 -0
- package/assets/ecs/EcsSystem.ts +191 -0
- package/assets/ecs/EcsSystem.ts.meta +9 -0
- package/assets/ecs.meta +12 -0
- package/assets/ecs.ts +339 -0
- package/assets/ecs.ts.meta +9 -0
- package/assets/lib/EcsCache.ts +43 -0
- package/assets/lib/EcsCache.ts.meta +9 -0
- package/assets/lib/EcsFilter.ts +210 -0
- package/assets/lib/EcsFilter.ts.meta +9 -0
- package/assets/lib/EcsManager.ts +502 -0
- package/assets/lib/EcsManager.ts.meta +9 -0
- package/assets/lib/EcsObject.ts +422 -0
- package/assets/lib/EcsObject.ts.meta +9 -0
- package/assets/lib/EcsTimer.ts +239 -0
- package/assets/lib/EcsTimer.ts.meta +9 -0
- package/assets/lib/EcsTween.ts +486 -0
- package/assets/lib/EcsTween.ts.meta +9 -0
- package/assets/lib/EcsUtils.ts +352 -0
- package/assets/lib/EcsUtils.ts.meta +9 -0
- package/assets/lib.meta +12 -0
- package/assets.meta +9 -0
- package/index.ts +33 -0
- package/index.ts.meta +9 -0
- package/package.json +20 -0
- package/package.json.meta +11 -0
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
import type { IComponent, IEntity, ITypeofComponent } from '../lib/EcsObject';
|
|
2
|
+
|
|
3
|
+
/** Dirty 掩码类型,用于标记组件的脏数据位。 */
|
|
4
|
+
export type EcsDirtyMask = number;
|
|
5
|
+
|
|
6
|
+
/** Dirty 掩码清空模式,用于指定清空的 dirty 位。 */
|
|
7
|
+
export const EcsDirtyClear = {
|
|
8
|
+
Matched: 'matched',
|
|
9
|
+
All: 'all',
|
|
10
|
+
None: 'none',
|
|
11
|
+
} as const;
|
|
12
|
+
|
|
13
|
+
export type EcsDirtyClearMode = typeof EcsDirtyClear[keyof typeof EcsDirtyClear];
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 业务 DirtyBits 的形状约束。
|
|
17
|
+
* cj-ecs 只认 number mask,不关心 Transform/Spatial/HealthBar 这些业务语义。
|
|
18
|
+
*/
|
|
19
|
+
export interface IEcsComponentDirtyBits {
|
|
20
|
+
/** 组件的 dirty mask。 */
|
|
21
|
+
readonly [name: string]: EcsDirtyMask | unknown;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* 业务层 DirtyBits 的辅助基类。
|
|
26
|
+
*
|
|
27
|
+
* 用法:
|
|
28
|
+
* class PositionDirtyBits extends EcsComponentDirtyBitsBase {
|
|
29
|
+
* static readonly Transform = this.bit(0);
|
|
30
|
+
* static readonly Spatial = this.bit(1);
|
|
31
|
+
* }
|
|
32
|
+
*
|
|
33
|
+
* 注意:这里只提供 bit 运算工具,不维护任何 dirty 队列。
|
|
34
|
+
*/
|
|
35
|
+
export abstract class EcsComponentDirtyBitsBase {
|
|
36
|
+
static readonly None: EcsDirtyMask = 0;
|
|
37
|
+
|
|
38
|
+
/** 定义单个 dirty 位。index 建议保持在 0-30,避免 JS 位运算符号位问题。
|
|
39
|
+
* @param index 位索引,从 0 开始。
|
|
40
|
+
* @returns 单个 dirty 位的 mask。
|
|
41
|
+
*/
|
|
42
|
+
protected static bit(index: number): EcsDirtyMask {
|
|
43
|
+
return 1 << index;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** 一次性组合多个 dirty 位,适合定义 AllSync 这类聚合 mask。
|
|
47
|
+
* @param indices 位索引列表,从 0 开始。
|
|
48
|
+
* @returns 多个 dirty 位的 mask。
|
|
49
|
+
*/
|
|
50
|
+
protected static bits(...indices: number[]): EcsDirtyMask {
|
|
51
|
+
let mask = 0;
|
|
52
|
+
for (let index = 0; index < indices.length; index++) {
|
|
53
|
+
mask |= 1 << indices[index];
|
|
54
|
+
}
|
|
55
|
+
return mask;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** 判断 mask 是否包含某个 dirty bit。
|
|
59
|
+
* @param mask 目标 mask。
|
|
60
|
+
* @param bit 要检查的 dirty bit。
|
|
61
|
+
* @returns 是否包含该 dirty bit。
|
|
62
|
+
*/
|
|
63
|
+
static has(mask: EcsDirtyMask, bit: EcsDirtyMask): boolean {
|
|
64
|
+
return (mask & bit) !== 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** 给 mask 增加一个或多个 dirty bit。
|
|
68
|
+
* @param mask 目标 mask。
|
|
69
|
+
* @param bit 要增加的 dirty bit。
|
|
70
|
+
* @returns 新的 mask。
|
|
71
|
+
*/
|
|
72
|
+
static add(mask: EcsDirtyMask, bit: EcsDirtyMask): EcsDirtyMask {
|
|
73
|
+
return mask | bit;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** 从 mask 中移除一个或多个 dirty bit。
|
|
77
|
+
* @param mask 目标 mask。
|
|
78
|
+
* @param bit 要移除的 dirty bit。
|
|
79
|
+
* @returns 新的 mask。
|
|
80
|
+
*/
|
|
81
|
+
static remove(mask: EcsDirtyMask, bit: EcsDirtyMask): EcsDirtyMask {
|
|
82
|
+
return mask & ~bit;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* cj-ecs 暴露给扩展包的最小 dirty sink。
|
|
88
|
+
* 未安装 observed runtime 时,组件只更新本地 dirtyMask/version,不会有队列成本。
|
|
89
|
+
*/
|
|
90
|
+
export interface IEcsComponentDirtySink {
|
|
91
|
+
/** component.markDirty(mask) 后触发,用于 observed runtime 入队。
|
|
92
|
+
* @param component 组件实例。
|
|
93
|
+
* @param mask 被标记的 dirty mask。
|
|
94
|
+
* @param oldMask 旧的 dirty mask。
|
|
95
|
+
* @param newMask 新的 dirty mask。
|
|
96
|
+
*/
|
|
97
|
+
onComponentDirty(
|
|
98
|
+
component: IComponent,
|
|
99
|
+
mask: EcsDirtyMask,
|
|
100
|
+
oldMask: EcsDirtyMask,
|
|
101
|
+
newMask: EcsDirtyMask,
|
|
102
|
+
): void;
|
|
103
|
+
|
|
104
|
+
/** component.clearDirty(mask) 后触发,用于从 observed 队列中清理已消费的 bit。
|
|
105
|
+
* @param component 组件实例。
|
|
106
|
+
* @param mask 被清理的 dirty mask。
|
|
107
|
+
* @param oldMask 旧的 dirty mask。
|
|
108
|
+
* @param newMask 新的 dirty mask。
|
|
109
|
+
*/
|
|
110
|
+
onComponentClearDirty?(
|
|
111
|
+
component: IComponent,
|
|
112
|
+
mask: EcsDirtyMask,
|
|
113
|
+
oldMask: EcsDirtyMask,
|
|
114
|
+
newMask: EcsDirtyMask,
|
|
115
|
+
): void;
|
|
116
|
+
|
|
117
|
+
/** 组件被移除时触发,用于清理相关 dirty 状态。
|
|
118
|
+
* @param component 组件实例。
|
|
119
|
+
*/
|
|
120
|
+
onComponentRemoved?(component: IComponent): void;
|
|
121
|
+
|
|
122
|
+
/** 组件启用状态变更时触发,用于处理层级启用逻辑。
|
|
123
|
+
* @param component 组件实例。
|
|
124
|
+
* @param enabledInHierarchy 是否在层级中启用。
|
|
125
|
+
*/
|
|
126
|
+
onComponentEnabledChanged?(component: IComponent, enabledInHierarchy: boolean): void;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* observed 这类扩展包需要同时感知结构变化和 dirty 变化。
|
|
131
|
+
* 这些 hook 只在安装 sink 后生效,核心 ECS 不持有任何字段索引。
|
|
132
|
+
*/
|
|
133
|
+
export interface IEcsExtensionSink extends IEcsComponentDirtySink {
|
|
134
|
+
/** 组件被添加到实体时触发,用于初始化相关 dirty 状态。
|
|
135
|
+
* @param entity 实体实例。
|
|
136
|
+
* @param component 组件实例。
|
|
137
|
+
*/
|
|
138
|
+
onComponentAdded?(entity: IEntity, component: IComponent): void;
|
|
139
|
+
|
|
140
|
+
/** 组件从实体移除时触发,用于清理相关 dirty 状态。
|
|
141
|
+
* @param entity 实体实例。
|
|
142
|
+
* @param component 组件实例。
|
|
143
|
+
*/
|
|
144
|
+
onComponentRemoving?(entity: IEntity, component: IComponent): void;
|
|
145
|
+
|
|
146
|
+
/** 实体被移除时触发,用于清理相关 dirty 状态。
|
|
147
|
+
* @param entity 实体实例。
|
|
148
|
+
*/
|
|
149
|
+
onEntityRemoved?(entity: IEntity): void;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** 安装 observed runtime 后挂到 ECS 上的统一查询入口。 */
|
|
153
|
+
export interface IEcsObservedQuery {
|
|
154
|
+
/** 组件级 dirty 查询:面向系统热路径,例如 Position.Spatial。 */
|
|
155
|
+
readonly dirty: IEcsComponentDirtyQuery;
|
|
156
|
+
/** 字段级 dirty 查询:面向网络增量同步、调试、细粒度变化消费。 */
|
|
157
|
+
readonly fieldDirty: IEcsFieldDirtyQuery;
|
|
158
|
+
/** 长期字段索引查询:面向“当前满足条件的集合”,例如 queryActive=true。 */
|
|
159
|
+
readonly index: IEcsIndexedFieldQuery;
|
|
160
|
+
/** 构造“结构条件 + indexed 字段条件”的组合 matcher。 */
|
|
161
|
+
indexedMatcher(): IEcsIndexedMatcherBuilder;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** 组件级 dirty 查询:面向系统热路径,例如 Position.Spatial。 */
|
|
165
|
+
export interface IEcsComponentDirtyQuery {
|
|
166
|
+
/** 查询某组件某 mask 当前待消费的数量,不分配实体数组。
|
|
167
|
+
* @param Comp 组件类型。
|
|
168
|
+
* @param mask 待查询的 dirty mask。
|
|
169
|
+
* @returns 待消费数量。
|
|
170
|
+
*/
|
|
171
|
+
count<T extends ITypeofComponent>(Comp: T, mask: EcsDirtyMask): number;
|
|
172
|
+
|
|
173
|
+
/** 只遍历 dirty 集合,不消费队列,适合调试观察或只读统计。
|
|
174
|
+
* @param Comp 组件类型。
|
|
175
|
+
* @param mask 待查询的 dirty mask。
|
|
176
|
+
* @param handler 遍历处理函数。
|
|
177
|
+
* @param options 遍历选项。
|
|
178
|
+
*/
|
|
179
|
+
forEach<T extends ITypeofComponent>(
|
|
180
|
+
Comp: T,
|
|
181
|
+
mask: EcsDirtyMask,
|
|
182
|
+
handler: (entity: IEntity, comp: InstanceType<T>, info: IEcsDirtyVisitInfo) => void,
|
|
183
|
+
options?: IEcsDirtyVisitOptions,
|
|
184
|
+
): void;
|
|
185
|
+
|
|
186
|
+
/** 遍历并消费 dirty 集合。
|
|
187
|
+
* @param Comp 组件类型。
|
|
188
|
+
* @param mask 待查询的 dirty mask。
|
|
189
|
+
* @param handler 遍历处理函数。
|
|
190
|
+
* @param options 遍历选项。
|
|
191
|
+
* 默认 clear='matched',只清本次请求 mask 命中的位;热路径系统通常用这个接口。
|
|
192
|
+
*/
|
|
193
|
+
drain<T extends ITypeofComponent>(
|
|
194
|
+
Comp: T,
|
|
195
|
+
mask: EcsDirtyMask,
|
|
196
|
+
handler: (entity: IEntity, comp: InstanceType<T>, info: IEcsDirtyVisitInfo) => void,
|
|
197
|
+
options?: IEcsDirtyDrainOptions,
|
|
198
|
+
): number;
|
|
199
|
+
|
|
200
|
+
/** 手动清空某组件某 mask 的队列状态,通常用于系统重置或场景切换。
|
|
201
|
+
* @param Comp 组件类型。
|
|
202
|
+
* @param mask 待清空的 dirty mask。
|
|
203
|
+
*/
|
|
204
|
+
clear<T extends ITypeofComponent>(Comp: T, mask: EcsDirtyMask): void;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** 字段级 dirty 查询:面向网络增量同步、调试、细粒度变化消费。 */
|
|
208
|
+
export interface IEcsFieldDirtyQuery {
|
|
209
|
+
count(ref: any): number;
|
|
210
|
+
|
|
211
|
+
/** 查询某字段当前待消费的变化数量。
|
|
212
|
+
* @param Comp 组件类型。
|
|
213
|
+
* @param field 待查询的字段名或索引。
|
|
214
|
+
* @returns 待消费数量。
|
|
215
|
+
*/
|
|
216
|
+
count<T extends ITypeofComponent>(Comp: T, field: string | number): number;
|
|
217
|
+
|
|
218
|
+
forEach(
|
|
219
|
+
ref: any,
|
|
220
|
+
handler: (entity: IEntity, comp: any, info: IEcsFieldDirtyVisitInfo) => void,
|
|
221
|
+
options?: IEcsDirtyVisitOptions,
|
|
222
|
+
): void;
|
|
223
|
+
|
|
224
|
+
/** 只遍历字段 dirty,不清理队列。
|
|
225
|
+
* @param Comp 组件类型。
|
|
226
|
+
* @param field 待查询的字段名或索引。
|
|
227
|
+
* @param handler 遍历处理函数。
|
|
228
|
+
* @param options 遍历选项。
|
|
229
|
+
*/
|
|
230
|
+
forEach<T extends ITypeofComponent>(
|
|
231
|
+
Comp: T,
|
|
232
|
+
field: string | number,
|
|
233
|
+
handler: (entity: IEntity, comp: InstanceType<T>, info: IEcsFieldDirtyVisitInfo) => void,
|
|
234
|
+
options?: IEcsDirtyVisitOptions,
|
|
235
|
+
): void;
|
|
236
|
+
|
|
237
|
+
drain(
|
|
238
|
+
ref: any,
|
|
239
|
+
handler: (entity: IEntity, comp: any, info: IEcsFieldDirtyVisitInfo) => void,
|
|
240
|
+
options?: IEcsDirtyDrainOptions,
|
|
241
|
+
): number;
|
|
242
|
+
|
|
243
|
+
/** 遍历并消费字段 dirty,适合网络同步写入增量包。
|
|
244
|
+
* @param Comp 组件类型。
|
|
245
|
+
* @param field 待查询的字段名或索引。
|
|
246
|
+
* @param handler 遍历处理函数。
|
|
247
|
+
* @param options 遍历选项。
|
|
248
|
+
* 默认 clear='matched',只清本次请求 mask 命中的位;热路径系统通常用这个接口。
|
|
249
|
+
*/
|
|
250
|
+
drain<T extends ITypeofComponent>(
|
|
251
|
+
Comp: T,
|
|
252
|
+
field: string | number,
|
|
253
|
+
handler: (entity: IEntity, comp: InstanceType<T>, info: IEcsFieldDirtyVisitInfo) => void,
|
|
254
|
+
options?: IEcsDirtyDrainOptions,
|
|
255
|
+
): number;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/** 长期字段索引查询:面向“当前满足条件的集合”,例如 queryActive=true。 */
|
|
259
|
+
export interface IEcsIndexedFieldQuery {
|
|
260
|
+
count(ref: any, condition: IEcsIndexedCondition): number;
|
|
261
|
+
|
|
262
|
+
/** 查询当前满足 indexed 条件的组件数量。
|
|
263
|
+
* @param Comp 组件类型。
|
|
264
|
+
* @param field 待查询的字段名或索引。
|
|
265
|
+
* @param condition 待查询的 indexed 条件。
|
|
266
|
+
* @returns 待查询数量。
|
|
267
|
+
*/
|
|
268
|
+
count<T extends ITypeofComponent>(Comp: T, field: string | number, condition: IEcsIndexedCondition): number;
|
|
269
|
+
|
|
270
|
+
forEach(
|
|
271
|
+
ref: any,
|
|
272
|
+
condition: IEcsIndexedCondition,
|
|
273
|
+
handler: (entity: IEntity, comp: any, info: IEcsIndexedVisitInfo) => void,
|
|
274
|
+
options?: IEcsIndexedVisitOptions,
|
|
275
|
+
): void;
|
|
276
|
+
|
|
277
|
+
/** 遍历当前满足 indexed 条件的集合,不会清理任何 dirty 状态。
|
|
278
|
+
* @param Comp 组件类型。
|
|
279
|
+
* @param field 待查询的字段名或索引。
|
|
280
|
+
* @param condition 待查询的 indexed 条件。
|
|
281
|
+
* @param handler 遍历处理函数。
|
|
282
|
+
* @param options 遍历选项。
|
|
283
|
+
*/
|
|
284
|
+
forEach<T extends ITypeofComponent>(
|
|
285
|
+
Comp: T,
|
|
286
|
+
field: string | number,
|
|
287
|
+
condition: IEcsIndexedCondition,
|
|
288
|
+
handler: (entity: IEntity, comp: InstanceType<T>, info: IEcsIndexedVisitInfo) => void,
|
|
289
|
+
options?: IEcsIndexedVisitOptions,
|
|
290
|
+
): void;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/** 长期字段索引查询的上下文信息。 */
|
|
294
|
+
export interface IEcsIndexedMatcher {
|
|
295
|
+
|
|
296
|
+
/** 当前满足组合条件的实体数量。 */
|
|
297
|
+
count(): number;
|
|
298
|
+
|
|
299
|
+
/** 遍历命中的实体。forEachEntity 的别名,保留使用习惯。
|
|
300
|
+
* @param handler 遍历处理函数。
|
|
301
|
+
* @param options 遍历选项。
|
|
302
|
+
*/
|
|
303
|
+
forEach(handler: (entity: IEntity) => void, options?: IEcsIndexedVisitOptions): void;
|
|
304
|
+
|
|
305
|
+
/** 遍历命中的实体,内部会从最小 indexed 候选集合开始过滤。
|
|
306
|
+
* @param handler 遍历处理函数。
|
|
307
|
+
* @param options 遍历选项。
|
|
308
|
+
*/
|
|
309
|
+
forEachEntity(handler: (entity: IEntity) => void, options?: IEcsIndexedVisitOptions): void;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/** 长期字段索引查询的构建器。 */
|
|
313
|
+
export interface IEcsIndexedMatcherBuilder {
|
|
314
|
+
|
|
315
|
+
/** 实体必须拥有这些启用组件。
|
|
316
|
+
* @param args 启用组件类型列表。
|
|
317
|
+
*/
|
|
318
|
+
all(...args: ITypeofComponent[]): this;
|
|
319
|
+
|
|
320
|
+
/** 实体不能拥有这些启用组件。
|
|
321
|
+
* @param args 启用组件类型列表。
|
|
322
|
+
*/
|
|
323
|
+
exclude(...args: ITypeofComponent[]): this;
|
|
324
|
+
|
|
325
|
+
/** indexed 字段必须等于指定值。
|
|
326
|
+
* @param Comp 组件类型。
|
|
327
|
+
* @param field 索引字段名或索引。
|
|
328
|
+
* @param value 等于值。
|
|
329
|
+
*/
|
|
330
|
+
whereEq(ref: any, value: unknown): this;
|
|
331
|
+
whereEq<T extends ITypeofComponent>(Comp: T, field: string | number, value: unknown): this;
|
|
332
|
+
|
|
333
|
+
/** flagAny 的别名:字段只要包含任一 mask 位即可。
|
|
334
|
+
* @param Comp 组件类型。
|
|
335
|
+
* @param field 索引字段名或索引。
|
|
336
|
+
* @param mask 待查询的 mask 位。
|
|
337
|
+
*/
|
|
338
|
+
whereFlag(ref: any, mask: number): this;
|
|
339
|
+
whereFlag<T extends ITypeofComponent>(Comp: T, field: string | number, mask: number): this;
|
|
340
|
+
|
|
341
|
+
/** flag 字段包含 mask 中任一位即可命中。
|
|
342
|
+
* @param Comp 组件类型。
|
|
343
|
+
* @param field 索引字段名或索引。
|
|
344
|
+
* @param mask 待查询的 mask 位。
|
|
345
|
+
*/
|
|
346
|
+
whereFlagAny(ref: any, mask: number): this;
|
|
347
|
+
whereFlagAny<T extends ITypeofComponent>(Comp: T, field: string | number, mask: number): this;
|
|
348
|
+
|
|
349
|
+
/** flag 字段必须包含 mask 中全部位。
|
|
350
|
+
* @param Comp 组件类型。
|
|
351
|
+
* @param field 索引字段名或索引。
|
|
352
|
+
* @param mask 待查询的 mask 位。
|
|
353
|
+
*/
|
|
354
|
+
whereFlagAll(ref: any, mask: number): this;
|
|
355
|
+
whereFlagAll<T extends ITypeofComponent>(Comp: T, field: string | number, mask: number): this;
|
|
356
|
+
|
|
357
|
+
/** 构建 matcher。构建后可复用,不需要每帧重新 build。 */
|
|
358
|
+
build(): IEcsIndexedMatcher;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/** 组件 dirty 访问时的上下文信息。 */
|
|
362
|
+
export interface IEcsDirtyVisitInfo {
|
|
363
|
+
/** 请求的 dirty mask。 */
|
|
364
|
+
readonly requestedMask: EcsDirtyMask;
|
|
365
|
+
/** 实际匹配到的 dirty mask。 */
|
|
366
|
+
readonly matchedMask: EcsDirtyMask;
|
|
367
|
+
/** 组件当前完整的 dirty mask。 */
|
|
368
|
+
readonly componentDirtyMask: EcsDirtyMask;
|
|
369
|
+
/** 组件的 dirty 版本号。 */
|
|
370
|
+
readonly dirtyVersion: number;
|
|
371
|
+
/** 实体的唯一标识。 */
|
|
372
|
+
readonly entityUuid: number;
|
|
373
|
+
/** 组件的唯一标识。 */
|
|
374
|
+
readonly componentUuid: number;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/** 字段级 dirty 访问时的上下文信息。 */
|
|
378
|
+
export interface IEcsFieldDirtyVisitInfo extends IEcsDirtyVisitInfo {
|
|
379
|
+
/** 发生变化的字段名或索引。 */
|
|
380
|
+
readonly field: string | number;
|
|
381
|
+
/** 字段的版本号。 */
|
|
382
|
+
readonly fieldVersion: number;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/** indexed 字段访问时的上下文信息。 */
|
|
386
|
+
export interface IEcsIndexedVisitInfo {
|
|
387
|
+
/** 索引字段名或索引。 */
|
|
388
|
+
readonly field: string | number;
|
|
389
|
+
/** 实体的唯一标识。 */
|
|
390
|
+
readonly entityUuid: number;
|
|
391
|
+
/** 组件的唯一标识。 */
|
|
392
|
+
readonly componentUuid: number;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/** dirty 访问选项。 */
|
|
396
|
+
export interface IEcsDirtyVisitOptions {
|
|
397
|
+
/** 是否保证遍历顺序稳定(可能牺牲性能)。 */
|
|
398
|
+
stable?: boolean;
|
|
399
|
+
/** 单次遍历的最大数量限制。 */
|
|
400
|
+
budget?: number;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/** dirty 消费选项。 */
|
|
404
|
+
export interface IEcsDirtyDrainOptions extends IEcsDirtyVisitOptions {
|
|
405
|
+
/** 清理策略:matched-只清理匹配的位,all-清理全部,none-不清理。 */
|
|
406
|
+
clear?: EcsDirtyClearMode;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/** indexed 字段访问选项。 */
|
|
410
|
+
export interface IEcsIndexedVisitOptions {
|
|
411
|
+
/** 是否保证遍历顺序稳定(可能牺牲性能)。 */
|
|
412
|
+
stable?: boolean;
|
|
413
|
+
/** 单次遍历的最大数量限制。 */
|
|
414
|
+
budget?: number;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/** indexed 字段模式常量,避免业务在 @EcsIndexedField({ mode }) 中手写字符串。 */
|
|
418
|
+
export const EcsIndexedFieldMode = {
|
|
419
|
+
/** 等值索引,适合 boolean、枚举、阵营、类型等离散值。 */
|
|
420
|
+
Eq: 'eq',
|
|
421
|
+
/** 位掩码索引,适合 Stunned/Burning/Silence 这类 flags。 */
|
|
422
|
+
Flag: 'flag',
|
|
423
|
+
} as const;
|
|
424
|
+
|
|
425
|
+
export type EcsIndexedFieldModeValue = typeof EcsIndexedFieldMode[keyof typeof EcsIndexedFieldMode];
|
|
426
|
+
|
|
427
|
+
/** indexed 查询条件类型常量,避免业务在 count/forEach 条件里手写字符串。 */
|
|
428
|
+
export const EcsIndexedConditionType = {
|
|
429
|
+
/** 字段值等于指定值。 */
|
|
430
|
+
Eq: 'eq',
|
|
431
|
+
/** flag 字段必须包含 mask 中全部位。 */
|
|
432
|
+
FlagAll: 'flagAll',
|
|
433
|
+
/** flag 字段包含 mask 中任意位即可命中。 */
|
|
434
|
+
FlagAny: 'flagAny',
|
|
435
|
+
} as const;
|
|
436
|
+
|
|
437
|
+
export type EcsIndexedConditionTypeValue = typeof EcsIndexedConditionType[keyof typeof EcsIndexedConditionType];
|
|
438
|
+
|
|
439
|
+
/** indexed 字段的查询条件类型。 */
|
|
440
|
+
export type IEcsIndexedCondition =
|
|
441
|
+
| { type: typeof EcsIndexedConditionType.Eq; value: unknown } // 字段值等于指定值
|
|
442
|
+
| { type: typeof EcsIndexedConditionType.FlagAll; mask: number } // flag 字段必须包含全部 mask 位
|
|
443
|
+
| { type: typeof EcsIndexedConditionType.FlagAny; mask: number }; // flag 字段包含任一 mask 位即可
|
|
444
|
+
|
|
445
|
+
/** indexed 查询条件构造器,业务侧优先使用它而不是手写 { type: ... }。 */
|
|
446
|
+
export const EcsIndexedCondition = {
|
|
447
|
+
/** 创建等值查询条件。 */
|
|
448
|
+
eq(value: unknown): IEcsIndexedCondition {
|
|
449
|
+
return { type: EcsIndexedConditionType.Eq, value };
|
|
450
|
+
},
|
|
451
|
+
/** 创建 flagAll 查询条件。 */
|
|
452
|
+
flagAll(mask: number): IEcsIndexedCondition {
|
|
453
|
+
return { type: EcsIndexedConditionType.FlagAll, mask };
|
|
454
|
+
},
|
|
455
|
+
/** 创建 flagAny 查询条件。 */
|
|
456
|
+
flagAny(mask: number): IEcsIndexedCondition {
|
|
457
|
+
return { type: EcsIndexedConditionType.FlagAny, mask };
|
|
458
|
+
},
|
|
459
|
+
} as const;
|