Exemplo n.º 1
0
        private void OnMercuryEvent(object sender, MercuryEventBase e)
        {
            if (e.eventId == (int)EMercuryEvent.E_ME_OBJ_DELIVER)
            {
                MEObjDeliver evt = (MEObjDeliver)e;
                if (evt.opcode == (int)EObjDeliverOPCode.E_OP_HANDLE_FRAMEPACK)
                {
                    object[] args = (object[])evt.obj;
                    if (!HandleFrameCommandPackage((uint)args[0], args[1]))
                    {
                        uint frameID = (uint)args[0];
                        if (frameID >= _begFrqNo)
                        {
                            FrapWrap wrap = ObjectCachePool.instance.Fetch <FrapWrap>();
                            wrap.frameID = frameID;
                            wrap.data    = args[1];

                            //Èç¹û¸ÃÖ¡ÒÑ´æÔÚ£¬Ôò¶ªÆú
                            if (!Utility.LinkedListInsert(_laterFrames, wrap, FrapWrap.FrapWrapInsertComparsionFunc))
                            {
                                ProcessFrameDropInternal(frameID, wrap.data, false);
                                wrap.Release();
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 2
0
        //
        private void PushFrame2LaterFrameList(MercuryEventBase e)
        {
            if (e != null)
            {
                MEObjDeliver evt  = (MEObjDeliver)e;
                FrapWrap     frap = ObjectCachePool.instance.Fetch <FrapWrap>();
                frap.frameID = (uint)evt.args[0];
                frap.data    = evt.args[1];
                e.Release();

                if (Utility.LinkedListInsert(_laterFrames, frap, FrapWrap.FrapWrapInsertComparsionFunc))
                {
                    if (_lastFrameNeedToTrace < frap.frameID)
                    {
                        _lastFrameNeedToTrace = (int)frap.frameID; // record last frame while tracing the newest frame.
                    }
                }
                else
                {
                    // release duplicated data
                    AbstractSmartObj obj = (AbstractSmartObj)frap.data;
                    if (obj != null)
                    {
                        obj.Release();
                    }
                    frap.Release();
                }
            }
        }
Exemplo n.º 3
0
        private void RequestRepairLackFrames()
        {
            if (_maxFrqNo <= _begFrqNo)
            {
                return;
            }

            //voilin: request small repair
            List <int> frames = new List <int>();

            //»á¶àÇëÇóÁ½Ö¡
            int len = Mathf.Min((int)(_maxFrqNo - _begFrqNo + 2u), (int)MAX_REPAIR_FRAMECOUNT);

            for (uint ii = _begFrqNo; ii < _begFrqNo + len; ++ii)
            {
                //ÔÙ×öÒ»´Î¼ì²â£¬·ÀÖ¹ÓÉÓÚÖ¡ÂÒÐòµ½´ï¶øÖظ´ÇëÇó
                int pos = (int)_FrameNo2WindowIdx(ii);
                if (_receiveWindow[pos] == null)
                {
                    frames.Add((int)ii);
                }
            }

            if (frames.Count > 0)
            {
                MEObjDeliver e   = ObjectCachePool.instance.Fetch <MEObjDeliver>();
                int[]        tmp = frames.ToArray();
                e.args[0] = (object)tmp;
                e.opcode  = (int)EObjDeliverOPCode.E_OP_LACK_FRAMES;
                Mercury.instance.Broadcast(EventTokenTable.et_game_framework, this, e);
            }
        }
Exemplo n.º 4
0
        private void ProcessFrameCommandInternal(object msg)
        {
            MEObjDeliver e = ObjectCachePool.instance.Fetch <MEObjDeliver>();

            e.args[0] = msg;
            e.opcode  = (int)EObjDeliverOPCode.E_OP_PROCESS_FRAMEPACK;

            Mercury.instance.Broadcast(EventTokenTable.et_game_framework, this, e);
        }
Exemplo n.º 5
0
        private void ProcessFrameDropInternal(uint frameID, object msg, bool releaseSharedBuf = true)
        {
            MEObjDeliver e = ObjectCachePool.instance.Fetch <MEObjDeliver>();

            e.args[0] = frameID;
            e.args[1] = msg;
            e.args[2] = releaseSharedBuf;
            e.opcode  = (int)EObjDeliverOPCode.E_OP_PROCESS_FRAMEDROP;

            Mercury.instance.Broadcast(EventTokenTable.et_game_framework, this, e);
        }
Exemplo n.º 6
0
        private void ReportProgress(int progress = -1)
        {
            // reconnection progress
            int percent = progress < 0 ? UnityEngine.Mathf.Clamp((int)(FrameSyncService.instance.GetFrameSyncChr().CurFrameNum * 1f / _lastFrameNeedToTrace * 100), 0, 99) : progress;

            if (percent > _lastReportPercent)
            {
                _lastReportPercent = percent;
                MEObjDeliver report = ObjectCachePool.instance.Fetch <MEObjDeliver>();
                report.opcode  = (int)EObjDeliverOPCode.E_OP_RECONNECTION_PROGRESS;
                report.args[0] = percent;//progress < 0 ? UnityEngine.Mathf.Clamp(percent, 0, 99) : progress;
                Mercury.instance.Broadcast(EventTokenTable.et_loading_ui, this, report);
            }
        }
Exemplo n.º 7
0
        private void ProcessLaterFrames()
        {
            if (_laterFrames.Count > 0)
            {
                LinkedListNode <FrapWrap> node = _laterFrames.First;
                while (node != null && node.Value != null)
                {
                    FrapWrap     frap = node.Value;
                    MEObjDeliver e    = ObjectCachePool.instance.Fetch <MEObjDeliver>();
                    e.args[0] = frap.frameID;
                    e.args[1] = frap.data;
                    e.opcode  = (int)EObjDeliverOPCode.E_OP_HANDLE_FRAMEPACK;
                    Mercury.instance.Broadcast(EventTokenTable.et_framewindow, this, e);

                    ReportProgress();

                    frap.Release();
                    node = node.Next;
                }

                _laterFrames.Clear();
            }
        }
Exemplo n.º 8
0
        // extension RequireReconnection to implement message pack and send logic
        // NOTE: do not use this internal function indepentently.
        public bool _RequireReconnection(int TotalFramesPassed)
        {
            if (_state == EState.E_STATE_NONE && TotalFramesPassed > 0)
            {
                _state = EState.E_STATE_RECEIVING_FRAMES;
                _lastFrameNeedToTrace = TotalFramesPassed;
                _currentFrameTraced   = 0;
                _lastReportPercent    = 0;
                _tracedFrame          = 0;
                _canPerformCheck      = false;
                _adjustGap            = true;

                MEObjDeliver e = ObjectCachePool.instance.Fetch <MEObjDeliver> ();
                e.opcode = (int)EObjDeliverOPCode.E_OP_START_RECONNECTION;
                Mercury.instance.Broadcast(EventTokenTable.et_game_framework, this, e);

                return(true);
            }
            else if (_state == EState.E_STATE_NONE && TotalFramesPassed == 0)
            {
                ReportProgress(100);
            }
            return(false);
        }
Exemplo n.º 9
0
        public void Update()
        {
            if (_state == EState.E_STATE_EXECUTING_FRAMES)
            {
                ProcessLaterFrames();

                if (FrameSyncService.instance.BlockFrameWaitNum > kFrameBlockThreshold &&
                    FrameSyncService.instance.GetFrameSyncChr().CurFrameNum < _lastFrameNeedToTrace)
                {
                    _currentFrameTraced = (int)FrameSyncService.instance.GetFrameSyncChr().CurFrameNum + 1;
                    _state           = EState.E_STATE_RECEIVING_FRAMES;
                    _canPerformCheck = false;
                    return;
                }

                // tolerent by maxium repair count
                bool fin = FrameSyncService.instance.GetFrameSyncChr().CurFrameNum >= _lastFrameNeedToTrace;
                if (fin)
                {
                    ReportProgress(100);

                    MEObjDeliver e = ObjectCachePool.instance.Fetch <MEObjDeliver>();
                    e.opcode = (int)EObjDeliverOPCode.E_OP_END_RECONNECTION;
                    Mercury.instance.Broadcast(EventTokenTable.et_game_framework, this, e);

                    _canPerformCheck = true;
                    _state           = EState.E_STATE_NONE;
                }
            }
            else if (_state == EState.E_STATE_RECEIVING_FRAMES)
            {
                if (_adjustGap)
                {
                    if (_laterFrames.Count > 0)
                    {
                        // adjust gap, the gap is generated by loading stuck
                        int gap = (int)_laterFrames.First.Value.frameID - _lastFrameNeedToTrace - 1;
                        if (gap > 0)
                        {
                            _lastFrameNeedToTrace = (int)_laterFrames.First.Value.frameID - 1;
                        }
                        _adjustGap = false;
                    }
                }
                int frameEnd = UnityEngine.Mathf.Min(_currentFrameTraced + kFramesDevourPerTick, _lastFrameNeedToTrace);
                if (frameEnd > _currentFrameTraced)
                {
                    MEObjDeliver e = ObjectCachePool.instance.Fetch <MEObjDeliver>();
                    e.opcode  = (int)EObjDeliverOPCode.E_OP_FETCH_RECONNECTION_FRAMES;
                    e.args[0] = _currentFrameTraced;
                    e.args[1] = frameEnd;

                    Mercury.instance.Broadcast(EventTokenTable.et_game_framework, this, e);

                    _lastTracedFrame = _currentFrameTraced;
                    _tracedFrame     = frameEnd;
                    _stuckTimes      = 0;
                    _state           = EState.E_STATE_WAIT_HANDLING_FRAMES;
                }
                else
                {
                    // force processing later frames
                    ProcessLaterFrames();
                    _state = EState.E_STATE_EXECUTING_FRAMES;
                }
            }
            else if (_state == EState.E_STATE_WAIT_HANDLING_FRAMES)
            {
                if (_currentFrameTraced == _lastTracedFrame)
                {
                    ++_stuckTimes;
                }
                else
                {
                    _lastTracedFrame = _currentFrameTraced;
                    _stuckTimes      = 0;
                }

                // request again while stucking
                if (_stuckTimes >= kFrameReqStuckTimesThreshold)
                {
                    _state = EState.E_STATE_RECEIVING_FRAMES;
                    return;
                }
                if (_currentFrameTraced < _tracedFrame)
                {
                    return;
                }
                if (_tracedFrame < _lastFrameNeedToTrace)
                {
                    _state = EState.E_STATE_RECEIVING_FRAMES;
                }
                //追上之后,处理后来帧
                else
                {
                    ProcessLaterFrames();
                    _canPerformCheck = true;
                    _state           = EState.E_STATE_EXECUTING_FRAMES;
                }
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// 该方法每个渲染帧会执行一次,但是会以逻辑帧间隔,经过平均延迟计算,触发逻辑帧的执行
        /// </summary>
        /// <param name="bLocalTimeDriver"></param>
        private void UpdateMultiFrame(bool bLocalTimeDriver = false)
        {
            {
                MEObjDeliver e = ObjectCachePool.instance.Fetch <MEObjDeliver>();
                e.opcode = (int)EObjDeliverOPCode.E_OP_UPDATE_TAILS_OF_GAME_LOGIC;
                Mercury.instance.Broadcast(EventTokenTable.et_framesynchr, this, e);
            }

            int drift = (int)((EndFrameNum - CurFrameNum) / (uint)nDriftFactor);

            tryCount = Mathf.Clamp(drift, 1, 100);
            int   i  = tryCount;
            float rt = Time.realtimeSinceStartup;

            if (bLocalTimeDriver)
            {
                rt = fLocalRunTime + startFrameTime;
            }

            //帧同步开始后经过了多少时间。nowtime 是渲染帧间隔,小于一个逻辑帧
            long nowTime = (long)((rt - startFrameTime) * 1000f);

            long nDelayMs = nowTime - (long)((SvrFrameIndex + 1u) * SvrFrameDelta);
            //平均延迟(以30帧计算)
            int smoothDelay = CalculateJitterDelay(nDelayMs);

            nowTime *= (long)frameSpeed;
            while (i > 0)
            {
                long lastTime  = (long)(CurFrameNum * FrameDelta);
                long deltaTime = nowTime - lastTime;
                deltaTime -= (long)smoothDelay;
                //这里是处理核心,如果 deltaTime 随着渲染帧的增长而增长,当他小于一个逻辑帧时,则不做任何处理,当他大于一个逻辑帧时,则触发一次逻辑帧处理
                if (deltaTime >= (long)FrameDelta)
                {
                    //假设一直没有收到新的逻辑帧,则每次都会执行到这里
                    if (CurFrameNum >= EndFrameNum)
                    {
                        EndBlockWaitNum += 1u;
                        i = 0;
                    }
                    else
                    {
                        EndBlockWaitNum = 0u;
                        CurFrameNum    += 1u;
                        LogicFrameTick += (ulong)FrameDelta;

                        //先执行命令,再刷新游戏逻辑
                        while (commandQueue.Count > 0)
                        {
                            IFrameCommand frameCommand = commandQueue.Peek();
                            uint          commandFrame = (frameCommand.frameNum + SvrFrameLater) * KeyFrameRate;
                            if (commandFrame > CurFrameNum)
                            {
                                break;
                            }

                            frameCommand          = commandQueue.Dequeue();
                            frameCommand.frameNum = commandFrame;
                            frameCommand.ExecCommand();

                            AbstractSmartObj obj = (AbstractSmartObj)frameCommand;
                            if (obj != null)
                            {
                                obj.Release();
                            }
                        }
                        if (!bEscape)
                        {
                            //通知刷新游戏逻辑层
                            MEObjDeliver e = ObjectCachePool.instance.Fetch <MEObjDeliver>();

                            e.args[0] = (int)FrameDelta;
                            e.args[1] = i == 1 && deltaTime < (long)(2u * FrameDelta); //false;
                            e.opcode  = (int)EObjDeliverOPCode.E_OP_UPDATE_GAME_LOGIC;

                            Mercury.instance.Broadcast(EventTokenTable.et_framesynchr, this, e);
                        }
                        i--;
                    }
                }
                else
                {
                    i = 0;
                }
            }
        }