Fixed clients who leave a server and re-join becoming desynced and not being kicked by the server.

The clients didn't reset their ChatMessage.LastID, which caused an exception to be thrown when clamping the chatmsg ID server-side, preventing the server from updating the lastRecvEntityEventID of the client later in the method. The server wouldn't kick the client, because ServerEntityEventManager wouldn't handle cases where a client is waiting for an event that doesn't exist anymore.
This commit is contained in:
Regalis
2017-03-14 22:33:33 +02:00
parent ac549f0feb
commit 8d8620047d
3 changed files with 18 additions and 5 deletions

View File

@@ -72,8 +72,11 @@ namespace Barotrauma.Networking
var newEvent = new ServerEntityEvent(entity, (UInt16)(ID + 1));
if (extraData != null) newEvent.SetData(extraData);
events.RemoveAll(e => NetIdUtils.IdMoreRecent((UInt16)(lastSentToAll+1),e.ID)); //remove events that have been sent to all clients, they are redundant now
//remove events that have been sent to all clients, they are redundant now
//keep at least one event in the list (lastSentToAll == e.ID) so we can use it to keep track of the latest ID
events.RemoveAll(e => NetIdUtils.IdMoreRecent(lastSentToAll, e.ID));
for (int i = events.Count - 1; i >= 0; i--)
{
//we already have an identical event that's waiting to be sent
@@ -139,6 +142,14 @@ namespace Barotrauma.Networking
if (toKick != null) toKick.ForEach(c => server.DisconnectClient(c, "", "You have been disconnected because of excessive desync"));
}
if (events.Count > 0)
{
//the client is waiting for an event that we don't have anymore
//(the ID they're expecting is smaller than the ID of the first event in our list)
List<Client> toKick = inGameClients.FindAll(c => NetIdUtils.IdMoreRecent(events[0].ID, (UInt16)(c.lastRecvEntityEventID+1)));
if (toKick != null) toKick.ForEach(c => server.DisconnectClient(c, "", "You have been disconnected because of excessive desync"));
}
}
var timedOutClients = clients.FindAll(c => c.inGame && c.NeedsMidRoundSync && Timing.TotalTime > c.MidRoundSyncTimeOut);
@@ -229,7 +240,7 @@ namespace Barotrauma.Networking
{
startIndex--;
}
for (int i = startIndex; i < eventList.Count; i++)
{
//find the first event that hasn't been sent in 1.5 * roundtriptime or at all