@@ -22,6 +22,12 @@ export class World<ExtraParams extends any[] = [deltaTime: number]> {
2222 private commandBuffer : CommandBuffer ;
2323 private componentToArchetypes = new Map < EntityId < any > , Archetype [ ] > ( ) ;
2424
25+ /**
26+ * Reverse index tracking which entities have relation components pointing to each target entity
27+ * Maps target entity ID to set of {sourceEntityId, relationType} pairs
28+ */
29+ private relationReverseIndex = new Map < EntityId , Set < { sourceEntityId : EntityId ; relationType : EntityId } > > ( ) ;
30+
2531 constructor ( ) {
2632 this . commandBuffer = new CommandBuffer ( ( entityId , commands ) => this . executeEntityCommands ( entityId , commands ) ) ;
2733 }
@@ -54,6 +60,41 @@ export class World<ExtraParams extends any[] = [deltaTime: number]> {
5460 return ; // Entity doesn't exist, nothing to do
5561 }
5662
63+ // Clean up relation components pointing to this entity
64+ const relationReferences = this . getRelationReferences ( entityId ) ;
65+ for ( const { sourceEntityId, relationType } of relationReferences ) {
66+ // Directly remove the relation component from the source entity
67+ const sourceArchetype = this . entityToArchetype . get ( sourceEntityId ) ;
68+ if ( sourceArchetype && sourceArchetype . componentTypes . includes ( relationType ) ) {
69+ // Remove from current archetype and move to new archetype without this component
70+ const currentComponents = new Map < EntityId < any > , any > ( ) ;
71+ for ( const componentType of sourceArchetype . componentTypes ) {
72+ if ( componentType !== relationType ) {
73+ const data = sourceArchetype . getComponent ( sourceEntityId , componentType ) ;
74+ if ( data !== undefined ) {
75+ currentComponents . set ( componentType , data ) ;
76+ }
77+ }
78+ }
79+
80+ const newComponentTypes = Array . from ( currentComponents . keys ( ) ) . sort ( ( a , b ) => a - b ) ;
81+ const newArchetype = this . getOrCreateArchetype ( newComponentTypes ) ;
82+
83+ // Remove from current archetype
84+ sourceArchetype . removeEntity ( sourceEntityId ) ;
85+
86+ // Add to new archetype
87+ newArchetype . addEntity ( sourceEntityId , currentComponents ) ;
88+ this . entityToArchetype . set ( sourceEntityId , newArchetype ) ;
89+
90+ // Remove from relation reverse index
91+ this . removeRelationReference ( sourceEntityId , relationType , entityId ) ;
92+ }
93+ }
94+
95+ // Clean up the reverse index for this entity
96+ this . relationReverseIndex . delete ( entityId ) ;
97+
5798 archetype . removeEntity ( entityId ) ;
5899 this . entityToArchetype . delete ( entityId ) ;
59100 this . entityIdManager . deallocate ( entityId ) ;
@@ -367,6 +408,24 @@ export class World<ExtraParams extends any[] = [deltaTime: number]> {
367408 }
368409 // Removals are already handled by not including them in finalComponents
369410 }
411+
412+ // Update relation reverse index for removed components
413+ for ( const componentType of removes ) {
414+ const detailedType = getDetailedIdType ( componentType ) ;
415+ if ( detailedType . type === "entity-relation" ) {
416+ const targetEntityId = detailedType . targetId ! ;
417+ this . removeRelationReference ( entityId , componentType , targetEntityId ) ;
418+ }
419+ }
420+
421+ // Update relation reverse index for added components
422+ for ( const [ componentType , component ] of adds ) {
423+ const detailedType = getDetailedIdType ( componentType ) ;
424+ if ( detailedType . type === "entity-relation" ) {
425+ const targetEntityId = detailedType . targetId ! ;
426+ this . addRelationReference ( entityId , componentType , targetEntityId ) ;
427+ }
428+ }
370429 }
371430
372431 /**
@@ -396,4 +455,47 @@ export class World<ExtraParams extends any[] = [deltaTime: number]> {
396455 return newArchetype ;
397456 } ) ;
398457 }
458+
459+ /**
460+ * Add a relation reference to the reverse index
461+ * @param sourceEntityId The entity that has the relation component
462+ * @param relationType The relation component type
463+ * @param targetEntityId The entity being pointed to
464+ */
465+ private addRelationReference ( sourceEntityId : EntityId , relationType : EntityId , targetEntityId : EntityId ) : void {
466+ if ( ! this . relationReverseIndex . has ( targetEntityId ) ) {
467+ this . relationReverseIndex . set ( targetEntityId , new Set ( ) ) ;
468+ }
469+ this . relationReverseIndex . get ( targetEntityId ) ! . add ( { sourceEntityId, relationType } ) ;
470+ }
471+
472+ /**
473+ * Remove a relation reference from the reverse index
474+ * @param sourceEntityId The entity that has the relation component
475+ * @param relationType The relation component type
476+ * @param targetEntityId The entity being pointed to
477+ */
478+ private removeRelationReference ( sourceEntityId : EntityId , relationType : EntityId , targetEntityId : EntityId ) : void {
479+ const references = this . relationReverseIndex . get ( targetEntityId ) ;
480+ if ( references ) {
481+ references . forEach ( ref => {
482+ if ( ref . sourceEntityId === sourceEntityId && ref . relationType === relationType ) {
483+ references . delete ( ref ) ;
484+ }
485+ } ) ;
486+ if ( references . size === 0 ) {
487+ this . relationReverseIndex . delete ( targetEntityId ) ;
488+ }
489+ }
490+ }
491+
492+ /**
493+ * Get all relation references pointing to a target entity
494+ * @param targetEntityId The target entity
495+ * @returns Array of {sourceEntityId, relationType} pairs
496+ */
497+ private getRelationReferences ( targetEntityId : EntityId ) : Array < { sourceEntityId : EntityId ; relationType : EntityId } > {
498+ const references = this . relationReverseIndex . get ( targetEntityId ) ;
499+ return references ? Array . from ( references ) : [ ] ;
500+ }
399501}
0 commit comments