8a2a718...633e54b
commit 633e54b2ffb4e5ec13c1fa5ce8170f5e726f8e10
Author: Joonas Rikkonen <poe.regalis@gmail.com>
Date: Tue Mar 19 18:02:21 2019 +0200
Include level equality check value in round start messages, so clients immediately know if the level generated at their end doesn't match the one generated by the server (which will cause ID mismatches and more hard-to-diagnose desync kicks during the rounds). Related to #848
commit 68e410705115ece2fcc4ca9c7d9856cc1dd5c1f8
Author: Joonas Rikkonen <poe.regalis@gmail.com>
Date: Tue Mar 19 18:01:01 2019 +0200
Readded client error handling from ef9afed. Not sure how it got removed, probably a messed up merge somewhere down the line when working on the client-server-separation branch or when merging the Steam version work from dev to master. In any case this should help diagnose desync kicks such as #1293.
This commit is contained in:
@@ -1029,9 +1029,10 @@ namespace Barotrauma.Networking
|
||||
|
||||
EndVoteTickBox.Selected = false;
|
||||
|
||||
int seed = inc.ReadInt32();
|
||||
string levelSeed = inc.ReadString();
|
||||
float levelDifficulty = inc.ReadFloat();
|
||||
int seed = inc.ReadInt32();
|
||||
string levelSeed = inc.ReadString();
|
||||
int levelEqualityCheckVal = inc.ReadInt32();
|
||||
float levelDifficulty = inc.ReadFloat();
|
||||
|
||||
byte losMode = inc.ReadByte();
|
||||
|
||||
@@ -1100,6 +1101,14 @@ namespace Barotrauma.Networking
|
||||
mirrorLevel: campaign.Map.CurrentLocation != campaign.Map.SelectedConnection.Locations[0]);
|
||||
}
|
||||
|
||||
if (Level.Loaded.EqualityCheckVal != levelEqualityCheckVal)
|
||||
{
|
||||
string errorMsg = " Level equality check failed. The level generated at your end doesn't match the level generated by the server (seed " + Level.Loaded.Seed + ").";
|
||||
DebugConsole.ThrowError(errorMsg, createMessageBox: true);
|
||||
CoroutineManager.StartCoroutine(EndGame(""));
|
||||
yield return CoroutineStatus.Failure;
|
||||
}
|
||||
|
||||
if (respawnAllowed) respawnManager = new RespawnManager(this, GameMain.NetLobbyScreen.UsingShuttle ? GameMain.NetLobbyScreen.SelectedShuttle : null);
|
||||
|
||||
gameStarted = true;
|
||||
@@ -1414,7 +1423,7 @@ namespace Barotrauma.Networking
|
||||
break;
|
||||
case ServerNetObject.ENTITY_EVENT:
|
||||
case ServerNetObject.ENTITY_EVENT_INITIAL:
|
||||
entityEventManager.Read(objHeader, inc, sendingTime, entities);
|
||||
if (!entityEventManager.Read(objHeader, inc, sendingTime, entities)) { break; }
|
||||
break;
|
||||
case ServerNetObject.CHAT_MESSAGE:
|
||||
ChatMessage.ClientRead(inc);
|
||||
|
||||
+4
-2
@@ -114,9 +114,9 @@ namespace Barotrauma.Networking
|
||||
private UInt16? firstNewID;
|
||||
|
||||
/// <summary>
|
||||
/// Read the events from the message, ignoring ones we've already received
|
||||
/// Read the events from the message, ignoring ones we've already received. Returns false if reading the events fails.
|
||||
/// </summary>
|
||||
public void Read(ServerNetObject type, NetIncomingMessage msg, float sendingTime, List<IServerSerializable> entities)
|
||||
public bool Read(ServerNetObject type, NetIncomingMessage msg, float sendingTime, List<IServerSerializable> entities)
|
||||
{
|
||||
UInt16 unreceivedEntityEventCount = 0;
|
||||
|
||||
@@ -192,6 +192,7 @@ namespace Barotrauma.Networking
|
||||
"Received msg " + thisEventID + ", entity " + entityID + " not found",
|
||||
Microsoft.Xna.Framework.Color.Red);
|
||||
GameMain.Client.ReportError(ClientNetError.MISSING_ENTITY, eventID: thisEventID, entityID: entityID);
|
||||
return false;
|
||||
}
|
||||
|
||||
msg.Position += msgLength * 8;
|
||||
@@ -230,6 +231,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
msg.ReadPadBits();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void WriteEvent(NetBuffer buffer, NetEntityEvent entityEvent, Client recipient = null)
|
||||
|
||||
@@ -734,9 +734,57 @@ namespace Barotrauma.Networking
|
||||
fileSender.ReadFileRequest(inc, connectedClient);
|
||||
}
|
||||
break;
|
||||
case ClientPacketHeader.ERROR:
|
||||
HandleClientError(inc, connectedClient);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleClientError(NetIncomingMessage inc, Client c)
|
||||
{
|
||||
string errorStr = "Unhandled error report";
|
||||
|
||||
ClientNetError error = (ClientNetError)inc.ReadByte();
|
||||
int levelEqualityCheckVal = inc.ReadInt32();
|
||||
switch (error)
|
||||
{
|
||||
case ClientNetError.MISSING_EVENT:
|
||||
UInt16 expectedID = inc.ReadUInt16();
|
||||
UInt16 receivedID = inc.ReadUInt16();
|
||||
errorStr = "Expecting event id " + expectedID.ToString() + ", received " + receivedID.ToString();
|
||||
break;
|
||||
case ClientNetError.MISSING_ENTITY:
|
||||
UInt16 eventID = inc.ReadUInt16();
|
||||
UInt16 entityID = inc.ReadUInt16();
|
||||
Entity entity = Entity.FindEntityByID(entityID);
|
||||
if (entity == null)
|
||||
{
|
||||
errorStr = "Received an update for an entity that doesn't exist (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
|
||||
}
|
||||
else if (entity is Character character)
|
||||
{
|
||||
errorStr = "Missing character " + character.Name + " (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
|
||||
}
|
||||
else if (entity is Item item)
|
||||
{
|
||||
errorStr = "Missing item " + item.Name + " (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
|
||||
}
|
||||
else
|
||||
{
|
||||
errorStr = "Missing entity " + entity.ToString() + " (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (Level.Loaded != null && levelEqualityCheckVal != Level.Loaded.EqualityCheckVal)
|
||||
{
|
||||
errorStr += " Level equality check failed. The level generated at your end doesn't match the level generated by the server (seed " + Level.Loaded.Seed + ").";
|
||||
}
|
||||
|
||||
Log(c.Name + " has reported an error: " + errorStr, ServerLog.MessageType.Error);
|
||||
KickClient(c, errorStr);
|
||||
}
|
||||
|
||||
public override void CreateEntityEvent(INetSerializable entity, object[] extraData = null)
|
||||
{
|
||||
if (!(entity is IServerSerializable)) throw new InvalidCastException("entity is not IServerSerializable");
|
||||
@@ -1759,6 +1807,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
msg.Write(seed);
|
||||
msg.Write(GameMain.GameSession.Level.Seed);
|
||||
msg.Write(GameMain.GameSession.Level.EqualityCheckVal);
|
||||
msg.Write(serverSettings.SelectedLevelDifficulty);
|
||||
|
||||
msg.Write((byte)GameMain.Config.LosMode);
|
||||
|
||||
Reference in New Issue
Block a user