@@ -58,6 +58,8 @@ public SendQueueItem(NetworkDelivery delivery, int writerSize, Allocator writerA
5858 private Dictionary < Type , uint > m_MessageTypes = new Dictionary < Type , uint > ( ) ;
5959 private Dictionary < ulong , NativeList < SendQueueItem > > m_SendQueues = new Dictionary < ulong , NativeList < SendQueueItem > > ( ) ;
6060
61+ private HashSet < ulong > m_DisconnectedClients = new HashSet < ulong > ( ) ;
62+
6163 // This is m_PerClientMessageVersion[clientId][messageType] = version
6264 private Dictionary < ulong , Dictionary < Type , int > > m_PerClientMessageVersions = new Dictionary < ulong , Dictionary < Type , int > > ( ) ;
6365 private Dictionary < uint , Type > m_MessagesByHash = new Dictionary < uint , Type > ( ) ;
@@ -155,8 +157,9 @@ public unsafe void Dispose()
155157 // from the queue.
156158 foreach ( var kvp in m_SendQueues )
157159 {
158- CleanupDisconnectedClient ( kvp . Key ) ;
160+ ClientDisconnected ( kvp . Key ) ;
159161 }
162+ CleanupDisconnectedClients ( ) ;
160163
161164 for ( var queueIndex = 0 ; queueIndex < m_IncomingMessageQueue . Length ; ++ queueIndex )
162165 {
@@ -464,41 +467,37 @@ internal void ClientConnected(ulong clientId)
464467 }
465468
466469 internal void ClientDisconnected ( ulong clientId )
470+ {
471+ m_DisconnectedClients . Add ( clientId ) ;
472+ }
473+
474+ private void CleanupDisconnectedClient ( ulong clientId )
467475 {
468476 if ( ! m_SendQueues . ContainsKey ( clientId ) )
469477 {
470478 return ;
471479 }
472- CleanupDisconnectedClient ( clientId ) ;
473- m_SendQueues . Remove ( clientId ) ;
474- }
475480
476- private void CleanupDisconnectedClient ( ulong clientId )
477- {
478481 var queue = m_SendQueues [ clientId ] ;
479482 for ( var i = 0 ; i < queue . Length ; ++ i )
480483 {
481484 queue . ElementAt ( i ) . Writer . Dispose ( ) ;
482485 }
483486
484487 queue . Dispose ( ) ;
488+ m_SendQueues . Remove ( clientId ) ;
489+
490+ m_PerClientMessageVersions . Remove ( clientId ) ;
485491 }
486492
487493 internal void CleanupDisconnectedClients ( )
488494 {
489- var removeList = new NativeList < ulong > ( Allocator . Temp ) ;
490- foreach ( var clientId in m_PerClientMessageVersions . Keys )
495+ foreach ( var clientId in m_DisconnectedClients )
491496 {
492- if ( ! m_SendQueues . ContainsKey ( clientId ) )
493- {
494- removeList . Add ( clientId ) ;
495- }
497+ CleanupDisconnectedClient ( clientId ) ;
496498 }
497499
498- foreach ( var clientId in removeList )
499- {
500- m_PerClientMessageVersions . Remove ( clientId ) ;
501- }
500+ m_DisconnectedClients . Clear ( ) ;
502501 }
503502
504503 public static int CreateMessageAndGetVersion < T > ( ) where T : INetworkMessage , new ( )
@@ -637,6 +636,10 @@ internal unsafe int SendPreSerializedMessage<TMessageType>(in FastBufferWriter t
637636
638637 for ( var i = 0 ; i < clientIds . Count ; ++ i )
639638 {
639+ if ( m_DisconnectedClients . Contains ( clientIds [ i ] ) )
640+ {
641+ continue ;
642+ }
640643 var messageVersion = 0 ;
641644 // Special case because this is the message that carries the version info - thus the version info isn't
642645 // populated yet when we get this. The first part of this message always has to be the version data
@@ -788,6 +791,14 @@ internal unsafe void ProcessSendQueues()
788791 for ( var i = 0 ; i < sendQueueItem . Length ; ++ i )
789792 {
790793 ref var queueItem = ref sendQueueItem . ElementAt ( i ) ;
794+ // this is checked at every iteration because
795+ // 1) each writer needs to be disposed, so we have to do the full loop regardless, and
796+ // 2) the call to m_MessageSender.Send() may result in calling ClientDisconnected(), so the result of this check may change partway through iteration
797+ if ( m_DisconnectedClients . Contains ( clientId ) )
798+ {
799+ queueItem . Writer . Dispose ( ) ;
800+ continue ;
801+ }
791802 if ( queueItem . BatchHeader . BatchCount == 0 )
792803 {
793804 queueItem . Writer . Dispose ( ) ;
0 commit comments