Skip to content

Commit 7e5a0ca

Browse files
committed
feat(messaging): Added support for named custom messaging
1 parent cd58b2f commit 7e5a0ca

File tree

6 files changed

+258
-37
lines changed

6 files changed

+258
-37
lines changed

MLAPI/Configuration/MLAPIConstants.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
/// </summary>
66
internal static class MLAPIConstants
77
{
8-
internal const string MLAPI_PROTOCOL_VERSION = "9.0.0";
8+
internal const string MLAPI_PROTOCOL_VERSION = "10.7.0";
99

1010
internal const byte MLAPI_CERTIFICATE_HAIL = 0;
1111
internal const byte MLAPI_CERTIFICATE_HAIL_RESPONSE = 1;
@@ -27,8 +27,9 @@ internal static class MLAPIConstants
2727
internal const byte MLAPI_CLIENT_RPC = 17;
2828
internal const byte MLAPI_CLIENT_RPC_REQUEST = 18;
2929
internal const byte MLAPI_CLIENT_RPC_RESPONSE = 19;
30-
internal const byte MLAPI_CUSTOM_MESSAGE = 20;
30+
internal const byte MLAPI_UNNAMED_MESSAGE = 20;
3131
internal const byte MLAPI_DESTROY_OBJECTS = 21;
32+
internal const byte MLAPI_NAMED_MESSAGE = 22;
3233
internal const byte INVALID = 32;
3334

3435
internal static readonly string[] MESSAGE_NAMES = {
@@ -52,9 +53,9 @@ internal static class MLAPIConstants
5253
"MLAPI_CLIENT_RPC",
5354
"MLAPI_CLIENT_RPC_REQUEST",
5455
"MLAPI_CLIENT_RPC_RESPONSE",
55-
"MLAPI_CUSTOM_MESSAGE",
56+
"MLAPI_UNNAMED_MESSAGE",
5657
"MLAPI_DESTROY_OBJECTS",
57-
"",
58+
"MLAPI_NAMED_MESSAGE",
5859
"",
5960
"",
6061
"",

MLAPI/Core/NetworkingManager.cs

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
using MLAPI.SceneManagement;
2323
using MLAPI.Serialization.Pooled;
2424
using MLAPI.Spawning;
25+
using static MLAPI.Messaging.NamedMessageManager;
26+
using static MLAPI.Messaging.CustomMessagingManager;
2527

2628
namespace MLAPI
2729
{
@@ -175,16 +177,8 @@ internal set
175177
/// </summary>
176178
[HideInInspector]
177179
public NetworkConfig NetworkConfig;
178-
/// <summary>
179-
/// Delegate used for incoming custom messages
180-
/// </summary>
181-
/// <param name="clientId">The clientId that sent the message</param>
182-
/// <param name="stream">The stream containing the message data</param>
183-
public delegate void CustomMessageDelegete(ulong clientId, Stream stream);
184-
/// <summary>
185-
/// Event invoked when custom messages arrive
186-
/// </summary>
187-
public event CustomMessageDelegete OnIncomingCustomMessage;
180+
[Obsolete("Use OnUnnamedMessage instead")]
181+
public event UnnamedMessageDelegate OnIncomingCustomMessage;
188182
/// <summary>
189183
/// The current hostname we are connected to, used to validate certificate
190184
/// </summary>
@@ -194,49 +188,55 @@ internal set
194188

195189
internal void InvokeOnIncomingCustomMessage(ulong clientId, Stream stream)
196190
{
197-
if (OnIncomingCustomMessage != null) OnIncomingCustomMessage(clientId, stream);
191+
if (OnIncomingCustomMessage != null)
192+
{
193+
OnIncomingCustomMessage(clientId, stream);
194+
}
198195
}
199196

200197
/// <summary>
201-
/// Sends custom message to a list of clients
198+
/// Sends unnamed message to a list of clients
202199
/// </summary>
203200
/// <param name="clientIds">The clients to send to, sends to everyone if null</param>
204201
/// <param name="stream">The message stream containing the data</param>
205202
/// <param name="channel">The channel to send the data on</param>
206203
/// <param name="security">The security settings to apply to the message</param>
204+
[Obsolete("Use CustomMessagingManager.SendUnnamedMessage instead")]
207205
public void SendCustomMessage(List<ulong> clientIds, BitStream stream, string channel = null, SecuritySendFlags security = SecuritySendFlags.None)
208206
{
209207
if (!IsServer)
210208
{
211-
if (LogHelper.CurrentLogLevel <= LogLevel.Error) LogHelper.LogWarning("Can not send custom message to multiple users as a client");
209+
if (LogHelper.CurrentLogLevel <= LogLevel.Error)
210+
LogHelper.LogWarning("Can not send unnamed message to multiple users as a client");
212211
return;
213212
}
214213
if (clientIds == null)
215214
{
216215
for (int i = 0; i < ConnectedClientsList.Count; i++)
217216
{
218-
InternalMessageSender.Send(ConnectedClientsList[i].ClientId, MLAPIConstants.MLAPI_CUSTOM_MESSAGE, string.IsNullOrEmpty(channel) ? "MLAPI_DEFAULT_MESSAGE" : channel, stream, security, null);
217+
InternalMessageSender.Send(ConnectedClientsList[i].ClientId, MLAPIConstants.MLAPI_UNNAMED_MESSAGE, string.IsNullOrEmpty(channel) ? "MLAPI_DEFAULT_MESSAGE" : channel, stream, security, null);
219218
}
220219
}
221220
else
222221
{
223222
for (int i = 0; i < clientIds.Count; i++)
224223
{
225-
InternalMessageSender.Send(clientIds[i], MLAPIConstants.MLAPI_CUSTOM_MESSAGE, string.IsNullOrEmpty(channel) ? "MLAPI_DEFAULT_MESSAGE" : channel, stream, security, null);
224+
InternalMessageSender.Send(clientIds[i], MLAPIConstants.MLAPI_UNNAMED_MESSAGE, string.IsNullOrEmpty(channel) ? "MLAPI_DEFAULT_MESSAGE" : channel, stream, security, null);
226225
}
227226
}
228227
}
229228

230229
/// <summary>
231-
/// Sends a custom message to a specific client
230+
/// Sends a unnamed message to a specific client
232231
/// </summary>
233232
/// <param name="clientId">The client to send the message to</param>
234233
/// <param name="stream">The message stream containing the data</param>
235234
/// <param name="channel">The channel tos end the data on</param>
236235
/// <param name="security">The security settings to apply to the message</param>
236+
[Obsolete("Use CustomMessagingManager.SendUnnamedMessage instead")]
237237
public void SendCustomMessage(ulong clientId, BitStream stream, string channel = null, SecuritySendFlags security = SecuritySendFlags.None)
238238
{
239-
InternalMessageSender.Send(clientId, MLAPIConstants.MLAPI_CUSTOM_MESSAGE, string.IsNullOrEmpty(channel) ? "MLAPI_DEFAULT_MESSAGE" : channel, stream, security, null);
239+
InternalMessageSender.Send(clientId, MLAPIConstants.MLAPI_UNNAMED_MESSAGE, string.IsNullOrEmpty(channel) ? "MLAPI_DEFAULT_MESSAGE" : channel, stream, security, null);
240240
}
241241

242242
private void OnValidate()
@@ -900,8 +900,11 @@ private void HandleIncomingData(ulong clientId, string channelName, ArraySegment
900900
case MLAPIConstants.MLAPI_CLIENT_RPC_RESPONSE:
901901
if (IsServer) InternalMessageHandler.HandleClientRPCResponse(clientId, messageStream);
902902
break;
903-
case MLAPIConstants.MLAPI_CUSTOM_MESSAGE:
904-
InternalMessageHandler.HandleCustomMessage(clientId, messageStream);
903+
case MLAPIConstants.MLAPI_UNNAMED_MESSAGE:
904+
InternalMessageHandler.HandleUnnamedMessage(clientId, messageStream);
905+
break;
906+
case MLAPIConstants.MLAPI_NAMED_MESSAGE:
907+
InternalMessageHandler.HandleNamedMessage(clientId, messageStream);
905908
break;
906909
#if !DISABLE_CRYPTOGRAPHY
907910
case MLAPIConstants.MLAPI_CERTIFICATE_HAIL:
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using MLAPI.Configuration;
5+
using MLAPI.Logging;
6+
using MLAPI.Security;
7+
using MLAPI.Serialization;
8+
using MLAPI.Serialization.Pooled;
9+
10+
namespace MLAPI.Messaging
11+
{
12+
/// <summary>
13+
/// The manager class to manage custom messages, note that this is different from the NetworkingManager custom messages.
14+
/// These are named and are much easier to use.
15+
/// </summary>
16+
public static class CustomMessagingManager
17+
{
18+
#region Unnamed
19+
/// <summary>
20+
/// Delegate used for incoming unnamed messages
21+
/// </summary>
22+
/// <param name="clientId">The clientId that sent the message</param>
23+
/// <param name="stream">The stream containing the message data</param>
24+
public delegate void UnnamedMessageDelegate(ulong clientId, Stream stream);
25+
26+
/// <summary>
27+
/// Event invoked when unnamed messages arrive
28+
/// </summary>
29+
public static event UnnamedMessageDelegate OnUnnamedMessage;
30+
31+
internal static void InvokeUnnamedMessage(ulong clientId, Stream stream)
32+
{
33+
if (OnUnnamedMessage != null)
34+
{
35+
OnUnnamedMessage(clientId, stream);
36+
}
37+
38+
NetworkingManager.Singleton.InvokeOnIncomingCustomMessage(clientId, stream);
39+
}
40+
41+
42+
/// <summary>
43+
/// Sends unnamed message to a list of clients
44+
/// </summary>
45+
/// <param name="clientIds">The clients to send to, sends to everyone if null</param>
46+
/// <param name="stream">The message stream containing the data</param>
47+
/// <param name="channel">The channel to send the data on</param>
48+
/// <param name="security">The security settings to apply to the message</param>
49+
public static void SendUnnamedMessage(List<ulong> clientIds, BitStream stream, string channel = null, SecuritySendFlags security = SecuritySendFlags.None)
50+
{
51+
if (!NetworkingManager.Singleton.IsServer)
52+
{
53+
if (LogHelper.CurrentLogLevel <= LogLevel.Error) LogHelper.LogWarning("Can not send unnamed messages to multiple users as a client");
54+
return;
55+
}
56+
57+
if (clientIds == null)
58+
{
59+
for (int i = 0; i < NetworkingManager.Singleton.ConnectedClientsList.Count; i++)
60+
{
61+
InternalMessageSender.Send(NetworkingManager.Singleton.ConnectedClientsList[i].ClientId, MLAPIConstants.MLAPI_UNNAMED_MESSAGE, string.IsNullOrEmpty(channel) ? "MLAPI_DEFAULT_MESSAGE" : channel, stream, security, null);
62+
}
63+
}
64+
else
65+
{
66+
for (int i = 0; i < clientIds.Count; i++)
67+
{
68+
InternalMessageSender.Send(clientIds[i], MLAPIConstants.MLAPI_UNNAMED_MESSAGE, string.IsNullOrEmpty(channel) ? "MLAPI_DEFAULT_MESSAGE" : channel, stream, security, null);
69+
}
70+
}
71+
}
72+
73+
/// <summary>
74+
/// Sends a unnamed message to a specific client
75+
/// </summary>
76+
/// <param name="clientId">The client to send the message to</param>
77+
/// <param name="stream">The message stream containing the data</param>
78+
/// <param name="channel">The channel tos end the data on</param>
79+
/// <param name="security">The security settings to apply to the message</param>
80+
public static void SendUnnamedMessage(ulong clientId, BitStream stream, string channel = null, SecuritySendFlags security = SecuritySendFlags.None)
81+
{
82+
InternalMessageSender.Send(clientId, MLAPIConstants.MLAPI_UNNAMED_MESSAGE, string.IsNullOrEmpty(channel) ? "MLAPI_DEFAULT_MESSAGE" : channel, stream, security, null);
83+
}
84+
#endregion
85+
#region Named
86+
87+
/// <summary>
88+
/// Delegate used to handle named messages
89+
/// </summary>
90+
public delegate void HandleNamedMessageDelegate(ulong sender, Stream payload);
91+
92+
private static readonly Dictionary<ulong, HandleNamedMessageDelegate> namedMessageHandlers = new Dictionary<ulong, HandleNamedMessageDelegate>();
93+
94+
internal static void InvokeNamedMessage(ulong hash, ulong sender, Stream stream)
95+
{
96+
if (namedMessageHandlers.ContainsKey(hash))
97+
{
98+
namedMessageHandlers[hash](sender, stream);
99+
}
100+
}
101+
102+
/// <summary>
103+
/// Registers a named message handler delegate.
104+
/// </summary>
105+
/// <param name="name">Name of the message.</param>
106+
/// <param name="callback">The callback to run when a named message is received.</param>
107+
public static void RegisterNamedMessageHandler(string name, HandleNamedMessageDelegate callback)
108+
{
109+
ulong hash = NetworkedBehaviour.HashMethodName(name);
110+
111+
namedMessageHandlers[hash] = callback;
112+
}
113+
114+
/// <summary>
115+
/// Sends a named message
116+
/// </summary>
117+
/// <param name="name">The message name to send</param>
118+
/// <param name="clientId">The client to send the message to</param>
119+
/// <param name="stream">The message stream containing the data</param>
120+
/// <param name="channel">The channel tos end the data on</param>
121+
/// <param name="security">The security settings to apply to the message</param>
122+
public static void SendNamedMessage(string name, ulong clientId, Stream stream, string channel = null, SecuritySendFlags security = SecuritySendFlags.None)
123+
{
124+
ulong hash = NetworkedBehaviour.HashMethodName(name);
125+
126+
using (PooledBitStream messageStream = PooledBitStream.Get())
127+
{
128+
using (PooledBitWriter writer = PooledBitWriter.Get(messageStream))
129+
{
130+
writer.WriteUInt64Packed(hash);
131+
}
132+
133+
messageStream.CopyFrom(stream);
134+
135+
InternalMessageSender.Send(clientId, MLAPIConstants.MLAPI_NAMED_MESSAGE, string.IsNullOrEmpty(channel) ? "MLAPI_DEFAULT_MESSAGE" : channel, messageStream, security, null);
136+
}
137+
}
138+
139+
/// <summary>
140+
/// Sends the named message
141+
/// </summary>
142+
/// <param name="name">The message name to send</param>
143+
/// <param name="clientIds">The clients to send to, sends to everyone if null</param>
144+
/// <param name="stream">The message stream containing the data</param>
145+
/// <param name="channel">The channel to send the data on</param>
146+
/// <param name="security">The security settings to apply to the message</param>
147+
public static void SendNamedMessage(string name, List<ulong> clientIds, Stream stream, string channel = null, SecuritySendFlags security = SecuritySendFlags.None)
148+
{
149+
ulong hash = NetworkedBehaviour.HashMethodName(name);
150+
151+
using (PooledBitStream messageStream = PooledBitStream.Get())
152+
{
153+
using (PooledBitWriter writer = PooledBitWriter.Get(messageStream))
154+
{
155+
writer.WriteUInt64Packed(hash);
156+
}
157+
158+
messageStream.CopyFrom(stream);
159+
160+
if (!NetworkingManager.Singleton.IsServer)
161+
{
162+
if (LogHelper.CurrentLogLevel <= LogLevel.Error) LogHelper.LogWarning("Can not send named messages to multiple users as a client");
163+
return;
164+
}
165+
if (clientIds == null)
166+
{
167+
for (int i = 0; i < NetworkingManager.Singleton.ConnectedClientsList.Count; i++)
168+
{
169+
InternalMessageSender.Send(NetworkingManager.Singleton.ConnectedClientsList[i].ClientId, MLAPIConstants.MLAPI_NAMED_MESSAGE, string.IsNullOrEmpty(channel) ? "MLAPI_DEFAULT_MESSAGE" : channel, messageStream, security, null);
170+
}
171+
}
172+
else
173+
{
174+
for (int i = 0; i < clientIds.Count; i++)
175+
{
176+
InternalMessageSender.Send(clientIds[i], MLAPIConstants.MLAPI_NAMED_MESSAGE, string.IsNullOrEmpty(channel) ? "MLAPI_DEFAULT_MESSAGE" : channel, messageStream, security, null);
177+
}
178+
}
179+
}
180+
}
181+
#endregion
182+
}
183+
}

MLAPI/Messaging/InternalMessageHandler.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -660,10 +660,19 @@ internal static void HandleClientRPCResponse(ulong clientId, Stream stream)
660660
}
661661
}
662662

663-
internal static void HandleCustomMessage(ulong clientId, Stream stream)
663+
internal static void HandleUnnamedMessage(ulong clientId, Stream stream)
664664
{
665-
NetworkingManager.Singleton.InvokeOnIncomingCustomMessage(clientId, stream);
665+
CustomMessagingManager.InvokeUnnamedMessage(clientId, stream);
666666
}
667667

668+
internal static void HandleNamedMessage(ulong clientId, Stream stream)
669+
{
670+
using (PooledBitReader reader = PooledBitReader.Get(stream))
671+
{
672+
ulong hash = reader.ReadUInt64Packed();
673+
674+
CustomMessagingManager.InvokeNamedMessage(hash, clientId, stream);
675+
}
676+
}
668677
}
669678
}

0 commit comments

Comments
 (0)