diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index e7c0c2f5e..e0468e417 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -565,7 +565,6 @@ namespace Barotrauma.Networking //game already started -> send start message immediately if (gameStarted) { - connectedClient.NeedsMidRoundSync = true; SendStartMessage(roundStartSeed, Submarine.MainSub, GameMain.GameSession.gameMode.Preset, connectedClient); } } @@ -655,12 +654,8 @@ namespace Barotrauma.Networking { if (!c.inGame) { - if (c.NeedsMidRoundSync) - { - //client joined mid-round and has just started up the game - //check which unique messages they've missed - entityEventManager.InitClientMidRoundSync(c); - } + //check if midround syncing is needed due to missed unique events + entityEventManager.InitClientMidRoundSync(c); c.inGame = true; } } diff --git a/Subsurface/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs b/Subsurface/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs index 8d875250c..a7a0b419e 100644 --- a/Subsurface/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs +++ b/Subsurface/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs @@ -133,12 +133,14 @@ namespace Barotrauma.Networking { //it's been 10 seconds since this event was created //kick everyone that hasn't received it yet, this is way too old - List toKick = inGameClients.FindAll(c => NetIdUtils.IdMoreRecent((UInt16)(lastSentToAll + 1), c.lastRecvEntityEventID)); + List toKick = inGameClients.FindAll(c => + NetIdUtils.IdMoreRecent((UInt16)(lastSentToAll + 1), c.lastRecvEntityEventID) && + (Timing.TotalTime - c.MidRoundSyncTimeOut) > 10.0f); //give mid-round joining players extra 10 seconds to receive the events + if (toKick != null) toKick.ForEach(c => server.DisconnectClient(c, "", "You have been disconnected because of excessive desync")); } } - - //TODO: calculate a reasonable timeout period for midround syncing and/or give the client more time if they're receiving messages + var timedOutClients = clients.FindAll(c => c.inGame && c.NeedsMidRoundSync && Timing.TotalTime > c.MidRoundSyncTimeOut); if (timedOutClients != null) timedOutClients.ForEach(c => GameMain.Server.DisconnectClient(c, "", "You have been disconnected because syncing your client with the server took too long.")); @@ -248,7 +250,14 @@ namespace Barotrauma.Networking public void InitClientMidRoundSync(Client client) { - if (uniqueEvents.Count > 0) + //no need for midround syncing if no events have been created, + //or if the first created unique event is still in the event list + if (uniqueEvents.Count == 0 || (events.Count > 0 && events[0].ID == uniqueEvents[0].ID)) + { + client.UnreceivedEntityEventCount = 0; + client.NeedsMidRoundSync = false; + } + else { double midRoundSyncTimeOut = uniqueEvents.Count / MaxEventsPerWrite * server.UpdateInterval.TotalSeconds; midRoundSyncTimeOut = Math.Max(5.0f, midRoundSyncTimeOut * 1.5f); @@ -257,11 +266,6 @@ namespace Barotrauma.Networking client.NeedsMidRoundSync = true; client.MidRoundSyncTimeOut = Timing.TotalTime + midRoundSyncTimeOut; } - else - { - client.UnreceivedEntityEventCount = 0; - client.NeedsMidRoundSync = false; - } } ///