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:
@@ -99,6 +99,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
otherClients = new List<Client>();
|
otherClients = new List<Client>();
|
||||||
|
|
||||||
|
ChatMessage.LastID = 0;
|
||||||
GameMain.NetLobbyScreen = new NetLobbyScreen();
|
GameMain.NetLobbyScreen = new NetLobbyScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -713,7 +713,8 @@ namespace Barotrauma.Networking
|
|||||||
DebugConsole.ThrowError("client.lastRecvEntityEventID > lastEntityEventID");
|
DebugConsole.ThrowError("client.lastRecvEntityEventID > lastEntityEventID");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
c.lastRecvChatMsgID = NetIdUtils.Clamp(c.lastRecvChatMsgID, lastRecvChatMsgID, c.lastChatMsgQueueID);
|
if (NetIdUtils.IdMoreRecent(lastRecvChatMsgID, c.lastRecvChatMsgID)) c.lastRecvChatMsgID = lastRecvChatMsgID;
|
||||||
|
if (NetIdUtils.IdMoreRecent(c.lastRecvChatMsgID, c.lastChatMsgQueueID)) c.lastRecvChatMsgID = c.lastChatMsgQueueID;
|
||||||
|
|
||||||
if (NetIdUtils.IdMoreRecent(lastRecvEntitySpawnID, c.lastRecvEntitySpawnID)) c.lastRecvEntitySpawnID = lastRecvEntitySpawnID;
|
if (NetIdUtils.IdMoreRecent(lastRecvEntitySpawnID, c.lastRecvEntitySpawnID)) c.lastRecvEntitySpawnID = lastRecvEntitySpawnID;
|
||||||
if (NetIdUtils.IdMoreRecent(c.lastRecvEntitySpawnID, lastEntitySpawnID)) c.lastRecvEntitySpawnID = lastEntitySpawnID;
|
if (NetIdUtils.IdMoreRecent(c.lastRecvEntitySpawnID, lastEntitySpawnID)) c.lastRecvEntitySpawnID = lastEntitySpawnID;
|
||||||
|
|||||||
@@ -73,7 +73,10 @@ namespace Barotrauma.Networking
|
|||||||
var newEvent = new ServerEntityEvent(entity, (UInt16)(ID + 1));
|
var newEvent = new ServerEntityEvent(entity, (UInt16)(ID + 1));
|
||||||
if (extraData != null) newEvent.SetData(extraData);
|
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--)
|
for (int i = events.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
//we already have an identical event that's waiting to be sent
|
//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 (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);
|
var timedOutClients = clients.FindAll(c => c.inGame && c.NeedsMidRoundSync && Timing.TotalTime > c.MidRoundSyncTimeOut);
|
||||||
|
|||||||
Reference in New Issue
Block a user