import { EventEmitter } from 'events' ; import ClusterNode , { ClusterNodeOptions } from '../ClusterNode' ; import Player from '../core/Player' ; import { VoiceStateUpdate , VoiceServerUpdate } from './Node' ; export default abstract class BaseCluster extends EventEmitter { public abstract send : ( guildID : string , packet : any ) => any ; public abstract filter : ( node : ClusterNode , guildID : string ) => boolean ; public readonly nodes : ClusterNode [ ] = [ ] ; constructor ( options ? ) { super ( ) ; if ( options ) this . spawn ( options ) ; } public spawn ( options ) ; public spawn ( options ) ; public spawn ( options ) { if ( Array . isArray ( options ) ) return options . map ( opt => this . spawn ( opt ) ) ; const node = new ClusterNode ( this , options ) ; this . nodes . push ( node ) ; return node ; } public sort ( ) { return this . nodes . filter ( n => n . connected ) . sort ( ( a , b ) => { if ( ! a . stats || ! b . stats ) return - 1 ; return ( a . stats . cpu ? a . stats . cpu . systemLoad / a . stats . cpu . cores : 0 ) - ( b . stats . cpu ? b . stats . cpu . systemLoad / b . stats . cpu . cores : 0 ) ; } ) ; } public getNode ( guildID ) { let node = this . nodes . find ( node => node . players . has ( guildID ) ) ; if ( ! node ) node = this . sort ( ) . find ( node => this . filter ( node , guildID ) ) ; if ( node ) return node ; throw new Error ( 'unable to find appropriate node; please check your filter' ) ; } public has ( guildID ) { return this . nodes . some ( node => node . players . has ( guildID ) ) ; } public get ( guildID ) { return this . getNode ( guildID ) . players . get ( guildID ) ; } public voiceStateUpdate ( state ) { return this . getNode ( state . guild_id ) . voiceStateUpdate ( state ) ; } public voiceServerUpdate ( server ) { return this . getNode ( server . guild_id ) . voiceServerUpdate ( server ) ; } }