From 5cd2a5a83819bc0d81e21560540262a34bbbdc49 Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Tue, 13 Jun 2017 20:47:15 +0300 Subject: [PATCH] NetEntityEventManager stops writing events to a message if the MTU is about to be exceeded and leaves the remaining events for the next message. Also got rid of the (now unnecessary) "maximum EntityEvent size exceeded" debug assertion; character spawn messages often went over the limit, causing issues when running debug builds. --- .../NetEntityEvent/NetEntityEventManager.cs | 57 +++++++++++-------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/Barotrauma/Source/Networking/NetEntityEvent/NetEntityEventManager.cs b/Barotrauma/Source/Networking/NetEntityEvent/NetEntityEventManager.cs index 495f4e705..186bbc7d4 100644 --- a/Barotrauma/Source/Networking/NetEntityEvent/NetEntityEventManager.cs +++ b/Barotrauma/Source/Networking/NetEntityEvent/NetEntityEventManager.cs @@ -1,10 +1,6 @@ using Lidgren.Network; using System; using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Barotrauma.Networking { @@ -12,55 +8,66 @@ namespace Barotrauma.Networking { public const int MaxEventBufferLength = 1024; public const int MaxEventsPerWrite = 64; - - //public UInt16 LastReceivedEntityEventID - //{ - // get { return lastReceivedEntityEventID; } - //} - + /// /// Write the events to the outgoing message. The recipient parameter is only needed for ServerEntityEventManager /// protected void Write(NetOutgoingMessage msg, List eventsToSync, Client recipient = null) { - msg.Write(eventsToSync[0].ID); - msg.Write((byte)eventsToSync.Count); + //write into a temporary buffer so we can write the number of events before the actual data + NetBuffer tempBuffer = new NetBuffer(); + int eventCount = 0; foreach (NetEntityEvent e in eventsToSync) { //write into a temporary buffer so we can write the length before the actual data - NetBuffer tempBuffer = new NetBuffer(); + NetBuffer tempEventBuffer = new NetBuffer(); try { - WriteEvent(tempBuffer, e, recipient); + WriteEvent(tempEventBuffer, e, recipient); } catch (Exception exception) { - DebugConsole.ThrowError("Failed to write an event for the entity \""+e.Entity+"\"", exception); + DebugConsole.ThrowError("Failed to write an event for the entity \"" + e.Entity + "\"", exception); + + //write an empty event to avoid messing up IDs + //(otherwise the clients might read the next event in the message and think its ID + //is consecutive to the previous one, even though we skipped over this broken event) + tempBuffer.Write((UInt16)0); + tempBuffer.WritePadBits(); + eventCount++; continue; } - Debug.Assert( - tempBuffer.LengthBytes < 128, - "Maximum EntityEvent size exceeded when serializing \""+e.Entity+"\"!"); - + if (msg.LengthBytes + tempBuffer.LengthBytes + tempEventBuffer.LengthBytes > NetPeerConfiguration.kDefaultMTU - 20) + { + //no more room in this packet + break; + } + //the ID has been taken by another entity (the original entity has been removed) -> write an empty event if (Entity.FindEntityByID(e.Entity.ID) != e.Entity) { //technically the clients don't have any use for these, but removing events and shifting the IDs of all //consecutive ones is so error-prone that I think this is a safer option - msg.Write((UInt16)0); - msg.WritePadBits(); + tempBuffer.Write((UInt16)0); + tempBuffer.WritePadBits(); } else { - msg.Write((UInt16)e.Entity.ID); - msg.Write((byte)tempBuffer.LengthBytes); - msg.Write(tempBuffer); - msg.WritePadBits(); + tempBuffer.Write((UInt16)e.Entity.ID); + tempBuffer.Write((byte)tempEventBuffer.LengthBytes); + tempBuffer.Write(tempEventBuffer); + tempBuffer.WritePadBits(); } + + eventCount++; } + + msg.Write(eventsToSync[0].ID); + msg.Write((byte)eventCount); + msg.Write(tempBuffer); } protected virtual void WriteEvent(NetBuffer buffer, NetEntityEvent entityEvent, Client recipient = null)