Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: distributed authority integration testing #3044

Draft
wants to merge 10 commits into
base: develop-2.0.0
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1123,7 +1123,7 @@ internal void Initialize(bool server)
UpdateTopology();

//DANGOEXP TODO: Remove this before finalizing the experimental release
NetworkConfig.AutoSpawnPlayerPrefabClientSide = DistributedAuthorityMode;
//NetworkConfig.AutoSpawnPlayerPrefabClientSide = DistributedAuthorityMode;

// Make sure the ServerShutdownState is reset when initializing
if (server)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,9 @@ public virtual void SetDirty(bool isDirty)

internal bool CanSend()
{
var timeSinceLastUpdate = m_NetworkBehaviour.NetworkManager.NetworkTimeSystem.LocalTime - LastUpdateSent;
// When connected to a service or not the server, always use the synchronized server time as opposed to the local time
var time = m_InternalNetworkManager.CMBServiceConnection || !m_InternalNetworkManager.IsServer ? m_NetworkBehaviour.NetworkManager.ServerTime.Time : m_NetworkBehaviour.NetworkManager.NetworkTimeSystem.LocalTime;
var timeSinceLastUpdate = time - LastUpdateSent;
return
(
UpdateTraits.MaxSecondsBetweenUpdates > 0 &&
Expand All @@ -201,7 +203,8 @@ internal bool CanSend()

internal void UpdateLastSentTime()
{
LastUpdateSent = m_NetworkBehaviour.NetworkManager.NetworkTimeSystem.LocalTime;
// When connected to a service or not the server, always use the synchronized server time as opposed to the local time
LastUpdateSent = m_InternalNetworkManager.CMBServiceConnection || !m_InternalNetworkManager.IsServer ? m_NetworkBehaviour.NetworkManager.ServerTime.Time : m_NetworkBehaviour.NetworkManager.NetworkTimeSystem.LocalTime;
}

internal static bool IgnoreInitializeWarning;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2011,7 +2011,8 @@ internal void SynchronizeNetworkObjects(ulong clientId)

// NetworkSceneManager does not synchronize scenes that are not loaded by NetworkSceneManager
// unless the scene in question is the currently active scene.
if (ExcludeSceneFromSychronization != null && !ExcludeSceneFromSychronization(scene))
if (ExcludeSceneFromSychronization != null && !ExcludeSceneFromSychronization(scene) &&
(!NetworkManager.CMBServiceConnection || (NetworkManager.CMBServiceConnection && clientId != 0)))
{
continue;
}
Expand All @@ -2025,7 +2026,8 @@ internal void SynchronizeNetworkObjects(ulong clientId)
// If we are the base scene, then we set the root scene index;
if (activeScene == scene)
{
if (!ValidateSceneBeforeLoading(scene.buildIndex, scene.name, sceneEventData.LoadSceneMode))
if (!ValidateSceneBeforeLoading(scene.buildIndex, scene.name, sceneEventData.LoadSceneMode) &&
(!NetworkManager.CMBServiceConnection || (NetworkManager.CMBServiceConnection && clientId != 0)))
{
continue;
}
Expand All @@ -2042,7 +2044,8 @@ internal void SynchronizeNetworkObjects(ulong clientId)
sceneEventData.SceneHandle = scene.handle;
}
}
else if (!ValidateSceneBeforeLoading(scene.buildIndex, scene.name, LoadSceneMode.Additive))
else if (!ValidateSceneBeforeLoading(scene.buildIndex, scene.name, LoadSceneMode.Additive) &&
(!NetworkManager.CMBServiceConnection || (NetworkManager.CMBServiceConnection && clientId != 0)))
{
continue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,27 @@ public enum HostOrServer
protected NetworkManager m_ServerNetworkManager;
protected NetworkManager[] m_ClientNetworkManagers;

/// <summary>
/// When using a client-server network topology, it will always return the m_ServerNetworkManager.
/// When using a distributed authority network topology:
/// - If running a DAHost it will return m_ServerNetworkManager
/// - If using a comb-server connection, it will return the client that is the currently assigned session owner.
/// </summary>
/// <returns><see cref="NetworkManager"/></returns>
protected NetworkManager GetSessionOwner()
{
if (!UseCMBService())
{
return m_ServerNetworkManager;
}
if (m_ClientNetworkManagers.Length > 0)
{
var sessionOwnerId = m_ClientNetworkManagers[0].CurrentSessionOwner;
return m_ClientNetworkManagers.Where((c) => c.LocalClientId == sessionOwnerId).FirstOrDefault();
}
return null;
}

/// <summary>
/// Contains each client relative set of player NetworkObject instances
/// [Client Relative set of player instances][The player instance ClientId][The player instance's NetworkObject]
Expand All @@ -141,9 +162,10 @@ public enum HostOrServer
protected bool m_DistributedAuthority;
protected NetworkTopologyTypes m_NetworkTopologyType = NetworkTopologyTypes.ClientServer;

public static bool UseCMBServiceForDATests;
protected virtual bool UseCMBService()
{
return false;
return UseCMBServiceForDATests ? m_DistributedAuthority : false;
}

protected virtual NetworkTopologyTypes OnGetNetworkTopologyType()
Expand Down Expand Up @@ -531,7 +553,7 @@ protected IEnumerator CreateAndStartNewClient()

AssertOnTimeout($"{nameof(CreateAndStartNewClient)} timed out waiting for the new client to be connected!\n {m_InternalErrorLog}");
ClientNetworkManagerPostStart(networkManager);
if (networkManager.DistributedAuthorityMode)
if (networkManager.DistributedAuthorityMode && networkManager.NetworkConfig.AutoSpawnPlayerPrefabClientSide)
{
yield return WaitForConditionOrTimeOut(() => AllPlayerObjectClonesSpawned(networkManager));
AssertOnTimeout($"{nameof(CreateAndStartNewClient)} timed out waiting for all sessions to spawn Client-{networkManager.LocalClientId}'s player object!");
Expand All @@ -546,19 +568,22 @@ private bool AllPlayerObjectClonesSpawned(NetworkManager joinedClient)
m_InternalErrorLog.Clear();
// Continue to populate the PlayerObjects list until all player object (local and clone) are found
ClientNetworkManagerPostStart(joinedClient);

var playerObjectRelative = m_ServerNetworkManager.SpawnManager.PlayerObjects.Where((c) => c.OwnerClientId == joinedClient.LocalClientId).FirstOrDefault();
if (playerObjectRelative == null)
var playerObjectRelative = (NetworkObject)null;
if (!UseCMBService())
{
m_InternalErrorLog.Append($"[AllPlayerObjectClonesSpawned][Server-Side] Joining Client-{joinedClient.LocalClientId} was not populated in the {nameof(NetworkSpawnManager.PlayerObjects)} list!");
return false;
}
else
{
// Go ahead and create an entry for this new client
if (!m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId].ContainsKey(joinedClient.LocalClientId))
playerObjectRelative = m_ServerNetworkManager.SpawnManager.PlayerObjects.Where((c) => c.OwnerClientId == joinedClient.LocalClientId).FirstOrDefault();
if (playerObjectRelative == null)
{
m_InternalErrorLog.Append($"[AllPlayerObjectClonesSpawned][Server-Side] Joining Client-{joinedClient.LocalClientId} was not populated in the {nameof(NetworkSpawnManager.PlayerObjects)} list!");
return false;
}
else
{
m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId].Add(joinedClient.LocalClientId, playerObjectRelative);
// Go ahead and create an entry for this new client
if (!m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId].ContainsKey(joinedClient.LocalClientId))
{
m_PlayerNetworkObjects[m_ServerNetworkManager.LocalClientId].Add(joinedClient.LocalClientId, playerObjectRelative);
}
}
}

