ecspresso 0.4.3 → 0.5.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.
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Screen/State management for ECSpresso ECS framework
3
+ */
4
+ import type EventBus from './event-bus';
5
+ import type AssetManager from './asset-manager';
6
+ import type ECSpresso from './ecspresso';
7
+ import type { ScreenDefinition, ScreenResource, ScreenEvents, ScreenConfigurator } from './screen-types';
8
+ /**
9
+ * Manages screen/state transitions for ECSpresso
10
+ */
11
+ export default class ScreenManager<Screens extends Record<string, ScreenDefinition<any, any>> = Record<string, never>> {
12
+ private readonly screens;
13
+ private currentScreen;
14
+ private screenStack;
15
+ private eventBus;
16
+ private assetManager;
17
+ private ecs;
18
+ /**
19
+ * Set dependencies for screen transitions
20
+ * @internal
21
+ */
22
+ setDependencies(eventBus: EventBus<ScreenEvents>, assetManager: AssetManager<any> | null, ecs: ECSpresso<any, any, any, any, any>): void;
23
+ /**
24
+ * Register a screen definition
25
+ */
26
+ register<K extends string, Config extends Record<string, unknown>, State extends Record<string, unknown>>(name: K, definition: ScreenDefinition<Config, State>): void;
27
+ /**
28
+ * Transition to a new screen, clearing the stack
29
+ */
30
+ setScreen<K extends keyof Screens>(name: K, config: Screens[K] extends ScreenDefinition<infer C, any> ? C : never): Promise<void>;
31
+ /**
32
+ * Push a screen onto the stack (overlay)
33
+ */
34
+ pushScreen<K extends keyof Screens>(name: K, config: Screens[K] extends ScreenDefinition<infer C, any> ? C : never): Promise<void>;
35
+ /**
36
+ * Pop the current screen and return to the previous one
37
+ */
38
+ popScreen(): Promise<void>;
39
+ /**
40
+ * Exit a screen by name (internal helper)
41
+ */
42
+ private exitScreen;
43
+ /**
44
+ * Verify required assets are loaded before screen transition
45
+ */
46
+ private verifyRequiredAssets;
47
+ /**
48
+ * Get the current screen name
49
+ */
50
+ getCurrentScreen(): keyof Screens | null;
51
+ /**
52
+ * Get the current screen config (immutable)
53
+ */
54
+ getConfig<K extends keyof Screens>(): Screens[K] extends ScreenDefinition<infer C, any> ? Readonly<C> : never;
55
+ /**
56
+ * Get the current screen config or null
57
+ */
58
+ getConfigOrNull<K extends keyof Screens>(): (Screens[K] extends ScreenDefinition<infer C, any> ? Readonly<C> : never) | null;
59
+ /**
60
+ * Get the current screen state (mutable)
61
+ */
62
+ getState<K extends keyof Screens>(): Screens[K] extends ScreenDefinition<any, infer S> ? S : never;
63
+ /**
64
+ * Get the current screen state or null
65
+ */
66
+ getStateOrNull<K extends keyof Screens>(): (Screens[K] extends ScreenDefinition<any, infer S> ? S : never) | null;
67
+ /**
68
+ * Update the current screen state
69
+ */
70
+ updateState<K extends keyof Screens>(update: Partial<Screens[K] extends ScreenDefinition<any, infer S> ? S : never> | ((current: Screens[K] extends ScreenDefinition<any, infer S> ? S : never) => Partial<Screens[K] extends ScreenDefinition<any, infer S> ? S : never>)): void;
71
+ /**
72
+ * Get the screen stack depth
73
+ */
74
+ getStackDepth(): number;
75
+ /**
76
+ * Check if current screen is an overlay
77
+ */
78
+ isOverlay(): boolean;
79
+ /**
80
+ * Check if a screen is active (current or in stack)
81
+ */
82
+ isActive(screenName: keyof Screens): boolean;
83
+ /**
84
+ * Check if a screen is the current screen
85
+ */
86
+ isCurrent(screenName: keyof Screens): boolean;
87
+ /**
88
+ * Create the $screen resource object
89
+ */
90
+ createResource(): ScreenResource<Screens>;
91
+ /**
92
+ * Get all registered screen names
93
+ */
94
+ getScreenNames(): Array<keyof Screens>;
95
+ /**
96
+ * Check if a screen is registered
97
+ */
98
+ hasScreen(name: keyof Screens): boolean;
99
+ }
100
+ /**
101
+ * Implementation of ScreenConfigurator for builder pattern
102
+ */
103
+ export declare class ScreenConfiguratorImpl<Screens extends Record<string, ScreenDefinition<any, any>>> implements ScreenConfigurator<Screens> {
104
+ private readonly manager;
105
+ constructor(manager: ScreenManager<Screens>);
106
+ add<K extends string, Config extends Record<string, unknown>, State extends Record<string, unknown>>(name: K, definition: ScreenDefinition<Config, State>): ScreenConfigurator<Screens & Record<K, ScreenDefinition<Config, State>>>;
107
+ /**
108
+ * Get the underlying manager
109
+ * @internal
110
+ */
111
+ getManager(): ScreenManager<Screens>;
112
+ }
113
+ /**
114
+ * Create a new ScreenConfigurator for builder pattern usage
115
+ */
116
+ export declare function createScreenConfigurator<Screens extends Record<string, ScreenDefinition<any, any>> = Record<string, never>>(manager?: ScreenManager<Screens>): ScreenConfiguratorImpl<Screens>;
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Screen/State management types for ECSpresso ECS framework
3
+ */
4
+ import type ECSpresso from './ecspresso';
5
+ /**
6
+ * Definition for a screen including its state, lifecycle hooks, and requirements
7
+ */
8
+ export interface ScreenDefinition<Config extends Record<string, unknown> = Record<string, never>, State extends Record<string, unknown> = Record<string, never>> {
9
+ /**
10
+ * Function to create initial state from config
11
+ */
12
+ readonly initialState: (config: Config) => State;
13
+ /**
14
+ * Lifecycle hook called when entering this screen
15
+ */
16
+ readonly onEnter?: (config: Config, ecs: ECSpresso<any, any, any, any, any>) => void | Promise<void>;
17
+ /**
18
+ * Lifecycle hook called when exiting this screen
19
+ */
20
+ readonly onExit?: (ecs: ECSpresso<any, any, any, any, any>) => void | Promise<void>;
21
+ /**
22
+ * Asset keys that must be loaded before entering this screen
23
+ */
24
+ readonly requiredAssets?: ReadonlyArray<string>;
25
+ /**
26
+ * Asset groups that must be loaded before entering this screen
27
+ */
28
+ readonly requiredAssetGroups?: ReadonlyArray<string>;
29
+ }
30
+ /**
31
+ * Entry in the screen stack for overlay support
32
+ */
33
+ export interface ScreenStackEntry<Screens extends Record<string, ScreenDefinition<any, any>>, K extends keyof Screens = keyof Screens> {
34
+ readonly name: K;
35
+ readonly config: Screens[K] extends ScreenDefinition<infer C, any> ? Readonly<C> : never;
36
+ state: Screens[K] extends ScreenDefinition<any, infer S> ? S : never;
37
+ }
38
+ /**
39
+ * Helper to extract config type from a screen definition
40
+ */
41
+ export type ScreenConfig<S extends ScreenDefinition<any, any>> = S extends ScreenDefinition<infer C, any> ? C : never;
42
+ /**
43
+ * Helper to extract state type from a screen definition
44
+ */
45
+ export type ScreenState<S extends ScreenDefinition<any, any>> = S extends ScreenDefinition<any, infer St> ? St : never;
46
+ /**
47
+ * Resource interface for accessing screen state in systems
48
+ * Exposed as $screen resource
49
+ */
50
+ export interface ScreenResource<Screens extends Record<string, ScreenDefinition<any, any>>> {
51
+ /**
52
+ * Current active screen name, or null if no screen
53
+ */
54
+ readonly current: keyof Screens | null;
55
+ /**
56
+ * Immutable config of the current screen
57
+ */
58
+ readonly config: Readonly<ScreenConfig<Screens[keyof Screens]>> | null;
59
+ /**
60
+ * Mutable state of the current screen
61
+ */
62
+ state: ScreenState<Screens[keyof Screens]> | null;
63
+ /**
64
+ * The screen stack (read-only view)
65
+ */
66
+ readonly stack: ReadonlyArray<ScreenStackEntry<Screens>>;
67
+ /**
68
+ * Whether the current screen is an overlay (has screens beneath it)
69
+ */
70
+ readonly isOverlay: boolean;
71
+ /**
72
+ * Current depth of the screen stack
73
+ */
74
+ readonly stackDepth: number;
75
+ /**
76
+ * Check if a specific screen is currently active (either current or in stack)
77
+ */
78
+ isActive(screenName: keyof Screens): boolean;
79
+ /**
80
+ * Check if a specific screen is the current screen
81
+ */
82
+ isCurrent(screenName: keyof Screens): boolean;
83
+ }
84
+ /**
85
+ * Events emitted by the screen system
86
+ */
87
+ export interface ScreenEvents {
88
+ screenEnter: {
89
+ screen: string;
90
+ config: unknown;
91
+ };
92
+ screenExit: {
93
+ screen: string;
94
+ };
95
+ screenPush: {
96
+ screen: string;
97
+ config: unknown;
98
+ };
99
+ screenPop: {
100
+ screen: string;
101
+ };
102
+ }
103
+ /**
104
+ * Configuration for screen definitions during builder setup
105
+ */
106
+ export interface ScreenConfigurator<Screens extends Record<string, ScreenDefinition<any, any>>> {
107
+ /**
108
+ * Add a screen definition
109
+ */
110
+ add<K extends string, Config extends Record<string, unknown>, State extends Record<string, unknown>>(name: K, definition: ScreenDefinition<Config, State>): ScreenConfigurator<Screens & Record<K, ScreenDefinition<Config, State>>>;
111
+ }
112
+ /**
113
+ * Type-safe screen state getter result
114
+ */
115
+ export type CurrentScreenState<Screens extends Record<string, ScreenDefinition<any, any>>, CurrentScreen extends keyof Screens> = Screens[CurrentScreen] extends ScreenDefinition<any, infer S> ? S : never;
116
+ /**
117
+ * Type-safe screen config getter result
118
+ */
119
+ export type CurrentScreenConfig<Screens extends Record<string, ScreenDefinition<any, any>>, CurrentScreen extends keyof Screens> = Screens[CurrentScreen] extends ScreenDefinition<infer C, any> ? Readonly<C> : never;
@@ -15,16 +15,19 @@ export declare class SystemBuilder<ComponentTypes extends Record<string, any> =
15
15
  private eventHandlers?;
