From e94a50a29a4443e822325c4a5d33be0e3ded484b Mon Sep 17 00:00:00 2001 From: Regalis Date: Sat, 8 Apr 2017 20:09:05 +0300 Subject: [PATCH] The server keeps track of which ID a client is going to switch to when midround syncing is done, and switches the ID immediately when the client is in sync (instead of waiting for the client to report the new ID). Fixes clients occasionally getting kicked out the moment they're in sync, because their latest received ID is still set to the ID of the last unique event and the server thinks they're requesting some old event that doesn't necessarily exist anymore. + added a debug command that creates a ton of entity events --- Subsurface/Source/DebugConsole.cs | 33 +++++++++++++++++++ Subsurface/Source/Networking/Client.cs | 1 + Subsurface/Source/Networking/GameServer.cs | 1 + .../ServerEntityEventManager.cs | 11 ++++--- 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/Subsurface/Source/DebugConsole.cs b/Subsurface/Source/DebugConsole.cs index 17dcde1e5..4d5b7ad40 100644 --- a/Subsurface/Source/DebugConsole.cs +++ b/Subsurface/Source/DebugConsole.cs @@ -708,6 +708,39 @@ namespace Barotrauma GameMain.Server.ShowNetStats = !GameMain.Server.ShowNetStats; break; +#if DEBUG + case "spamevents": + foreach (Item item in Item.ItemList) + { + for (int i = 0; i(); + if (itemContainer != null) + { + GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.InventoryState }); + } + + GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.Status }); + + item.NeedsPositionUpdate = true; + } + } + + foreach (Character c in Character.CharacterList) + { + GameMain.Server.CreateEntityEvent(c, new object[] { NetEntityEvent.Type.Status }); + } + + foreach (Structure wall in Structure.WallList) + { + GameMain.Server.CreateEntityEvent(wall); + } + break; +#endif case "cleanbuild": GameMain.Config.MusicVolume = 0.5f; GameMain.Config.SoundVolume = 0.5f; diff --git a/Subsurface/Source/Networking/Client.cs b/Subsurface/Source/Networking/Client.cs index c35e1023c..faf46853a 100644 --- a/Subsurface/Source/Networking/Client.cs +++ b/Subsurface/Source/Networking/Client.cs @@ -50,6 +50,7 @@ namespace Barotrauma.Networking public bool NeedsMidRoundSync; //how many unique events the client missed before joining the server public UInt16 UnreceivedEntityEventCount; + public UInt16 FirstNewEventID; private List kickVoters; diff --git a/Subsurface/Source/Networking/GameServer.cs b/Subsurface/Source/Networking/GameServer.cs index d6ab8044b..7f8569503 100644 --- a/Subsurface/Source/Networking/GameServer.cs +++ b/Subsurface/Source/Networking/GameServer.cs @@ -692,6 +692,7 @@ namespace Barotrauma.Networking c.UnreceivedEntityEventCount == 0) { c.NeedsMidRoundSync = false; + lastRecvEntityEventID = (UInt16)(c.FirstNewEventID - 1); } else { diff --git a/Subsurface/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs b/Subsurface/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs index 9804f5537..3b45edd46 100644 --- a/Subsurface/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs +++ b/Subsurface/Source/Networking/NetEntityEvent/ServerEntityEventManager.cs @@ -212,15 +212,16 @@ namespace Barotrauma.Networking if (client.NeedsMidRoundSync) { msg.Write((byte)ServerNetObject.ENTITY_EVENT_INITIAL); + //how many (unique) events the clients had missed before joining client.UnreceivedEntityEventCount = (UInt16)uniqueEvents.Count; - msg.Write(client.UnreceivedEntityEventCount); - //ID of the first event sent after the client joined //(after the client has been synced they'll switch their lastReceivedID //to the one before this, and the eventmanagers will start to function "normally") - msg.Write(events.Count == 0 ? (UInt16)0 : events[events.Count - 1].ID); + client.FirstNewEventID = events.Count == 0 ? (UInt16)0 : events[events.Count - 1].ID; + msg.Write(client.UnreceivedEntityEventCount); + msg.Write(client.FirstNewEventID); Write(msg, eventsToSync, client); } else @@ -273,14 +274,16 @@ namespace Barotrauma.Networking if (uniqueEvents.Count == 0 || (events.Count > 0 && events[0].ID == uniqueEvents[0].ID)) { client.UnreceivedEntityEventCount = 0; + client.FirstNewEventID = 0; client.NeedsMidRoundSync = false; } else { double midRoundSyncTimeOut = uniqueEvents.Count / MaxEventsPerWrite * server.UpdateInterval.TotalSeconds; - midRoundSyncTimeOut = Math.Max(5.0f, midRoundSyncTimeOut * 1.5f); + midRoundSyncTimeOut = Math.Max(5.0f, midRoundSyncTimeOut * 2.0f); client.UnreceivedEntityEventCount = (UInt16)uniqueEvents.Count; + client.FirstNewEventID = 0; client.NeedsMidRoundSync = true; client.MidRoundSyncTimeOut = Timing.TotalTime + midRoundSyncTimeOut; }