import { GlobalCheck , GroupHitList , HitCallback , HitCheck , HitsCheck , Actor , ActorFunction , ActorFunctionContainer , ActorFunctionContainerGroup , ActorFunctionGenerator , ActorFunctionGeneratorContainerGroup , ActorHittrSettings , } from "./types" ; /**
 * Automation for physics collisions and reactions.
 */ export class ActorHittr { /**
     * For each group name, the names of other groups it is allowed to hit.
     */ private readonly groupHitLists : GroupHitList ; /**
     * Function generator for globalChecks.
     */ private readonly globalCheckGenerator ? : ActorFunctionGenerator < GlobalCheck > ; /**
     * Function generators for hitChecks.
     */ private readonly hitCheckGenerators : ActorFunctionGeneratorContainerGroup < HitCheck > ; /**
     * Function generators for HitCallbacks.
     */ private readonly hitCallbackGenerators : ActorFunctionGeneratorContainerGroup < HitCallback > ; /**
     * Check Functions for Actors within groups to see if they're able to
     * collide in the first place.
     */ private readonly generatedGlobalChecks : ActorFunctionContainer < GlobalCheck > ; /**
     * Collision detection Functions to check two Actors for collision.
     */ private readonly generatedHitChecks : ActorFunctionContainerGroup < HitCheck > ; /**
     * Hit Function callbacks for when two Actors do collide.
     */ private readonly generatedHitCallbacks : ActorFunctionContainerGroup < HitCallback > ; /**
     * Hits checkers for when an Actor should have its hits detected.
     */ private readonly generatedHitsChecks : ActorFunctionContainer < HitsCheck > ; param settings public constructor ( settings = { } ) { this . globalCheckGenerator = settings . globalCheckGenerator ; this . hitCheckGenerators = settings . hitCheckGenerators || { } ; this . hitCallbackGenerators = settings . hitCallbackGenerators || { } ; this . generatedHitChecks = { } ; this . generatedHitCallbacks = { } ; this . generatedGlobalChecks = { } ; this . generatedHitsChecks = { } ; this . groupHitLists = this . generateGroupHitLists ( this . hitCheckGenerators ) ; } param groupName param typeName public cacheChecksForType ( groupName , typeName ) { if ( ! { } . hasOwnProperty . call ( this . generatedGlobalChecks , groupName ) && this . globalCheckGenerator ) { this . generatedGlobalChecks [ typeName ] = this . globalCheckGenerator ( ) ; } if ( ! { } . hasOwnProperty . call ( this . generatedHitsChecks , groupName ) && { } . hasOwnProperty . call ( this . hitCheckGenerators , groupName ) ) { this . generatedHitsChecks [ typeName ] = this . generateHitsCheck ( groupName ) ; } } param actor public checkHitsForActor ( actor ) { this . generatedHitsChecks [ actor . title ] ( actor ) ; } param actor param other returns public checkHitForActors ( actor , other ) { return ! ! this . runActorsFunctionSafely ( this . generatedHitChecks , actor , other , this . hitCheckGenerators ) ; } param actor param other public runHitCallbackForActors ( actor , other ) { this . runActorsFunctionSafely ( this . generatedHitCallbacks , actor , other , this . hitCallbackGenerators ) ; } param groupName returns private generateHitsCheck ( groupName ) { param actor return ( actor ) : void => { if ( { } . hasOwnProperty . call ( this . generatedGlobalChecks , groupName ) && ! this . generatedGlobalChecks [ groupName ] ( actor ) ) { return ; } for ( let i = 0 ; i < actor . numQuadrants ; i += 1 ) { for ( const groupName of this . groupHitLists [ actor . groupType ] ) { for ( let j = 0 ; j < actor . quadrants [ i ] . numactors [ groupName ] ; j += 1 ) { const other = actor . quadrants [ i ] . actors [ groupName ] [ j ] ; if ( actor === other ) { break ; } if ( ! this . generatedGlobalChecks [ other . title ] ( other ) ) { continue ; } if ( this . checkHitForActors ( actor , other ) ) { this . runHitCallbackForActors ( actor , other ) ; } } } } } ; } param group param actor param other returns private runActorsFunctionSafely ( group , actor , other , generators ) { const typeActor = actor . title ; const typeOther = other . title ; let container = group [ typeActor ] ; if ( container === undefined ) { container = group [ typeActor ] = { } ; } let check = container [ typeOther ] ; if ( check === undefined ) { check = container [ typeOther ] = generators [ actor . groupType ] [ other . groupType ] ( ) ; } return ( check as HitCheck ) ( actor , other ) ; } param group private generateGroupHitLists ( group ) { const output = { } ; for ( const i in group ) { if ( { } . hasOwnProperty . call ( group , i ) ) { output [ i ] = Object . keys ( group [ i ] ) ; } } return output ; } }