16
16
  private _priority;
17
17
  private _isRegistered;
18
+ private _inScreens?;
19
+ private _excludeScreens?;
20
+ private _requiredAssets?;
18
21
  constructor(_label: string, _ecspresso?: ECSpresso<ComponentTypes, EventTypes, ResourceTypes> | null, _bundle?: Bundle<ComponentTypes, EventTypes, ResourceTypes> | null);
19
22
  get label(): string;
20
23
  /**
21
24
  * Returns the associated bundle if one was provided in the constructor
22
25
  */
23
- get bundle(): Bundle<ComponentTypes, EventTypes, ResourceTypes> | null;
26
+ get bundle(): Bundle<ComponentTypes, EventTypes, ResourceTypes, {}, {}> | null;
24
27
  /**
25
28
  * Returns the associated ECSpresso instance if one was provided in the constructor
26
29
  */
27
- get ecspresso(): ECSpresso<ComponentTypes, EventTypes, ResourceTypes> | null;
30
+ get ecspresso(): ECSpresso<ComponentTypes, EventTypes, ResourceTypes, {}, {}> | null;
28
31
  /**
29
32
  * Auto-register this system with its ECSpresso instance if not already registered
30
33
  * @private
@@ -48,6 +51,30 @@ export declare class SystemBuilder<ComponentTypes extends Record<string, any> =
48
51
  * @returns This SystemBuilder instance for method chaining
49
52
  */
