@codehz/ecs 0.10.1 → 0.10.2
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/dist/builder.d.mts +116 -82
- package/dist/world.mjs +1 -0
- package/dist/world.mjs.map +1 -1
- package/package.json +1 -1
- package/src/world/world.ts +117 -82
package/package.json
CHANGED
package/src/world/world.ts
CHANGED
|
@@ -273,34 +273,41 @@ export class World {
|
|
|
273
273
|
}
|
|
274
274
|
|
|
275
275
|
/**
|
|
276
|
-
*
|
|
276
|
+
* Marks a void component as present on an entity.
|
|
277
277
|
* The change is buffered and takes effect after calling `world.sync()`.
|
|
278
|
-
* If the entity does not exist, throws an error.
|
|
279
278
|
*
|
|
280
|
-
* @
|
|
281
|
-
*
|
|
279
|
+
* @throws {Error} If the entity does not exist
|
|
280
|
+
* @throws {Error} If the component type is invalid or is a wildcard relation
|
|
282
281
|
*
|
|
283
|
-
* @
|
|
282
|
+
* @example
|
|
283
|
+
* world.set(entity, Marker);
|
|
284
|
+
* world.sync();
|
|
285
|
+
*/
|
|
286
|
+
set(entityId: EntityId, componentType: EntityId<void>): void;
|
|
287
|
+
/**
|
|
284
288
|
* @deprecated Use `world.singleton(componentId).set(value)` or `world.set(componentId, componentId, value)` instead.
|
|
285
|
-
* Compatibility shorthand for singleton component data when the second argument is not a number
|
|
289
|
+
* Compatibility shorthand for singleton component data when the second argument is not a number.
|
|
286
290
|
*
|
|
287
|
-
* @
|
|
288
|
-
*
|
|
291
|
+
* @throws {Error} If the component entity does not exist
|
|
292
|
+
*
|
|
293
|
+
* @example
|
|
294
|
+
* world.set(GlobalConfig, { debug: true });
|
|
295
|
+
* world.sync();
|
|
296
|
+
*/
|
|
297
|
+
set<T>(componentId: ComponentId<T>, component: Exclude<NoInfer<T>, number>): void;
|
|
298
|
+
/**
|
|
299
|
+
* Adds or updates component data on an entity.
|
|
300
|
+
* The change is buffered and takes effect after calling `world.sync()`.
|
|
289
301
|
*
|
|
290
302
|
* @throws {Error} If the entity does not exist
|
|
291
303
|
* @throws {Error} If the component type is invalid or is a wildcard relation
|
|
292
304
|
*
|
|
293
305
|
* @example
|
|
294
306
|
* world.set(entity, Position, { x: 10, y: 20 });
|
|
295
|
-
* world.
|
|
296
|
-
* world.singleton(GlobalConfig).set({ debug: true }); // singleton component
|
|
297
|
-
* world.set(GlobalConfig, { debug: true }); // deprecated singleton compatibility shorthand
|
|
298
|
-
* world.sync(); // Apply changes
|
|
307
|
+
* world.sync();
|
|
299
308
|
*/
|
|
300
|
-
set(entityId: EntityId, componentType: EntityId<void>): void;
|
|
301
|
-
/** @deprecated Use `world.singleton(componentId).set(value)` or `world.set(componentId, componentId, value)` instead. */
|
|
302
|
-
set<T>(componentId: ComponentId<T>, component: Exclude<NoInfer<T>, number>): void;
|
|
303
309
|
set<T>(entityId: EntityId, componentType: EntityId<T>, component: NoInfer<T>): void;
|
|
310
|
+
/** Internal implementation for `set()` overloads. */
|
|
304
311
|
set(entityId: EntityId | ComponentId, componentTypeOrComponent?: EntityId | any, maybeComponent?: any): void {
|
|
305
312
|
const {
|
|
306
313
|
entityId: targetEntityId,
|
|
@@ -319,13 +326,6 @@ export class World {
|
|
|
319
326
|
/**
|
|
320
327
|
* Removes a component from an entity.
|
|
321
328
|
* The change is buffered and takes effect after calling `world.sync()`.
|
|
322
|
-
* If the entity does not exist, throws an error.
|
|
323
|
-
*
|
|
324
|
-
* @overload remove<T>(entityId: EntityId, componentType: EntityId<T>): void
|
|
325
|
-
* Removes a component from an entity.
|
|
326
|
-
*
|
|
327
|
-
* @overload remove<T>(componentId: ComponentId<T>): void
|
|
328
|
-
* Removes a singleton component (shorthand for remove(componentId, componentId)).
|
|
329
329
|
*
|
|
330
330
|
* @template T - The component data type
|
|
331
331
|
* @param entityId - The entity identifier
|
|
@@ -336,11 +336,22 @@ export class World {
|
|
|
336
336
|
*
|
|
337
337
|
* @example
|
|
338
338
|
* world.remove(entity, Position);
|
|
339
|
+
* world.sync(); // Apply changes
|
|
340
|
+
*/
|
|
341
|
+
remove<T>(entityId: EntityId, componentType: EntityId<T>): void;
|
|
342
|
+
/**
|
|
343
|
+
* Removes a singleton component (shorthand for remove(componentId, componentId)).
|
|
344
|
+
* The change is buffered and takes effect after calling `world.sync()`.
|
|
345
|
+
*
|
|
346
|
+
* @template T - The component data type
|
|
347
|
+
*
|
|
348
|
+
* @throws {Error} If the component entity does not exist
|
|
349
|
+
*
|
|
350
|
+
* @example
|
|
339
351
|
* world.remove(GlobalConfig); // Remove singleton component
|
|
340
352
|
* world.sync(); // Apply changes
|
|
341
353
|
*/
|
|
342
354
|
remove<T>(componentId: ComponentId<T>): void;
|
|
343
|
-
remove<T>(entityId: EntityId, componentType: EntityId<T>): void;
|
|
344
355
|
remove<T>(entityId: EntityId | ComponentId, componentType?: EntityId<T>): void {
|
|
345
356
|
const { entityId: targetEntityId, componentType: targetComponentType } = resolveRemoveOperation(
|
|
346
357
|
entityId,
|
|
@@ -400,15 +411,8 @@ export class World {
|
|
|
400
411
|
*
|
|
401
412
|
* Immediately reflects the current state without waiting for `sync()`.
|
|
402
413
|
*
|
|
403
|
-
* @overload has<T>(entityId: EntityId, componentType: EntityId<T>): boolean
|
|
404
|
-
* Checks if a specific component type is present on the entity.
|
|
405
|
-
*
|
|
406
|
-
* @overload has<T>(componentId: ComponentId<T>): boolean
|
|
407
|
-
* Shorthand for checking a **singleton component** — a component that is its own
|
|
408
|
-
* entity (component-as-entity pattern). Equivalent to `has(componentId, componentId)`.
|
|
409
|
-
*
|
|
410
414
|
* @template T - The component data type
|
|
411
|
-
* @param entityId - The entity identifier
|
|
415
|
+
* @param entityId - The entity identifier
|
|
412
416
|
* @param componentType - The component type to check
|
|
413
417
|
* @returns `true` if the entity has the component, `false` otherwise
|
|
414
418
|
*
|
|
@@ -417,17 +421,24 @@ export class World {
|
|
|
417
421
|
* if (world.has(entity, Position)) {
|
|
418
422
|
* const pos = world.get(entity, Position);
|
|
419
423
|
* }
|
|
424
|
+
*/
|
|
425
|
+
has<T>(entityId: EntityId, componentType: EntityId<T>): boolean;
|
|
426
|
+
/**
|
|
427
|
+
* Checks if a **singleton component** (component-as-entity) is present.
|
|
428
|
+
* Equivalent to `has(componentId, componentId)`.
|
|
429
|
+
*
|
|
430
|
+
* Immediately reflects the current state without waiting for `sync()`.
|
|
420
431
|
*
|
|
421
|
-
*
|
|
432
|
+
* @template T - The component data type
|
|
433
|
+
* @param componentId - The singleton component ID
|
|
434
|
+
* @returns `true` if the singleton component exists, `false` otherwise
|
|
435
|
+
*
|
|
436
|
+
* @example
|
|
422
437
|
* if (world.has(GlobalConfig)) {
|
|
423
438
|
* const config = world.get(GlobalConfig);
|
|
424
439
|
* }
|
|
425
|
-
*
|
|
426
|
-
* // Use exists() for entity liveness checks
|
|
427
|
-
* if (world.exists(entity)) { ... }
|
|
428
440
|
*/
|
|
429
441
|
has<T>(componentId: ComponentId<T>): boolean;
|
|
430
|
-
has<T>(entityId: EntityId, componentType: EntityId<T>): boolean;
|
|
431
442
|
has<T>(entityId: EntityId | ComponentId, componentType?: EntityId<T>): boolean {
|
|
432
443
|
// Handle singleton component overload: has(componentId)
|
|
433
444
|
if (componentType === undefined) {
|
|
@@ -461,28 +472,45 @@ export class World {
|
|
|
461
472
|
|
|
462
473
|
/**
|
|
463
474
|
* Retrieves a component from an entity.
|
|
464
|
-
* For wildcard relations, returns all relations of that type.
|
|
465
475
|
* Throws an error if the component does not exist; use `has()` to check first or use `getOptional()`.
|
|
466
476
|
*
|
|
467
|
-
* @
|
|
468
|
-
*
|
|
477
|
+
* @template T - The component data type
|
|
478
|
+
* @param entityId - The entity identifier
|
|
479
|
+
* @param componentType - The component type to retrieve
|
|
469
480
|
*
|
|
470
|
-
* @
|
|
471
|
-
*
|
|
481
|
+
* @throws {Error} If the entity does not exist
|
|
482
|
+
* @throws {Error} If the component does not exist on the entity
|
|
472
483
|
*
|
|
473
|
-
* @
|
|
474
|
-
*
|
|
484
|
+
* @example
|
|
485
|
+
* const position = world.get(entity, Position);
|
|
486
|
+
*/
|
|
487
|
+
get<T>(entityId: EntityId, componentType: EntityId<T>): T;
|
|
488
|
+
/**
|
|
489
|
+
* Retrieves all relations of a given wildcard type for an entity.
|
|
490
|
+
* Returns an array of [target entity, component value] pairs.
|
|
491
|
+
*
|
|
492
|
+
* @template T - The component data type
|
|
493
|
+
* @param entityId - The entity identifier
|
|
494
|
+
* @param componentType - The wildcard relation type
|
|
495
|
+
* @returns Array of [target entity, component value] pairs
|
|
475
496
|
*
|
|
476
497
|
* @throws {Error} If the entity does not exist
|
|
477
|
-
* @throws {Error} If the component does not exist on the entity
|
|
478
498
|
*
|
|
479
499
|
* @example
|
|
480
|
-
* const
|
|
481
|
-
* const relations = world.get(entity, relation(Parent, "*")); // Wildcard relation
|
|
500
|
+
* const relations = world.get(entity, relation(Parent, "*"));
|
|
482
501
|
*/
|
|
483
|
-
get<T>(entityId: EntityId<T>): T;
|
|
484
502
|
get<T>(entityId: EntityId, componentType: WildcardRelationId<T>): [EntityId<unknown>, T][];
|
|
485
|
-
|
|
503
|
+
/**
|
|
504
|
+
* Retrieves the entity's primary component when called with only an entity ID.
|
|
505
|
+
*
|
|
506
|
+
* @template T - The component data type
|
|
507
|
+
* @param entityId - The entity identifier
|
|
508
|
+
* @returns The component value
|
|
509
|
+
*
|
|
510
|
+
* @throws {Error} If the entity does not exist
|
|
511
|
+
* @throws {Error} If the component does not exist on the entity
|
|
512
|
+
*/
|
|
513
|
+
get<T>(entityId: EntityId<T>): T;
|
|
486
514
|
get<T>(
|
|
487
515
|
entityId: EntityId,
|
|
488
516
|
componentType: EntityId<T> | WildcardRelationId<T> = entityId as EntityId<T>,
|
|
@@ -521,17 +549,11 @@ export class World {
|
|
|
521
549
|
/**
|
|
522
550
|
* Safely retrieves a component from an entity without throwing an error.
|
|
523
551
|
* Returns `undefined` if the component does not exist.
|
|
524
|
-
* For wildcard relations, returns `undefined` if there are no relations.
|
|
525
552
|
*
|
|
526
553
|
* @template T - The component data type
|
|
527
|
-
* @
|
|
528
|
-
*
|
|
529
|
-
*
|
|
530
|
-
* @overload getOptional<T>(entityId: EntityId, componentType: WildcardRelationId<T>): { value: [EntityId<unknown>, T][] } | undefined
|
|
531
|
-
* Retrieves all matching relation values safely.
|
|
532
|
-
*
|
|
533
|
-
* @overload getOptional<T>(entityId: EntityId, componentType: EntityId<T>): { value: T } | undefined
|
|
534
|
-
* Retrieves a specific component safely.
|
|
554
|
+
* @param entityId - The entity identifier
|
|
555
|
+
* @param componentType - The component type to retrieve
|
|
556
|
+
* @returns The component value wrapped in `{ value }`, or `undefined` if absent
|
|
535
557
|
*
|
|
536
558
|
* @throws {Error} If the entity does not exist
|
|
537
559
|
*
|
|
@@ -541,12 +563,33 @@ export class World {
|
|
|
541
563
|
* console.log(position.value.x);
|
|
542
564
|
* }
|
|
543
565
|
*/
|
|
544
|
-
getOptional<T>(entityId: EntityId<T>): { value: T } | undefined;
|
|
566
|
+
getOptional<T>(entityId: EntityId, componentType: EntityId<T>): { value: T } | undefined;
|
|
567
|
+
/**
|
|
568
|
+
* Safely retrieves all matching relation values for a wildcard relation type.
|
|
569
|
+
* Returns `undefined` if there are no relations.
|
|
570
|
+
*
|
|
571
|
+
* @template T - The component data type
|
|
572
|
+
* @param entityId - The entity identifier
|
|
573
|
+
* @param componentType - The wildcard relation type
|
|
574
|
+
* @returns Array of [target, value] pairs wrapped in `{ value }`, or `undefined` if none
|
|
575
|
+
*
|
|
576
|
+
* @throws {Error} If the entity does not exist
|
|
577
|
+
*/
|
|
545
578
|
getOptional<T>(
|
|
546
579
|
entityId: EntityId,
|
|
547
580
|
componentType: WildcardRelationId<T>,
|
|
548
581
|
): { value: [EntityId<unknown>, T][] } | undefined;
|
|
549
|
-
|
|
582
|
+
/**
|
|
583
|
+
* Safely retrieves the entity's primary component without throwing an error.
|
|
584
|
+
* Returns `undefined` if the component does not exist.
|
|
585
|
+
*
|
|
586
|
+
* @template T - The component data type
|
|
587
|
+
* @param entityId - The entity identifier
|
|
588
|
+
* @returns The component value wrapped in `{ value }`, or `undefined` if absent
|
|
589
|
+
*
|
|
590
|
+
* @throws {Error} If the entity does not exist
|
|
591
|
+
*/
|
|
592
|
+
getOptional<T>(entityId: EntityId<T>): { value: T } | undefined;
|
|
550
593
|
getOptional<T>(
|
|
551
594
|
entityId: EntityId,
|
|
552
595
|
componentType: EntityId<T> | WildcardRelationId<T> = entityId as EntityId<T>,
|
|
@@ -786,21 +829,15 @@ export class World {
|
|
|
786
829
|
|
|
787
830
|
/**
|
|
788
831
|
* Registers a lifecycle hook that responds to component changes.
|
|
789
|
-
* The hook callback is invoked when components matching the specified types
|
|
790
|
-
*
|
|
791
|
-
* componentTypes: T,
|
|
792
|
-
* hook: LifecycleHook<T> | LifecycleCallback<T>,
|
|
793
|
-
* filter?: QueryFilter,
|
|
794
|
-
* ): () => void
|
|
795
|
-
* Registers a hook for multiple component types.
|
|
796
|
-
* The hook is triggered when entities enter/exit the matching set.
|
|
832
|
+
* The hook callback is invoked when components matching the specified types
|
|
833
|
+
* are added, updated, or removed.
|
|
797
834
|
*
|
|
798
835
|
* @param componentTypes - Component types that define the matching entity set
|
|
799
836
|
* @param hook - Either a hook object with on_init/on_set/on_remove handlers, or a callback function
|
|
800
837
|
* @param filter - Optional query-style filter applied to the hook match set
|
|
801
838
|
* @returns A function that unsubscribes the hook when called
|
|
802
839
|
*
|
|
803
|
-
* @throws {Error} If no required components are specified
|
|
840
|
+
* @throws {Error} If no required components are specified
|
|
804
841
|
*
|
|
805
842
|
* @example
|
|
806
843
|
* const unsubscribe = world.hook([Position, Velocity], {
|
|
@@ -1085,32 +1122,30 @@ export class World {
|
|
|
1085
1122
|
|
|
1086
1123
|
/**
|
|
1087
1124
|
* Queries entities with specific components.
|
|
1088
|
-
* For simpler use cases, prefer using `createQuery()` with `forEach()` which is cached and more efficient.
|
|
1089
|
-
*
|
|
1090
|
-
* @overload query(componentTypes: EntityId<any>[]): EntityId[]
|
|
1091
1125
|
* Returns an array of entity IDs that have all specified components.
|
|
1092
|
-
*
|
|
1093
|
-
* @overload query<const T extends readonly EntityId<any>[]>(
|
|
1094
|
-
* componentTypes: T,
|
|
1095
|
-
* includeComponents: true,
|
|
1096
|
-
* ): Array<{ entity: EntityId; components: ComponentTuple<T> }>
|
|
1097
|
-
* Returns entities along with their component data.
|
|
1126
|
+
* For simpler use cases, prefer using `createQuery()` with `forEach()` which is cached and more efficient.
|
|
1098
1127
|
*
|
|
1099
1128
|
* @param componentTypes - Array of component types to query
|
|
1100
|
-
* @
|
|
1101
|
-
* @returns Array of entity IDs or objects with entities and components
|
|
1129
|
+
* @returns Array of entity IDs matching the query
|
|
1102
1130
|
*
|
|
1103
1131
|
* @example
|
|
1104
|
-
* // Just entity IDs
|
|
1105
1132
|
* const entities = world.query([Position, Velocity]);
|
|
1133
|
+
*/
|
|
1134
|
+
query(componentTypes: EntityId<any>[]): EntityId[];
|
|
1135
|
+
/**
|
|
1136
|
+
* Queries entities with specific components and returns their component data.
|
|
1137
|
+
*
|
|
1138
|
+
* @template T - The tuple of component types
|
|
1139
|
+
* @param componentTypes - Array of component types to query
|
|
1140
|
+
* @param includeComponents - Must be `true` to include component data
|
|
1141
|
+
* @returns Array of objects with entity and component data
|
|
1106
1142
|
*
|
|
1107
|
-
*
|
|
1143
|
+
* @example
|
|
1108
1144
|
* const results = world.query([Position, Velocity], true);
|
|
1109
1145
|
* results.forEach(({ entity, components: [pos, vel] }) => {
|
|
1110
1146
|
* pos.x += vel.x;
|
|
1111
1147
|
* });
|
|
1112
1148
|
*/
|
|
1113
|
-
query(componentTypes: EntityId<any>[]): EntityId[];
|
|
1114
1149
|
query<const T extends readonly EntityId<any>[]>(
|
|
1115
1150
|
componentTypes: T,
|
|
1116
1151
|
includeComponents: true,
|