Expand Down Expand Up @@ -770,6 +795,11 @@ protected virtual void OnTimeTravelServerAndClientsConnected()

private void ClientNetworkManagerPostStart(NetworkManager networkManager)
{
if (m_DistributedAuthority && !networkManager.NetworkConfig.AutoSpawnPlayerPrefabClientSide)
{
return;
}

networkManager.name = $"NetworkManager - Client - {networkManager.LocalClientId}";
Assert.NotNull(networkManager.LocalClient.PlayerObject, $"{nameof(StartServerAndClients)} detected that client {networkManager.LocalClientId} does not have an assigned player NetworkObject!");

Expand Down Expand Up @@ -818,14 +848,19 @@ private void ClientNetworkManagerPostStart(NetworkManager networkManager)

protected void ClientNetworkManagerPostStartInit()
{

// Creates a dictionary for all player instances client and server relative
// This provides a simpler way to get a specific player instance relative to a client instance
foreach (var networkManager in m_ClientNetworkManagers)
{
if (networkManager.DistributedAuthorityMode && !networkManager.AutoSpawnPlayerPrefabClientSide)
{
continue;
}
ClientNetworkManagerPostStart(networkManager);
}

if (m_UseHost)
if (m_UseHost && !UseCMBService())
{
#if UNITY_2023_1_OR_NEWER
var clientSideServerPlayerClones = Object.FindObjectsByType<NetworkObject>(FindObjectsSortMode.None).Where((c) => c.IsPlayerObject && c.OwnerClientId == m_ServerNetworkManager.LocalClientId);
Expand Down Expand Up @@ -901,7 +936,7 @@ protected IEnumerator StartServerAndClients()

AssertOnTimeout($"{nameof(StartServerAndClients)} timed out waiting for all clients to be connected!\n {m_InternalErrorLog}");

if (m_UseHost || m_ServerNetworkManager.IsHost)
if (!UseCMBService() && (m_UseHost || m_ServerNetworkManager.IsHost))
{
#if UNITY_2023_1_OR_NEWER
// Add the server player instance to all m_ClientSidePlayerNetworkObjects entries
Expand All @@ -926,13 +961,13 @@ protected IEnumerator StartServerAndClients()
//AssertOnTimeout($"{nameof(CreateAndStartNewClient)} timed out waiting for all sessions to spawn all player objects!");
foreach (var networkManager in m_ClientNetworkManagers)
{
if (networkManager.DistributedAuthorityMode)
if (networkManager.DistributedAuthorityMode && networkManager.AutoSpawnPlayerPrefabClientSide)
{
yield return WaitForConditionOrTimeOut(() => AllPlayerObjectClonesSpawned(networkManager));
AssertOnTimeout($"{nameof(CreateAndStartNewClient)} timed out waiting for all sessions to spawn Client-{networkManager.LocalClientId}'s player object!\n {m_InternalErrorLog}");
}
}
if (m_ServerNetworkManager != null)
if (m_ServerNetworkManager != null && !UseCMBService())
{
yield return WaitForConditionOrTimeOut(() => AllPlayerObjectClonesSpawned(m_ServerNetworkManager));
AssertOnTimeout($"{nameof(CreateAndStartNewClient)} timed out waiting for all sessions to spawn Client-{m_ServerNetworkManager.LocalClientId}'s player object!\n {m_InternalErrorLog}");
Expand Down Expand Up @@ -1459,22 +1494,29 @@ private bool CheckClientsConnected(NetworkManager[] clientsToCheck)
{
m_InternalErrorLog.Clear();
var allClientsConnected = true;

var actualConnected = 0;
for (int i = 0; i < clientsToCheck.Length; i++)
{
if (!clientsToCheck[i].IsConnectedClient)
{
allClientsConnected = false;
m_InternalErrorLog.AppendLine($"[Client-{i + 1}] Client is not connected!");
}
else
{
actualConnected++;
}
}
var expectedCount = m_ServerNetworkManager.IsHost ? clientsToCheck.Length + 1 : clientsToCheck.Length;
var currentCount = m_ServerNetworkManager.ConnectedClients.Count;

if (currentCount != expectedCount)
var expectedCount = m_ServerNetworkManager.IsHost && !UseCMBService() && !m_ServerNetworkManager.IsConnectedClient ? clientsToCheck.Length + 1 : clientsToCheck.Length;


if (expectedCount != actualConnected)
{
var currentCount = GetSessionOwner().ConnectedClients.Count;
var logErrorHeader = !UseCMBService() ? "[Server-Side]" : "[SessionOwner-Side]";
allClientsConnected = false;
m_InternalErrorLog.AppendLine($"[Server-Side] Expected {expectedCount} clients to connect but only {currentCount} connected!");
m_InternalErrorLog.AppendLine($"{logErrorHeader} Expected {expectedCount} clients to connect but only {actualConnected} connected with a total of {currentCount} connected clients!");
}

return allClientsConnected;
Expand Down
Loading
Loading