50
53
  setPriority(priority: number): this;
54
+ /**
55
+ * Restrict this system to only run in specified screens.
56
+ * System will be skipped during update() when the current screen
57
+ * is not in this list.
58
+ * @param screens Array of screen names where this system should run
59
+ * @returns This SystemBuilder instance for method chaining
60
+ */
61
+ inScreens(screens: ReadonlyArray<string>): this;
62
+ /**
63
+ * Exclude this system from running in specified screens.
64
+ * System will be skipped during update() when the current screen
65
+ * is in this list.
66
+ * @param screens Array of screen names where this system should NOT run
67
+ * @returns This SystemBuilder instance for method chaining
68
+ */
69
+ excludeScreens(screens: ReadonlyArray<string>): this;
70
+ /**
71
+ * Require specific assets to be loaded for this system to run.
72
+ * System will be skipped during update() if any required asset
73
+ * is not loaded.
74
+ * @param assets Array of asset keys that must be loaded
75
+ * @returns This SystemBuilder instance for method chaining
76
+ */
77
+ requiresAssets(assets: ReadonlyArray<string>): this;
51
78
  /**
52
79
  * Add a query definition to the system
53
80
  */
package/dist/types.d.ts CHANGED
@@ -3,6 +3,26 @@ export interface Entity<ComponentTypes> {
3
3
  id: number;
4
4
  components: Partial<ComponentTypes>;
5
5
  }
