Skip to content

feat: OnAllClientsReady #755

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

Merged
merged 19 commits into from
May 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
fa0fef6
Added delegate types and appropriate events in NetworkSceneManager.
pdeschain Apr 20, 2021
adf18e3
Added a new internal message that is sent out to all the clients when…
pdeschain Apr 21, 2021
d10910b
Added comments and an array of timed out client IDs to the OnAllClien…
pdeschain Apr 21, 2021
c802347
Noticed that I was trying to check the list of connected clients on t…
pdeschain Apr 22, 2021
ffb06da
Added automated tests for introduced callbacks.
pdeschain Apr 26, 2021
6dfbebb
More work on tests
pdeschain Apr 27, 2021
d23e199
More work on tests
pdeschain Apr 28, 2021
16468ef
Merge branch 'develop' of https://github.com/Unity-Technologies/com.u…
pdeschain Apr 28, 2021
9fb4a8c
Merge branch 'develop' into feature/onclientready-mtt588
NoelStephensUnity Apr 28, 2021
531ebdb
Moved scenes used for OnClientReady tests under the Assets/ directory
pdeschain Apr 30, 2021
4f0b4e3
Moved OnAllClientsReady scenes back into package, testing how Yamato …
pdeschain Apr 30, 2021
b8280e2
Moved the test scenes back under Assets/ folder, tweaked the code tha…
pdeschain Apr 30, 2021
1e2c31a
More of the same attempts to placate Yamato
pdeschain Apr 30, 2021
e3beeb1
#
pdeschain Apr 30, 2021
fcd7f42
Due to current limitations in our ability to reference scenes in Asse…
pdeschain Apr 30, 2021
73efb2e
Renamed the message and added events and delegates to be more underst…
pdeschain May 3, 2021
007719f
Merge branch 'develop' of https://github.com/Unity-Technologies/com.u…
pdeschain May 3, 2021
cf3d516
doc tweaks
pdeschain May 3, 2021
a7f9add
Yamato taming
pdeschain May 3, 2021
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 @@ -18,6 +18,7 @@ internal static class NetworkConstants
internal const byte TIME_SYNC = 11;
internal const byte NETWORK_VARIABLE_DELTA = 12;
internal const byte NETWORK_VARIABLE_UPDATE = 13;
internal const byte ALL_CLIENTS_LOADED_SCENE = 14;
internal const byte UNNAMED_MESSAGE = 20;
internal const byte DESTROY_OBJECTS = 21;
internal const byte NAMED_MESSAGE = 22;
Expand All @@ -42,7 +43,7 @@ internal static class NetworkConstants
"TIME_SYNC",
"NETWORK_VARIABLE_DELTA",
"NETWORK_VARIABLE_UPDATE",
"",
"ALL_CLIENTS_SWITCH_SCENE_COMPLETED",
"",
"", // 16
"",
Expand Down
7 changes: 7 additions & 0 deletions com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1255,6 +1255,13 @@ internal void HandleIncomingData(ulong clientId, NetworkChannel networkChannel,
NetworkLog.LogWarning($"Server received {nameof(NetworkConstants.CLIENT_SWITCH_SCENE_COMPLETED)} from client id {clientId}");
}

break;
case NetworkConstants.ALL_CLIENTS_LOADED_SCENE:
if (IsClient)
{
MessageHandler.HandleAllClientsSwitchSceneCompleted(clientId, messageStream);
}

break;
case NetworkConstants.SERVER_LOG:
if (IsServer && NetworkConfig.EnableNetworkLogs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ internal interface IInternalMessageHandler
void HandleUnnamedMessage(ulong clientId, Stream stream);
void HandleNamedMessage(ulong clientId, Stream stream);
void HandleNetworkLog(ulong clientId, Stream stream);
void HandleAllClientsSwitchSceneCompleted(ulong clientId, Stream stream);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ internal class InternalMessageHandler : IInternalMessageHandler
private static ProfilerMarker s_HandleNetworkLog = new ProfilerMarker($"{nameof(InternalMessageHandler)}.{nameof(HandleNetworkLog)}");
private static ProfilerMarker s_RpcReceiveQueueItemServerRpc = new ProfilerMarker($"{nameof(InternalMessageHandler)}.{nameof(RpcReceiveQueueItem)}.{nameof(RpcQueueContainer.QueueItemType.ServerRpc)}");
private static ProfilerMarker s_RpcReceiveQueueItemClientRpc = new ProfilerMarker($"{nameof(InternalMessageHandler)}.{nameof(RpcReceiveQueueItem)}.{nameof(RpcQueueContainer.QueueItemType.ClientRpc)}");
private static ProfilerMarker s_HandleAllClientsSwitchSceneCompleted = new ProfilerMarker($"{nameof(InternalMessageHandler)}.{nameof(HandleAllClientsSwitchSceneCompleted)}");
#endif

public NetworkManager NetworkManager => m_NetworkManager;
Expand Down Expand Up @@ -570,6 +571,22 @@ public void HandleNetworkLog(ulong clientId, Stream stream)
}
#if DEVELOPMENT_BUILD || UNITY_EDITOR
s_HandleNetworkLog.End();
#endif
}

