From ef9afedf42f4ca6539f8feae5670f52fcb1c48df Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Thu, 18 Oct 2018 00:18:57 +0300 Subject: [PATCH] Added a level equality check to client error handling to make it easier to diagnose bugs like #848 in the future. --- .../Source/Networking/GameClient.cs | 3 ++- .../BarotraumaShared/Source/Map/Levels/Level.cs | 13 +++++++++++++ .../Source/Networking/GameServer.cs | 16 +++++++++++----- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs b/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs index 08897f112..541c878df 100644 --- a/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs +++ b/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs @@ -1647,11 +1647,12 @@ namespace Barotrauma.Networking return false; } - public void ReportError(ClientNetError error,UInt16 expectedID=0,UInt16 eventID=0,UInt16 entityID=0) + public void ReportError(ClientNetError error, UInt16 expectedID = 0, UInt16 eventID = 0, UInt16 entityID = 0) { NetOutgoingMessage outMsg = client.CreateMessage(); outMsg.Write((byte)ClientPacketHeader.ERROR); outMsg.Write((byte)error); + outMsg.Write(Level.Loaded == null ? 0 : Level.Loaded.EqualityCheckVal); switch (error) { case ClientNetError.MISSING_EVENT: diff --git a/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs b/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs index ec25608db..419bab0b6 100644 --- a/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs +++ b/Barotrauma/BarotraumaShared/Source/Map/Levels/Level.cs @@ -128,6 +128,16 @@ namespace Barotrauma get { return seed; } } + /// + /// A random integer assigned at the end of level generation. If these values differ between clients/server, + /// it means the levels aren't identical for some reason and there will most likely be major ID mismatches. + /// + public int EqualityCheckVal + { + get; + private set; + } + public float Difficulty { get; @@ -538,6 +548,9 @@ namespace Barotrauma GenerateSeaFloor(mirror); backgroundSpriteManager.PlaceSprites(this, generationParams.BackgroundSpriteAmount); + + EqualityCheckVal = Rand.Int(int.MaxValue, Rand.RandSync.Server); + #if CLIENT backgroundCreatureManager.SpawnSprites(80); #endif diff --git a/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs b/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs index 0989ffc84..e1d2b39f7 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs @@ -618,6 +618,7 @@ namespace Barotrauma.Networking string errorStr = "Unhandled error report"; ClientNetError error = (ClientNetError)inc.ReadByte(); + int levelEqualityCheckVal = inc.ReadInt32(); switch (error) { case ClientNetError.MISSING_EVENT: @@ -631,30 +632,35 @@ namespace Barotrauma.Networking 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() + ")"; + 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() + ")"; + 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() + ")"; + 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() + ")"; + 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, something went wrong during level generation (seed " + Level.Loaded.Seed + ")."; + } + if (c == null) { KickClient(inc.SenderConnection, errorStr); } else { - GameServer.Log(c.Name + " has reported an error: " + errorStr, ServerLog.MessageType.Error); + Log(c.Name + " has reported an error: " + errorStr, ServerLog.MessageType.Error); KickClient(c, errorStr); } }