using System.Collections;
using NUnit.Framework;
using Unity.Netcode.TestHelpers.Runtime;
using UnityEngine;
using UnityEngine.TestTools;
namespace Unity.Netcode.RuntimeTests
{
[TestFixture(HostOrServer.DAHost, true)]
[TestFixture(HostOrServer.DAHost, false)]
public class ExtendedNetworkShowAndHideTests : NetcodeIntegrationTest
{
protected override int NumberOfClients => 3;
private bool m_EnableSceneManagement;
private GameObject m_ObjectToSpawn;
private NetworkObject m_SpawnedObject;
private NetworkManager m_ClientToHideFrom;
private NetworkManager m_LateJoinClient;
private NetworkManager m_SpawnOwner;
public ExtendedNetworkShowAndHideTests(HostOrServer hostOrServer, bool enableSceneManagement) : base(hostOrServer)
{
m_EnableSceneManagement = enableSceneManagement;
}
protected override void OnServerAndClientsCreated()
{
if (!UseCMBService())
{
m_ServerNetworkManager.NetworkConfig.EnableSceneManagement = m_EnableSceneManagement;
}
foreach (var client in m_ClientNetworkManagers)
{
client.NetworkConfig.EnableSceneManagement = m_EnableSceneManagement;
}
m_ObjectToSpawn = CreateNetworkObjectPrefab("TestObject");
m_ObjectToSpawn.SetActive(false);
base.OnServerAndClientsCreated();
}
private bool AllClientsSpawnedObject()
{
if (!UseCMBService())
{
if (!s_GlobalNetworkObjects.ContainsKey(m_ServerNetworkManager.LocalClientId))
{
return false;
}
if (!s_GlobalNetworkObjects[m_ServerNetworkManager.LocalClientId].ContainsKey(m_SpawnedObject.NetworkObjectId))
{
return false;
}
}
foreach (var client in m_ClientNetworkManagers)
{
if (!s_GlobalNetworkObjects.ContainsKey(client.LocalClientId))
{
return false;
}
if (!s_GlobalNetworkObjects[client.LocalClientId].ContainsKey(m_SpawnedObject.NetworkObjectId))
{
return false;
}
}
return true;
}
private bool IsClientPromotedToSessionOwner()
{
if (!UseCMBService())
{
if (m_ServerNetworkManager.CurrentSessionOwner != m_ClientToHideFrom.LocalClientId)
{
return false;
}
}
foreach (var client in m_ClientNetworkManagers)
{
if (!client.IsConnectedClient)
{
continue;
}
if (client.CurrentSessionOwner != m_ClientToHideFrom.LocalClientId)
{
return false;
}
}
return true;
}
protected override void OnNewClientCreated(NetworkManager networkManager)
{
m_LateJoinClient = networkManager;
networkManager.NetworkConfig.EnableSceneManagement = m_EnableSceneManagement;
networkManager.NetworkConfig.Prefabs = m_SpawnOwner.NetworkConfig.Prefabs;
base.OnNewClientCreated(networkManager);
}
///
/// This test validates the following NetworkShow - NetworkHide issue:
/// - During a session, a spawned object is hidden from a client.
/// - The current session owner disconnects and the client the object is hidden from is prommoted to the session owner.
/// - A new client joins and the newly promoted session owner synchronizes the newly joined client with only objects visible to it.
/// - Any already connected non-session owner client should "NetworkShow" the object to the newly connected client
/// (but only if the hidden object has SpawnWithObservers enabled)
///
[UnityTest]
public IEnumerator HiddenObjectPromotedSessionOwnerNewClientSynchronizes()
{
// Get the test relative session owner
var sessionOwner = UseCMBService() ? m_ClientNetworkManagers[0] : m_ServerNetworkManager;
m_SpawnOwner = UseCMBService() ? m_ClientNetworkManagers[1] : m_ClientNetworkManagers[0];
m_ClientToHideFrom = UseCMBService() ? m_ClientNetworkManagers[NumberOfClients - 1] : m_ClientNetworkManagers[1];
m_ObjectToSpawn.SetActive(true);
// Spawn the object with a non-session owner client
m_SpawnedObject = SpawnObject(m_ObjectToSpawn, m_SpawnOwner).GetComponent();
yield return WaitForConditionOrTimeOut(AllClientsSpawnedObject);
AssertOnTimeout($"Not all clients spawned and instance of {m_SpawnedObject.name}");
// Hide the spawned object from the to be promoted session owner
m_SpawnedObject.NetworkHide(m_ClientToHideFrom.LocalClientId);
yield return WaitForConditionOrTimeOut(() => !m_ClientToHideFrom.SpawnManager.SpawnedObjects.ContainsKey(m_SpawnedObject.NetworkObjectId));
AssertOnTimeout($"{m_SpawnedObject.name} was not hidden from Client-{m_ClientToHideFrom.LocalClientId}!");
// Promoted a new session owner (DAHost promotes while CMB Session we disconnect the current session owner)
if (!UseCMBService())
{
m_ServerNetworkManager.PromoteSessionOwner(m_ClientToHideFrom.LocalClientId);
}
else
{
sessionOwner.Shutdown();
}
// Wait for the new session owner to be promoted and for all clients to acknowledge the promotion
yield return WaitForConditionOrTimeOut(IsClientPromotedToSessionOwner);
AssertOnTimeout($"Client-{m_ClientToHideFrom.LocalClientId} was not promoted as session owner on all client instances!");
// Connect a new client instance
yield return CreateAndStartNewClient();
// Assure the newly connected client is synchronized with the NetworkObject hidden from the newly promoted session owner
yield return WaitForConditionOrTimeOut(() => m_LateJoinClient.SpawnManager.SpawnedObjects.ContainsKey(m_SpawnedObject.NetworkObjectId));
AssertOnTimeout($"Client-{m_LateJoinClient.LocalClientId} never spawned {nameof(NetworkObject)} {m_SpawnedObject.name}!");
}
}
}