// helper function protected bool UnpackAndInvoke(NetworkReader reader, int channelId) { if (MessagePacking.Unpack(reader, out int msgType)) { // try to invoke the handler for that message if (messageHandlers.TryGetValue(msgType, out NetworkMessageDelegate msgDelegate)) { msgDelegate.Invoke(this, reader, channelId); try { lastMessageTime = Time.time; } catch (Exception e) { Debug.Log("It tried dying again"); } return(true); } else { // Debug.Log("Unknown message ID " + msgType + " " + this + ". May be due to no existing RegisterHandler for this message."); return(false); } } else { Debug.LogError("Closed connection: " + this + ". Invalid message header."); Disconnect(); return(false); } }
/// <summary> /// Replaces a handler for a particular message type. /// <para>See also <see cref="RegisterHandler{T}(Action{NetworkConnection, T}, bool)">RegisterHandler(T)(Action(NetworkConnection, T), bool)</see></para> /// </summary> /// <typeparam name="T">Message type</typeparam> /// <param name="handler">Function handler which will be invoked when this message type is received.</param> /// <param name="requireAuthentication">True if the message requires an authenticated connection</param> public static void ReplaceHandler <T>(Action <NetworkConnection, T> handler, bool requireAuthentication = true) where T : struct, NetworkMessage { int msgType = MessagePacking.GetId <T>(); handlers[msgType] = MessagePacking.WrapHandler(handler, requireAuthentication); }
/// <summary> /// Unregisters a network message handler. /// </summary> /// <typeparam name="T">The message type to unregister.</typeparam> public static bool UnregisterHandler <T>() where T : struct, NetworkMessage { // use int to minimize collisions int msgType = MessagePacking.GetId <T>(); return(handlers.Remove(msgType)); }
/// <summary>Send a NetworkMessage to this connection over the given channel.</summary> public void Send <T>(T msg, int channelId = Channels.Reliable) where T : struct, NetworkMessage { using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter()) { // pack message and send allocation free MessagePacking.Pack(msg, writer); NetworkDiagnostics.OnSend(msg, channelId, writer.Position, 1); Send(writer.ToArraySegment(), channelId); } }
/// <summary> /// Register a handler for a particular message type. /// <para>There are several system message types which you can add handlers for. You can also add your own message types.</para> /// </summary> /// <typeparam name="T">Message type</typeparam> /// <param name="handler">Function handler which will be invoked when this message type is received.</param> /// <param name="requireAuthentication">True if the message requires an authenticated connection</param> public static void RegisterHandler <T>(Action <NetworkConnection, T> handler, bool requireAuthentication = true) where T : struct, NetworkMessage { int msgType = MessagePacking.GetId <T>(); if (handlers.ContainsKey(msgType)) { Debug.LogWarning($"NetworkClient.RegisterHandler replacing handler for {typeof(T).FullName}, id={msgType}. If replacement is intentional, use ReplaceHandler instead to avoid this warning."); } handlers[msgType] = MessagePacking.WrapHandler(handler, requireAuthentication); }