2
2
using System . Collections . Generic ;
3
3
using System . Diagnostics . CodeAnalysis ;
4
4
using System . Linq ;
5
+ using System . Runtime . CompilerServices ;
5
6
using System . Text ;
6
7
using UnityEngine ;
7
8
@@ -443,10 +444,12 @@ internal void ChangeOwnership(NetworkObject networkObject, ulong clientId, bool
443
444
return ;
444
445
}
445
446
447
+ var distributedAuthorityMode = NetworkManager . DistributedAuthorityMode ;
448
+
446
449
// For client-server:
447
450
// If ownership changes faster than the latency between the client-server and there are NetworkVariables being updated during ownership changes,
448
451
// 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 )
450
453
{
451
454
for ( int i = 0 ; i < networkObject . ChildNetworkBehaviours . Count ; i ++ )
452
455
{
@@ -458,7 +461,7 @@ internal void ChangeOwnership(NetworkObject networkObject, ulong clientId, bool
458
461
}
459
462
}
460
463
461
- if ( NetworkManager . DistributedAuthorityMode )
464
+ if ( distributedAuthorityMode )
462
465
{
463
466
// 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
464
467
// ownership of a NetworkObject with SessionOwner permissions.
@@ -523,15 +526,6 @@ internal void ChangeOwnership(NetworkObject networkObject, ulong clientId, bool
523
526
throw new SpawnStateException ( "Object is not spawned" ) ;
524
527
}
525
528
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
-
535
529
if ( ! networkObject . Observers . Contains ( clientId ) )
536
530
{
537
531
if ( NetworkManager . LogLevel == LogLevel . Developer )
@@ -560,91 +554,8 @@ internal void ChangeOwnership(NetworkObject networkObject, ulong clientId, bool
560
554
networkObject . SynchronizeOwnerNetworkVariables ( originalOwner , originalPreviousOwnerId ) ;
561
555
}
562
556
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 ) ;
648
559
649
560
// After we have sent the change ownership message to all client observers, invoke the ownership changed notification.
650
561
// !!Important!!
@@ -653,7 +564,7 @@ internal void ChangeOwnership(NetworkObject networkObject, ulong clientId, bool
653
564
networkObject . InvokeOwnershipChanged ( networkObject . PreviousOwnerId , clientId ) ;
654
565
655
566
// 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 )
657
568
{
658
569
if ( ! m_LastChangeInOwnership . ContainsKey ( networkObject . NetworkObjectId ) )
659
570
{
@@ -671,7 +582,7 @@ internal void ChangeOwnership(NetworkObject networkObject, ulong clientId, bool
671
582
/// </summary>
672
583
/// <param name="clientId">the client to check</param>
673
584
/// <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 ) ]
675
586
internal bool IsObjectVisibilityPending ( ulong clientId , ref NetworkObject networkObject )
676
587
{
677
588
if ( NetworkManager . DistributedAuthorityMode && ClientsToShowObject . ContainsKey ( networkObject ) )
@@ -685,6 +596,71 @@ internal bool IsObjectVisibilityPending(ulong clientId, ref NetworkObject networ
685
596
return false ;
686
597
}
687
598
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
+
688
664
internal bool HasPrefab ( NetworkObject . SceneObject sceneObject )
689
665
{
690
666
if ( ! NetworkManager . NetworkConfig . EnableSceneManagement || ! sceneObject . IsSceneObject )
0 commit comments