From fbf82040fafad43fc32f7ade6754136f16376587 Mon Sep 17 00:00:00 2001 From: Adam Mitchell Date: Thu, 14 Jan 2021 09:29:56 +0000 Subject: [PATCH] Improve smoothness in tickrate --- OpenRA.Game/Game.cs | 12 +++++++++--- OpenRA.Game/Network/OrderManager.cs | 4 ++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index ee417049c6d6..ec8c19bdd645 100644 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -35,7 +35,7 @@ public static class Game public const int NewNetcodeNetTickScale = 1; // Net tick every world frame public const int Timestep = 40; public const int TimestepJankThreshold = 250; // Don't catch up for delays larger than 250ms - public const double NetCatchupFactor = 0.25; + public const double NetCatchupFactor = 0.1; public static InstalledMods Mods { get; private set; } public static ExternalMods ExternalMods { get; private set; } @@ -600,6 +600,8 @@ static void InnerLogicTick(OrderManager orderManager) worldTimestep = Timestep; else if (world.IsLoadingGameSave) worldTimestep = 1; + else if (orderManager.IsStalling) + worldTimestep = 1; else if (orderManager.CatchUpFrames > 0) worldTimestep = (int)Math.Floor(world.Timestep / (1.0 + NetCatchupFactor * orderManager.CatchUpFrames)); // Smooth catchup else @@ -805,8 +807,11 @@ static void Loop() var maxFramerate = Settings.Graphics.CapFramerate ? Settings.Graphics.MaxFramerate.Clamp(1, 1000) : 1000; var renderInterval = 1000 / maxFramerate; + if (OrderManager.IsStalling) + logicInterval = 1; + // TODO: limit rendering if we are taking too long to catch up - if (OrderManager.CatchUpFrames > 0) + else if (OrderManager.CatchUpFrames > 0) logicInterval = (int)Math.Floor(logicInterval / (1.0 + NetCatchupFactor * OrderManager.CatchUpFrames)); // Tick as fast as possible while restoring game saves, capping rendering at 5 FPS @@ -835,7 +840,8 @@ static void Loop() LogicTick(); // Force at least one render per tick during regular gameplay - if (!(OrderManager.CatchUpFrames > 0) && OrderManager.World != null && !OrderManager.World.IsLoadingGameSave && !OrderManager.World.IsReplay) + // TODO: Have OrderManager tell us when we should force render + if (!OrderManager.IsStalling && !(OrderManager.CatchUpFrames > 2) && OrderManager.World != null && !OrderManager.World.IsLoadingGameSave && !OrderManager.World.IsReplay) renderBeforeNextTick = true; } diff --git a/OpenRA.Game/Network/OrderManager.cs b/OpenRA.Game/Network/OrderManager.cs index c3d0c0c17aae..0288c9aeaebc 100644 --- a/OpenRA.Game/Network/OrderManager.cs +++ b/OpenRA.Game/Network/OrderManager.cs @@ -47,6 +47,7 @@ public sealed class OrderManager : IDisposable public int OrderLatency; // Set during lobby by a "SyncInfo" packet, see UnitOrders public int NextOrderFrame; public int CatchUpFrames { get; private set; } + public bool IsStalling { get; private set; } public long LastTickTime = Game.RunTime; @@ -197,6 +198,7 @@ void CheckSync(byte[] packet) void CompensateForLatency() { + // NOTE: subtract 1 because we are only interested in *excess* frames var catchUpNetFrames = frameData.BufferSizeForClient(Connection.LocalClientId) - 1; if (catchUpNetFrames < 0) catchUpNetFrames = 0; @@ -309,6 +311,8 @@ public bool TryTick() willTick = frameData.IsReadyForFrame(); if (willTick) ProcessOrders(); + + IsStalling = !willTick; } if (willTick)