ecspresso 0.10.1 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -20
- package/dist/asset-manager.d.ts +15 -15
- package/dist/asset-types.d.ts +16 -14
- package/dist/bundle.d.ts +66 -16
- package/dist/bundles/audio.d.ts +293 -0
- package/dist/bundles/{utils/bounds.d.ts → bounds.d.ts} +9 -7
- package/dist/bundles/camera.d.ts +89 -0
- package/dist/bundles/collision.d.ts +289 -0
- package/dist/bundles/diagnostics.d.ts +48 -0
- package/dist/bundles/{utils/input.d.ts → input.d.ts} +16 -32
- package/dist/bundles/physics2D.d.ts +159 -0
- package/dist/bundles/renderers/renderer2D.d.ts +65 -24
- package/dist/bundles/spatial-index.d.ts +57 -0
- package/dist/bundles/state-machine.d.ts +298 -0
- package/dist/bundles/{utils/timers.d.ts → timers.d.ts} +9 -8
- package/dist/bundles/{utils/transform.d.ts → transform.d.ts} +10 -10
- package/dist/bundles/tween.d.ts +197 -0
- package/dist/command-buffer.d.ts +20 -20
- package/dist/ecspresso-builder.d.ts +165 -0
- package/dist/ecspresso.d.ts +157 -178
- package/dist/entity-manager.d.ts +76 -40
- package/dist/event-bus.d.ts +6 -1
- package/dist/index.d.ts +1 -9
- package/dist/reactive-query-manager.d.ts +14 -3
- package/dist/resource-manager.d.ts +35 -19
- package/dist/screen-manager.d.ts +4 -4
- package/dist/screen-types.d.ts +12 -11
- package/dist/src/bundles/audio.js +4 -0
- package/dist/src/bundles/audio.js.map +10 -0
- package/dist/src/bundles/bounds.js +4 -0
- package/dist/src/bundles/bounds.js.map +10 -0
- package/dist/src/bundles/camera.js +4 -0
- package/dist/src/bundles/camera.js.map +10 -0
- package/dist/src/bundles/collision.js +4 -0
- package/dist/src/bundles/collision.js.map +11 -0
- package/dist/src/bundles/diagnostics.js +5 -0
- package/dist/src/bundles/diagnostics.js.map +10 -0
- package/dist/src/bundles/input.js +4 -0
- package/dist/src/bundles/input.js.map +10 -0
- package/dist/src/bundles/physics2D.js +4 -0
- package/dist/src/bundles/physics2D.js.map +11 -0
- package/dist/src/bundles/renderers/renderer2D.js +4 -0
- package/dist/src/bundles/renderers/renderer2D.js.map +10 -0
- package/dist/src/bundles/spatial-index.js +4 -0
- package/dist/src/bundles/spatial-index.js.map +11 -0
- package/dist/src/bundles/state-machine.js +4 -0
- package/dist/src/bundles/state-machine.js.map +10 -0
- package/dist/src/bundles/timers.js +4 -0
- package/dist/src/bundles/timers.js.map +10 -0
- package/dist/src/bundles/transform.js +4 -0
- package/dist/src/bundles/transform.js.map +10 -0
- package/dist/src/bundles/tween.js +4 -0
- package/dist/src/bundles/tween.js.map +11 -0
- package/dist/src/index.js +4 -0
- package/dist/src/index.js.map +25 -0
- package/dist/system-builder.d.ts +36 -42
- package/dist/type-utils.d.ts +52 -3
- package/dist/types.d.ts +10 -19
- package/dist/utils/check-required-cycle.d.ts +12 -0
- package/dist/utils/easing.d.ts +71 -0
- package/dist/utils/math.d.ts +67 -0
- package/dist/utils/narrowphase.d.ts +63 -0
- package/dist/utils/spatial-hash.d.ts +53 -0
- package/package.json +50 -20
- package/dist/bundles/renderers/renderer2D.js +0 -4
- package/dist/bundles/renderers/renderer2D.js.map +0 -10
- package/dist/bundles/utils/bounds.js +0 -4
- package/dist/bundles/utils/bounds.js.map +0 -10
- package/dist/bundles/utils/collision.d.ts +0 -204
- package/dist/bundles/utils/collision.js +0 -4
- package/dist/bundles/utils/collision.js.map +0 -10
- package/dist/bundles/utils/input.js +0 -4
- package/dist/bundles/utils/input.js.map +0 -10
- package/dist/bundles/utils/movement.d.ts +0 -86
- package/dist/bundles/utils/movement.js +0 -4
- package/dist/bundles/utils/movement.js.map +0 -10
- package/dist/bundles/utils/timers.js +0 -4
- package/dist/bundles/utils/timers.js.map +0 -10
- package/dist/bundles/utils/transform.js +0 -4
- package/dist/bundles/utils/transform.js.map +0 -10
- package/dist/index.js +0 -4
- package/dist/index.js.map +0 -22
package/README.md
CHANGED
|
@@ -20,6 +20,7 @@ A type-safe, modular, and extensible Entity Component System (ECS) framework for
|
|
|
20
20
|
- **Reactive Queries**: Enter/exit callbacks when entities match or unmatch queries
|
|
21
21
|
- **System Groups**: Enable/disable groups of systems at runtime
|
|
22
22
|
- **Component Lifecycle**: Callbacks for component add/remove with unsubscribe support
|
|
23
|
+
- **Required Components**: Auto-add dependent components on spawn/addComponent (e.g. `localTransform` implies `worldTransform`)
|
|
23
24
|
- **Command Buffer**: Deferred structural changes for safe entity/component operations during systems
|
|
24
25
|
- **Timer Bundle**: ECS-native timers with event-based completion notifications
|
|
25
26
|
|
|
@@ -47,7 +48,7 @@ npm install ecspresso
|
|
|
47
48
|
- [Entity Hierarchy](#entity-hierarchy) -- [Traversal](#traversal), [Parent-First Traversal](#parent-first-traversal), [Cascade Deletion](#cascade-deletion)
|
|
48
49
|
- [Change Detection](#change-detection) -- [Marking Changes](#marking-changes), [Changed Query Filter](#changed-query-filter), [Sequence Timing](#sequence-timing)
|
|
49
50
|
- [Command Buffer](#command-buffer) -- [Available Commands](#available-commands)
|
|
50
|
-
- [Bundles](#bundles) -- [Built-in Bundles](#built-in-bundles), [Timer Bundle](#timer-bundle)
|
|
51
|
+
- [Bundles](#bundles) -- [Required Components](#required-components), [Built-in Bundles](#built-in-bundles), [Timer Bundle](#timer-bundle)
|
|
51
52
|
- [Asset Management](#asset-management)
|
|
52
53
|
- [Screen Management](#screen-management) -- [Screen-Scoped Systems](#screen-scoped-systems), [Screen Resource](#screen-resource)
|
|
53
54
|
- [Type Safety](#type-safety)
|
|
@@ -107,7 +108,7 @@ const entity = world.spawn({
|
|
|
107
108
|
// Add components later
|
|
108
109
|
world.entityManager.addComponent(entity.id, 'velocity', { x: 5, y: 0 });
|
|
109
110
|
|
|
110
|
-
// Get component data (returns
|
|
111
|
+
// Get component data (returns undefined if not found)
|
|
111
112
|
const position = world.entityManager.getComponent(entity.id, 'position');
|
|
112
113
|
|
|
113
114
|
// Remove components or entities
|
|
@@ -687,16 +688,66 @@ const game = ECSpresso.create<GameComponents, {}, GameResources>()
|
|
|
687
688
|
.build();
|
|
688
689
|
```
|
|
689
690
|
|
|
691
|
+
### Required Components
|
|
692
|
+
|
|
693
|
+
Bundles can declare that certain components depend on others. When an entity gains a trigger component, any required components that aren't already present are auto-added with default values:
|
|
694
|
+
|
|
695
|
+
```typescript
|
|
696
|
+
const transformBundle = new Bundle<TransformComponents>('transform')
|
|
697
|
+
.registerRequired('localTransform', 'worldTransform', () => ({
|
|
698
|
+
x: 0, y: 0, rotation: 0, scaleX: 1, scaleY: 1,
|
|
699
|
+
}));
|
|
700
|
+
|
|
701
|
+
const world = ECSpresso.create()
|
|
702
|
+
.withBundle(transformBundle)
|
|
703
|
+
.build();
|
|
704
|
+
|
|
705
|
+
// worldTransform is auto-added with defaults
|
|
706
|
+
const entity = world.spawn({
|
|
707
|
+
localTransform: { x: 100, y: 200, rotation: 0, scaleX: 1, scaleY: 1 },
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
// Explicit values always win — no auto-add if already provided
|
|
711
|
+
const entity2 = world.spawn({
|
|
712
|
+
localTransform: { x: 100, y: 200, rotation: 0, scaleX: 1, scaleY: 1 },
|
|
713
|
+
worldTransform: { x: 50, y: 50, rotation: 0, scaleX: 2, scaleY: 2 }, // used as-is
|
|
714
|
+
});
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
Requirements can also be registered via the builder or at runtime:
|
|
718
|
+
|
|
719
|
+
```typescript
|
|
720
|
+
// Builder
|
|
721
|
+
const world = ECSpresso.create()
|
|
722
|
+
.withComponentTypes<Components>()
|
|
723
|
+
.withRequired('rigidBody', 'velocity', () => ({ x: 0, y: 0 }))
|
|
724
|
+
.withRequired('rigidBody', 'force', () => ({ x: 0, y: 0 }))
|
|
725
|
+
.build();
|
|
726
|
+
|
|
727
|
+
// Runtime
|
|
728
|
+
world.registerRequired('position', 'velocity', () => ({ x: 0, y: 0 }));
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
**Behavior:**
|
|
732
|
+
- Enforced at insertion time (`spawn`, `addComponent`, `addComponents`, `spawnChild`, command buffer)
|
|
733
|
+
- Removal is unrestricted — removing a required component does not cascade
|
|
734
|
+
- Transitive requirements resolve automatically (A requires B, B requires C → all three added)
|
|
735
|
+
- Circular dependencies are detected and rejected at registration time
|
|
736
|
+
- Auto-added components are marked as changed and trigger reactive queries
|
|
737
|
+
- Component names and factory return types are fully type-checked
|
|
738
|
+
|
|
739
|
+
**Built-in requirements:** The Transform bundle registers `localTransform` → `worldTransform`. The Physics 2D bundle registers `rigidBody` → `velocity` and `rigidBody` → `force`.
|
|
740
|
+
|
|
690
741
|
### Built-in Bundles
|
|
691
742
|
|
|
692
743
|
| Bundle | Import | Default Phase | Description |
|
|
693
744
|
|--------|--------|---------------|-------------|
|
|
694
|
-
| **Input** | `ecspresso/bundles/
|
|
695
|
-
| **Timers** | `ecspresso/bundles/
|
|
696
|
-
| **Movement** | `ecspresso/bundles/
|
|
697
|
-
| **Transform** | `ecspresso/bundles/
|
|
698
|
-
| **Bounds** | `ecspresso/bundles/
|
|
699
|
-
| **Collision** | `ecspresso/bundles/
|
|
745
|
+
| **Input** | `ecspresso/bundles/input` | `preUpdate` | Frame-accurate keyboard/pointer input with action mapping |
|
|
746
|
+
| **Timers** | `ecspresso/bundles/timers` | `preUpdate` | ECS-native timers with event-based completion |
|
|
747
|
+
| **Movement** | `ecspresso/bundles/movement` | `fixedUpdate` | Velocity-based movement integration |
|
|
748
|
+
| **Transform** | `ecspresso/bundles/transform` | `postUpdate` | Hierarchical transform propagation (local/world transforms) |
|
|
749
|
+
| **Bounds** | `ecspresso/bundles/bounds` | `postUpdate` | Screen bounds enforcement (destroy, clamp, wrap) |
|
|
750
|
+
| **Collision** | `ecspresso/bundles/collision` | `postUpdate` | Layer-based AABB/circle collision detection with events |
|
|
700
751
|
| **2D Renderer** | `ecspresso/bundles/renderers/renderer2D` | `render` | Automated PixiJS scene graph wiring |
|
|
701
752
|
|
|
702
753
|
Each bundle accepts a `phase` option to override its default.
|
|
@@ -707,20 +758,18 @@ The input bundle provides frame-accurate keyboard, pointer (mouse + touch via Po
|
|
|
707
758
|
|
|
708
759
|
```typescript
|
|
709
760
|
import {
|
|
710
|
-
createInputBundle,
|
|
761
|
+
createInputBundle,
|
|
711
762
|
type InputResourceTypes, type KeyCode
|
|
712
|
-
} from 'ecspresso/bundles/
|
|
713
|
-
|
|
714
|
-
interface Resources extends InputResourceTypes {}
|
|
763
|
+
} from 'ecspresso/bundles/input';
|
|
715
764
|
|
|
716
|
-
const world = ECSpresso.create
|
|
765
|
+
const world = ECSpresso.create()
|
|
717
766
|
.withBundle(createInputBundle({
|
|
718
|
-
actions:
|
|
767
|
+
actions: {
|
|
719
768
|
jump: { keys: [' ', 'ArrowUp'] },
|
|
720
769
|
shoot: { keys: ['z'], buttons: [0] },
|
|
721
770
|
moveLeft: { keys: ['a', 'ArrowLeft'] },
|
|
722
771
|
moveRight: { keys: ['d', 'ArrowRight'] },
|
|
723
|
-
}
|
|
772
|
+
},
|
|
724
773
|
}))
|
|
725
774
|
.build();
|
|
726
775
|
|
|
@@ -730,10 +779,17 @@ if (input.actions.justActivated('jump')) { /* ... */ }
|
|
|
730
779
|
if (input.keyboard.isDown('ArrowRight')) { /* ... */ }
|
|
731
780
|
if (input.pointer.justPressed(0)) { /* ... */ }
|
|
732
781
|
|
|
733
|
-
// Runtime remapping
|
|
734
|
-
input.setActionMap({
|
|
782
|
+
// Runtime remapping — must include all configured actions
|
|
783
|
+
input.setActionMap({
|
|
784
|
+
jump: { keys: ['w'] },
|
|
785
|
+
shoot: { keys: ['z'], buttons: [0] },
|
|
786
|
+
moveLeft: { keys: ['a'] },
|
|
787
|
+
moveRight: { keys: ['d'] },
|
|
788
|
+
});
|
|
735
789
|
```
|
|
736
790
|
|
|
791
|
+
Action names are type-safe — `isActive`, `justActivated`, `justDeactivated`, `setActionMap`, and `getActionMap` only accept action names from the config. The type parameter `A` is inferred from the `actions` object keys passed to `createInputBundle`. Defaults to `string` when no actions are configured.
|
|
792
|
+
|
|
737
793
|
Key values use the `KeyCode` type — a union of all standard `KeyboardEvent.key` values — providing autocomplete and compile-time validation. Note that the space bar key is `' '` (a space character), not `'Space'`.
|
|
738
794
|
|
|
739
795
|
### Timer Bundle
|
|
@@ -744,7 +800,7 @@ The timer bundle provides ECS-native timers that follow the "data, not callbacks
|
|
|
744
800
|
import {
|
|
745
801
|
createTimerBundle, createTimer, createRepeatingTimer,
|
|
746
802
|
type TimerComponentTypes, type TimerEventData
|
|
747
|
-
} from 'ecspresso/bundles/
|
|
803
|
+
} from 'ecspresso/bundles/timers';
|
|
748
804
|
|
|
749
805
|
// Events used with onComplete must have TimerEventData payload
|
|
750
806
|
interface Events {
|
|
@@ -949,8 +1005,8 @@ world.getResource('nonexistent');
|
|
|
949
1005
|
world.entityManager.addComponent(999, 'position', { x: 0, y: 0 });
|
|
950
1006
|
// → "Cannot add component 'position': Entity with ID 999 does not exist"
|
|
951
1007
|
|
|
952
|
-
// Component not found returns
|
|
953
|
-
world.entityManager.getComponent(123, 'position'); //
|
|
1008
|
+
// Component not found returns undefined (no throw)
|
|
1009
|
+
world.entityManager.getComponent(123, 'position'); // undefined
|
|
954
1010
|
```
|
|
955
1011
|
|
|
956
1012
|
## Performance Tips
|
package/dist/asset-manager.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import type { AssetStatus, AssetDefinition, AssetHandle, AssetsResource, AssetEv
|
|
|
6
6
|
/**
|
|
7
7
|
* Manages asset loading and access for ECSpresso
|
|
8
8
|
*/
|
|
9
|
-
export default class AssetManager<AssetTypes extends Record<string, unknown> = Record<string, never
|
|
9
|
+
export default class AssetManager<AssetTypes extends Record<string, unknown> = Record<string, never>, AssetGroupNames extends string = string> {
|
|
10
10
|
private readonly assets;
|
|
11
11
|
private readonly groups;
|
|
12
12
|
private eventBus;
|
|
@@ -14,7 +14,7 @@ export default class AssetManager<AssetTypes extends Record<string, unknown> = R
|
|
|
14
14
|
* Set the event bus for asset events
|
|
15
15
|
* @internal
|
|
16
16
|
*/
|
|
17
|
-
setEventBus(eventBus: EventBus<AssetEvents
|
|
17
|
+
setEventBus(eventBus: EventBus<AssetEvents<keyof AssetTypes & string, AssetGroupNames>>): void;
|
|
18
18
|
/**
|
|
19
19
|
* Register an asset definition
|
|
20
20
|
*/
|
|
@@ -30,7 +30,7 @@ export default class AssetManager<AssetTypes extends Record<string, unknown> = R
|
|
|
30
30
|
/**
|
|
31
31
|
* Load all assets in a group
|
|
32
32
|
*/
|
|
33
|
-
loadAssetGroup(groupName:
|
|
33
|
+
loadAssetGroup(groupName: AssetGroupNames): Promise<void>;
|
|
34
34
|
/**
|
|
35
35
|
* Get a loaded asset. Throws if not loaded.
|
|
36
36
|
*/
|
|
@@ -54,15 +54,15 @@ export default class AssetManager<AssetTypes extends Record<string, unknown> = R
|
|
|
54
54
|
/**
|
|
55
55
|
* Check if all assets in a group are loaded
|
|
56
56
|
*/
|
|
57
|
-
isGroupLoaded(groupName:
|
|
57
|
+
isGroupLoaded(groupName: AssetGroupNames): boolean;
|
|
58
58
|
/**
|
|
59
59
|
* Get the loading progress of a group (0-1)
|
|
60
60
|
*/
|
|
61
|
-
getGroupProgress(groupName:
|
|
61
|
+
getGroupProgress(groupName: AssetGroupNames): number;
|
|
62
62
|
/**
|
|
63
63
|
* Get detailed group progress
|
|
64
64
|
*/
|
|
65
|
-
getGroupProgressDetails(groupName:
|
|
65
|
+
getGroupProgressDetails(groupName: AssetGroupNames): {
|
|
66
66
|
loaded: number;
|
|
67
67
|
total: number;
|
|
68
68
|
progress: number;
|
|
@@ -74,7 +74,7 @@ export default class AssetManager<AssetTypes extends Record<string, unknown> = R
|
|
|
74
74
|
/**
|
|
75
75
|
* Create the $assets resource object
|
|
76
76
|
*/
|
|
77
|
-
createResource(): AssetsResource<AssetTypes>;
|
|
77
|
+
createResource(): AssetsResource<AssetTypes, AssetGroupNames>;
|
|
78
78
|
/**
|
|
79
79
|
* Get all registered asset keys
|
|
80
80
|
*/
|
|
@@ -91,21 +91,21 @@ export default class AssetManager<AssetTypes extends Record<string, unknown> = R
|
|
|
91
91
|
/**
|
|
92
92
|
* Implementation of AssetConfigurator for builder pattern
|
|
93
93
|
*/
|
|
94
|
-
export declare class AssetConfiguratorImpl<A extends Record<string, unknown
|
|
94
|
+
export declare class AssetConfiguratorImpl<A extends Record<string, unknown>, G extends string = never> implements AssetConfigurator<A, G> {
|
|
95
95
|
private readonly manager;
|
|
96
|
-
constructor(manager: AssetManager<A>);
|
|
97
|
-
add<K extends string, T>(key: K, loader: () => Promise<T>): AssetConfigurator<A & Record<K, T
|
|
98
|
-
addWithConfig<K extends string, T>(key: K, definition: AssetDefinition<T>): AssetConfigurator<A & Record<K, T
|
|
99
|
-
addGroup<
|
|
96
|
+
constructor(manager: AssetManager<A, G>);
|
|
97
|
+
add<K extends string, T>(key: K, loader: () => Promise<T>): AssetConfigurator<A & Record<K, T>, G>;
|
|
98
|
+
addWithConfig<K extends string, T>(key: K, definition: AssetDefinition<T>): AssetConfigurator<A & Record<K, T>, G>;
|
|
99
|
+
addGroup<GN extends string, T extends Record<string, () => Promise<unknown>>>(groupName: GN, assets: T): AssetConfigurator<A & {
|
|
100
100
|
[K in keyof T]: Awaited<ReturnType<T[K]>>;
|
|
101
|
-
}>;
|
|
101
|
+
}, G | GN>;
|
|
102
102
|
/**
|
|
103
103
|
* Get the underlying manager
|
|
104
104
|
* @internal
|
|
105
105
|
*/
|
|
106
|
-
getManager(): AssetManager<A>;
|
|
106
|
+
getManager(): AssetManager<A, G>;
|
|
107
107
|
}
|
|
108
108
|
/**
|
|
109
109
|
* Create a new AssetConfigurator for builder pattern usage
|
|
110
110
|
*/
|
|
111
|
-
export declare function createAssetConfigurator<A extends Record<string, unknown> = Record<string, never
|
|
111
|
+
export declare function createAssetConfigurator<A extends Record<string, unknown> = Record<string, never>, G extends string = never>(manager?: AssetManager<A, G>): AssetConfiguratorImpl<A, G>;
|
package/dist/asset-types.d.ts
CHANGED
|
@@ -32,7 +32,7 @@ export interface AssetHandle<T> {
|
|
|
32
32
|
* Resource interface for accessing assets in systems
|
|
33
33
|
* Exposed as $assets resource
|
|
34
34
|
*/
|
|
35
|
-
export interface AssetsResource<A extends Record<string, unknown
|
|
35
|
+
export interface AssetsResource<A extends Record<string, unknown>, G extends string = string> {
|
|
36
36
|
/**
|
|
37
37
|
* Get the loading status of an asset
|
|
38
38
|
*/
|
|
@@ -44,11 +44,11 @@ export interface AssetsResource<A extends Record<string, unknown>> {
|
|
|
44
44
|
/**
|
|
45
45
|
* Check if all assets in a group are loaded
|
|
46
46
|
*/
|
|
47
|
-
isGroupLoaded(groupName:
|
|
47
|
+
isGroupLoaded(groupName: G): boolean;
|
|
48
48
|
/**
|
|
49
49
|
* Get the loading progress of a group (0-1)
|
|
50
50
|
*/
|
|
51
|
-
getGroupProgress(groupName:
|
|
51
|
+
getGroupProgress(groupName: G): number;
|
|
52
52
|
/**
|
|
53
53
|
* Get a loaded asset. Throws if not loaded.
|
|
54
54
|
*/
|
|
@@ -63,21 +63,23 @@ export interface AssetsResource<A extends Record<string, unknown>> {
|
|
|
63
63
|
getHandle<K extends keyof A>(key: K): AssetHandle<A[K]>;
|
|
64
64
|
}
|
|
65
65
|
/**
|
|
66
|
-
* Events emitted by the asset system
|
|
66
|
+
* Events emitted by the asset system.
|
|
67
|
+
* @typeParam K - Asset key type (defaults to `string` for backward compatibility)
|
|
68
|
+
* @typeParam G - Asset group name type (defaults to `string` for backward compatibility)
|
|
67
69
|
*/
|
|
68
|
-
export interface AssetEvents {
|
|
70
|
+
export interface AssetEvents<K extends string = string, G extends string = string> {
|
|
69
71
|
assetLoaded: {
|
|
70
|
-
key:
|
|
72
|
+
key: K;
|
|
71
73
|
};
|
|
72
74
|
assetFailed: {
|
|
73
|
-
key:
|
|
75
|
+
key: K;
|
|
74
76
|
error: Error;
|
|
75
77
|
};
|
|
76
78
|
assetGroupLoaded: {
|
|
77
|
-
group:
|
|
79
|
+
group: G;
|
|
78
80
|
};
|
|
79
81
|
assetGroupProgress: {
|
|
80
|
-
group:
|
|
82
|
+
group: G;
|
|
81
83
|
progress: number;
|
|
82
84
|
loaded: number;
|
|
83
85
|
total: number;
|
|
@@ -86,19 +88,19 @@ export interface AssetEvents {
|
|
|
86
88
|
/**
|
|
87
89
|
* Configuration for asset definitions during builder setup
|
|
88
90
|
*/
|
|
89
|
-
export interface AssetConfigurator<A extends Record<string, unknown
|
|
91
|
+
export interface AssetConfigurator<A extends Record<string, unknown>, G extends string = never> {
|
|
90
92
|
/**
|
|
91
93
|
* Add a single eager asset
|
|
92
94
|
*/
|
|
93
|
-
add<K extends string, T>(key: K, loader: () => Promise<T>): AssetConfigurator<A & Record<K, T
|
|
95
|
+
add<K extends string, T>(key: K, loader: () => Promise<T>): AssetConfigurator<A & Record<K, T>, G>;
|
|
94
96
|
/**
|
|
95
97
|
* Add a single asset with full configuration
|
|
96
98
|
*/
|
|
97
|
-
addWithConfig<K extends string, T>(key: K, definition: AssetDefinition<T>): AssetConfigurator<A & Record<K, T
|
|
99
|
+
addWithConfig<K extends string, T>(key: K, definition: AssetDefinition<T>): AssetConfigurator<A & Record<K, T>, G>;
|
|
98
100
|
/**
|
|
99
101
|
* Add a group of assets that can be loaded together
|
|
100
102
|
*/
|
|
101
|
-
addGroup<
|
|
103
|
+
addGroup<GN extends string, T extends Record<string, () => Promise<unknown>>>(groupName: GN, assets: T): AssetConfigurator<A & {
|
|
102
104
|
[K in keyof T]: Awaited<ReturnType<T[K]>>;
|
|
103
|
-
}>;
|
|
105
|
+
}, G | GN>;
|
|
104
106
|
}
|
package/dist/bundle.d.ts
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import { SystemBuilderWithBundle } from './system-builder';
|
|
2
2
|
import type ECSpresso from './ecspresso';
|
|
3
|
+
import type { ResourceFactoryWithDeps } from './resource-manager';
|
|
3
4
|
import type { AssetDefinition } from './asset-types';
|
|
4
5
|
import type { ScreenDefinition } from './screen-types';
|
|
5
6
|
import type { BundlesAreCompatible } from './type-utils';
|
|
7
|
+
import type { QueryDefinition } from './types';
|
|
6
8
|
/**
|
|
7
9
|
* Bundle class that encapsulates a set of components, resources, events, and systems
|
|
8
10
|
* that can be merged into a ECSpresso instance
|
|
9
11
|
*/
|
|
10
|
-
export default class Bundle<ComponentTypes extends Record<string, any> = {}, EventTypes extends Record<string, any> = {}, ResourceTypes extends Record<string, any> = {}, AssetTypes extends Record<string, unknown> = {}, ScreenStates extends Record<string, ScreenDefinition<any, any>> = {}> {
|
|
12
|
+
export default class Bundle<ComponentTypes extends Record<string, any> = {}, EventTypes extends Record<string, any> = {}, ResourceTypes extends Record<string, any> = {}, AssetTypes extends Record<string, unknown> = {}, ScreenStates extends Record<string, ScreenDefinition<any, any>> = {}, Labels extends string = never, Groups extends string = never, AssetGroupNames extends string = never, ReactiveQueryNames extends string = never> {
|
|
11
13
|
private _systems;
|
|
12
14
|
private _resources;
|
|
13
15
|
private _assets;
|
|
14
16
|
private _assetGroups;
|
|
15
17
|
private _screens;
|
|
18
|
+
private _disposeCallbacks;
|
|
19
|
+
private _requiredComponents;
|
|
16
20
|
private _id;
|
|
17
21
|
constructor(id?: string);
|
|
18
22
|
/**
|
|
@@ -27,17 +31,14 @@ export default class Bundle<ComponentTypes extends Record<string, any> = {}, Eve
|
|
|
27
31
|
/**
|
|
28
32
|
* Add a system to this bundle, by label (creating a new builder) or by reusing an existing one
|
|
29
33
|
*/
|
|
30
|
-
addSystem<Q extends Record<string,
|
|
31
|
-
addSystem(label:
|
|
34
|
+
addSystem<Q extends Record<string, QueryDefinition<ComponentTypes>>, BL extends string, BG extends string, L extends string, SG extends string>(builder: SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, Q, BL, BG, L, SG, any, any>): SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, Q, Labels, Groups, L, SG, AssetGroupNames, ReactiveQueryNames>;
|
|
35
|
+
addSystem<L extends string>(label: L): SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, {}, Labels, Groups, L, never, AssetGroupNames, ReactiveQueryNames>;
|
|
32
36
|
/**
|
|
33
37
|
* Add a resource to this bundle
|
|
34
38
|
* @param label The resource key
|
|
35
39
|
* @param resource The resource value, a factory function, or a factory with dependencies
|
|
36
40
|
*/
|
|
37
|
-
addResource<K extends keyof ResourceTypes>(label: K, resource: ResourceTypes[K] | ((ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>) => ResourceTypes[K] | Promise<ResourceTypes[K]>) |
|
|
38
|
-
dependsOn: readonly string[];
|
|
39
|
-
factory: (ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>) => ResourceTypes[K] | Promise<ResourceTypes[K]>;
|
|
40
|
-
}): this;
|
|
41
|
+
addResource<K extends keyof ResourceTypes>(label: K, resource: ResourceTypes[K] | ((ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>) => ResourceTypes[K] | Promise<ResourceTypes[K]>) | ResourceFactoryWithDeps<ResourceTypes[K], ECSpresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>, keyof ResourceTypes & string>): this;
|
|
41
42
|
/**
|
|
42
43
|
* Add an asset to this bundle
|
|
43
44
|
* @param key The asset key
|
|
@@ -47,21 +48,21 @@ export default class Bundle<ComponentTypes extends Record<string, any> = {}, Eve
|
|
|
47
48
|
addAsset<K extends string, T>(key: K, loader: () => Promise<T>, options?: {
|
|
48
49
|
eager?: boolean;
|
|
49
50
|
group?: string;
|
|
50
|
-
}): Bundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes & Record<K, T>, ScreenStates>;
|
|
51
|
+
}): Bundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes & Record<K, T>, ScreenStates, Labels, Groups, AssetGroupNames, ReactiveQueryNames>;
|
|
51
52
|
/**
|
|
52
53
|
* Add a group of assets to this bundle
|
|
53
54
|
* @param groupName The group name
|
|
54
55
|
* @param assets Object mapping asset keys to loader functions
|
|
55
56
|
*/
|
|
56
|
-
addAssetGroup<
|
|
57
|
+
addAssetGroup<GN extends string, T extends Record<string, () => Promise<unknown>>>(groupName: GN, assets: T): Bundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes & {
|
|
57
58
|
[K in keyof T]: Awaited<ReturnType<T[K]>>;
|
|
58
|
-
}, ScreenStates>;
|
|
59
|
+
}, ScreenStates, Labels, Groups, AssetGroupNames | GN, ReactiveQueryNames>;
|
|
59
60
|
/**
|
|
60
61
|
* Add a screen to this bundle
|
|
61
62
|
* @param name The screen name
|
|
62
63
|
* @param definition The screen definition
|
|
63
64
|
*/
|
|
64
|
-
addScreen<K extends string, Config extends Record<string, unknown>, State extends Record<string, unknown>>(name: K, definition: ScreenDefinition<Config, State
|
|
65
|
+
addScreen<K extends string, Config extends Record<string, unknown>, State extends Record<string, unknown>>(name: K, definition: ScreenDefinition<Config, State, ECSpresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, Record<string, ScreenDefinition>>>): Bundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates & Record<K, ScreenDefinition<Config, State>>, Labels, Groups, AssetGroupNames, ReactiveQueryNames>;
|
|
65
66
|
/**
|
|
66
67
|
* Get all asset definitions in this bundle
|
|
67
68
|
*/
|
|
@@ -70,6 +71,50 @@ export default class Bundle<ComponentTypes extends Record<string, any> = {}, Eve
|
|
|
70
71
|
* Get all screen definitions in this bundle
|
|
71
72
|
*/
|
|
72
73
|
getScreens(): Map<string, ScreenDefinition<any, any>>;
|
|
74
|
+
/**
|
|
75
|
+
* Register a dispose callback for a component type in this bundle.
|
|
76
|
+
* Called when a component is removed (explicit removal, entity destruction, or replacement).
|
|
77
|
+
* @param componentName The component type to register disposal for
|
|
78
|
+
* @param callback Function receiving the component value being disposed
|
|
79
|
+
* @returns This bundle for method chaining
|
|
80
|
+
*/
|
|
81
|
+
registerDispose<K extends keyof ComponentTypes>(componentName: K, callback: (value: ComponentTypes[K]) => void): this;
|
|
82
|
+
/**
|
|
83
|
+
* Get all registered dispose callbacks in this bundle
|
|
84
|
+
*/
|
|
85
|
+
getDisposeCallbacks(): Map<string, (value: unknown) => void>;
|
|
86
|
+
/**
|
|
87
|
+
* Register a required component relationship.
|
|
88
|
+
* When an entity gains `trigger`, the `required` component is auto-added
|
|
89
|
+
* (using `factory` for the default value) if not already present.
|
|
90
|
+
* @param trigger The component whose presence triggers auto-addition
|
|
91
|
+
* @param required The component to auto-add
|
|
92
|
+
* @param factory Function that creates the default value for the required component
|
|
93
|
+
* @returns This bundle for method chaining
|
|
94
|
+
*/
|
|
95
|
+
registerRequired<Trigger extends keyof ComponentTypes, Required extends keyof ComponentTypes>(trigger: Trigger, required: Required, factory: (triggerValue: ComponentTypes[Trigger]) => ComponentTypes[Required]): this;
|
|
96
|
+
/**
|
|
97
|
+
* Declare reactive query names that this bundle will register at runtime.
|
|
98
|
+
* This is a pure type-level operation with no runtime cost.
|
|
99
|
+
*/
|
|
100
|
+
withReactiveQueryNames<N extends string>(): Bundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, Labels, Groups, AssetGroupNames, ReactiveQueryNames | N>;
|
|
101
|
+
/**
|
|
102
|
+
* Get all registered required component mappings in this bundle
|
|
103
|
+
*/
|
|
104
|
+
getRequiredComponents(): Map<string, Array<{
|
|
105
|
+
component: string;
|
|
106
|
+
factory: (triggerValue: any) => unknown;
|
|
107
|
+
}>>;
|
|
108
|
+
/**
|
|
109
|
+
* Check for circular dependencies in the required components graph
|
|
110
|
+
* @throws Error if adding the new edge would create a cycle
|
|
111
|
+
*/
|
|
112
|
+
private _checkRequiredCycle;
|
|
113
|
+
/**
|
|
114
|
+
* Internal method to set a dispose callback
|
|
115
|
+
* @internal Used by mergeBundles
|
|
116
|
+
*/
|
|
117
|
+
_setDisposeCallback(name: string, callback: (value: unknown) => void): void;
|
|
73
118
|
/**
|
|
74
119
|
* Internal method to set a resource
|
|
75
120
|
* @internal Used by mergeBundles
|
|
@@ -85,16 +130,21 @@ export default class Bundle<ComponentTypes extends Record<string, any> = {}, Eve
|
|
|
85
130
|
* @internal Used by mergeBundles
|
|
86
131
|
*/
|
|
87
132
|
_setScreen(name: string, definition: ScreenDefinition<any, any>): void;
|
|
133
|
+
/**
|
|
134
|
+
* Internal method to add a required component entry
|
|
135
|
+
* @internal Used by mergeBundles
|
|
136
|
+
*/
|
|
137
|
+
_addRequired(trigger: string, component: string, factory: (triggerValue: any) => unknown): void;
|
|
88
138
|
/**
|
|
89
139
|
* Get all systems defined in this bundle
|
|
90
140
|
* Returns built System objects instead of SystemBuilders
|
|
91
141
|
*/
|
|
92
|
-
getSystems(): SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes, any>[];
|
|
142
|
+
getSystems(): SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, any, any, any, any, any, any, any>[];
|
|
93
143
|
/**
|
|
94
144
|
* Register all systems in this bundle with an ECSpresso instance
|
|
95
145
|
* @internal Used by ECSpresso when adding a bundle
|
|
96
146
|
*/
|
|
97
|
-
registerSystemsWithEcspresso(ecspresso: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>): void;
|
|
147
|
+
registerSystemsWithEcspresso(ecspresso: ECSpresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>): void;
|
|
98
148
|
/**
|
|
99
149
|
* Get all resources defined in this bundle
|
|
100
150
|
*/
|
|
@@ -108,7 +158,7 @@ export default class Bundle<ComponentTypes extends Record<string, any> = {}, Eve
|
|
|
108
158
|
/**
|
|
109
159
|
* Get all system builders in this bundle
|
|
110
160
|
*/
|
|
111
|
-
getSystemBuilders(): SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes, any>[];
|
|
161
|
+
getSystemBuilders(): SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, any, any, any, any, any, any, any>[];
|
|
112
162
|
/**
|
|
113
163
|
* Check if this bundle has a specific resource
|
|
114
164
|
* @param key The resource key to check
|
|
@@ -119,5 +169,5 @@ export default class Bundle<ComponentTypes extends Record<string, any> = {}, Eve
|
|
|
119
169
|
/**
|
|
120
170
|
* Function that merges multiple bundles into a single bundle
|
|
121
171
|
*/
|
|
122
|
-
export declare function mergeBundles<C1 extends Record<string, any>, E1 extends Record<string, any>, R1 extends Record<string, any>, A1 extends Record<string, unknown>, S1 extends Record<string, ScreenDefinition<any, any>>, C2 extends Record<string, any>, E2 extends Record<string, any>, R2 extends Record<string, any>, A2 extends Record<string, unknown>, S2 extends Record<string, ScreenDefinition<any, any
|
|
123
|
-
export declare function mergeBundles<ComponentTypes extends Record<string, any>, EventTypes extends Record<string, any>, ResourceTypes extends Record<string, any>, AssetTypes extends Record<string, unknown>, ScreenStates extends Record<string, ScreenDefinition<any, any
|
|
172
|
+
export declare function mergeBundles<C1 extends Record<string, any>, E1 extends Record<string, any>, R1 extends Record<string, any>, A1 extends Record<string, unknown>, S1 extends Record<string, ScreenDefinition<any, any>>, L1 extends string, G1 extends string, AG1 extends string, RQ1 extends string, C2 extends Record<string, any>, E2 extends Record<string, any>, R2 extends Record<string, any>, A2 extends Record<string, unknown>, S2 extends Record<string, ScreenDefinition<any, any>>, L2 extends string, G2 extends string, AG2 extends string, RQ2 extends string>(id: string, bundle1: Bundle<C1, E1, R1, A1, S1, L1, G1, AG1, RQ1>, bundle2: BundlesAreCompatible<C1, C2, E1, E2, R1, R2, A1, A2, S1, S2> extends true ? Bundle<C2, E2, R2, A2, S2, L2, G2, AG2, RQ2> : never): Bundle<C1 & C2, E1 & E2, R1 & R2, A1 & A2, S1 & S2, L1 | L2, G1 | G2, AG1 | AG2, RQ1 | RQ2>;
|
|
173
|
+
export declare function mergeBundles<ComponentTypes extends Record<string, any>, EventTypes extends Record<string, any>, ResourceTypes extends Record<string, any>, AssetTypes extends Record<string, unknown>, ScreenStates extends Record<string, ScreenDefinition<any, any>>, Labels extends string, Groups extends string, AssetGroupNamesParam extends string, ReactiveQueryNamesParam extends string>(id: string, ...bundles: Array<Bundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, Labels, Groups, AssetGroupNamesParam, ReactiveQueryNamesParam>>): Bundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, Labels, Groups, AssetGroupNamesParam, ReactiveQueryNamesParam>;
|