module import ECS from "./ecs" ; import System from "./system" ; import { UIDGenerator , DefaultUIDGenerator } from "./uid" ; import { fastSplice } from "./utils" ; import { ComponentProperties as Components , ComponentIDs , components as allComponents , } from "../../components" ; class class Entity { class constructor param { Number | UIDGenerator } idOrUidGenerator param { Array [ Component ] } components id : number ; ecs : null | ECS ; systems : System [ ] ; systemsDirty : boolean ; components : Partial < Components > ; constructor ( idOrUidGenerator ? , components = { } as Components ) { property this . id = - 1 ; if ( typeof idOrUidGenerator === "number" ) { this . id = idOrUidGenerator ; } else if ( idOrUidGenerator instanceof UIDGenerator ) { this . id = idOrUidGenerator . next ( ) ; } else { this . id = DefaultUIDGenerator . next ( ) ; } property this . systems = [ ] ; property this . systemsDirty = false ; property this . components = { } as Components ; for ( let component in components ) { const componentClass = Object . values ( allComponents ) . find ( c => c && c . id === component ) as any ; const data = components [ component as ComponentIDs ] ; let componentData = data instanceof componentClass ? data : new componentClass ( ) . init ( data ) ; this . components [ component as ComponentIDs ] = componentData ; } property this . ecs = null ; } toJSON ( ) { return { id : this . id , components : Object . fromEntries ( Object . entries ( this . components ) . map ( ( [ key , comp ] ) => { let newValue = allComponents [ key as keyof typeof allComponents ] ?. serialize ( comp as any ) || comp ; return [ key , newValue ] ; } ) ) , } ; } private param { ECS } ecs addToECS ( ecs ) { this . ecs = ecs ; this . setSystemsDirty ( ) ; } /**
     * Set the systems dirty flag so the ECS knows this entity
     * needs to recompute eligibility at the beginning of next
     * tick.
     */ setSystemsDirty ( ) { if ( ! this . systemsDirty && this . ecs ) { this . systemsDirty = true ; this . ecs . entitiesSystemsDirty . push ( this ) ; } } private param { System } system addSystem ( system ) { this . systems . push ( system ) ; } private param { System } system removeSystem ( system ) { let index = this . systems . indexOf ( system ) ; if ( index !== - 1 ) { fastSplice ( this . systems , index , 1 ) ; } } param { String } name param { Object } data addComponent < Name extends keyof Components , Data extends Components [ Name ] > ( name , data ? ) { const componentClass = Object . values ( allComponents ) . find ( c => c && c . id === name ) as any ; let componentData = ( data as any ) instanceof componentClass ? data : new componentClass ( ) . init ( data ) ; this . components [ name ] = componentData ; this . setSystemsDirty ( ) ; } param { String } name removeComponent ( name ) { if ( ! this . components [ name ] ) { return ; } delete this . components [ name ] ; this . setSystemsDirty ( ) ; } method param { String } name param { Object } data example updateComponent < Name extends keyof Components , Data extends Components [ Name ] > ( name , data ) { let component = this . components [ name ] ; if ( ! component ) { this . addComponent ( name , data ) ; } else { Object . assign ( this . components [ name ] , data ) ; } } param { Object } componentsData updateComponents < K extends keyof Components > ( componentsData ) { let components = Object . keys ( componentsData ) as K [ ] ; for ( let i = 0 , component ; ( component = components [ i ] as K ) ; i += 1 ) { this . updateComponent ( component , ( componentsData [ component ] || { } ) as any ) ; } } private dispose ( ) { for ( let i = 0 , system ; ( system = this . systems [ 0 ] ) ; i += 1 ) { system . removeEntity ( this ) ; } } } export default Entity ;