public void HandleAllClientsSwitchSceneCompleted(ulong clientId, Stream stream)
{
#if DEVELOPMENT_BUILD || UNITY_EDITOR
s_HandleAllClientsSwitchSceneCompleted.Begin();
#endif
using (var reader = PooledNetworkReader.Get(stream))
{
var clientIds = reader.ReadULongArray();
var timedOutClientIds = reader.ReadULongArray();
NetworkManager.SceneManager.AllClientsReady(clientIds, timedOutClientIds);
}
#if DEVELOPMENT_BUILD || UNITY_EDITOR
s_HandleAllClientsSwitchSceneCompleted.End();
#endif
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System;
using System.IO;
using System.Linq;
using MLAPI.Configuration;
using MLAPI.Exceptions;
using MLAPI.Logging;
Expand Down Expand Up @@ -29,6 +30,24 @@ public class NetworkSceneManager
/// </summary>
public delegate void SceneSwitchStartedDelegate(AsyncOperation operation);

/// <summary>
/// Delegate for when a client has reported to the server that it has completed scene transition
/// <see cref='OnNotifyServerClientLoadedScene'/>
/// </summary>
public delegate void NotifyServerClientLoadedSceneDelegate(SceneSwitchProgress progress, ulong clientId);

/// <summary>
/// Delegate for when all clients have reported to the server that they have completed scene transition or timed out
/// <see cref='OnNotifyServerAllClientsLoadedScene'/>
/// </summary>
public delegate void NotifyServerAllClientsLoadedSceneDelegate(SceneSwitchProgress progress, bool timedOut);

/// <summary>
/// Delegate for when the clients get notified by the server that all clients have completed their scene transitions.
/// <see cref='OnNotifyClientAllClientsLoadedScene'/>
/// </summary>
public delegate void NotifyClientAllClientsLoadedSceneDelegate(ulong[] clientIds, ulong[] timedOutClientIds);

/// <summary>
/// Event that is invoked when the scene is switched
/// </summary>
Expand All @@ -39,6 +58,23 @@ public class NetworkSceneManager
/// </summary>
public event SceneSwitchStartedDelegate OnSceneSwitchStarted;

/// <summary>
/// Event that is invoked on the server when a client completes scene transition
/// </summary>
public event NotifyServerClientLoadedSceneDelegate OnNotifyServerClientLoadedScene;

/// <summary>
/// Event that is invoked on the server when all clients have reported that they have completed scene transition
/// </summary>
public event NotifyServerAllClientsLoadedSceneDelegate OnNotifyServerAllClientsLoadedScene;

/// <summary>
/// Event that is invoked on the clients after all clients have successfully completed scene transition or timed out.
/// <remarks>This event happens after <see cref="OnNotifyServerAllClientsLoadedScene"/> fires on the server and the <see cref="NetworkConstants.ALL_CLIENTS_LOADED_SCENE"/> message is sent to the clients.
/// It relies on MessageSender, which doesn't send events from the server to itself (which is the case for a Host client).</remarks>
/// </summary>
public event NotifyClientAllClientsLoadedSceneDelegate OnNotifyClientAllClientsLoadedScene;

internal readonly HashSet<string> RegisteredSceneNames = new HashSet<string>();
internal readonly Dictionary<string, uint> SceneNameToIndex = new Dictionary<string, uint>();
internal readonly Dictionary<uint, string> SceneIndexToString = new Dictionary<uint, string>();
Expand Down Expand Up @@ -139,6 +175,24 @@ public SceneSwitchProgress SwitchScene(string sceneName)
var switchSceneProgress = new SceneSwitchProgress(m_NetworkManager);
SceneSwitchProgresses.Add(switchSceneProgress.Guid, switchSceneProgress);
CurrentSceneSwitchProgressGuid = switchSceneProgress.Guid;

switchSceneProgress.OnClientLoadedScene += clientId => { OnNotifyServerClientLoadedScene?.Invoke(switchSceneProgress, clientId); };
switchSceneProgress.OnComplete += timedOut =>
{
OnNotifyServerAllClientsLoadedScene?.Invoke(switchSceneProgress, timedOut);

using (var buffer = PooledNetworkBuffer.Get())
using (var writer = PooledNetworkWriter.Get(buffer))
{
var doneClientIds = switchSceneProgress.DoneClients.ToArray();
var timedOutClientIds = m_NetworkManager.ConnectedClients.Keys.Except(doneClientIds).ToArray();

writer.WriteULongArray(doneClientIds, doneClientIds.Length);
writer.WriteULongArray(timedOutClientIds, timedOutClientIds.Length);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Both active and timed out clients!
Very useful!


m_NetworkManager.MessageSender.Send(NetworkManager.Singleton.ServerClientId, NetworkConstants.ALL_CLIENTS_LOADED_SCENE, NetworkChannel.Internal, buffer);
}
};

// Move ALL NetworkObjects to the temp scene
MoveObjectsToDontDestroyOnLoad();
Expand Down Expand Up @@ -400,5 +454,10 @@ private void MoveObjectsToScene(Scene scene)
SceneManager.MoveGameObjectToScene(sobj.gameObject, scene);
}
}

