import { ServerConnector } from "../net/ServerConnector" ; import { EventApi } from "../event/EventApi" ; import { makeKey } from "../decorator/Decorators" ; import { Message , MessageHeader , IMessage } from "../net/Message" ; import { Manager } from "../Framework" ; description description export type MessageHandleFunc = ( handleTypeData : any ) => number ; export interface ProtoListenerData { mainCmd : number ; subCmd : number ; func : MessageHandleFunc ; type : typeof Message ; isQueue : boolean ; data ? : any ; target ? : any ; } export class Service extends ServerConnector { private _messageHeader : typeof MessageHeader = MessageHeader ; description public set messageHeader ( value ) { this . _messageHeader = value ; } private _Heartbeat : typeof Message = null ; description public get heartbeat ( ) : typeof Message { return this . _Heartbeat ; } public set heartbeat ( value ) { this . _Heartbeat = value ; } description protected sendHeartbeat ( ) { super . sendHeartbeat ( ) ; } description protected getMaxHeartbeatTimeOut ( ) { return super . getMaxHeartbeatTimeOut ( ) ; } description protected onHeartbeatTimeOut ( ) { super . onHeartbeatTimeOut ( ) ; } description protected isHeartBeat ( data ) { return super . isHeartBeat ( data ) ; } protected onOpen ( ) { super . onOpen ( ) ; dispatch ( EventApi . NetEvent . ON_OPEN ) ; } protected onClose ( ev ) { super . onClose ( ev ) ; dispatch ( EventApi . NetEvent . ON_CLOSE , ev ) ; } protected onError ( ev ) { super . onError ( ev ) ; dispatch ( EventApi . NetEvent . ON_ERROR , ev ) ; } protected onMessage ( data ) { let header = new this . _messageHeader ( ) ; if ( ! header . decode ( data ) ) { cc . error ( `decode header error` ) ; return ; } super . onMessage ( data ) ; if ( this . isHeartBeat ( header ) ) { return ; } cc . log ( `recv data main cmd : ${ header . mainCmd } sub cmd : ${ header . subCmd } buffer length : ${ header . size }` ) ; let key = makeKey ( header . mainCmd , header . subCmd ) ; if ( ! this . _listeners [ key ] ) { cc . warn ( `no find listener data main cmd : ${ header . mainCmd } sub cmd : ${ header . subCmd }` ) ; return ; } if ( this . _listeners [ key ] . length <= 0 ) { return ; } let listenerDatas = this . _listeners [ key ] ; let queueDatas = [ ] ; for ( let i = 0 ; i < listenerDatas . length ; i ++ ) { let obj = null ; if ( listenerDatas [ i ] . type ) { obj = new listenerDatas [ i ] . type ( ) ; obj . decode ( header . buffer ) ; } else { obj = header . buffer as any ; } if ( listenerDatas [ i ] . isQueue ) { queueDatas . push ( this . copyListenerData ( listenerDatas [ i ] , obj ) ) ; } else { try { listenerDatas [ i ] . func && listenerDatas [ i ] . func . call ( listenerDatas [ i ] . target , obj ) ; } catch ( error ) { cc . error ( error ) ; } } } if ( queueDatas . length > 0 ) { this . _masseageQueue . push ( queueDatas ) ; } } /** 监听集合*/ private _listeners : { [ key ] : ProtoListenerData [ ] ; } = { } ; /** 消息处理队列 */ private _masseageQueue : Array < ProtoListenerData [ ] > = new Array < ProtoListenerData [ ] > ( ) ; /** 是否正在处理消息 ，消息队列处理消息有时间，如执行一个消息需要多少秒后才执行一下个*/ private _isDoingMessage : boolean = false ; description private _isPause : boolean = false ; description public pauseMessageQueue ( ) { this . _isPause = true ; } description public resumeMessageQueue ( ) { this . _isPause = false ; } description param mainCmd param subCmd param handleType param handleFunc param isQueue public addListener ( mainCmd , subCmd , handleType , handleFunc , isQueue , target ) { let key = makeKey ( mainCmd , subCmd ) ; if ( this . _listeners [ key ] ) { let hasSame = false ; for ( let i = 0 ; i < this . _listeners [ key ] . length ; i ++ ) { if ( this . _listeners [ key ] [ i ] . target === target ) { hasSame = true ; break ; } } if ( hasSame ) { return ; } this . _listeners [ key ] . push ( { mainCmd : mainCmd , subCmd : subCmd , func : handleFunc , type : handleType , isQueue : isQueue , target : target } ) ; } else { this . _listeners [ key ] = [ ] ; this . _listeners [ key ] . push ( { mainCmd : mainCmd , subCmd : subCmd , func : handleFunc , type : handleType , isQueue : isQueue , target : target } ) ; } } public removeListeners ( target , mainCmd ? , subCmd ? ) { if ( mainCmd && subCmd ) { let self = this ; Object . keys ( this . _listeners ) . forEach ( ( value ) => { let datas = self . _listeners [ value ] ; let i = datas . length ; while ( i -- ) { if ( datas [ i ] . target == target && datas [ i ] . mainCmd == mainCmd && datas [ i ] . subCmd == subCmd ) { datas . splice ( i , 1 ) ; } } if ( datas . length == 0 ) { delete self . _listeners [ value ] ; } } ) ; let i = this . _masseageQueue . length ; while ( i -- ) { let datas = this . _masseageQueue [ i ] ; let j = datas . length ; while ( j -- ) { if ( datas [ j ] . target == target && datas [ j ] . mainCmd == mainCmd && datas [ j ] . subCmd == subCmd ) { datas . splice ( j , 1 ) ; } } if ( datas . length == 0 ) { this . _masseageQueue . splice ( i , 1 ) ; } } } else { let self = this ; Object . keys ( this . _listeners ) . forEach ( ( value , index , arr ) => { let datas = self . _listeners [ value ] ; let i = datas . length ; while ( i -- ) { if ( datas [ i ] . target == target ) { datas . splice ( i , 1 ) ; } } if ( datas . length == 0 ) { delete self . _listeners [ value ] ; } } ) ; let i = this . _masseageQueue . length ; while ( i -- ) { let datas = this . _masseageQueue [ i ] ; let j = datas . length ; while ( j -- ) { if ( datas [ j ] . target == target ) { datas . splice ( j , 1 ) ; } } if ( datas . length == 0 ) { this . _masseageQueue . splice ( i , 1 ) ; } } } } description param msg public send ( msg ) { if ( this . _messageHeader ) { if ( msg . encode ( ) ) { let header = new this . _messageHeader ( ) ; header . encode ( msg ) ; if ( this . isHeartBeat ( msg ) ) { if ( CC_DEBUG ) cc . log ( `send request main cmd : ${ msg . mainCmd } , sub cmd : ${ msg . subCmd } ` ) ; } else { cc . log ( `send request main cmd : ${ msg . mainCmd } , sub cmd : ${ msg . subCmd } ` ) ; } this . sendBuffer ( header . buffer ) ; } else { cc . error ( `encode error` ) ; } } else { cc . error ( "请求指定数据包头处理类型" ) ; } } description param input param data private copyListenerData ( input , data ) { return { mainCmd : input . mainCmd , subCmd : input . subCmd , type : input . type , func : input . func , isQueue : input . isQueue , data : data , target : input . target } ; } description public handMessage ( ) { if ( this . _isPause ) return ; if ( this . _isDoingMessage ) return ; if ( this . _masseageQueue . length == 0 ) return ; let datas = this . _masseageQueue . shift ( ) ; if ( datas == undefined ) return ; if ( datas . length == 0 ) return ; this . _isDoingMessage = true ; let handleTime = 0 ; if ( CC_DEBUG ) cc . log ( "---handMessage---" ) ; for ( let i = 0 ; i < datas . length ; i ++ ) { let data = datas [ i ] ; if ( data . func instanceof Function ) { try { let tempTime = data . func . call ( data . target , data . data ) ; if ( typeof tempTime == "number" ) { handleTime = Math . max ( handleTime , tempTime ) ; } } catch ( error ) { cc . error ( error ) ; } } } if ( handleTime == 0 ) { this . _isDoingMessage = false ; } else { Manager . uiManager . getCanvasComponent ( ) . scheduleOnce ( ( ) => { this . _isDoingMessage = false ; } , handleTime ) ; } } description public reset ( ) { this . _isDoingMessage = false ; this . _listeners = { } ; this . _masseageQueue = [ ] ; this . resumeMessageQueue ( ) ; } public close ( ) { this . _masseageQueue = [ ] ; this . _isDoingMessage = false ; super . close ( ) ; } }