private void DoClientUpdate() { int maxRollbackCount = 5; if (_isDebugRollback && _world.Tick > maxRollbackCount && _world.Tick % maxRollbackCount == 0) { var rawTick = _world.Tick; var revertCount = LRandom.Range(1, maxRollbackCount); for (int i = 0; i < revertCount; i++) { var input = new Msg_PlayerInput(_world.Tick, LocalActorId, _inputService.GetDebugInputCmds()); var frame = new ServerFrame() { tick = rawTick - i, _inputs = new Msg_PlayerInput[] { input } }; _cmdBuffer.ForcePushDebugFrame(frame); } _debugService.Trace("RollbackTo " + (_world.Tick - revertCount)); if (!RollbackTo(_world.Tick - revertCount, _world.Tick)) { _commonStateService.IsPause = true; return; } while (_world.Tick < rawTick) { var sFrame = _cmdBuffer.GetServerFrame(_world.Tick); Logging.Debug.Assert(sFrame != null && sFrame.tick == _world.Tick, $" logic error: server Frame must exist tick {_world.Tick}"); _cmdBuffer.PushLocalFrame(sFrame); Simulate(sFrame); if (_commonStateService.IsPause) { return; } } } while (_world.Tick < TargetTick) { FramePredictCount = 0; var input = new Msg_PlayerInput(_world.Tick, LocalActorId, _inputService.GetInputCmds()); var frame = new ServerFrame() { tick = _world.Tick, _inputs = new Msg_PlayerInput[] { input } }; _cmdBuffer.PushLocalFrame(frame); _cmdBuffer.PushServerFrames(new ServerFrame[] { frame }); Simulate(_cmdBuffer.GetFrame(_world.Tick)); if (_commonStateService.IsPause) { return; } } }
private void DoNormalUpdate() { //make sure client is not move ahead too much than server var maxContinueServerTick = _cmdBuffer.MaxContinueServerTick; if ((_world.Tick - maxContinueServerTick) > MaxPredictFrameCount) { return; } var minTickToBackup = (maxContinueServerTick - (maxContinueServerTick % snapshotFrameInterval)); // Pursue Server frames var deadline = LTime.realtimeSinceStartupMS + MaxSimulationMsPerFrame; while (_world.Tick < _cmdBuffer.CurTickInServer) { var tick = _world.Tick; var sFrame = _cmdBuffer.GetServerFrame(tick); if (sFrame == null) { OnPursuingFrame(); return; } _cmdBuffer.PushLocalFrame(sFrame); Simulate(sFrame, tick == minTickToBackup); if (LTime.realtimeSinceStartupMS > deadline) { OnPursuingFrame(); return; } } if (_constStateService.IsPursueFrame) { _constStateService.IsPursueFrame = false; EventHelper.Trigger(EEvent.PursueFrameDone); } // Roll back if (_cmdBuffer.IsNeedRollback) { RollbackTo(_cmdBuffer.NextTickToCheck, maxContinueServerTick); CleanUselessSnapshot(System.Math.Min(_cmdBuffer.NextTickToCheck - 1, _world.Tick)); minTickToBackup = System.Math.Max(minTickToBackup, _world.Tick + 1); while (_world.Tick <= maxContinueServerTick) { var sFrame = _cmdBuffer.GetServerFrame(_world.Tick); Logging.Debug.Assert(sFrame != null && sFrame.tick == _world.Tick, $" logic error: server Frame must exist tick {_world.Tick}"); _cmdBuffer.PushLocalFrame(sFrame); Simulate(sFrame, _world.Tick == minTickToBackup); } } //Run frames while (_world.Tick <= TargetTick) { var curTick = _world.Tick; ServerFrame frame = null; var sFrame = _cmdBuffer.GetServerFrame(curTick); if (sFrame != null) { frame = sFrame; } else { var cFrame = _cmdBuffer.GetLocalFrame(curTick); FillInputWithLastFrame(cFrame); frame = cFrame; } _cmdBuffer.PushLocalFrame(frame); Predict(frame, true); } _hashHelper.CheckAndSendHashCodes(); }