Skip to content

Commit 596b941

Browse files
authored
fix: Fix IsOwner/IsOwnedByServer being wrong on the server after calling RemoveOwnership [MTT-4259] (#2211)
* fix: Fix IsOwner/IsOwnedByServer being wrong on the server after calling RemoveOwnership
1 parent b92c6b8 commit 596b941

File tree

5 files changed

+115
-7
lines changed

5 files changed

+115
-7
lines changed

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
3636
- Fixed throwing an exception in `OnNetworkUpdate` causing other `OnNetworkUpdate` calls to not be executed. (#1739)
3737
- Fixed synchronization when Time.timeScale is set to 0. This changes timing update to use unscaled deltatime. Now network updates rate are independent from the local time scale. (#2171)
3838
- Fixed not sending all NetworkVariables to all clients when a client connects to a server. (#1987)
39+
- Fixed IsOwner/IsOwnedByServer being wrong on the server after calling RemoveOwnership (#2211)
3940

4041
## [1.0.2] - 2022-09-12
4142

com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,11 +213,11 @@ internal void RemoveOwnership(NetworkObject networkObject)
213213
return;
214214
}
215215

216+
networkObject.OwnerClientId = NetworkManager.ServerClientId;
217+
216218
// Server removes the entry and takes over ownership before notifying
217219
UpdateOwnershipTable(networkObject, NetworkManager.ServerClientId, true);
218220

219-
networkObject.OwnerClientId = NetworkManager.ServerClientId;
220-
221221
var message = new ChangeOwnershipMessage
222222
{
223223
NetworkObjectId = networkObject.NetworkObjectId,

com.unity.netcode.gameobjects/TestHelpers/Runtime/MessageHooksConditional.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using System.Collections.Generic;
23
using System.Linq;
34
using NUnit.Framework;
@@ -86,10 +87,19 @@ internal void AssignMessageType<T>() where T : INetworkMessage
8687
Initialize();
8788
}
8889

90+
internal void AssignMessageType(Type type)
91+
{
92+
MessageType = type.Name;
93+
m_MessageReceiptCheck = (message) =>
94+
{
95+
return message.GetType() == type;
96+
};
97+
Initialize();
98+
}
99+
89100
public MessageHookEntry(NetworkManager networkManager)
90101
{
91102
m_NetworkManager = networkManager;
92103
}
93104
}
94105
}
95-

com.unity.netcode.gameobjects/TestHelpers/Runtime/NetcodeIntegrationTest.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,39 @@ protected IEnumerator WaitForClientsConnectedOrTimeOut()
762762
yield return WaitForClientsConnectedOrTimeOut(m_ClientNetworkManagers);
763763
}
764764

765+
internal IEnumerator WaitForMessageReceived<T>(List<NetworkManager> wiatForReceivedBy) where T : INetworkMessage
766+
{
767+
// Build our message hook entries tables so we can determine if all clients received spawn or ownership messages
768+
var messageHookEntriesForSpawn = new List<MessageHookEntry>();
769+
foreach (var clientNetworkManager in wiatForReceivedBy)
770+
{
771+
var messageHook = new MessageHookEntry(clientNetworkManager);
772+
messageHook.AssignMessageType<T>();
773+
messageHookEntriesForSpawn.Add(messageHook);
774+
}
775+
// Used to determine if all clients received the CreateObjectMessage
776+
var hooks = new MessageHooksConditional(messageHookEntriesForSpawn);
777+
yield return WaitForConditionOrTimeOut(hooks);
778+
}
779+
780+
internal IEnumerator WaitForMessagesReceived(List<Type> messagesInOrder, List<NetworkManager> wiatForReceivedBy)
781+
{
782+
// Build our message hook entries tables so we can determine if all clients received spawn or ownership messages
783+
var messageHookEntriesForSpawn = new List<MessageHookEntry>();
784+
foreach (var clientNetworkManager in wiatForReceivedBy)
785+
{
786+
foreach (var message in messagesInOrder)
787+
{
788+
var messageHook = new MessageHookEntry(clientNetworkManager);
789+
messageHook.AssignMessageType(message);
790+
messageHookEntriesForSpawn.Add(messageHook);
791+
}
792+
}
793+
// Used to determine if all clients received the CreateObjectMessage
794+
var hooks = new MessageHooksConditional(messageHookEntriesForSpawn);
795+
yield return WaitForConditionOrTimeOut(hooks);
796+
}
797+
765798
/// <summary>
766799
/// Creates a basic NetworkObject test prefab, assigns it to a new
767800
/// NetworkPrefab entry, and then adds it to the server and client(s)

com.unity.netcode.gameobjects/Tests/Runtime/NetworkObject/NetworkObjectNetworkClientOwnedObjectsTests.cs

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,19 @@ namespace Unity.Netcode.RuntimeTests
99
{
1010
public class NetworkObjectNetworkClientOwnedObjectsTests : NetcodeIntegrationTest
1111
{
12+
private class DummyNetworkBehaviour : NetworkBehaviour
13+
{
14+
15+
}
16+
1217
protected override int NumberOfClients => 1;
1318
private NetworkPrefab m_NetworkPrefab;
1419
protected override void OnServerAndClientsCreated()
1520
{
1621
// create prefab
1722
var gameObject = new GameObject("ClientOwnedObject");
1823
var networkObject = gameObject.AddComponent<NetworkObject>();
24+
gameObject.AddComponent<DummyNetworkBehaviour>();
1925
NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(networkObject);
2026

2127
m_NetworkPrefab = (new NetworkPrefab()
@@ -39,7 +45,7 @@ public IEnumerator ChangeOwnershipOwnedObjectsAddTest()
3945
serverObject.Spawn();
4046

4147
// Provide enough time for the client to receive and process the spawned message.
42-
yield return s_DefaultWaitForTick;
48+
yield return WaitForMessageReceived<CreateObjectMessage>(m_ClientNetworkManagers.ToList());
4349

4450
// The object is owned by server
4551
Assert.False(m_ServerNetworkManager.SpawnManager.GetClientOwnedObjects(m_ClientNetworkManagers[0].LocalClientId).Any(x => x.NetworkObjectId == serverObject.NetworkObjectId));
@@ -48,13 +54,71 @@ public IEnumerator ChangeOwnershipOwnedObjectsAddTest()
4854
serverObject.ChangeOwnership(m_ClientNetworkManagers[0].LocalClientId);
4955

5056
// Provide enough time for the client to receive and process the change in ownership message.
51-
yield return s_DefaultWaitForTick;
57+
yield return WaitForMessageReceived<ChangeOwnershipMessage>(m_ClientNetworkManagers.ToList());
5258

5359
// Ensure it's now added to the list
54-
yield return WaitForConditionOrTimeOut(() => m_ClientNetworkManagers[0].SpawnManager.GetClientOwnedObjects(m_ClientNetworkManagers[0].LocalClientId).Any(x => x.NetworkObjectId == serverObject.NetworkObjectId));
55-
Assert.False(s_GlobalTimeoutHelper.TimedOut, $"Timed out waiting for client to gain ownership!");
5660
Assert.True(m_ClientNetworkManagers[0].SpawnManager.GetClientOwnedObjects(m_ClientNetworkManagers[0].LocalClientId).Any(x => x.NetworkObjectId == serverObject.NetworkObjectId));
5761
Assert.True(m_ServerNetworkManager.SpawnManager.GetClientOwnedObjects(m_ClientNetworkManagers[0].LocalClientId).Any(x => x.NetworkObjectId == serverObject.NetworkObjectId));
5862
}
63+
64+
[UnityTest]
65+
public IEnumerator WhenOwnershipIsChanged_OwnershipValuesUpdateCorrectly()
66+
{
67+
NetworkObject serverObject = Object.Instantiate(m_NetworkPrefab.Prefab).GetComponent<NetworkObject>();
68+
serverObject.NetworkManagerOwner = m_ServerNetworkManager;
69+
serverObject.Spawn();
70+
71+
// Provide enough time for the client to receive and process the spawned message.
72+
yield return WaitForMessageReceived<CreateObjectMessage>(m_ClientNetworkManagers.ToList());
73+
74+
// The object is owned by server
75+
Assert.False(m_ServerNetworkManager.SpawnManager.GetClientOwnedObjects(m_ClientNetworkManagers[0].LocalClientId).Any(x => x.NetworkObjectId == serverObject.NetworkObjectId));
76+
77+
// Change the ownership
78+
serverObject.ChangeOwnership(m_ClientNetworkManagers[0].LocalClientId);
79+
80+
// Provide enough time for the client to receive and process the change in ownership message.
81+
yield return WaitForMessageReceived<ChangeOwnershipMessage>(m_ClientNetworkManagers.ToList());
82+
83+
Assert.IsFalse(serverObject.IsOwner);
84+
Assert.IsFalse(serverObject.IsOwnedByServer);
85+
Assert.AreEqual(m_ClientNetworkManagers[0].LocalClientId, serverObject.OwnerClientId);
86+
87+
var serverBehaviour = serverObject.GetComponent<DummyNetworkBehaviour>();
88+
Assert.IsFalse(serverBehaviour.IsOwner);
89+
Assert.IsFalse(serverBehaviour.IsOwnedByServer);
90+
Assert.AreEqual(m_ClientNetworkManagers[0].LocalClientId, serverBehaviour.OwnerClientId);
91+
92+
var clientObject = Object.FindObjectsOfType<NetworkObject>().Where((obj) => obj.NetworkManagerOwner == m_ClientNetworkManagers[0]).FirstOrDefault();
93+
94+
Assert.IsNotNull(clientObject);
95+
Assert.IsTrue(clientObject.IsOwner);
96+
Assert.IsFalse(clientObject.IsOwnedByServer);
97+
Assert.AreEqual(m_ClientNetworkManagers[0].LocalClientId, clientObject.OwnerClientId);
98+
99+
var clientBehaviour = clientObject.GetComponent<DummyNetworkBehaviour>();
100+
Assert.IsTrue(clientBehaviour.IsOwner);
101+
Assert.IsFalse(clientBehaviour.IsOwnedByServer);
102+
Assert.AreEqual(m_ClientNetworkManagers[0].LocalClientId, clientBehaviour.OwnerClientId);
103+
104+
serverObject.RemoveOwnership();
105+
106+
// Provide enough time for the client to receive and process the change in ownership message.
107+
yield return WaitForMessageReceived<ChangeOwnershipMessage>(m_ClientNetworkManagers.ToList());
108+
109+
Assert.IsTrue(serverObject.IsOwner);
110+
Assert.IsTrue(serverObject.IsOwnedByServer);
111+
Assert.AreEqual(NetworkManager.ServerClientId, serverObject.OwnerClientId);
112+
Assert.IsTrue(serverBehaviour.IsOwner);
113+
Assert.IsTrue(serverBehaviour.IsOwnedByServer);
114+
Assert.AreEqual(NetworkManager.ServerClientId, serverBehaviour.OwnerClientId);
115+
116+
Assert.IsFalse(clientObject.IsOwner);
117+
Assert.IsTrue(clientObject.IsOwnedByServer);
118+
Assert.AreEqual(NetworkManager.ServerClientId, clientObject.OwnerClientId);
119+
Assert.IsFalse(clientBehaviour.IsOwner);
120+
Assert.IsTrue(clientBehaviour.IsOwnedByServer);
121+
Assert.AreEqual(NetworkManager.ServerClientId, clientBehaviour.OwnerClientId);
122+
}
59123
}
60124
}

0 commit comments

Comments
 (0)