@@ -180,24 +180,16 @@ protected NetworkManager GetAuthorityNetworkManager()
180180        { 
181181            if  ( m_UseCmbService ) 
182182            { 
183-                 // TODO: Because we start the NetworkManagers back-to-back, the service can make a NetworkManager 
184-                 // (other than the very first one) the session owner. This could lead to test instabilities and 
185-                 // we need to add additional code during the start process that will start the very 1st instance 
186-                 // and wait for it to be approved and assigned the session owner before we assume anything. 
187-                 // Otherwise, any pick from the m_NetworkManagers could result in that specific instance not being 
188-                 // the first session owner. 
189-                 // If we haven't even started any NetworkManager, then just return the first 
190-                 // instance until we resolve the above issue. 
183+                 // If we haven't even started any NetworkManager, then return the first instance 
184+                 // since it will be the session owner. 
191185                if  ( ! NetcodeIntegrationTestHelpers . IsStarted ) 
192186                { 
193187                    return  m_NetworkManagers [ 0 ] ; 
194188                } 
195189
196190                foreach  ( var  client  in  m_NetworkManagers ) 
197191                { 
198-                     // See above notes. 
199-                     // TODO: Once the above is resolved, just check for client.LocalClient.IsSessionOwner 
200-                     if  ( ! client . LocalClient . IsApproved  ||  client . LocalClient . IsSessionOwner ) 
192+                     if  ( client . LocalClient . IsSessionOwner ) 
201193                    { 
202194                        return  client ; 
203195                    } 
@@ -584,15 +576,6 @@ private void CreatePlayerPrefab()
584576            VerboseDebug ( $ "Exiting { nameof ( CreatePlayerPrefab ) } ") ; 
585577        } 
586578
587-         /// <summary> 
588-         /// This is invoked before the server and client(s) are started. 
589-         /// Override this method if you want to make any adjustments to their 
590-         /// NetworkManager instances. 
591-         /// </summary> 
592-         protected  virtual  void  OnServerAndClientsCreated ( ) 
593-         { 
594-         } 
595- 
596579        private  void  AddRemoveNetworkManager ( NetworkManager  networkManager ,  bool  addNetworkManager ) 
597580        { 
598581            var  clientNetworkManagersList  =  new  List < NetworkManager > ( m_ClientNetworkManagers ) ; 
@@ -615,6 +598,78 @@ private void AddRemoveNetworkManager(NetworkManager networkManager, bool addNetw
615598            m_NetworkManagers  =  clientNetworkManagersList . ToArray ( ) ; 
616599        } 
617600
601+         /// <summary> 
602+         /// This is invoked before the server and client(s) are started. 
603+         /// Override this method if you want to make any adjustments to their 
604+         /// NetworkManager instances. 
605+         /// </summary> 
606+         protected  virtual  void  OnServerAndClientsCreated ( ) 
607+         { 
608+         } 
609+ 
610+         /// <summary> 
611+         /// Will create <see cref="NumberOfClients"/> number of clients. 
612+         /// To create a specific number of clients <see cref="CreateServerAndClients(int)"/> 
613+         /// </summary> 
614+         protected  void  CreateServerAndClients ( ) 
615+         { 
616+             CreateServerAndClients ( NumberOfClients ) ; 
617+         } 
618+ 
619+         /// <summary> 
620+         /// Creates the server and clients 
621+         /// </summary> 
622+         /// <param name="numberOfClients">The number of client instances to create</param> 
623+         protected  void  CreateServerAndClients ( int  numberOfClients ) 
624+         { 
625+             VerboseDebug ( $ "Entering { nameof ( CreateServerAndClients ) } ") ; 
626+ 
627+             CreatePlayerPrefab ( ) ; 
628+ 
629+             if  ( m_EnableTimeTravel ) 
630+             { 
631+                 m_TargetFrameRate  =  - 1 ; 
632+             } 
633+ 
634+             // If we are connecting to a CMB server we add +1 for the session owner 
635+             if  ( m_UseCmbService ) 
636+             { 
637+                 numberOfClients ++ ; 
638+             } 
639+ 
640+             // Create multiple NetworkManager instances 
641+             if  ( ! NetcodeIntegrationTestHelpers . Create ( numberOfClients ,  out  NetworkManager  server ,  out  NetworkManager [ ]  clients ,  m_TargetFrameRate ,  m_CreateServerFirst ,  m_EnableTimeTravel ,  m_UseCmbService ) ) 
642+             { 
643+                 Debug . LogError ( "Failed to create instances" ) ; 
644+                 Assert . Fail ( "Failed to create instances" ) ; 
645+             } 
646+             m_NumberOfClients  =  numberOfClients ; 
647+             m_ClientNetworkManagers  =  clients ; 
648+             m_ServerNetworkManager  =  server ; 
649+ 
650+             var  managers  =  clients . ToList ( ) ; 
651+             if  ( ! m_UseCmbService ) 
652+             { 
653+                 managers . Insert ( 0 ,  m_ServerNetworkManager ) ; 
654+             } 
655+             m_NetworkManagers  =  managers . ToArray ( ) ; 
656+ 
657+             s_DefaultWaitForTick  =  new  WaitForSecondsRealtime ( 1.0f  /  GetAuthorityNetworkManager ( ) . NetworkConfig . TickRate ) ; 
658+ 
659+             // Set the player prefab for the server and clients 
660+             foreach  ( var  manager  in  m_NetworkManagers ) 
661+             { 
662+                 manager . NetworkConfig . PlayerPrefab  =  m_PlayerPrefab ; 
663+                 SetDistributedAuthorityProperties ( manager ) ; 
664+             } 
665+ 
666+             // Provides opportunity to allow child derived classes to 
667+             // modify the NetworkManager's configuration before starting. 
668+             OnServerAndClientsCreated ( ) ; 
669+ 
670+             VerboseDebug ( $ "Exiting { nameof ( CreateServerAndClients ) } ") ; 
671+         } 
672+ 
618673        /// <summary> 
619674        /// CreateAndStartNewClient Only 
620675        /// Invoked when the newly created client has been created 
@@ -863,69 +918,6 @@ protected void SetTimeTravelSimulatedLatencyJitter(float jitterSeconds)
863918            } 
864919        } 
865920
866-         /// <summary> 
867-         /// Will create <see cref="NumberOfClients"/> number of clients. 
868-         /// To create a specific number of clients <see cref="CreateServerAndClients(int)"/> 
869-         /// </summary> 
870-         protected  void  CreateServerAndClients ( ) 
871-         { 
872-             CreateServerAndClients ( NumberOfClients ) ; 
873-         } 
874- 
875-         /// <summary> 
876-         /// Creates the server and clients 
877-         /// </summary> 
878-         /// <param name="numberOfClients">The number of client instances to create</param> 
879-         protected  void  CreateServerAndClients ( int  numberOfClients ) 
880-         { 
881-             VerboseDebug ( $ "Entering { nameof ( CreateServerAndClients ) } ") ; 
882- 
883-             CreatePlayerPrefab ( ) ; 
884- 
885-             if  ( m_EnableTimeTravel ) 
886-             { 
887-                 m_TargetFrameRate  =  - 1 ; 
888-             } 
889- 
890-             // If we are connecting to a CMB server we add +1 for the session owner 
891-             if  ( m_UseCmbService ) 
892-             { 
893-                 numberOfClients ++ ; 
894-             } 
895- 
896-             // Create multiple NetworkManager instances 
897-             if  ( ! NetcodeIntegrationTestHelpers . Create ( numberOfClients ,  out  NetworkManager  server ,  out  NetworkManager [ ]  clients ,  m_TargetFrameRate ,  m_CreateServerFirst ,  m_EnableTimeTravel ,  m_UseCmbService ) ) 
898-             { 
899-                 Debug . LogError ( "Failed to create instances" ) ; 
900-                 Assert . Fail ( "Failed to create instances" ) ; 
901-             } 
902-             m_NumberOfClients  =  numberOfClients ; 
903-             m_ClientNetworkManagers  =  clients ; 
904-             m_ServerNetworkManager  =  server ; 
905- 
906-             var  managers  =  clients . ToList ( ) ; 
907-             if  ( ! m_UseCmbService ) 
908-             { 
909-                 managers . Insert ( 0 ,  m_ServerNetworkManager ) ; 
910-             } 
911-             m_NetworkManagers  =  managers . ToArray ( ) ; 
912- 
913-             s_DefaultWaitForTick  =  new  WaitForSecondsRealtime ( 1.0f  /  GetAuthorityNetworkManager ( ) . NetworkConfig . TickRate ) ; 
914- 
915-             // Set the player prefab for the server and clients 
916-             foreach  ( var  manager  in  m_NetworkManagers ) 
917-             { 
918-                 manager . NetworkConfig . PlayerPrefab  =  m_PlayerPrefab ; 
919-                 SetDistributedAuthorityProperties ( manager ) ; 
920-             } 
921- 
922-             // Provides opportunity to allow child derived classes to 
923-             // modify the NetworkManager's configuration before starting. 
924-             OnServerAndClientsCreated ( ) ; 
925- 
926-             VerboseDebug ( $ "Exiting { nameof ( CreateServerAndClients ) } ") ; 
927-         } 
928- 
929921        /// <summary> 
930922        /// Override this method and return false in order to be able 
931923        /// to manually control when the server and clients are started. 
@@ -1028,11 +1020,7 @@ protected void ClientNetworkManagerPostStartInit()
10281020
10291021            if  ( m_UseHost ) 
10301022            { 
1031- #if UNITY_2023_1_OR_NEWER 
10321023                var  clientSideServerPlayerClones  =  Object . FindObjectsByType < NetworkObject > ( FindObjectsSortMode . None ) . Where ( ( c )  =>  c . IsPlayerObject  &&  c . OwnerClientId  ==  NetworkManager . ServerClientId ) ; 
1033- #else
1034-                 var  clientSideServerPlayerClones  =  Object . FindObjectsOfType < NetworkObject > ( ) . Where ( ( c )  =>  c . IsPlayerObject  &&  c . OwnerClientId  ==  m_ServerNetworkManager . LocalClientId ) ; 
1035- #endif
10361024                foreach  ( var  playerNetworkObject  in  clientSideServerPlayerClones ) 
10371025                { 
10381026                    // When the server is not the host this needs to be done 
@@ -1056,6 +1044,19 @@ protected virtual bool ShouldCheckForSpawnedPlayers()
10561044            return  true ; 
10571045        } 
10581046
1047+         /// <summary> 
1048+         /// Starts the session owner and awaits for it to connect before starting the remaining clients. 
1049+         /// </summary> 
1050+         private  IEnumerator  StartSessionOwner ( ) 
1051+         { 
1052+             VerboseDebug ( "Starting session owner..." ) ; 
1053+             NetcodeIntegrationTestHelpers . StartOneClient ( m_ClientNetworkManagers [ 0 ] ) ; 
1054+             yield  return  WaitForConditionOrTimeOut ( ( )  =>  m_ClientNetworkManagers [ 0 ] . IsConnectedClient ) ; 
1055+             AssertOnTimeout ( $ "Timed out waiting for the session owner to connect to CMB Server!") ; 
1056+             Assert . True ( m_ClientNetworkManagers [ 0 ] . LocalClient . IsSessionOwner ,  $ "Client-{ m_ClientNetworkManagers [ 0 ] . LocalClientId }  started session but was not set to be the session owner!") ; 
1057+             VerboseDebug ( "Session owner connected and approved." ) ; 
1058+         } 
1059+ 
10591060        /// <summary> 
10601061        /// This starts the server and clients as long as <see cref="CanStartServerAndClients"/> 
10611062        /// returns true. 
@@ -1066,17 +1067,21 @@ protected IEnumerator StartServerAndClients()
10661067            { 
10671068                VerboseDebug ( $ "Entering { nameof ( StartServerAndClients ) } ") ; 
10681069
1070+                 if  ( m_UseCmbService ) 
1071+                 { 
1072+                     VerboseDebug ( "Using a distributed authority CMB Server for connection." ) ; 
1073+                     yield  return  StartSessionOwner ( ) ; 
1074+                 } 
1075+ 
10691076                // Start the instances and pass in our SceneManagerInitialization action that is invoked immediately after host-server 
10701077                // is started and after each client is started. 
1071- 
1072-                 VerboseDebug ( $ "Starting with useCmbService: { m_UseCmbService } ") ; 
10731078                if  ( ! NetcodeIntegrationTestHelpers . Start ( m_UseHost ,  ! m_UseCmbService ,  m_ServerNetworkManager ,  m_ClientNetworkManagers ) ) 
10741079                { 
10751080                    Debug . LogError ( "Failed to start instances" ) ; 
10761081                    Assert . Fail ( "Failed to start instances" ) ; 
10771082                } 
10781083
1079-                 // When using  the CMBService, we don't have a server, so get the appropriate authority network manager  
1084+                 // Get  the authority NetworkMananger (Server, Host, or Session Owner)  
10801085                var  authorityManager  =  GetAuthorityNetworkManager ( ) ; 
10811086
10821087                // When scene management is enabled, we need to re-apply the scenes populated list since we have overriden the ISceneManagerHandler 
@@ -1108,13 +1113,8 @@ protected IEnumerator StartServerAndClients()
11081113
11091114                    if  ( m_UseHost  ||  authorityManager . IsHost ) 
11101115                    { 
1111- #if UNITY_2023_1_OR_NEWER 
11121116                        // Add the server player instance to all m_ClientSidePlayerNetworkObjects entries 
11131117                        var  serverPlayerClones  =  Object . FindObjectsByType < NetworkObject > ( FindObjectsSortMode . None ) . Where ( ( c )  =>  c . IsPlayerObject  &&  c . OwnerClientId  ==  authorityManager . LocalClientId ) ; 
1114- #else
1115-                         // Add the server player instance to all m_ClientSidePlayerNetworkObjects entries 
1116-                         var  serverPlayerClones  =  Object . FindObjectsOfType < NetworkObject > ( ) . Where ( ( c )  =>  c . IsPlayerObject  &&  c . OwnerClientId  ==  authorityManager . LocalClientId ) ; 
1117- #endif
11181118                        foreach  ( var  playerNetworkObject  in  serverPlayerClones ) 
11191119                        { 
11201120                            if  ( ! m_PlayerNetworkObjects . ContainsKey ( playerNetworkObject . NetworkManager . LocalClientId ) ) 
@@ -1128,6 +1128,8 @@ protected IEnumerator StartServerAndClients()
11281128                            } 
11291129                        } 
11301130                    } 
1131+ 
1132+                     // With distributed authority, we check that all players have spawned on all NetworkManager instances 
11311133                    if  ( m_DistributedAuthority ) 
11321134                    { 
11331135                        foreach  ( var  networkManager  in  m_NetworkManagers ) 
@@ -1137,8 +1139,10 @@ protected IEnumerator StartServerAndClients()
11371139                        } 
11381140                    } 
11391141
1140-                     if  ( ShouldCheckForSpawnedPlayers ( ) ) 
1142+                     // Client-Server or DAHost 
1143+                     if  ( ShouldCheckForSpawnedPlayers ( )  &&  ! m_UseCmbService ) 
11411144                    { 
1145+                         // Check for players being spawned on server instance 
11421146                        ClientNetworkManagerPostStartInit ( ) ; 
11431147                    } 
11441148
@@ -1698,13 +1702,12 @@ private bool CheckClientsConnected(NetworkManager[] clientsToCheck)
16981702            } 
16991703
17001704            var  manager  =  GetAuthorityNetworkManager ( ) ; 
1701-             var  expectedCount  =  manager . IsHost  ?  clientsToCheck . Length  +  1  :  clientsToCheck . Length ; 
17021705            var  currentCount  =  manager . ConnectedClients . Count ; 
17031706
1704-             if  ( currentCount  !=  expectedCount ) 
1707+             if  ( currentCount  !=  TotalClients ) 
17051708            { 
17061709                allClientsConnected  =  false ; 
1707-                 m_InternalErrorLog . AppendLine ( $ "[Server-Side] Expected { expectedCount }  clients to connect but only { currentCount }  connected!") ; 
1710+                 m_InternalErrorLog . AppendLine ( $ "[Server-Side] Expected { TotalClients }  clients to connect but only { currentCount }  connected!") ; 
17081711            } 
17091712
17101713            return  allClientsConnected ; 
0 commit comments