@codehz/ecs 0.6.7 → 0.6.9

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/builder.d.mts CHANGED
@@ -163,13 +163,21 @@ declare class ComponentChangeset {
163
163
  //#region src/commands/command-buffer.d.ts
164
164
  /**
165
165
  * Command for deferred execution
166
+ * Uses discriminated union for type safety
166
167
  */
167
- interface Command {
168
- type: "set" | "delete" | "destroy";
168
+ type Command = {
169
+ type: "set";
169
170
  entityId: EntityId;
170
- componentType?: EntityId<any>;
171
- component?: any;
172
- }
171
+ componentType: EntityId<any>;
172
+ component: any;
173
+ } | {
174
+ type: "delete";
175
+ entityId: EntityId;
176
+ componentType: EntityId<any>;
177
+ } | {
178
+ type: "destroy";
179
+ entityId: EntityId;
180
+ };
173
181
  //#endregion
174
182
  //#region src/core/types.d.ts
175
183
  /**
@@ -181,7 +189,7 @@ interface LegacyLifecycleHook<T = unknown> {
181
189
  */
182
190
  on_init?: (entityId: EntityId, componentType: EntityId<T>, component: T) => void;
183
191
  /**
184
- * Called when a component is added to an entity
192
+ * Called when a component is updated on an entity
185
193
  */
186
194
  on_set?: (entityId: EntityId, componentType: EntityId<T>, component: T) => void;
187
195
  /**
@@ -235,6 +243,10 @@ declare class Archetype {
235
243
  * The component types that define this archetype
236
244
  */
237
245
  readonly componentTypes: EntityId<any>[];
246
+ /**
247
+ * Set version of componentTypes for O(1) lookups in hot paths
248
+ */
249
+ readonly componentTypeSet: ReadonlySet<EntityId<any>>;
238
250
  /**
239
251
  * List of entities in this archetype
240
252
  */
@@ -254,9 +266,6 @@ declare class Archetype {
254
266
  * Stored in World to avoid migration overhead when entities change archetypes
255
267
  */
256
268
  private dontFragmentRelations;
257
- /**
258
- * Cache for pre-computed component data sources to avoid repeated calculations
259
- */
260
269
  /**
261
270
  * Multi-hooks that match this archetype
262
271
  */
@@ -267,6 +276,12 @@ declare class Archetype {
267
276
  private componentDataSourcesCache;
268
277
  constructor(componentTypes: EntityId<any>[], dontFragmentRelations: Map<EntityId, Map<EntityId<any>, any>>);
269
278
  get size(): number;
279
+ /**
280
+ * Check if the given component types match this archetype
281
+ * @param componentTypes - Component types to check (can be in any order)
282
+ * @returns true if the types match this archetype's component set
283
+ * @note This method handles unsorted input by internally sorting for comparison
284
+ */
270
285
  matches(componentTypes: EntityId<any>[]): boolean;
271
286
  addEntity(entityId: EntityId, componentData: Map<EntityId<any>, any>): void;
272
287
  private addDontFragmentRelations;
@@ -320,6 +335,8 @@ declare class Query {
320
335
  private filter;
321
336
  private cachedArchetypes;
322
337
  private isDisposed;
338
+ /** Cache key assigned by World for O(1) releaseQuery lookup */
339
+ _cacheKey: string | undefined;
323
340
  /** Cached wildcard component types for faster entity filtering */
324
341
  private wildcardTypes;
325
342
  /** Cached specific dontFragment relation types that need entity-level filtering */
@@ -401,9 +418,16 @@ type SerializedEntityId = number | string | {
401
418
  component: string;
402
419
  target: number | string | "*";
403
420
  };
421
+ /**
422
+ * Serialized state of EntityIdManager
423
+ */
424
+ interface SerializedEntityIdManager {
425
+ nextId: number;
426
+ freelist?: number[];
427
+ }
404
428
  type SerializedWorld = {
405
429
  version: number;
406
- entityManager: any;
430
+ entityManager: SerializedEntityIdManager;
407
431
  entities: SerializedEntity[];
408
432
  componentEntities?: SerializedEntity[];
409
433
  };
@@ -482,21 +506,32 @@ declare class World {
482
506
  * @overload set<T>(entityId: EntityId, componentType: EntityId<T>, component: NoInfer<T>): void
483
507
  * Adds or updates a component with data on the entity
484
508
  *
509
+ * @overload set<T>(componentId: ComponentId<T>, component: NoInfer<T>): void
510
+ * Adds or updates a singleton component (shorthand for set(componentId, componentId, component))
511
+ *
485
512
  * @throws {Error} If the entity does not exist
486
513
  * @throws {Error} If the component type is invalid or is a wildcard relation
487
514
  *
488
515
  * @example
489
516
  * world.set(entity, Position, { x: 10, y: 20 });
490
517
  * world.set(entity, Marker); // void component
518
+ * world.set(GlobalConfig, { debug: true }); // singleton component
491
519
  * world.sync(); // Apply changes
492
520
  */
493
521
  set(entityId: EntityId, componentType: EntityId<void>): void;
494
522
  set<T>(entityId: EntityId, componentType: EntityId<T>, component: NoInfer<T>): void;
523
+ set<T>(componentId: ComponentId<T>, component: NoInfer<T>): void;
495
524
  /**
496
525
  * Removes a component from an entity.
497
526
  * The change is buffered and takes effect after calling `world.sync()`.
498
527
  * If the entity does not exist, throws an error.
499
528
  *
529
+ * @overload remove<T>(entityId: EntityId, componentType: EntityId<T>): void
530
+ * Removes a component from an entity.
531
+ *
532
+ * @overload remove<T>(componentId: ComponentId<T>): void
533
+ * Removes a singleton component (shorthand for remove(componentId, componentId)).
534
+ *
500
535
  * @template T - The component data type
501
536
  * @param entityId - The entity identifier
502
537
  * @param componentType - The component type to remove
@@ -506,8 +541,10 @@ declare class World {
506
541
  *
507
542
  * @example
508
543
  * world.remove(entity, Position);
544
+ * world.remove(GlobalConfig); // Remove singleton component
509
545
  * world.sync(); // Apply changes
510
546
  */
547
+ remove<T>(componentId: ComponentId<T>): void;
511
548
  remove<T>(entityId: EntityId, componentType: EntityId<T>): void;
512
549
  /**
513
550
  * Deletes an entity and all its components from the world.
@@ -525,6 +562,12 @@ declare class World {
525
562
  * Checks if an entity has a specific component.
526
563
  * Immediately reflects the current state without waiting for `sync()`.
527
564
  *
565
+ * @overload has<T>(entityId: EntityId, componentType: EntityId<T>): boolean
566
+ * Checks if a specific component type is present on the entity.
567
+ *
568
+ * @overload has<T>(componentId: ComponentId<T>): boolean
569
+ * Checks if a singleton component has data (shorthand for has(componentId, componentId)).
570
+ *
528
571
  * @template T - The component data type
529
572
  * @param entityId - The entity identifier
530
573
  * @param componentType - The component type to check
@@ -534,7 +577,11 @@ declare class World {
534
577
  * if (world.has(entity, Position)) {
535
578
  * const pos = world.get(entity, Position);
536
579
  * }
580
+ * if (world.has(GlobalConfig)) {
581
+ * const config = world.get(GlobalConfig);
582
+ * }
537
583
  */
584
+ has<T>(componentId: ComponentId<T>): boolean;
538
585
  has<T>(entityId: EntityId, componentType: EntityId<T>): boolean;
539
586
  /**
540
587
  * Retrieves a component from an entity.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codehz/ecs",
3
- "version": "0.6.7",
3
+ "version": "0.6.9",
4
4
  "repository": {
5
5
  "url": "https://github.com/codehz/ecs"
6
6
  },