internal void AllClientsReady(ulong[] clientIds, ulong[] timedOutClientIds)
{
OnNotifyClientAllClientsLoadedScene?.Invoke(clientIds, timedOutClientIds);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,8 @@ internal class DummyMessageHandler : IInternalMessageHandler
public void HandleNamedMessage(ulong clientId, Stream stream) => VerifyCalled(nameof(HandleNamedMessage));

public void HandleNetworkLog(ulong clientId, Stream stream) => VerifyCalled(nameof(HandleNetworkLog));

public void HandleAllClientsSwitchSceneCompleted(ulong clientId, Stream stream) => VerifyCalled(nameof(HandleAllClientsSwitchSceneCompleted));

private void VerifyCalled(string method)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using MLAPI.Configuration;
using UnityEngine;
using UnityEngine.SceneManagement;
using NUnit.Framework;
Expand Down Expand Up @@ -48,8 +49,9 @@ public enum NetworkManagerOperatingMode
/// As such, the default setting is to start in Host mode.
/// </summary>
/// <param name="managerMode">parameter to specify which mode you want to start the NetworkManager</param>
/// <param name="networkConfig">parameter to specify custom NetworkConfig settings</param>
/// <returns>true if it was instantiated or is already instantiate otherwise false means it failed to instantiate</returns>
public static bool StartNetworkManager(out NetworkManager networkManager, NetworkManagerOperatingMode managerMode = NetworkManagerOperatingMode.Host)
public static bool StartNetworkManager(out NetworkManager networkManager, NetworkManagerOperatingMode managerMode = NetworkManagerOperatingMode.Host, NetworkConfig networkConfig = null)
{
//If we are changing the current manager mode and the current manager mode is not "None", then stop the NetworkManager mode
if (CurrentNetworkManagerMode != managerMode && CurrentNetworkManagerMode != NetworkManagerOperatingMode.None)
Expand All @@ -61,7 +63,7 @@ public static bool StartNetworkManager(out NetworkManager networkManager, Networ
{
NetworkManagerGameObject = new GameObject(nameof(NetworkManager));
NetworkManagerObject = NetworkManagerGameObject.AddComponent<NetworkManager>();

if (NetworkManagerObject == null)
{
networkManager = null;
Expand All @@ -72,11 +74,21 @@ public static bool StartNetworkManager(out NetworkManager networkManager, Networ

var unetTransport = NetworkManagerGameObject.AddComponent<UNetTransport>();

NetworkManagerObject.NetworkConfig = new Configuration.NetworkConfig
if (networkConfig == null)
{
networkConfig = new NetworkConfig
{
EnableSceneManagement = false,
RegisteredScenes = new List<string>() {SceneManager.GetActiveScene().name}
};
}
else
{
EnableSceneManagement = false,
RegisteredScenes = new List<string>() { SceneManager.GetActiveScene().name }
};
networkConfig.RegisteredScenes.Add(SceneManager.GetActiveScene().name);
}

NetworkManagerObject.NetworkConfig = networkConfig;

unetTransport.ConnectAddress = "127.0.0.1";
unetTransport.ConnectPort = 7777;
unetTransport.ServerListenPort = 7777;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
using System;
using System.Collections;
using System.Linq;
using MLAPI.SceneManagement;
using MLAPI.Configuration;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;

namespace MLAPI.RuntimeTests
{
public class NetworkSceneManagerTests
Expand Down
1 change: 1 addition & 0 deletions testproject/Assets/ManualTests/ManualTestsMenu.unity
Original file line number Diff line number Diff line change
Expand Up @@ -917,6 +917,7 @@ MonoBehaviour:
- {fileID: 11400000, guid: d8c6d81e6a2574f4aa66a10aeb02f946, type: 2}
- {fileID: 11400000, guid: 50c51a066c0971b49ab65929d5ba9630, type: 2}
- {fileID: 11400000, guid: eb84694ca0950574981c9544bf99a552, type: 2}
- {fileID: 11400000, guid: 52e575f2e50d52f428e055ad5c4f8797, type: 2}
m_SceneMenusDropDownList: {fileID: 8786710035000454136}
m_OptionsList:
m_Options:
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading