ecspresso 0.10.2 → 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.
Files changed (82) hide show
  1. package/README.md +73 -17
  2. package/dist/asset-manager.d.ts +15 -15
  3. package/dist/asset-types.d.ts +16 -14
  4. package/dist/bundle.d.ts +66 -16
  5. package/dist/bundles/audio.d.ts +293 -0
  6. package/dist/bundles/{utils/bounds.d.ts → bounds.d.ts} +9 -7
  7. package/dist/bundles/camera.d.ts +89 -0
  8. package/dist/bundles/collision.d.ts +289 -0
  9. package/dist/bundles/diagnostics.d.ts +48 -0
  10. package/dist/bundles/{utils/input.d.ts → input.d.ts} +16 -17
  11. package/dist/bundles/physics2D.d.ts +159 -0
  12. package/dist/bundles/renderers/renderer2D.d.ts +65 -24
  13. package/dist/bundles/spatial-index.d.ts +57 -0
  14. package/dist/bundles/state-machine.d.ts +298 -0
  15. package/dist/bundles/{utils/timers.d.ts → timers.d.ts} +9 -8
  16. package/dist/bundles/{utils/transform.d.ts → transform.d.ts} +10 -10
  17. package/dist/bundles/tween.d.ts +197 -0
  18. package/dist/command-buffer.d.ts +20 -20
  19. package/dist/ecspresso-builder.d.ts +165 -0
  20. package/dist/ecspresso.d.ts +157 -178
  21. package/dist/entity-manager.d.ts +76 -40
  22. package/dist/event-bus.d.ts +6 -1
  23. package/dist/index.d.ts +1 -9
  24. package/dist/reactive-query-manager.d.ts +14 -3
  25. package/dist/resource-manager.d.ts +35 -19
  26. package/dist/screen-manager.d.ts +4 -4
  27. package/dist/screen-types.d.ts +12 -11
  28. package/dist/src/bundles/audio.js +4 -0
  29. package/dist/src/bundles/audio.js.map +10 -0
  30. package/dist/src/bundles/bounds.js +4 -0
  31. package/dist/src/bundles/bounds.js.map +10 -0
  32. package/dist/src/bundles/camera.js +4 -0
  33. package/dist/src/bundles/camera.js.map +10 -0
  34. package/dist/src/bundles/collision.js +4 -0
  35. package/dist/src/bundles/collision.js.map +11 -0
  36. package/dist/src/bundles/diagnostics.js +5 -0
  37. package/dist/src/bundles/diagnostics.js.map +10 -0
  38. package/dist/src/bundles/input.js +4 -0
  39. package/dist/src/bundles/input.js.map +10 -0
  40. package/dist/src/bundles/physics2D.js +4 -0
  41. package/dist/src/bundles/physics2D.js.map +11 -0
  42. package/dist/src/bundles/renderers/renderer2D.js +4 -0
  43. package/dist/src/bundles/renderers/renderer2D.js.map +10 -0
  44. package/dist/src/bundles/spatial-index.js +4 -0
  45. package/dist/src/bundles/spatial-index.js.map +11 -0
  46. package/dist/src/bundles/state-machine.js +4 -0
  47. package/dist/src/bundles/state-machine.js.map +10 -0
  48. package/dist/src/bundles/timers.js +4 -0
  49. package/dist/src/bundles/timers.js.map +10 -0
  50. package/dist/src/bundles/transform.js +4 -0
  51. package/dist/src/bundles/transform.js.map +10 -0
  52. package/dist/src/bundles/tween.js +4 -0
  53. package/dist/src/bundles/tween.js.map +11 -0
  54. package/dist/src/index.js +4 -0
  55. package/dist/src/index.js.map +25 -0
  56. package/dist/system-builder.d.ts +36 -42
  57. package/dist/type-utils.d.ts +52 -3
  58. package/dist/types.d.ts +10 -19
  59. package/dist/utils/check-required-cycle.d.ts +12 -0
  60. package/dist/utils/easing.d.ts +71 -0
  61. package/dist/utils/math.d.ts +67 -0
  62. package/dist/utils/narrowphase.d.ts +63 -0
  63. package/dist/utils/spatial-hash.d.ts +53 -0
  64. package/package.json +50 -20
  65. package/dist/bundles/renderers/renderer2D.js +0 -4
  66. package/dist/bundles/renderers/renderer2D.js.map +0 -10
  67. package/dist/bundles/utils/bounds.js +0 -4
  68. package/dist/bundles/utils/bounds.js.map +0 -10
  69. package/dist/bundles/utils/collision.d.ts +0 -204
  70. package/dist/bundles/utils/collision.js +0 -4
  71. package/dist/bundles/utils/collision.js.map +0 -10
  72. package/dist/bundles/utils/input.js +0 -4
  73. package/dist/bundles/utils/input.js.map +0 -10
  74. package/dist/bundles/utils/movement.d.ts +0 -86
  75. package/dist/bundles/utils/movement.js +0 -4
  76. package/dist/bundles/utils/movement.js.map +0 -10
  77. package/dist/bundles/utils/timers.js +0 -4
  78. package/dist/bundles/utils/timers.js.map +0 -10
  79. package/dist/bundles/utils/transform.js +0 -4
  80. package/dist/bundles/utils/transform.js.map +0 -10
  81. package/dist/index.js +0 -4
  82. package/dist/index.js.map +0 -22
@@ -1,10 +1,10 @@
1
1
  import Bundle from "./bundle";
2
2
  import ECSpresso from "./ecspresso";
3
- import type { FilteredEntity, System, SystemPhase } from "./types";
3
+ import type { FilteredEntity, QueryDefinition, System, SystemPhase } from "./types";
4
4
  /**
5
5
  * Builder class for creating type-safe ECS Systems with proper query inference
6
6
  */
