22using System . Collections . Generic ;
33using System . Diagnostics . CodeAnalysis ;
44using System . Linq ;
5+ using System . Runtime . CompilerServices ;
56using System . Text ;
67using UnityEngine ;
78
@@ -443,10 +444,12 @@ internal void ChangeOwnership(NetworkObject networkObject, ulong clientId, bool
443444 return ;
444445 }
445446
447+ var distributedAuthorityMode = NetworkManager . DistributedAuthorityMode ;
448+
446449 // For client-server:
447450 // If ownership changes faster than the latency between the client-server and there are NetworkVariables being updated during ownership changes,
448451 // then notify the user they could potentially lose state updates if developer logging is enabled.
449- if ( NetworkManager . LogLevel == LogLevel . Developer && ! NetworkManager . DistributedAuthorityMode && m_LastChangeInOwnership . ContainsKey ( networkObject . NetworkObjectId ) && m_LastChangeInOwnership [ networkObject . NetworkObjectId ] > Time . realtimeSinceStartup )
452+ if ( NetworkManager . LogLevel == LogLevel . Developer && ! distributedAuthorityMode && m_LastChangeInOwnership . ContainsKey ( networkObject . NetworkObjectId ) && m_LastChangeInOwnership [ networkObject . NetworkObjectId ] > Time . realtimeSinceStartup )
450453 {
451454 for ( int i = 0 ; i < networkObject . ChildNetworkBehaviours . Count ; i ++ )
452455 {
@@ -458,7 +461,7 @@ internal void ChangeOwnership(NetworkObject networkObject, ulong clientId, bool
458461 }
459462 }
460463
461- if ( NetworkManager . DistributedAuthorityMode )
464+ if ( distributedAuthorityMode )
462465 {
463466 // Ensure only the session owner can change ownership (i.e. acquire) and that the session owner is not trying to assign a non-session owner client
464467 // ownership of a NetworkObject with SessionOwner permissions.
@@ -523,15 +526,6 @@ internal void ChangeOwnership(NetworkObject networkObject, ulong clientId, bool
523526 throw new SpawnStateException ( "Object is not spawned" ) ;
524527 }
525528
526- if ( networkObject . OwnerClientId == clientId && networkObject . PreviousOwnerId == clientId )
527- {
528- if ( NetworkManager . LogLevel == LogLevel . Developer )
529- {
530- NetworkLog . LogWarningServer ( $ "[Already Owner] Unnecessary ownership change for { networkObject . name } as it is already the owned by client-{ clientId } ") ;
531- }
532- return ;
533- }
534-
535529 if ( ! networkObject . Observers . Contains ( clientId ) )
536530 {
537531 if ( NetworkManager . LogLevel == LogLevel . Developer )
@@ -560,91 +554,8 @@ internal void ChangeOwnership(NetworkObject networkObject, ulong clientId, bool
560554 networkObject . SynchronizeOwnerNetworkVariables ( originalOwner , originalPreviousOwnerId ) ;
561555 }
562556
563- var size = 0 ;
564-
565- if ( NetworkManager . DistributedAuthorityMode )
566- {
567- var message = new ChangeOwnershipMessage
568- {
569- ChangeMessageType = isRequestApproval ? ChangeOwnershipMessage . ChangeType . RequestApproved : ChangeOwnershipMessage . ChangeType . OwnershipChanging ,
570- NetworkObjectId = networkObject . NetworkObjectId ,
571- OwnerClientId = networkObject . OwnerClientId ,
572- DistributedAuthorityMode = true ,
573- RequestClientId = networkObject . PreviousOwnerId ,
574- OwnershipFlags = ( ushort ) networkObject . Ownership ,
575- } ;
576-
577- // If we are connected to the CMB service or not the DAHost (i.e. pure DA-Clients only)
578- if ( NetworkManager . CMBServiceConnection || ! NetworkManager . DAHost )
579- {
580- // Calculate valid target client identifiers that should receive this change in ownership message.
581- var clientIds = new List < ulong > ( NetworkManager . ConnectedClientsIds . Count ) ;
582- foreach ( var id in NetworkManager . ConnectedClientsIds )
583- {
584- if ( id == NetworkManager . LocalClientId )
585- {
586- continue ;
587- }
588-
589- if ( networkObject . IsNetworkVisibleTo ( id ) && ! IsObjectVisibilityPending ( id , ref networkObject ) )
590- {
591- clientIds . Add ( id ) ;
592- }
593- }
594-
595- // Don't send the message if there are no valid receivers
596- if ( clientIds . Count > 0 )
597- {
598- message . ClientIds = clientIds . ToArray ( ) ;
599- message . ClientIdCount = clientIds . Count ;
600-
601- size = NetworkManager . ConnectionManager . SendMessage ( ref message , NetworkDelivery . ReliableSequenced , NetworkManager . ServerClientId ) ;
602- NetworkManager . NetworkMetrics . TrackOwnershipChangeSent ( NetworkManager . LocalClientId , networkObject , size ) ;
603- }
604- }
605- else // We are the DAHost so broadcast the ownership change
606- {
607- foreach ( var client in NetworkManager . ConnectedClients )
608- {
609- if ( client . Value . ClientId == NetworkManager . ServerClientId || IsObjectVisibilityPending ( client . Key , ref networkObject ) )
610- {
611- continue ;
612- }
613-
614- if ( networkObject . IsNetworkVisibleTo ( client . Value . ClientId ) )
615- {
616- size = NetworkManager . ConnectionManager . SendMessage ( ref message , NetworkDelivery . ReliableSequenced , client . Value . ClientId ) ;
617- NetworkManager . NetworkMetrics . TrackOwnershipChangeSent ( client . Key , networkObject , size ) ;
618- }
619- }
620- }
621- }
622- else // Normal Client-Server mode
623- {
624- var message = new ChangeOwnershipMessage
625- {
626- ChangeMessageType = ChangeOwnershipMessage . ChangeType . OwnershipChanging ,
627- NetworkObjectId = networkObject . NetworkObjectId ,
628- OwnerClientId = networkObject . OwnerClientId ,
629- } ;
630- foreach ( var client in NetworkManager . ConnectedClients )
631- {
632- if ( client . Value . ClientId == NetworkManager . ServerClientId || IsObjectVisibilityPending ( client . Key , ref networkObject ) )
633- {
634- continue ;
635- }
636- if ( networkObject . IsNetworkVisibleTo ( client . Value . ClientId ) )
637- {
638- if ( client . Key != client . Value . ClientId )
639- {
640- NetworkLog . LogError ( $ "[Client-{ client . Key } ] Client key ({ client . Key } ) does not match the { nameof ( NetworkClient ) } client Id { client . Value . ClientId } ! Client-{ client . Key } will not receive ownership changed message!") ;
641- continue ;
642- }
643- size = NetworkManager . ConnectionManager . SendMessage ( ref message , NetworkDelivery . ReliableSequenced , client . Value . ClientId ) ;
644- NetworkManager . NetworkMetrics . TrackOwnershipChangeSent ( client . Key , networkObject , size ) ;
645- }
646- }
647- }
557+ // Send a message to client observers
558+ SendChangeOwnershipMessage ( ref networkObject , isRequestApproval ) ;
648559
649560 // After we have sent the change ownership message to all client observers, invoke the ownership changed notification.
650561 // !!Important!!
@@ -653,7 +564,7 @@ internal void ChangeOwnership(NetworkObject networkObject, ulong clientId, bool
653564 networkObject . InvokeOwnershipChanged ( networkObject . PreviousOwnerId , clientId ) ;
654565
655566 // Keep track of the ownership change frequency to assure a user is not exceeding changes faster than 2x the current Tick Rate.
656- if ( ! NetworkManager . DistributedAuthorityMode )
567+ if ( ! distributedAuthorityMode )
657568 {
658569 if ( ! m_LastChangeInOwnership . ContainsKey ( networkObject . NetworkObjectId ) )
659570 {
@@ -671,7 +582,7 @@ internal void ChangeOwnership(NetworkObject networkObject, ulong clientId, bool
671582 /// </summary>
672583 /// <param name="clientId">the client to check</param>
673584 /// <param name="networkObject">the <see cref="NetworkObject"/> to check if it is pending show</param>
674- [ System . Runtime . CompilerServices . MethodImpl ( System . Runtime . CompilerServices . MethodImplOptions . AggressiveInlining ) ]
585+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
675586 internal bool IsObjectVisibilityPending ( ulong clientId , ref NetworkObject networkObject )
676587 {
677588 if ( NetworkManager . DistributedAuthorityMode && ClientsToShowObject . ContainsKey ( networkObject ) )
@@ -685,6 +596,71 @@ internal bool IsObjectVisibilityPending(ulong clientId, ref NetworkObject networ
685596 return false ;
686597 }
687598
599+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
600+ private void SendChangeOwnershipMessage ( ref NetworkObject networkObject , bool isRequestApproval )
601+ {
602+ var distributedAuthorityMode = NetworkManager . DistributedAuthorityMode ;
603+ var daClient = distributedAuthorityMode && ! NetworkManager . DAHost ;
604+
605+ int size ;
606+ List < ulong > targetClientIds = null ;
607+ var message = new ChangeOwnershipMessage
608+ {
609+ ChangeMessageType = ChangeOwnershipMessage . ChangeType . OwnershipChanging ,
610+ NetworkObjectId = networkObject . NetworkObjectId ,
611+ OwnerClientId = networkObject . OwnerClientId ,
612+ } ;
613+
614+ if ( distributedAuthorityMode )
615+ {
616+ message . DistributedAuthorityMode = true ;
617+ message . RequestClientId = networkObject . PreviousOwnerId ;
618+ message . OwnershipFlags = ( ushort ) networkObject . Ownership ;
619+
620+ if ( isRequestApproval )
621+ {
622+ message . ChangeMessageType = ChangeOwnershipMessage . ChangeType . RequestApproved ;
623+ }
624+
625+ // Allocate our targetClientIds list
626+ if ( daClient )
627+ {
628+ targetClientIds = new List < ulong > ( NetworkManager . ConnectedClientsIds . Count ) ;
629+ }
630+ }
631+
632+ foreach ( var id in NetworkManager . ConnectedClientsIds )
633+ {
634+ // Don't send a message to self, or to any client that either can't see the object or visibility is pending
635+ if ( id == NetworkManager . LocalClientId || ! networkObject . IsNetworkVisibleTo ( id ) || IsObjectVisibilityPending ( id , ref networkObject ) )
636+ {
637+ continue ;
638+ }
639+
640+ // If we're a DA client, calculate valid target client identifiers that should receive this change in ownership message.
641+ if ( daClient )
642+ {
643+ targetClientIds . Add ( id ) ;
644+ continue ;
645+ }
646+
647+ // If we're the server or DAHost, send the message directly to the client
648+ size = NetworkManager . ConnectionManager . SendMessage ( ref message , NetworkDelivery . ReliableSequenced , id ) ;
649+ NetworkManager . NetworkMetrics . TrackOwnershipChangeSent ( id , networkObject , size ) ;
650+ }
651+
652+ // If we're a DA client, now we send the message with the collectedIds to the server.
653+ if ( daClient && targetClientIds . Count > 0 )
654+ {
655+ message . ClientIds = targetClientIds . ToArray ( ) ;
656+ message . ClientIdCount = targetClientIds . Count ;
657+
658+ size = NetworkManager . ConnectionManager . SendMessage ( ref message , NetworkDelivery . ReliableSequenced , NetworkManager . ServerClientId ) ;
659+ NetworkManager . NetworkMetrics . TrackOwnershipChangeSent ( NetworkManager . ServerClientId , networkObject , size ) ;
660+ }
661+ }
662+
663+
688664 internal bool HasPrefab ( NetworkObject . SceneObject sceneObject )
689665 {
690666 if ( ! NetworkManager . NetworkConfig . EnableSceneManagement || ! sceneObject . IsSceneObject )
0 commit comments