public override void UpdateAfter() { if (!m_clientReady || !m_hasTypeTable || ClientState == null) { return; } NetProfiler.Begin("Replication client update", 0); var simulationTime = m_callback.GetUpdateTime(); if (m_clientStartTimeStamp == MyTimeSpan.Zero) { m_clientStartTimeStamp = simulationTime; // (uint)DateTime.Now.TimeOfDay.TotalMilliseconds; } var timeStamp = simulationTime - m_clientStartTimeStamp; UpdatePingSmoothing(); NetProfiler.CustomTime("Ping", (float)m_ping.Milliseconds, "{0} ms"); NetProfiler.CustomTime("SmoothPing", (float)m_smoothPing.Milliseconds, "{0} ms"); NetProfiler.Begin("Packet stats"); NetProfiler.CustomTime("Server Drops", (float)m_serverStats.Drops, "{0}"); NetProfiler.CustomTime("Server OutOfOrder", (float)m_serverStats.OutOfOrder, "{0}"); NetProfiler.CustomTime("Server Duplicates", (float)m_serverStats.Duplicates, "{0}"); NetProfiler.CustomTime("Client Drops", (float)m_clientStatsFromServer.Drops, "{0}"); NetProfiler.CustomTime("Client OutOfOrder", (float)m_clientStatsFromServer.OutOfOrder, "{0}"); NetProfiler.CustomTime("Client Duplicates", (float)m_clientStatsFromServer.Duplicates, "{0}"); m_serverStats.Reset(); m_clientStatsFromServer.Reset(); NetProfiler.End(); MyTimeSpan ping = UseSmoothPing ? m_smoothPing : m_ping; var diffCorrection = -ping.Milliseconds * m_callback.GetServerSimulationRatio(); var diffMS = timeStamp.Milliseconds - m_lastServerTimeStamp.Milliseconds; var correctionCurrent = diffMS + diffCorrection; int correction = 0, nextFrameDelta = 0; MyTimeSpan currentTime = MyTimeSpan.FromTicks(Stopwatch.GetTimestamp()); MyTimeSpan realtimeDelta = currentTime - m_lastTime; // try to be always one simulation step ahead correctionCurrent -= m_simulationTimeStep; //if (Math.Abs(correctionCurrent) > 200) // m_correctionSmooth = MyTimeSpan.FromMilliseconds(correctionCurrent); correctionCurrent = Math.Min(correctionCurrent, (int)(m_simulationTimeStep * 2 / m_callback.GetServerSimulationRatio())); if (diffMS < -MAX_TIMESTAMP_DIFF_LOW || diffMS > MAX_TIMESTAMP_DIFF_HIGH) { m_clientStartTimeStamp = MyTimeSpan.FromMilliseconds(m_clientStartTimeStamp.Milliseconds + diffMS); timeStamp = simulationTime - m_clientStartTimeStamp; m_correctionSmooth = MyTimeSpan.Zero; TimestampReset(); if (VRage.MyCompilationSymbols.EnableNetworkPositionTracking) { Trace.MyTrace.Send(Trace.TraceWindow.MTiming, "---------------------------------------------------------------- DESYNC"); } } else { var factor = Math.Min(realtimeDelta.Seconds / SmoothCorrectionAmplitude, 1.0); m_correctionSmooth = MyTimeSpan.FromMilliseconds(correctionCurrent * factor + m_correctionSmooth.Milliseconds * (1 - factor)); // special case: we really dont want the client timestamp to fall behind if (diffMS < 0) { correction = (int)correctionCurrent; } else { correction = UseSmoothCorrection ? (int)m_correctionSmooth.Milliseconds : (int)correctionCurrent; } NetProfiler.CustomTime("Correction", (float)correctionCurrent, "{0} ms"); NetProfiler.CustomTime("SmoothCorrection", (float)m_correctionSmooth.Milliseconds, "{0} ms"); if (ApplyCorrectionsDebug && (LastMessageFromServer - DateTime.UtcNow).Seconds < 1.0f) { if (diffMS < 0) { nextFrameDelta = correction; m_callback.SetNextFrameDelayDelta(nextFrameDelta); } else if (Math.Abs(correction) > TimestampCorrectionMinimum) { nextFrameDelta = (Math.Abs(correction) - TimestampCorrectionMinimum) * Math.Sign(correction); m_callback.SetNextFrameDelayDelta(nextFrameDelta); } } } NetProfiler.CustomTime("GameTimeDelta", (float)(timeStamp - Timestamp).Milliseconds, "{0} ms"); NetProfiler.CustomTime("RealTimeDelta", (float)realtimeDelta.Milliseconds, "{0} ms"); Timestamp = timeStamp; //if (VRage.MyCompilationSymbols.EnableNetworkPositionTracking) { string trace = "realtime delta: " + realtimeDelta + ", client: " + Timestamp + ", server: " + m_lastServerTimeStamp + ", diff: " + diffMS.ToString("##.#") + " => " + (Timestamp.Milliseconds - m_lastServerTimeStamp.Milliseconds).ToString("##.#") + ", Ping: " + m_ping.Milliseconds.ToString("##.#") + " / " + m_smoothPing.Milliseconds.ToString("##.#") + "ms, Correction " + correctionCurrent + " / " + m_correctionSmooth.Milliseconds + " / " + nextFrameDelta + ", ratio " + m_callback.GetServerSimulationRatio(); Trace.MyTrace.Send(Trace.TraceWindow.MTiming, trace); //Trace.MyTrace.Send(Trace.TraceWindow.MPositions2, trace); } m_lastTime = currentTime; NetProfiler.End(); if (StressSleep.X > 0) { int sleep; if (StressSleep.Z == 0) { sleep = MyRandom.Instance.Next(StressSleep.X, StressSleep.Y); } else { sleep = (int)(Math.Sin(simulationTime.Milliseconds * Math.PI / StressSleep.Z) * StressSleep.Y + StressSleep.X); } System.Threading.Thread.Sleep(sleep); } }