diff --git a/OpenRA.Game/Network/OrderManager.cs b/OpenRA.Game/Network/OrderManager.cs index 8018e82450..1c4e5ece81 100644 --- a/OpenRA.Game/Network/OrderManager.cs +++ b/OpenRA.Game/Network/OrderManager.cs @@ -38,8 +38,6 @@ namespace OpenRA.Network public int NetFrameNumber { get; private set; } public int LocalFrameNumber; public int FramesAhead = 0; - public bool IsReadyForNextFrame { get; private set; } - int lastFrameSent; public long LastTickTime = Game.RunTime; @@ -76,9 +74,9 @@ namespace OpenRA.Network NetFrameNumber = 1; - // Technically redundant since we will attempt to send orders before the next frame - SendOrders(); - IsReadyForNextFrame = false; + if (GameSaveLastFrame < 0) + for (var i = NetFrameNumber; i <= FramesAhead; i++) + Connection.Send(i, new List()); } public OrderManager(ConnectionTarget endpoint, string password, IConnection conn) @@ -111,17 +109,8 @@ namespace OpenRA.Network chatCache.Add(new ChatLine(name, nameColor, text, textColor)); } - /* - * Send all frame orders that are ready if we can (game is started and our next available send frame is free), - * Send all immediate orders, - * Receive and dispatch immediate orders, check incoming sync matchs, and buffer received frame orders, - * Update our ready status for the next frame for Tick(). - */ public void TickImmediate() { - // Send our frame orders if we should - SendOrders(); - if (localImmediateOrders.Count != 0 && GameSaveLastFrame < NetFrameNumber + FramesAhead) Connection.SendImmediate(localImmediateOrders.Select(o => o.Serialize())); localImmediateOrders.Clear(); @@ -153,9 +142,6 @@ namespace OpenRA.Network return; } } - - if (!IsReadyForNextFrame) - IsReadyForNextFrame = NetFrameNumber >= 1 && frameData.IsReadyForFrame(NetFrameNumber); } Dictionary syncForFrame = new Dictionary(); @@ -177,6 +163,11 @@ namespace OpenRA.Network syncForFrame.Add(frame, packet); } + public bool IsReadyForNextFrame + { + get { return NetFrameNumber >= 1 && frameData.IsReadyForFrame(NetFrameNumber); } + } + public IEnumerable GetClientsNotReadyForNextFrame { get @@ -188,31 +179,16 @@ namespace OpenRA.Network } } - void SendOrders() - { - if (NetFrameNumber < 1) - return; - - // Loop exists to ensure we never miss a frame, since that would stall the game. - // This loop also sends the initial blank frames to get to the correct order latency. - while (lastFrameSent < NetFrameNumber + FramesAhead) - { - lastFrameSent++; - if (GameSaveLastFrame < NetFrameNumber + FramesAhead) - Connection.Send(lastFrameSent, localOrders.Select(o => o.Serialize()).ToList()); - localOrders.Clear(); - } - } - - /* - * Only available if TickImmediate() is called first and we are ready to dispatch received orders locally. - * Process all incoming orders for this frame, handle sync hashes and step our net frame. - */ public void Tick() { if (!IsReadyForNextFrame) throw new InvalidOperationException(); + if (GameSaveLastFrame < NetFrameNumber + FramesAhead) + Connection.Send(NetFrameNumber + FramesAhead, localOrders.Select(o => o.Serialize()).ToList()); + + localOrders.Clear(); + foreach (var order in frameData.OrdersForFrame(World, NetFrameNumber)) UnitOrders.ProcessOrder(this, World, order.Client, order.Order); @@ -226,7 +202,6 @@ namespace OpenRA.Network syncReport.UpdateSyncReport(); ++NetFrameNumber; - IsReadyForNextFrame = false; } public void Dispose() diff --git a/OpenRA.Game/Server/Server.cs b/OpenRA.Game/Server/Server.cs index eb504b11bf..ccc5e801f8 100644 --- a/OpenRA.Game/Server/Server.cs +++ b/OpenRA.Game/Server/Server.cs @@ -1005,7 +1005,7 @@ namespace OpenRA.Server // HACK: Turn down the latency if there is only one real player if (LobbyInfo.NonBotClients.Count() == 1) - LobbyInfo.GlobalSettings.OrderLatency = 0; + LobbyInfo.GlobalSettings.OrderLatency = 1; // Enable game saves for singleplayer missions only // TODO: Enable for multiplayer (non-dedicated servers only) once the lobby UI has been created