1+ using System . Linq ;
12using System . Runtime . CompilerServices ;
3+ using UnityEngine ;
24
35namespace Unity . Netcode
46{
@@ -143,42 +145,47 @@ public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int
143145 public void Handle ( ref NetworkContext context )
144146 {
145147 var networkManager = ( NetworkManager ) context . SystemOwner ;
148+ var hasObject = networkManager . SpawnManager . SpawnedObjects . TryGetValue ( NetworkObjectId , out var networkObject ) ;
146149
147150 // If we are the DAHost then forward this message
148151 if ( networkManager . DAHost )
149152 {
150- var shouldProcessLocally = HandleDAHostMessageForwarding ( ref networkManager , context . SenderId ) ;
153+ var shouldProcessLocally = HandleDAHostMessageForwarding ( ref networkManager , context . SenderId , hasObject , ref networkObject ) ;
151154 if ( ! shouldProcessLocally )
152155 {
153156 return ;
154157 }
155158 }
156159
160+ if ( ! hasObject )
161+ {
162+ if ( networkManager . LogLevel <= LogLevel . Normal )
163+ {
164+ NetworkLog . LogError ( "Ownership change received for an unknown network object. This should not happen." ) ;
165+ }
166+ return ;
167+ }
168+
157169 // If ownership is changing (either a straight change or a request approval), then run through the ownership changed sequence
158170 // Note: There is some extended ownership script at the bottom of HandleOwnershipChange
159171 // If not in distributed authority mode, ChangeMessageType will always be OwnershipChanging.
160172 if ( ChangeMessageType == ChangeType . OwnershipChanging || ChangeMessageType == ChangeType . RequestApproved || ! networkManager . DistributedAuthorityMode )
161173 {
162- HandleOwnershipChange ( ref context ) ;
174+ HandleOwnershipChange ( ref context , ref networkManager , ref networkObject ) ;
163175 }
164176 else if ( networkManager . DistributedAuthorityMode )
165177 {
166178 // Otherwise, we handle and extended ownership update
167- HandleExtendedOwnershipUpdate ( ref context ) ;
179+ HandleExtendedOwnershipUpdate ( ref context , ref networkObject ) ;
168180 }
169181 }
170182
171183 /// <summary>
172184 /// Handle the extended distributed authority ownership updates
173185 /// </summary>
174186 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
175- private void HandleExtendedOwnershipUpdate ( ref NetworkContext context )
187+ private void HandleExtendedOwnershipUpdate ( ref NetworkContext context , ref NetworkObject networkObject )
176188 {
177- var networkManager = ( NetworkManager ) context . SystemOwner ;
178-
179- // Handle the extended ownership message types
180- var networkObject = networkManager . SpawnManager . SpawnedObjects [ NetworkObjectId ] ;
181-
182189 if ( ChangeMessageType == ChangeType . OwnershipFlagsUpdate )
183190 {
184191 // Just update the ownership flags
@@ -199,10 +206,8 @@ private void HandleExtendedOwnershipUpdate(ref NetworkContext context)
199206 /// Handle the traditional change in ownership message type logic
200207 /// </summary>
201208 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
202- private void HandleOwnershipChange ( ref NetworkContext context )
209+ private void HandleOwnershipChange ( ref NetworkContext context , ref NetworkManager networkManager , ref NetworkObject networkObject )
203210 {
204- var networkManager = ( NetworkManager ) context . SystemOwner ;
205- var networkObject = networkManager . SpawnManager . SpawnedObjects [ NetworkObjectId ] ;
206211 var distributedAuthorityMode = networkManager . DistributedAuthorityMode ;
207212
208213 // Sanity check that we are not sending duplicated change ownership messages
@@ -260,12 +265,12 @@ private void HandleOwnershipChange(ref NetworkContext context)
260265 /// </summary>
261266 /// <param name="networkManager">The current NetworkManager from the NetworkContext</param>
262267 /// <param name="senderId">The sender of the current message from the NetworkContext</param>
268+ /// <param name="hasObject">Whether the local client has this object spawned</param>
269+ /// <param name="networkObject">The networkObject we are changing ownership on. Will be null if hasObject is false.</param>
263270 /// <returns>true if this message should also be processed locally; false if the message should only be forwarded</returns>
264271 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
265- private bool HandleDAHostMessageForwarding ( ref NetworkManager networkManager , ulong senderId )
272+ private bool HandleDAHostMessageForwarding ( ref NetworkManager networkManager , ulong senderId , bool hasObject , ref NetworkObject networkObject )
266273 {
267- var clientList = ClientIdCount > 0 ? ClientIds : networkManager . ConnectedClientsIds ;
268-
269274 var message = new ChangeOwnershipMessage ( )
270275 {
271276 NetworkObjectId = NetworkObjectId ,
@@ -302,20 +307,44 @@ private bool HandleDAHostMessageForwarding(ref NetworkManager networkManager, ul
302307 }
303308 else
304309 {
310+ var clientList = ClientIds ;
311+ var errorOnSender = true ;
312+
313+ // OwnershipFlagsUpdate doesn't populate the ClientIds list.
314+ if ( ChangeMessageType == ChangeType . OwnershipFlagsUpdate )
315+ {
316+ // if the DAHost can see this object, forward the message to all observers.
317+ // if the DAHost can't see the object, forward the message to everyone.
318+ clientList = hasObject ? networkObject . Observers . ToArray ( ) : networkManager . ConnectedClientsIds . ToArray ( ) ;
319+
320+ // Both clientList arrays will have the local client so we can not throw an error.
321+ errorOnSender = false ;
322+ }
323+
305324 foreach ( var clientId in clientList )
306325 {
307326 // Don't forward to self or originating client
308- if ( clientId == networkManager . LocalClientId || clientId == senderId )
327+ if ( clientId == networkManager . LocalClientId )
309328 {
310329 continue ;
311330 }
312331
332+ if ( clientId == senderId )
333+ {
334+ if ( errorOnSender )
335+ {
336+ Debug . LogError ( $ "client-{ senderId } sent a ChangeOwnershipMessage with themself inside the ClientIds list.") ;
337+ }
338+
339+ continue ;
340+ }
341+
313342 networkManager . ConnectionManager . SendMessage ( ref message , NetworkDelivery . Reliable , clientId ) ;
314343 }
315344 }
316345
317346 // Return whether to process the message on the DAHost itself (only if object is spawned).
318- return networkManager . SpawnManager . SpawnedObjects . ContainsKey ( NetworkObjectId ) ;
347+ return hasObject ;
319348 }
320349 }
321350}
0 commit comments