1
+ using System . Linq ;
1
2
using System . Runtime . CompilerServices ;
3
+ using UnityEngine ;
2
4
3
5
namespace Unity . Netcode
4
6
{
@@ -143,42 +145,47 @@ public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int
143
145
public void Handle ( ref NetworkContext context )
144
146
{
145
147
var networkManager = ( NetworkManager ) context . SystemOwner ;
148
+ var hasObject = networkManager . SpawnManager . SpawnedObjects . TryGetValue ( NetworkObjectId , out var networkObject ) ;
146
149
147
150
// If we are the DAHost then forward this message
148
151
if ( networkManager . DAHost )
149
152
{
150
- var shouldProcessLocally = HandleDAHostMessageForwarding ( ref networkManager , context . SenderId ) ;
153
+ var shouldProcessLocally = HandleDAHostMessageForwarding ( ref networkManager , context . SenderId , hasObject , ref networkObject ) ;
151
154
if ( ! shouldProcessLocally )
152
155
{
153
156
return ;
154
157
}
155
158
}
156
159
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
+
157
169
// If ownership is changing (either a straight change or a request approval), then run through the ownership changed sequence
158
170
// Note: There is some extended ownership script at the bottom of HandleOwnershipChange
159
171
// If not in distributed authority mode, ChangeMessageType will always be OwnershipChanging.
160
172
if ( ChangeMessageType == ChangeType . OwnershipChanging || ChangeMessageType == ChangeType . RequestApproved || ! networkManager . DistributedAuthorityMode )
161
173
{
162
- HandleOwnershipChange ( ref context ) ;
174
+ HandleOwnershipChange ( ref context , ref networkManager , ref networkObject ) ;
163
175
}
164
176
else if ( networkManager . DistributedAuthorityMode )
165
177
{
166
178
// Otherwise, we handle and extended ownership update
167
- HandleExtendedOwnershipUpdate ( ref context ) ;
179
+ HandleExtendedOwnershipUpdate ( ref context , ref networkObject ) ;
168
180
}
169
181
}
170
182
171
183
/// <summary>
172
184
/// Handle the extended distributed authority ownership updates
173
185
/// </summary>
174
186
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
175
- private void HandleExtendedOwnershipUpdate ( ref NetworkContext context )
187
+ private void HandleExtendedOwnershipUpdate ( ref NetworkContext context , ref NetworkObject networkObject )
176
188
{
177
- var networkManager = ( NetworkManager ) context . SystemOwner ;
178
-
179
- // Handle the extended ownership message types
180
- var networkObject = networkManager . SpawnManager . SpawnedObjects [ NetworkObjectId ] ;
181
-
182
189
if ( ChangeMessageType == ChangeType . OwnershipFlagsUpdate )
183
190
{
184
191
// Just update the ownership flags
@@ -199,10 +206,8 @@ private void HandleExtendedOwnershipUpdate(ref NetworkContext context)
199
206
/// Handle the traditional change in ownership message type logic
200
207
/// </summary>
201
208
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
202
- private void HandleOwnershipChange ( ref NetworkContext context )
209
+ private void HandleOwnershipChange ( ref NetworkContext context , ref NetworkManager networkManager , ref NetworkObject networkObject )
203
210
{
204
- var networkManager = ( NetworkManager ) context . SystemOwner ;
205
- var networkObject = networkManager . SpawnManager . SpawnedObjects [ NetworkObjectId ] ;
206
211
var distributedAuthorityMode = networkManager . DistributedAuthorityMode ;
207
212
208
213
// Sanity check that we are not sending duplicated change ownership messages
@@ -260,12 +265,12 @@ private void HandleOwnershipChange(ref NetworkContext context)
260
265
/// </summary>
261
266
/// <param name="networkManager">The current NetworkManager from the NetworkContext</param>
262
267
/// <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>
263
270
/// <returns>true if this message should also be processed locally; false if the message should only be forwarded</returns>
264
271
[ 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 )
266
273
{
267
- var clientList = ClientIdCount > 0 ? ClientIds : networkManager . ConnectedClientsIds ;
268
-
269
274
var message = new ChangeOwnershipMessage ( )
270
275
{
271
276
NetworkObjectId = NetworkObjectId ,
@@ -302,20 +307,44 @@ private bool HandleDAHostMessageForwarding(ref NetworkManager networkManager, ul
302
307
}
303
308
else
304
309
{
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
+
305
324
foreach ( var clientId in clientList )
306
325
{
307
326
// Don't forward to self or originating client
308
- if ( clientId == networkManager . LocalClientId || clientId == senderId )
327
+ if ( clientId == networkManager . LocalClientId )
309
328
{
310
329
continue ;
311
330
}
312
331
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
+
313
342
networkManager . ConnectionManager . SendMessage ( ref message , NetworkDelivery . Reliable , clientId ) ;
314
343
}
315
344
}
316
345
317
346
// 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 ;
319
348
}
320
349
}
321
350
}
0 commit comments