6
+ /**
7
+ * Options for removing an entity
8
+ */
9
+ export interface RemoveEntityOptions {
10
+ /**
11
+ * Whether to also remove all descendants (default: true)
12
+ */
13
+ cascade?: boolean;
14
+ }
15
+ /**
16
+ * Event data emitted when an entity's parent changes
17
+ */
18
+ export interface HierarchyChangedEvent {
19
+ /** The entity whose parent changed */
20
+ entityId: number;
21
+ /** The previous parent, or null if entity had no parent */
22
+ oldParent: number | null;
23
+ /** The new parent, or null if entity was orphaned */
24
+ newParent: number | null;
25
+ }
6
26
  export interface EventHandler<T> {
7
27
  callback: (data: T) => void;
8
28
  once: boolean;
@@ -80,13 +100,28 @@ export declare function createQueryDefinition<ComponentTypes extends Record<stri
80
100
  with: ReadonlyArray<keyof ComponentTypes>;
81
101
  without?: ReadonlyArray<keyof ComponentTypes>;
82
102
  }>(queryDef: QueryDef): QueryDef;
83
- export interface System<ComponentTypes extends Record<string, any> = {}, WithComponents extends keyof ComponentTypes = never, WithoutComponents extends keyof ComponentTypes = never, EventTypes extends Record<string, any> = {}, ResourceTypes extends Record<string, any> = {}> {
103
+ export interface System<ComponentTypes extends Record<string, any> = {}, WithComponents extends keyof ComponentTypes = never, WithoutComponents extends keyof ComponentTypes = never, EventTypes extends Record<string, any> = {}, ResourceTypes extends Record<string, any> = {}, AssetTypes extends Record<string, unknown> = {}, ScreenStates extends Record<string, any> = {}> {
84
104
  label: string;
85
105
  /**
86
106
  * System priority - higher values execute first (default: 0)
87
107
  * When systems have the same priority, they execute in registration order
88
108
  */
89
109
  priority?: number;
110
+ /**
111
+ * Screens where this system should run. If specified, system only runs
112
+ * when current screen is in this list.
113
+ */
114
+ inScreens?: string[];
115
+ /**
116
+ * Screens where this system should NOT run. If specified, system skips
117
+ * when current screen is in this list.
118
+ */
119
+ excludeScreens?: string[];
120
+ /**
121
+ * Assets that must be loaded for this system to run.
122
+ * System will be skipped if any required asset is not loaded.
123
+ */
124
+ requiredAssets?: string[];
90
125
  entityQueries?: {
91
126
  [queryName: string]: QueryConfig<ComponentTypes, WithComponents, WithoutComponents>;
92
127
  };
@@ -98,19 +133,19 @@ export interface System<ComponentTypes extends Record<string, any> = {}, WithCom
98
133
  */
99
134
  process?(queries: {
100
135
  [queryName: string]: Array<FilteredEntity<ComponentTypes, WithComponents, WithoutComponents>>;
101
- } | Array<FilteredEntity<ComponentTypes, WithComponents, WithoutComponents>>, deltaTime: number, ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>): void;
136
+ } | Array<FilteredEntity<ComponentTypes, WithComponents, WithoutComponents>>, deltaTime: number, ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>): void;
102
137
  /**
103
138
  * Lifecycle hook called when the system is initialized
104
139
  * This is called when ECSpresso.initialize() is invoked, after resources are initialized
105
140
  * Use this for one-time initialization that depends on resources
106
141
  * @param ecs The ECSpresso instance providing access to all ECS functionality
107
142
  */
108
- onInitialize?(ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>): void | Promise<void>;
143
+ onInitialize?(ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>): void | Promise<void>;
109
144
  /**
110
145
  * Lifecycle hook called when the system is detached from the ECS
111
146
  * @param ecs The ECSpresso instance providing access to all ECS functionality
112
147
  */
113
- onDetach?(ecs: import("./ecspresso").default<ComponentTypes, EventTypes, ResourceTypes>): void;
148
+ onDetach?(ecs: import("./ecspresso").default<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>): void;
114
149
  /**
115
150
  * Event handlers for specific event types
116
151
  */
@@ -121,7 +156,7 @@ export interface System<ComponentTypes extends Record<string, any> = {}, WithCom
121
156
  * @param data The event data specific to this event type
122
157
  * @param ecs The ECSpresso instance providing access to all ECS functionality
123
158
  */
124
- handler(data: EventTypes[EventName], ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes>): void;
159
+ handler(data: EventTypes[EventName], ecs: ECSpresso<ComponentTypes, EventTypes, ResourceTypes, AssetTypes, ScreenStates>): void;
125
160
  };
126
161
  };
127
162
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ecspresso",
3
- "version": "0.4.3",
3
+ "version": "0.5.0",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.js",
6
6
  "types": "dist/index.d.ts",