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)