Skip to content
Merged
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
11 changes: 10 additions & 1 deletion com.unity.multiplayer.mlapi/Runtime/Core/NetworkManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ public class NetworkManager : MonoBehaviour, INetworkUpdateSystem, IProfilableTr
/// </summary>
public NetworkSpawnManager SpawnManager { get; private set; }

public CustomMessagingManager CustomMessagingManager { get; private set; }

internal BufferManager BufferManager { get; private set; }

// Has to have setter for tests
Expand Down Expand Up @@ -207,7 +209,7 @@ public ulong LocalClientId

#if UNITY_EDITOR
internal static bool IsTestRun = false;

private void OnValidate()
{
if (NetworkConfig == null)
Expand Down Expand Up @@ -298,6 +300,8 @@ private void Init(bool server)
// Create spawn manager instance
SpawnManager = new NetworkSpawnManager(this);

CustomMessagingManager = new CustomMessagingManager(this);

BufferManager = new BufferManager();

if (MessageHandler == null)
Expand Down Expand Up @@ -700,6 +704,11 @@ public void Shutdown()
MessageHandler = null;
}

if (CustomMessagingManager != null)
{
CustomMessagingManager = null;
}

//The Transport is set during Init time, thus it is possible for the Transport to be null
NetworkConfig?.NetworkTransport?.Shutdown();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,15 @@ namespace MLAPI.Messaging
/// The manager class to manage custom messages, note that this is different from the NetworkManager custom messages.
/// These are named and are much easier to use.
/// </summary>
public static class CustomMessagingManager
public class CustomMessagingManager
{
private NetworkManager m_NetworkManager { get; }
Copy link
Contributor

@mattwalsh-unity mattwalsh-unity Apr 16, 2021

Choose a reason for hiding this comment

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

Idea for later refactor, since several classes all have this pattern of having their own m_NetworkManager, you could have a base class like "NetworkManagerBound" or something. You could then wrap the xtor, m_NetworkManager property, its getter and maybe more things in that. You could then put those in an array in the NetworkManager.cs file and then loop over them to null them out, vs having the list of if statements that have to be maintained.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good input. At least a field would be nice, but some classes already have constructors like noels RPC queues so I think those should be left.


internal CustomMessagingManager(NetworkManager networkManager)
{
m_NetworkManager = networkManager;
}

#region Unnamed

/// <summary>
Expand All @@ -28,19 +35,19 @@ public static class CustomMessagingManager
/// <summary>
/// Event invoked when unnamed messages arrive
/// </summary>
public static event UnnamedMessageDelegate OnUnnamedMessage;
public event UnnamedMessageDelegate OnUnnamedMessage;

internal static void InvokeUnnamedMessage(ulong clientId, Stream stream) => OnUnnamedMessage?.Invoke(clientId, stream);
internal void InvokeUnnamedMessage(ulong clientId, Stream stream) => OnUnnamedMessage?.Invoke(clientId, stream);

/// <summary>
/// Sends unnamed message to a list of clients
/// </summary>
/// <param name="clientIds">The clients to send to, sends to everyone if null</param>
/// <param name="buffer">The message stream containing the data</param>
/// <param name="networkChannel">The channel to send the data on</param>
public static void SendUnnamedMessage(List<ulong> clientIds, NetworkBuffer buffer, NetworkChannel networkChannel = NetworkChannel.Internal)
public void SendUnnamedMessage(List<ulong> clientIds, NetworkBuffer buffer, NetworkChannel networkChannel = NetworkChannel.Internal)
{
if (!NetworkManager.Singleton.IsServer)
if (!m_NetworkManager.IsServer)
{
if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
{
Expand All @@ -60,7 +67,7 @@ public static void SendUnnamedMessage(List<ulong> clientIds, NetworkBuffer buffe
/// <param name="clientId">The client to send the message to</param>
/// <param name="buffer">The message stream containing the data</param>
/// <param name="networkChannel">The channel tos end the data on</param>
public static void SendUnnamedMessage(ulong clientId, NetworkBuffer buffer, NetworkChannel networkChannel = NetworkChannel.Internal)
public void SendUnnamedMessage(ulong clientId, NetworkBuffer buffer, NetworkChannel networkChannel = NetworkChannel.Internal)
{
InternalMessageSender.Send(clientId, NetworkConstants.UNNAMED_MESSAGE, networkChannel, buffer);
PerformanceDataManager.Increment(ProfilerConstants.UnnamedMessageSent);
Expand All @@ -75,12 +82,12 @@ public static void SendUnnamedMessage(ulong clientId, NetworkBuffer buffer, Netw
/// </summary>
public delegate void HandleNamedMessageDelegate(ulong sender, Stream payload);

private static Dictionary<ulong, HandleNamedMessageDelegate> s_NamedMessageHandlers32 = new Dictionary<ulong, HandleNamedMessageDelegate>();
private static Dictionary<ulong, HandleNamedMessageDelegate> s_NamedMessageHandlers64 = new Dictionary<ulong, HandleNamedMessageDelegate>();
private Dictionary<ulong, HandleNamedMessageDelegate> s_NamedMessageHandlers32 = new Dictionary<ulong, HandleNamedMessageDelegate>();
private Dictionary<ulong, HandleNamedMessageDelegate> s_NamedMessageHandlers64 = new Dictionary<ulong, HandleNamedMessageDelegate>();

internal static void InvokeNamedMessage(ulong hash, ulong sender, Stream stream)
internal void InvokeNamedMessage(ulong hash, ulong sender, Stream stream)
{
if (NetworkManager.Singleton == null)
if (m_NetworkManager == null)
{
// We dont know what size to use. Try every (more collision prone)
if (s_NamedMessageHandlers32.ContainsKey(hash))
Expand All @@ -96,7 +103,7 @@ internal static void InvokeNamedMessage(ulong hash, ulong sender, Stream stream)
else
{
// Only check the right size.
switch (NetworkManager.Singleton.NetworkConfig.RpcHashSize)
switch (m_NetworkManager.NetworkConfig.RpcHashSize)
{
case HashSize.VarIntFourBytes:
if (s_NamedMessageHandlers32.ContainsKey(hash))
Expand All @@ -119,7 +126,7 @@ internal static void InvokeNamedMessage(ulong hash, ulong sender, Stream stream)
/// </summary>
/// <param name="name">Name of the message.</param>
/// <param name="callback">The callback to run when a named message is received.</param>
public static void RegisterNamedMessageHandler(string name, HandleNamedMessageDelegate callback)
public void RegisterNamedMessageHandler(string name, HandleNamedMessageDelegate callback)
{
s_NamedMessageHandlers32[XXHash.Hash32(name)] = callback;
s_NamedMessageHandlers64[XXHash.Hash64(name)] = callback;
Expand All @@ -129,7 +136,7 @@ public static void RegisterNamedMessageHandler(string name, HandleNamedMessageDe
/// Unregisters a named message handler.
/// </summary>
/// <param name="name">The name of the message.</param>
public static void UnregisterNamedMessageHandler(string name)
public void UnregisterNamedMessageHandler(string name)
{
s_NamedMessageHandlers32.Remove(XXHash.Hash32(name));
s_NamedMessageHandlers64.Remove(XXHash.Hash64(name));
Expand All @@ -142,10 +149,10 @@ public static void UnregisterNamedMessageHandler(string name)
/// <param name="clientId">The client to send the message to</param>
/// <param name="stream">The message stream containing the data</param>
/// <param name="networkChannel">The channel to send the data on</param>
public static void SendNamedMessage(string name, ulong clientId, Stream stream, NetworkChannel networkChannel = NetworkChannel.Internal)
public void SendNamedMessage(string name, ulong clientId, Stream stream, NetworkChannel networkChannel = NetworkChannel.Internal)
{
ulong hash = 0;
switch (NetworkManager.Singleton.NetworkConfig.RpcHashSize)
switch (m_NetworkManager.NetworkConfig.RpcHashSize)
{
case HashSize.VarIntFourBytes:
hash = XXHash.Hash32(name);
Expand Down Expand Up @@ -174,10 +181,10 @@ public static void SendNamedMessage(string name, ulong clientId, Stream stream,
/// <param name="clientIds">The clients to send to, sends to everyone if null</param>
/// <param name="stream">The message stream containing the data</param>
/// <param name="networkChannel">The channel to send the data on</param>
public static void SendNamedMessage(string name, List<ulong> clientIds, Stream stream, NetworkChannel networkChannel = NetworkChannel.Internal)
public void SendNamedMessage(string name, List<ulong> clientIds, Stream stream, NetworkChannel networkChannel = NetworkChannel.Internal)
{
ulong hash = 0;
switch (NetworkManager.Singleton.NetworkConfig.RpcHashSize)
switch (m_NetworkManager.NetworkConfig.RpcHashSize)
{
case HashSize.VarIntFourBytes:
hash = XXHash.Hash32(name);
Expand All @@ -194,7 +201,7 @@ public static void SendNamedMessage(string name, List<ulong> clientIds, Stream s

messageBuffer.CopyFrom(stream);

if (!NetworkManager.Singleton.IsServer)
if (!m_NetworkManager.IsServer)
{
if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,7 @@ public void HandleUnnamedMessage(ulong clientId, Stream stream)
#if DEVELOPMENT_BUILD || UNITY_EDITOR
s_HandleUnnamedMessage.Begin();
#endif
CustomMessagingManager.InvokeUnnamedMessage(clientId, stream);
NetworkManager.CustomMessagingManager.InvokeUnnamedMessage(clientId, stream);
#if DEVELOPMENT_BUILD || UNITY_EDITOR
s_HandleUnnamedMessage.End();
#endif
Expand All @@ -574,7 +574,7 @@ public void HandleNamedMessage(ulong clientId, Stream stream)
{
ulong hash = reader.ReadUInt64Packed();

CustomMessagingManager.InvokeNamedMessage(hash, clientId, stream);
NetworkManager.CustomMessagingManager.InvokeNamedMessage(hash, clientId, stream);
}
#if DEVELOPMENT_BUILD || UNITY_EDITOR
s_HandleNamedMessage.End();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System.Collections.Generic;
using MLAPI.Configuration;
using MLAPI.Messaging;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace MLAPI.EditorTests
{
public class NetworkManagerCustomMessageManagerTests
{
[Test]
public void CustomMessageManagerAssigned()
{
var gameObject = new GameObject(nameof(CustomMessageManagerAssigned));
var networkManager = gameObject.AddComponent<NetworkManager>();
var transport = gameObject.AddComponent<DummyTransport>();

// MLAPI sets this in validate
networkManager.NetworkConfig = new NetworkConfig()
{
// Set the current scene to prevent unexpected log messages which would trigger a failure
RegisteredScenes = new List<string>() {SceneManager.GetActiveScene().name}
};

// Set dummy transport that does nothing
networkManager.NetworkConfig.NetworkTransport = transport;

CustomMessagingManager preManager = networkManager.CustomMessagingManager;

// Start server to cause init
networkManager.StartServer();

Debug.Assert(preManager == null);
Debug.Assert(networkManager.CustomMessagingManager != null);
Copy link
Contributor

Choose a reason for hiding this comment

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

Assuming you like the 'base class' idea above, then you could test all of the "NetworkManager-extended" classes in a loop here.


Object.DestroyImmediate(gameObject);
}
}
}

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