7
- export declare class SystemBuilder<ComponentTypes extends Record<string, any> = Record<string, any>, EventTypes extends Record<string, any> = Record<string, any>, ResourceTypes extends Record<string, any> = Record<string, any>, Queries extends Record<string, QueryDefinition<ComponentTypes>> = {}> {
7
+ export declare class SystemBuilder<ComponentTypes extends Record<string, any> = Record<string, any>, EventTypes extends Record<string, any> = Record<string, any>, ResourceTypes extends Record<string, any> = Record<string, any>, AssetTypes extends Record<string, unknown> = Record<string, unknown>, ScreenStates extends Record<string, any> = Record<string, any>, Queries extends Record<string, QueryDefinition<ComponentTypes>> = {}, Label extends string = string, SysGroups extends string = never, BundleLabels extends string = never, BundleGroups extends string = never, BundleAssetGroupNames extends string = never, BundleReactiveQueryNames extends string = never> {
8
8
  private _label;
9
9
  private _ecspresso;
10
10
  private _bundle;
@@ -20,26 +20,22 @@ export declare class SystemBuilder<ComponentTypes extends Record<string, any> =
20
20
  private _inScreens?;
21
21
  private _excludeScreens?;
22
22
  private _requiredAssets?;
23
- constructor(_label: string, _ecspresso?: ECSpresso<ComponentTypes, EventTypes, ResourceTypes> | null, _bundle?: Bundle<ComponentTypes, EventTypes, ResourceTypes> | null);
23
+ private _runWhenEmpty;
24
+ constructor(_label: string, _ecspresso?: ECSpresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates> | null, _bundle?: Bundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, BundleLabels, BundleGroups, BundleAssetGroupNames, BundleReactiveQueryNames> | null);
24
25
  get label(): string;
25
26
  /**
26
27
  * Returns the associated bundle if one was provided in the constructor
27
28
  */
28
- get bundle(): Bundle<ComponentTypes, EventTypes, ResourceTypes, {}, {}> | null;
29
+ get bundle(): Bundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, BundleLabels, BundleGroups, BundleAssetGroupNames, BundleReactiveQueryNames> | null;
29
30
  /**
30
31
  * Returns the associated ECSpresso instance if one was provided in the constructor
31
32
  */
32
- get ecspresso(): ECSpresso<ComponentTypes, EventTypes, ResourceTypes, {}, {}> | null;
33
+ get ecspresso(): ECSpresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, string, string, string, string> | null;
33
34
  /**
34
35
  * Auto-register this system with its ECSpresso instance if not already registered
35
36
  * @private
36
37
  */
37
38
  private _autoRegister;
38
- /**
39
- * Create the system object without registering it
40
- * @private
41
- */
42
- private _buildSystemObject;
43
39
  /**
44
40
  * Create a system object with all configured properties
45
41
  * @private
@@ -67,7 +63,7 @@ export declare class SystemBuilder<ComponentTypes extends Record<string, any> =
67
63
  * @param groupName The name of the group to add the system to
68
64
  * @returns This SystemBuilder instance for method chaining
69
65
  */
70
- inGroup(groupName: string): this;
66
+ inGroup<G extends string>(groupName: G): this extends SystemBuilderWithEcspresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, Queries, Label, SysGroups> ? SystemBuilderWithEcspresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, Queries, Label, SysGroups | G> : this extends SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, Queries, BundleLabels, BundleGroups, Label, SysGroups, BundleAssetGroupNames, BundleReactiveQueryNames> ? SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, Queries, BundleLabels, BundleGroups, Label, SysGroups | G, BundleAssetGroupNames, BundleReactiveQueryNames> : SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, Queries, Label, SysGroups | G, BundleLabels, BundleGroups, BundleAssetGroupNames, BundleReactiveQueryNames>;
71
67
  /**
72
68
  * Restrict this system to only run in specified screens.
73
69
  * System will be skipped during update() when the current screen
@@ -75,7 +71,7 @@ export declare class SystemBuilder<ComponentTypes extends Record<string, any> =
75
71
  * @param screens Array of screen names where this system should run
76
72
  * @returns This SystemBuilder instance for method chaining
77
73
  */
78
- inScreens(screens: ReadonlyArray<string>): this;
74
+ inScreens(screens: ReadonlyArray<keyof ScreenStates & string>): this;
79
75
  /**
80
76
  * Exclude this system from running in specified screens.
81
77
  * System will be skipped during update() when the current screen
@@ -83,7 +79,7 @@ export declare class SystemBuilder<ComponentTypes extends Record<string, any> =
83
79
  * @param screens Array of screen names where this system should NOT run
84
80
  * @returns This SystemBuilder instance for method chaining
85
81
  */
86
- excludeScreens(screens: ReadonlyArray<string>): this;
82
+ excludeScreens(screens: ReadonlyArray<keyof ScreenStates & string>): this;
87
83
  /**
88
84
  * Require specific assets to be loaded for this system to run.
89
85
  * System will be skipped during update() if any required asset
@@ -91,7 +87,12 @@ export declare class SystemBuilder<ComponentTypes extends Record<string, any> =
91
87
  * @param assets Array of asset keys that must be loaded
92
88
  * @returns This SystemBuilder instance for method chaining
93
89
  */
94
- requiresAssets(assets: ReadonlyArray<string>): this;
90
+ requiresAssets(assets: ReadonlyArray<keyof AssetTypes & string>): this;
91
+ /**
92
+ * Allow this system to run even when all queries return zero entities.
93
+ * By default, systems with queries are skipped when no entities match.
94
+ */
95
+ runWhenEmpty(): this;
95
96
  /**
96
97
  * Add a query definition to the system
97
98
  */
@@ -101,40 +102,40 @@ export declare class SystemBuilder<ComponentTypes extends Record<string, any> =
101
102
  changed?: ReadonlyArray<WithComponents>;
102
103
  optional?: ReadonlyArray<OptionalComponents>;
103
104
  parentHas?: ReadonlyArray<keyof ComponentTypes>;
104
- }): this extends SystemBuilderWithEcspresso<ComponentTypes, EventTypes, ResourceTypes, Queries> ? SystemBuilderWithEcspresso<ComponentTypes, EventTypes, ResourceTypes, NewQueries> : this extends SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes, Queries> ? SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes, NewQueries> : SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, NewQueries>;
105
+ }): this extends SystemBuilderWithEcspresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, Queries, Label, SysGroups> ? SystemBuilderWithEcspresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, NewQueries, Label, SysGroups> : this extends SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, Queries, BundleLabels, BundleGroups, Label, SysGroups, BundleAssetGroupNames, BundleReactiveQueryNames> ? SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, NewQueries, BundleLabels, BundleGroups, Label, SysGroups, BundleAssetGroupNames, BundleReactiveQueryNames> : SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, NewQueries, Label, SysGroups, BundleLabels, BundleGroups, BundleAssetGroupNames, BundleReactiveQueryNames>;
105
106
  /**
106
107
  * Set the system's process function that runs each update
107
108
  * @param process Function to process entities matching the system's queries each update
108
109
  * @returns This SystemBuilder instance for method chaining
109
110
  */
110
- setProcess(process: ProcessFunction<ComponentTypes, EventTypes, ResourceTypes, Queries>): this;
111
+ setProcess(process: ProcessFunction<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, Queries>): this;
111
112
  /**
112
113
  * Register this system with its ECSpresso instance and return the ECSpresso for chaining
113
114
  * This enables seamless method chaining: .registerAndContinue().addSystem(...)
114
115
  * @returns ECSpresso instance if attached to one, otherwise throws an error
115
116
  */
116
- registerAndContinue(): ECSpresso<ComponentTypes, EventTypes, ResourceTypes>;
117
+ registerAndContinue(): ECSpresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>;
117
118
  /**
118
119
  * Complete this system and return the parent container for seamless chaining
119
120
  * - For ECSpresso-attached builders: registers the system and returns ECSpresso
120
121
  * - For Bundle-attached builders: returns the Bundle
121
122
  * This method is typed via the specialized interfaces (SystemBuilderWithEcspresso, SystemBuilderWithBundle)
122
123
  */
123
- and(): ECSpresso<ComponentTypes, EventTypes, ResourceTypes> | Bundle<ComponentTypes, EventTypes, ResourceTypes>;
124
+ and(): ECSpresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates> | Bundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, BundleLabels | Label, BundleGroups | SysGroups, BundleAssetGroupNames, BundleReactiveQueryNames>;
124
125
  /**
125
126
  * Set the onDetach lifecycle hook
126
127
  * Called when the system is removed from the ECS
127
128
  * @param onDetach Function to run when this system is detached from the ECS
128
129
  * @returns This SystemBuilder instance for method chaining
129
130
  */
130
- setOnDetach(onDetach: LifecycleFunction<ComponentTypes, EventTypes, ResourceTypes>): this;
131
+ setOnDetach(onDetach: LifecycleFunction<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>): this;
131
132
  /**
132
133
  * Set the onInitialize lifecycle hook
133
134
  * Called when the system is initialized via ECSpresso.initialize() method
134
135
  * @param onInitialize Function to run when this system is initialized
135
136
  * @returns This SystemBuilder instance for method chaining
136
137
  */
137
- setOnInitialize(onInitialize: LifecycleFunction<ComponentTypes, EventTypes, ResourceTypes>): this;
138
+ setOnInitialize(onInitialize: LifecycleFunction<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>): this;
138
139
  /**
139
140
  * Set event handlers for the system
140
141
  * These handlers will be automatically subscribed when the system is attached
@@ -143,29 +144,22 @@ export declare class SystemBuilder<ComponentTypes extends Record<string, any> =
143
144
  */
144
145
  setEventHandlers(handlers: {
145
146
  [EventName in keyof EventTypes]?: {
146
- handler(data: EventTypes[EventName], ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>): void;
147
+ handler(data: EventTypes[EventName], ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>): void;
147
148
  };
148
149
  }): this;
149
150
  /**
150
151
  * Build the final system object
151
152
  */
152
- build(ecspresso?: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>): this;
153
+ build(ecspresso?: ECSpresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>): this;
153
154
  }
154
155
  /**
155
156
  * Helper function to register a system with an ECSpresso instance
156
157
  * This handles attaching the system and setting up event handlers
157
158
  * @internal Used by SystemBuilder and Bundle
158
159
  */
159
- export declare function registerSystemWithEcspresso<ComponentTypes extends Record<string, any>, EventTypes extends Record<string, any>, ResourceTypes extends Record<string, any>>(system: System<ComponentTypes, any, any, EventTypes, ResourceTypes>, ecspresso: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>): void;
160
- type QueryDefinition<ComponentTypes, WithComponents extends keyof ComponentTypes = any, WithoutComponents extends keyof ComponentTypes = any, OptionalComponents extends keyof ComponentTypes = any> = {
161
- with: ReadonlyArray<WithComponents>;
162
- without?: ReadonlyArray<WithoutComponents>;
163
- changed?: ReadonlyArray<WithComponents>;
164
- optional?: ReadonlyArray<OptionalComponents>;
165
- parentHas?: ReadonlyArray<keyof ComponentTypes>;
166
- };
167
- type QueryResults<ComponentTypes, Queries extends Record<string, QueryDefinition<ComponentTypes>>> = {
168
- [QueryName in keyof Queries]: QueryName extends string ? FilteredEntity<ComponentTypes, Queries[QueryName] extends QueryDefinition<ComponentTypes, infer W, any, any> ? W : never, Queries[QueryName] extends QueryDefinition<ComponentTypes, any, infer WO, any> ? WO : never, Queries[QueryName] extends QueryDefinition<ComponentTypes, any, any, infer O> ? O : never>[] : never;
160
+ export declare function registerSystemWithEcspresso<ComponentTypes extends Record<string, any>, EventTypes extends Record<string, any>, ResourceTypes extends Record<string, any>, AssetTypes extends Record<string, unknown>, ScreenStates extends Record<string, any>>(system: System<ComponentTypes, any, any, EventTypes, ResourceTypes, AssetTypes, ScreenStates>, ecspresso: ECSpresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>): void;
161
+ type QueryResults<ComponentTypes extends Record<string, any>, Queries extends Record<string, QueryDefinition<ComponentTypes>>> = {
162
+ [QueryName in keyof Queries]: QueryName extends string ? FilteredEntity<ComponentTypes, Queries[QueryName] extends QueryDefinition<ComponentTypes, infer W> ? W : never, Queries[QueryName] extends QueryDefinition<ComponentTypes, any, infer WO> ? WO : never, Queries[QueryName] extends QueryDefinition<ComponentTypes, any, any, infer O> ? O : never>[] : never;
169
163
  };
170
164
  /**
171
165
  * Function signature for system process methods
@@ -173,42 +167,42 @@ type QueryResults<ComponentTypes, Queries extends Record<string, QueryDefinition
173
167
  * @param deltaTime Time elapsed since last update in seconds
174
168
  * @param ecs The ECSpresso instance providing access to all ECS functionality
175
169
  */
176
- type ProcessFunction<ComponentTypes extends Record<string, any>, EventTypes extends Record<string, any>, ResourceTypes extends Record<string, any>, Queries extends Record<string, QueryDefinition<ComponentTypes>>> = (queries: QueryResults<ComponentTypes, Queries>, deltaTime: number, ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>) => void;
170
+ type ProcessFunction<ComponentTypes extends Record<string, any>, EventTypes extends Record<string, any>, ResourceTypes extends Record<string, any>, AssetTypes extends Record<string, unknown>, ScreenStates extends Record<string, any>, Queries extends Record<string, QueryDefinition<ComponentTypes>>> = (queries: QueryResults<ComponentTypes, Queries>, deltaTime: number, ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>) => void;
177
171
  /**
178
172
  * Type for system initialization functions
179
173
  * These can be asynchronous
180
174
  */
181
- type LifecycleFunction<ComponentTypes extends Record<string, any>, EventTypes extends Record<string, any>, ResourceTypes extends Record<string, any>> = (ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>) => void | Promise<void>;
175
+ type LifecycleFunction<ComponentTypes extends Record<string, any>, EventTypes extends Record<string, any>, ResourceTypes extends Record<string, any>, AssetTypes extends Record<string, unknown>, ScreenStates extends Record<string, any>> = (ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>) => void | Promise<void>;
182
176
  /**
183
177
  * Create a SystemBuilder attached to an ECSpresso instance
184
178
  * Helper function used by ECSpresso.addSystem
185
179
  */
186
- export declare function createEcspressoSystemBuilder<ComponentTypes extends Record<string, any>, EventTypes extends Record<string, any>, ResourceTypes extends Record<string, any>>(label: string, ecspresso: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>): SystemBuilderWithEcspresso<ComponentTypes, EventTypes, ResourceTypes>;
180
+ export declare function createEcspressoSystemBuilder<ComponentTypes extends Record<string, any>, EventTypes extends Record<string, any>, ResourceTypes extends Record<string, any>, AssetTypes extends Record<string, unknown>, ScreenStates extends Record<string, any>>(label: string, ecspresso: ECSpresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>): SystemBuilderWithEcspresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>;
187
181
  /**
188
182
  * Create a SystemBuilder attached to a Bundle
189
183
  * Helper function used by Bundle.addSystem
190
184
  */
191
- export declare function createBundleSystemBuilder<ComponentTypes extends Record<string, any>, EventTypes extends Record<string, any>, ResourceTypes extends Record<string, any>>(label: string, bundle: Bundle<ComponentTypes, EventTypes, ResourceTypes>): SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes>;
185
+ export declare function createBundleSystemBuilder<ComponentTypes extends Record<string, any>, EventTypes extends Record<string, any>, ResourceTypes extends Record<string, any>, AssetTypes extends Record<string, unknown>, ScreenStates extends Record<string, any>, BundleLabels extends string = never, BundleGroups extends string = never, Label extends string = string, BundleAssetGroupNames extends string = never, BundleReactiveQueryNames extends string = never>(label: Label, bundle: Bundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, BundleLabels, BundleGroups, BundleAssetGroupNames, BundleReactiveQueryNames>): SystemBuilderWithBundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, {}, BundleLabels, BundleGroups, Label, never, BundleAssetGroupNames, BundleReactiveQueryNames>;
192
186
  /**
193
187
  * SystemBuilder with a guaranteed non-null reference to an ECSpresso instance
194
188
  */
195
- export interface SystemBuilderWithEcspresso<ComponentTypes extends Record<string, any>, EventTypes extends Record<string, any>, ResourceTypes extends Record<string, any>, Queries extends Record<string, QueryDefinition<ComponentTypes>> = {}> extends SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries> {
196
- readonly ecspresso: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>;
189
+ export interface SystemBuilderWithEcspresso<ComponentTypes extends Record<string, any>, EventTypes extends Record<string, any>, ResourceTypes extends Record<string, any>, AssetTypes extends Record<string, unknown>, ScreenStates extends Record<string, any>, Queries extends Record<string, QueryDefinition<ComponentTypes>> = {}, Label extends string = string, SysGroups extends string = never> extends SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, Queries, Label, SysGroups> {
190
+ readonly ecspresso: ECSpresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>;
197
191
  /**
198
192
  * Complete this system and return ECSpresso for seamless chaining
199
193
  * Automatically registers the system when called
200
194
  */
201
- and(): ECSpresso<ComponentTypes, EventTypes, ResourceTypes>;
195
+ and(): ECSpresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>;
202
196
  }
203
197
  /**
204
198
  * SystemBuilder with a guaranteed non-null reference to a Bundle
205
199
  */
206
- export interface SystemBuilderWithBundle<ComponentTypes extends Record<string, any>, EventTypes extends Record<string, any>, ResourceTypes extends Record<string, any>, Queries extends Record<string, QueryDefinition<ComponentTypes>> = {}> extends SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, Queries> {
207
- readonly bundle: Bundle<ComponentTypes, EventTypes, ResourceTypes>;
200
+ export interface SystemBuilderWithBundle<ComponentTypes extends Record<string, any>, EventTypes extends Record<string, any>, ResourceTypes extends Record<string, any>, AssetTypes extends Record<string, unknown>, ScreenStates extends Record<string, any>, Queries extends Record<string, QueryDefinition<ComponentTypes>> = {}, BundleLabels extends string = never, BundleGroups extends string = never, Label extends string = string, SysGroups extends string = never, BundleAssetGroupNames extends string = never, BundleReactiveQueryNames extends string = never> extends SystemBuilder<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, Queries, Label, SysGroups, BundleLabels, BundleGroups, BundleAssetGroupNames, BundleReactiveQueryNames> {
201
+ readonly bundle: Bundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, BundleLabels, BundleGroups, BundleAssetGroupNames, BundleReactiveQueryNames>;
208
202
  /**
209
203
  * Complete this system and return the Bundle for chaining
210
204
  * Enables fluent API: bundle.addSystem(...).and().addSystem(...)
211
205
  */
212
- and(): Bundle<ComponentTypes, EventTypes, ResourceTypes>;
206
+ and(): Bundle<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates, BundleLabels | Label, BundleGroups | SysGroups, BundleAssetGroupNames, BundleReactiveQueryNames>;
213
207
  }
214
208
  export {};
@@ -29,7 +29,56 @@ export type Merge<T1, T2> = T1 & T2;
29
29
  * Utility type for merging an array of types
30
30
  */
31
31
  export type MergeAll<T extends any[]> = T extends [infer First, ...infer Rest] ? Rest extends [] ? First : Merge<First, MergeAll<Rest>> : {};
32
- export {};
33
32
  /**
34
- * Basic utility types that can be used independently
35
- */
33
+ * Extract the ComponentTypes from a Bundle instance
34
+ */
35
+ export type ComponentsOf<B> = B extends import('./bundle').default<infer C extends Record<string, any>, any, any, any, any, any, any, any, any> ? C : never;
36
+ /**
37
+ * Extract the EventTypes from a Bundle instance
38
+ */
39
+ export type EventsOf<B> = B extends import('./bundle').default<any, infer E extends Record<string, any>, any, any, any, any, any, any, any> ? E : never;
40
+ /**
41
+ * Extract the ResourceTypes from a Bundle instance
42
+ */
43
+ export type ResourcesOf<B> = B extends import('./bundle').default<any, any, infer R extends Record<string, any>, any, any, any, any, any, any> ? R : never;
44
+ /**
45
+ * Extract the system Labels from a Bundle instance
46
+ */
47
+ export type LabelsOf<B> = B extends import('./bundle').default<any, any, any, any, any, infer L extends string, any, any, any> ? L : never;
48
+ /**
49
+ * Extract the system Groups from a Bundle instance
50
+ */
51
+ export type GroupsOf<B> = B extends import('./bundle').default<any, any, any, any, any, any, infer G extends string, any, any> ? G : never;
52
+ /**
53
+ * Extract the AssetGroupNames from a Bundle instance
54
+ */
55
+ export type AssetGroupNamesOf<B> = B extends import('./bundle').default<any, any, any, any, any, any, any, infer AG extends string, any> ? AG : never;
56
+ /**
57
+ * Extract the ReactiveQueryNames from a Bundle instance
58
+ */
59
+ export type ReactiveQueryNamesOf<B> = B extends import('./bundle').default<any, any, any, any, any, any, any, any, infer RQ extends string> ? RQ : never;
60
+ /**
61
+ * Extract AssetTypes from a Bundle instance
62
+ */
63
+ export type AssetTypesOf<B> = B extends import('./bundle').default<any, any, any, infer A extends Record<string, unknown>, any, any, any, any, any> ? A : never;
64
+ /**
65
+ * Extract ScreenStates from a Bundle instance
66
+ */
67
+ export type ScreenStatesOf<B> = B extends import('./bundle').default<any, any, any, any, infer S extends Record<string, import('./screen-types').ScreenDefinition<any, any>>, any, any, any, any> ? S : never;
68
+ /**
69
+ * Extract ScreenStates from an ECSpresso world instance type
70
+ */
71
+ export type ScreenStatesOfWorld<W> = W extends import('./ecspresso').default<any, any, any, any, infer S extends Record<string, import('./screen-types').ScreenDefinition<any, any>>, any, any, any, any> ? S : never;
72
+ /**
73
+ * Extract ComponentTypes from an ECSpresso world instance type.
74
+ */
75
+ export type ComponentsOfWorld<W> = W extends import('./ecspresso').default<infer C extends Record<string, any>, any, any, any, any, any, any, any, any> ? C : never;
76
+ /**
77
+ * Extract EventTypes from an ECSpresso world instance type.
78
+ */
79
+ export type EventsOfWorld<W> = W extends import('./ecspresso').default<any, infer E extends Record<string, any>, any, any, any, any, any, any, any> ? E : never;
80
+ /**
81
+ * Extract AssetTypes from an ECSpresso world instance type.
82
+ */
83
+ export type AssetsOfWorld<W> = W extends import('./ecspresso').default<any, any, any, infer A extends Record<string, unknown>, any, any, any, any, any> ? A : never;
84
+ export {};
package/dist/types.d.ts CHANGED
@@ -18,17 +18,6 @@ export interface RemoveEntityOptions {
18
18
  */
19
19
  cascade?: boolean;
20
20
  }
21
- /**
22
- * Event data emitted when an entity's parent changes
23
- */
24
- export interface HierarchyChangedEvent {
25
- /** The entity whose parent changed */
26
- entityId: number;
27
- /** The previous parent, or null if entity had no parent */
28
- oldParent: number | null;
29
- /** The new parent, or null if entity was orphaned */
30
- newParent: number | null;
31
- }
32
21
  /**
33
22
  * Options for hierarchy traversal methods
34
23
  */
@@ -47,10 +36,6 @@ export interface HierarchyEntry {
47
36
  /** Depth in the hierarchy (0 for roots) */
48
37
  depth: number;
49
38
  }
50
- export interface EventHandler<T> {
51
- callback: (data: T) => void;
52
- once: boolean;
53
- }
54
39
  export interface FilteredEntity<ComponentTypes, WithComponents extends keyof ComponentTypes = never, WithoutComponents extends keyof ComponentTypes = never, OptionalComponents extends keyof ComponentTypes = never> {
55
40
  id: number;
56
41
  components: Omit<Partial<ComponentTypes>, WithoutComponents | OptionalComponents> & {
@@ -159,17 +144,23 @@ export interface System<ComponentTypes extends Record<string, any> = {}, WithCom
159
144
  * Screens where this system should run. If specified, system only runs
160
145
  * when current screen is in this list.
161
146
  */
162
- inScreens?: string[];
147
+ inScreens?: ReadonlyArray<keyof ScreenStates & string>;
163
148
  /**
164
149
  * Screens where this system should NOT run. If specified, system skips
165
150
  * when current screen is in this list.
166
151
  */
167
- excludeScreens?: string[];
152
+ excludeScreens?: ReadonlyArray<keyof ScreenStates & string>;
168
153
  /**
169
154
  * Assets that must be loaded for this system to run.
170
155
  * System will be skipped if any required asset is not loaded.
171
156
  */
172
- requiredAssets?: string[];
157
+ requiredAssets?: ReadonlyArray<keyof AssetTypes & string>;
158
+ /**
159
+ * When true, the system's process function runs even when all queries
160
+ * return zero entities. Default is false (system is skipped when all
161
+ * queries are empty).
162
+ */
163
+ runWhenEmpty?: boolean;
173
164
  entityQueries?: {
174
165
  [queryName: string]: QueryConfig<ComponentTypes, WithComponents, WithoutComponents>;
175
166
  };
@@ -208,4 +199,4 @@ export interface System<ComponentTypes extends Record<string, any> = {}, WithCom
208
199
  };
209
200
  };
210
201
  }
211
- export type { Merge, MergeAll } from './type-utils';
202
+ export type { Merge, MergeAll, TypesAreCompatible, ComponentsOf, EventsOf, ResourcesOf, LabelsOf, GroupsOf, AssetGroupNamesOf, ReactiveQueryNamesOf, AssetTypesOf, ScreenStatesOf, ComponentsOfWorld, EventsOfWorld, AssetsOfWorld, ScreenStatesOfWorld } from './type-utils';
@@ -0,0 +1,12 @@
1
+ /**
2
+ * BFS cycle detection for required component graphs.
3
+ * Shared by ECSpresso and Bundle.
4
+ *
5
+ * @param trigger The component that triggers the requirement
6
+ * @param newRequired The component about to be added as required
7
+ * @param getRequirements Callback returning the existing requirements for a component
8
+ * @throws Error if adding trigger→newRequired would create a cycle
9
+ */
10
+ export declare function checkRequiredCycle<K>(trigger: K, newRequired: K, getRequirements: (component: K) => Iterable<{
11
+ component: K;
12
+ }> | undefined): void;
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Easing Functions
3
+ *
4
+ * 31 standard easing functions for animation. Pure math, no dependencies.
5
+ */
6
+ export type EasingFn = (t: number) => number;
7
+ export declare function linear(t: number): number;
8
+ export declare function easeInQuad(t: number): number;
9
+ export declare function easeOutQuad(t: number): number;
10
+ export declare function easeInOutQuad(t: number): number;
11
+ export declare function easeInCubic(t: number): number;
12
+ export declare function easeOutCubic(t: number): number;
13
+ export declare function easeInOutCubic(t: number): number;
14
+ export declare function easeInQuart(t: number): number;
15
+ export declare function easeOutQuart(t: number): number;
16
+ export declare function easeInOutQuart(t: number): number;
17
+ export declare function easeInQuint(t: number): number;
18
+ export declare function easeOutQuint(t: number): number;
19
+ export declare function easeInOutQuint(t: number): number;
20
+ export declare function easeInSine(t: number): number;
21
+ export declare function easeOutSine(t: number): number;
22
+ export declare function easeInOutSine(t: number): number;
23
+ export declare function easeInExpo(t: number): number;
24
+ export declare function easeOutExpo(t: number): number;
25
+ export declare function easeInOutExpo(t: number): number;
26
+ export declare function easeInCirc(t: number): number;
27
+ export declare function easeOutCirc(t: number): number;
28
+ export declare function easeInOutCirc(t: number): number;
29
+ export declare function easeInBack(t: number): number;
30
+ export declare function easeOutBack(t: number): number;
31
+ export declare function easeInOutBack(t: number): number;
32
+ export declare function easeInElastic(t: number): number;
33
+ export declare function easeOutElastic(t: number): number;
34
+ export declare function easeInOutElastic(t: number): number;
35
+ export declare function easeOutBounce(t: number): number;
36
+ export declare function easeInBounce(t: number): number;
37
+ export declare function easeInOutBounce(t: number): number;
38
+ /** Runtime lookup of all easing functions by name */
39
+ export declare const easings: {
40
+ readonly linear: typeof linear;
41
+ readonly easeInQuad: typeof easeInQuad;
42
+ readonly easeOutQuad: typeof easeOutQuad;
43
+ readonly easeInOutQuad: typeof easeInOutQuad;
44
+ readonly easeInCubic: typeof easeInCubic;
45
+ readonly easeOutCubic: typeof easeOutCubic;
46
+ readonly easeInOutCubic: typeof easeInOutCubic;
47
+ readonly easeInQuart: typeof easeInQuart;
48
+ readonly easeOutQuart: typeof easeOutQuart;
49
+ readonly easeInOutQuart: typeof easeInOutQuart;
50
+ readonly easeInQuint: typeof easeInQuint;
51
+ readonly easeOutQuint: typeof easeOutQuint;
52
+ readonly easeInOutQuint: typeof easeInOutQuint;
53
+ readonly easeInSine: typeof easeInSine;
54
+ readonly easeOutSine: typeof easeOutSine;
55
+ readonly easeInOutSine: typeof easeInOutSine;
56
+ readonly easeInExpo: typeof easeInExpo;
57
+ readonly easeOutExpo: typeof easeOutExpo;
58
+ readonly easeInOutExpo: typeof easeInOutExpo;
59
+ readonly easeInCirc: typeof easeInCirc;
60
+ readonly easeOutCirc: typeof easeOutCirc;
61
+ readonly easeInOutCirc: typeof easeInOutCirc;
62
+ readonly easeInBack: typeof easeInBack;
63
+ readonly easeOutBack: typeof easeOutBack;
64
+ readonly easeInOutBack: typeof easeInOutBack;
65
+ readonly easeInElastic: typeof easeInElastic;
66
+ readonly easeOutElastic: typeof easeOutElastic;
67
+ readonly easeInOutElastic: typeof easeInOutElastic;
68
+ readonly easeInBounce: typeof easeInBounce;
69
+ readonly easeOutBounce: typeof easeOutBounce;
70
+ readonly easeInOutBounce: typeof easeInOutBounce;
71
+ };
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Shared 2D vector math utilities for ECSpresso bundles.
3
+ * All functions are pure — they return new vectors, never mutate inputs.
4
+ */
5
+ /**
6
+ * A 2D vector with x and y components.
7
+ */
8
+ export interface Vector2D {
9
+ x: number;
10
+ y: number;
11
+ }
12
+ /**
13
+ * Create a Vector2D from x and y components.
14
+ */
15
+ export declare function vec2(x: number, y: number): Vector2D;
16
+ /**
17
+ * Return a zero vector {x: 0, y: 0}.
18
+ */
19
+ export declare function vec2Zero(): Vector2D;
20
+ /**
21
+ * Add two vectors component-wise.
22
+ */
23
+ export declare function vec2Add(a: Vector2D, b: Vector2D): Vector2D;
24
+ /**
25
+ * Subtract b from a component-wise.
26
+ */
27
+ export declare function vec2Sub(a: Vector2D, b: Vector2D): Vector2D;
28
+ /**
29
+ * Scale a vector by a scalar.
30
+ */
31
+ export declare function vec2Scale(v: Vector2D, scalar: number): Vector2D;
32
+ /**
33
+ * Negate a vector (flip both components).
34
+ */
35
+ export declare function vec2Negate(v: Vector2D): Vector2D;
36
+ /**
37
+ * Compute the dot product of two vectors.
38
+ */
39
+ export declare function vec2Dot(a: Vector2D, b: Vector2D): number;
40
+ /**
41
+ * Compute the 2D cross product (scalar z-component of the 3D cross product).
42
+ */
43
+ export declare function vec2Cross(a: Vector2D, b: Vector2D): number;
44
+ /**
45
+ * Compute the squared length of a vector. Avoids sqrt when only comparing magnitudes.
46
+ */
47
+ export declare function vec2LengthSq(v: Vector2D): number;
48
+ /**
49
+ * Compute the length (magnitude) of a vector.
50
+ */
51
+ export declare function vec2Length(v: Vector2D): number;
52
+ /**
53
+ * Return a unit vector in the same direction. Returns zero vector if input is zero-length.
54
+ */
55
+ export declare function vec2Normalize(v: Vector2D): Vector2D;
56
+ /**
57
+ * Compute the squared distance between two points. Avoids sqrt when only comparing.
58
+ */
59
+ export declare function vec2DistanceSq(a: Vector2D, b: Vector2D): number;
60
+ /**
61
+ * Compute the distance between two points.
62
+ */
63
+ export declare function vec2Distance(a: Vector2D, b: Vector2D): number;
64
+ /**
65
+ * Check if two vectors are approximately equal within an epsilon tolerance.
66
+ */
67
+ export declare function vec2Equals(a: Vector2D, b: Vector2D, epsilon?: number): boolean;
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Shared Narrowphase Module
3
+ *
4
+ * Provides contact-computing narrowphase tests and a generic collision
5
+ * iteration pipeline used by both the collision bundle (event-only) and
6
+ * the physics2D bundle (impulse response).
7
+ */
8
+ import type { SpatialIndex } from './spatial-hash';
9
+ /** Contact result from a narrowphase test. Normal points from A toward B. */
10
+ export interface Contact {
11
+ normalX: number;
12
+ normalY: number;
13
+ /** Penetration depth (positive = overlapping) */
14
+ depth: number;
15
+ }
16
+ /** Minimum collider data shared by collision and physics bundles. */
17
+ export interface BaseColliderInfo<L extends string = string> {
18
+ entityId: number;
19
+ x: number;
20
+ y: number;
21
+ layer: L;
22
+ collidesWith: readonly L[];
23
+ aabb?: {
24
+ halfWidth: number;
25
+ halfHeight: number;
26
+ };
27
+ circle?: {
28
+ radius: number;
29
+ };
30
+ }
31
+ /**
32
+ * Build a BaseColliderInfo from raw entity/collider component data.
33
+ * Returns null if the entity has neither an AABB nor circle collider.
34
+ * Shared by collision bundle (event-only) and physics2D bundle (impulse response).
35
+ */
36
+ export declare function buildBaseColliderInfo<L extends string>(entityId: number, x: number, y: number, layer: L, collidesWith: readonly L[], aabb: {
37
+ width: number;
38
+ height: number;
39
+ offsetX?: number;
40
+ offsetY?: number;
41
+ } | undefined, circle: {
42
+ radius: number;
43
+ offsetX?: number;
44
+ offsetY?: number;
45
+ } | undefined): BaseColliderInfo<L> | null;
46
+ /**
47
+ * Retrieve the optional spatialIndex resource, returning null when absent.
48
+ * Centralizes the cross-bundle typed lookup so individual bundles don't each
49
+ * need to import SpatialIndex or repeat the tryGetResource pattern.
50
+ */
51
+ export declare function tryGetSpatialIndex(tryGetResource: <T>(key: string) => T | undefined): SpatialIndex | null;
52
+ export declare function computeAABBvsAABB(ax: number, ay: number, ahw: number, ahh: number, bx: number, by: number, bhw: number, bhh: number): Contact | null;
53
+ export declare function computeCircleVsCircle(ax: number, ay: number, ar: number, bx: number, by: number, br: number): Contact | null;
54
+ export declare function computeAABBvsCircle(aabbX: number, aabbY: number, ahw: number, ahh: number, circleX: number, circleY: number, radius: number): Contact | null;
55
+ export declare function computeContact(a: BaseColliderInfo, b: BaseColliderInfo): Contact | null;
56
+ /**
57
+ * Generic collision detection pipeline: brute-force or broadphase,
58
+ * with layer filtering and contact computation.
59
+ *
60
+ * Uses a context parameter forwarded to the callback to avoid
61
+ * per-frame closure allocation.
62
+ */
63
+ export declare function detectCollisions<I extends BaseColliderInfo, C>(colliders: I[], spatialIndex: SpatialIndex | null, onContact: (a: I, b: I, contact: Contact, context: C) => void, context: C): void;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Spatial Hash Grid
3
+ *
4
+ * Uniform-grid spatial hash for broadphase collision detection and
5
+ * proximity queries. Pure data structure, no ECS dependencies.
6
+ */
7
+ export interface SpatialEntry {
8
+ entityId: number;
9
+ x: number;
10
+ y: number;
11
+ halfW: number;
12
+ halfH: number;
13
+ }
14
+ export interface SpatialHashGrid {
15
+ cellSize: number;
16
+ invCellSize: number;
17
+ cells: Map<number, number[]>;
18
+ entries: Map<number, SpatialEntry>;
19
+ }
20
+ /**
21
+ * Hash a cell coordinate pair to a single integer key.
22
+ * Uses large-prime XOR to distribute values.
23
+ */
24
+ export declare function hashCell(cx: number, cy: number): number;
25
+ /**
26
+ * Create a new empty spatial hash grid.
27
+ */
28
+ export declare function createGrid(cellSize: number): SpatialHashGrid;
29
+ /**
30
+ * Clear all data from the grid without reallocating the Maps.
31
+ */
32
+ export declare function clearGrid(grid: SpatialHashGrid): void;
33
+ /**
34
+ * Insert an entity into all overlapping cells of the grid.
35
+ */
36
+ export declare function insertEntity(grid: SpatialHashGrid, entityId: number, x: number, y: number, halfW: number, halfH: number): void;
37
+ /**
38
+ * Collect entity IDs from all cells overlapping the given rectangle.
39
+ */
40
+ export declare function gridQueryRect(grid: SpatialHashGrid, minX: number, minY: number, maxX: number, maxY: number, result: Set<number>): void;
41
+ /**
42
+ * Collect entity IDs within a circle. Uses rect broadphase then
43
+ * AABB-to-point distance filter.
44
+ */
45
+ export declare function gridQueryRadius(grid: SpatialHashGrid, cx: number, cy: number, radius: number, result: Set<number>): void;
46
+ export interface SpatialIndex {
47
+ readonly grid: SpatialHashGrid;
48
+ queryRect(minX: number, minY: number, maxX: number, maxY: number): number[];
49
+ queryRectInto(minX: number, minY: number, maxX: number, maxY: number, result: Set<number>): void;
50
+ queryRadius(cx: number, cy: number, radius: number): number[];
51
+ queryRadiusInto(cx: number, cy: number, radius: number, result: Set<number>): void;
52
+ getEntry(entityId: number): SpatialEntry | undefined;
53
+ }