@@ -22,6 +22,21 @@ export interface ComponentLifecycleHook<T> {
2222 onRemoved ?: ( entityId : EntityId , componentType : EntityId < T > ) => void ;
2323}
2424
25+ /**
26+ * Hook types for wildcard relation lifecycle events
27+ * These hooks are triggered for any component that matches a wildcard relation pattern
28+ */
29+ export interface WildcardRelationLifecycleHook < T = unknown > {
30+ /**
31+ * Called when any component matching the wildcard relation pattern is added to an entity
32+ */
33+ onAdded ?: ( entityId : EntityId , componentType : EntityId < T > , component : T ) => void ;
34+ /**
35+ * Called when any component matching the wildcard relation pattern is removed from an entity
36+ */
37+ onRemoved ?: ( entityId : EntityId , componentType : EntityId < T > ) => void ;
38+ }
39+
2540/**
2641 * World class for ECS architecture
2742 * Manages entities, components, and systems
@@ -41,6 +56,12 @@ export class World<ExtraParams extends any[] = [deltaTime: number]> {
4156 */
4257 private componentLifecycleHooks = new Map < EntityId < any > , Set < ComponentLifecycleHook < any > > > ( ) ;
4358
59+ /**
60+ * Hook storage for wildcard relation lifecycle events
61+ * Maps base component type to set of wildcard relation hooks
62+ */
63+ private wildcardRelationLifecycleHooks = new Map < EntityId < any > , Set < WildcardRelationLifecycleHook > > ( ) ;
64+
4465 /**
4566 * Reverse index tracking which entities use each entity as a component type
4667 * Maps entity ID to set of {sourceEntityId, componentType} pairs where componentType uses this entity
@@ -219,6 +240,30 @@ export class World<ExtraParams extends any[] = [deltaTime: number]> {
219240 }
220241 }
221242
243+ /**
244+ * Register a lifecycle hook for wildcard relation events
245+ * The hook will be triggered for any component that matches the wildcard relation pattern
246+ */
247+ registerWildcardRelationLifecycleHook < T > ( baseComponentType : EntityId < T > , hook : WildcardRelationLifecycleHook < T > ) : void {
248+ if ( ! this . wildcardRelationLifecycleHooks . has ( baseComponentType ) ) {
249+ this . wildcardRelationLifecycleHooks . set ( baseComponentType , new Set ( ) ) ;
250+ }
251+ this . wildcardRelationLifecycleHooks . get ( baseComponentType ) ! . add ( hook as WildcardRelationLifecycleHook < any > ) ;
252+ }
253+
254+ /**
255+ * Unregister a lifecycle hook for wildcard relation events
256+ */
257+ unregisterWildcardRelationLifecycleHook < T > ( baseComponentType : EntityId < T > , hook : WildcardRelationLifecycleHook < T > ) : void {
258+ const hooks = this . wildcardRelationLifecycleHooks . get ( baseComponentType ) ;
259+ if ( hooks ) {
260+ hooks . delete ( hook as WildcardRelationLifecycleHook < any > ) ;
261+ if ( hooks . size === 0 ) {
262+ this . wildcardRelationLifecycleHooks . delete ( baseComponentType ) ;
263+ }
264+ }
265+ }
266+
222267 /**
223268 * Update the world (run all systems)
224269 */
@@ -616,6 +661,19 @@ export class World<ExtraParams extends any[] = [deltaTime: number]> {
616661 }
617662 }
618663 }
664+
665+ // Trigger wildcard relation hooks for added components
666+ const detailedType = getDetailedIdType ( componentType ) ;
667+ if ( detailedType . type === "entity-relation" || detailedType . type === "component-relation" || detailedType . type === "wildcard-relation" ) {
668+ const wildcardHooks = this . wildcardRelationLifecycleHooks . get ( detailedType . componentId ! ) ;
669+ if ( wildcardHooks ) {
670+ for ( const hook of wildcardHooks ) {
671+ if ( hook . onAdded ) {
672+ ( hook as any ) . onAdded ( entityId , componentType , component ) ;
673+ }
674+ }
675+ }
676+ }
619677 }
620678
621679 // Trigger component removed hooks
@@ -628,6 +686,19 @@ export class World<ExtraParams extends any[] = [deltaTime: number]> {
628686 }
629687 }
630688 }
689+
690+ // Trigger wildcard relation hooks for removed components
691+ const detailedType = getDetailedIdType ( componentType ) ;
692+ if ( detailedType . type === "entity-relation" || detailedType . type === "component-relation" || detailedType . type === "wildcard-relation" ) {
693+ const wildcardHooks = this . wildcardRelationLifecycleHooks . get ( detailedType . componentId ! ) ;
694+ if ( wildcardHooks ) {
695+ for ( const hook of wildcardHooks ) {
696+ if ( hook . onRemoved ) {
697+ ( hook as any ) . onRemoved ( entityId , componentType ) ;
698+ }
699+ }
700+ }
701+ }
631702 }
632703 }
633704}
0 commit comments