using System.Collections; using System.Collections.Generic; using Unity.Collections; using Unity.Netcode; using UnityEngine; namespace TcgEngine { /// /// 发送和接收网络消息的基础类 /// public class NetworkMessaging { private TcgNetwork network; private Dictionary> msg_dict = new Dictionary>(); public NetworkMessaging(TcgNetwork network) { this.network = network; network.onConnect += OnConnect; } private void OnConnect() { foreach (KeyValuePair> pair in msg_dict) { RegisterNetMsg(pair.Key, pair.Value); } } public void ListenMsg(string type, System.Action callback) { msg_dict[type] = callback; RegisterNetMsg(type, callback); } public void UnListenMsg(string type) { msg_dict.Remove(type); if (network.NetworkManager.CustomMessagingManager != null) network.NetworkManager.CustomMessagingManager.UnregisterNamedMessageHandler(type); } private void RegisterNetMsg(string type, System.Action callback) { if (IsOnline) { network.NetworkManager.CustomMessagingManager.RegisterNamedMessageHandler(type, (ulong client_id, FastBufferReader reader) => { ReceiveNetMessage(type, client_id, reader); }); } } private void ReceiveNetMessage(string type, ulong client_id, FastBufferReader reader) { bool valid = msg_dict.TryGetValue(type, out System.Action callback); if (valid && IsOnline) { callback(client_id, reader); } } //--------- Send Single ---------- public void SendEmpty(string type, ulong target, NetworkDelivery delivery) { FastBufferWriter writer = new FastBufferWriter(0, Allocator.Temp); Send(type, target, writer, delivery); writer.Dispose(); } public void SendBytes(string type, ulong target, byte[] msg, NetworkDelivery delivery) { FastBufferWriter writer = new FastBufferWriter(msg.Length, Allocator.Temp); writer.WriteBytesSafe(msg, msg.Length); Send(type, target, writer, delivery); writer.Dispose(); } public void SendString(string type, ulong target, string msg, NetworkDelivery delivery) { FastBufferWriter writer = new FastBufferWriter(msg.Length, Allocator.Temp, TcgNetwork.MsgSizeMax); writer.WriteValueSafe(msg); Send(type, target, writer, delivery); writer.Dispose(); } public void SendInt(string type, ulong target, int data, NetworkDelivery delivery) { FastBufferWriter writer = new FastBufferWriter(4, Allocator.Temp); writer.WriteValueSafe(data); Send(type, target, writer, delivery); writer.Dispose(); } public void SendUInt64(string type, ulong target, ulong data, NetworkDelivery delivery) { FastBufferWriter writer = new FastBufferWriter(8, Allocator.Temp); writer.WriteValueSafe(data); Send(type, target, writer, delivery); writer.Dispose(); } public void SendFloat(string type, ulong target, float data, NetworkDelivery delivery) { FastBufferWriter writer = new FastBufferWriter(4, Allocator.Temp); writer.WriteValueSafe(data); Send(type, target, writer, delivery); writer.Dispose(); } public void SendObject(string type, ulong target, T data, NetworkDelivery delivery) where T : INetworkSerializable { Debug.Log("=== SendObject 开始 ==="); Debug.Log("SendObject 步骤1: 参数检查 - type: " + type + " target: " + target + " data: " + data + " delivery: " + delivery); // 增加初始缓冲区大小,特别是对于包含字符串的对象 int initialSize = 1024; // 从 256 增加到 1024 Debug.Log("SendObject 步骤2: 创建 FastBufferWriter,初始大小: " + initialSize + ", 最大大小: " + TcgNetwork.MsgSizeMax); FastBufferWriter writer = new FastBufferWriter(initialSize, Allocator.Temp, TcgNetwork.MsgSizeMax); try { Debug.Log("SendObject 步骤3: 序列化数据到 writer"); writer.WriteNetworkSerializable(data); Debug.Log("SendObject 步骤4: 序列化完成,writer 当前位置: " + writer.Position + ", 总长度: " + writer.Length); // 检查是否超出最大大小 if (writer.Length > TcgNetwork.MsgSizeMax) { Debug.LogError("SendObject 错误: 消息大小 " + writer.Length + " 超出最大限制 " + TcgNetwork.MsgSizeMax); writer.Dispose(); return; } Debug.Log("SendObject 步骤5: 调用 Send 方法"); Send(type, target, writer, delivery); } catch (System.Exception e) { Debug.LogError("SendObject 序列化失败: " + e.Message); } finally { Debug.Log("SendObject 步骤6: 释放 writer 资源"); writer.Dispose(); } Debug.Log("=== SendObject 结束 ==="); } //--------- Send Multi ---------- public void SendEmpty(string type, IReadOnlyList targets, NetworkDelivery delivery) { if (IsServer) { FastBufferWriter writer = new FastBufferWriter(0, Allocator.Temp); Send(type, targets, writer, delivery); writer.Dispose(); } } public void SendBytes(string type, IReadOnlyList targets, byte[] msg, NetworkDelivery delivery) { if (IsServer) { FastBufferWriter writer = new FastBufferWriter(msg.Length, Allocator.Temp); writer.WriteBytesSafe(msg, msg.Length); Send(type, targets, writer, delivery); writer.Dispose(); } } public void SendString(string type, IReadOnlyList targets, string msg, NetworkDelivery delivery) { if (IsServer) { FastBufferWriter writer = new FastBufferWriter(msg.Length, Allocator.Temp, TcgNetwork.MsgSizeMax); writer.WriteValueSafe(msg); Send(type, targets, writer, delivery); writer.Dispose(); } } public void SendInt(string type, IReadOnlyList targets, int data, NetworkDelivery delivery) { if (IsServer) { FastBufferWriter writer = new FastBufferWriter(4, Allocator.Temp); writer.WriteValueSafe(data); Send(type, targets, writer, delivery); writer.Dispose(); } } public void SendUInt64(string type, IReadOnlyList targets, ulong data, NetworkDelivery delivery) { if (IsServer) { FastBufferWriter writer = new FastBufferWriter(8, Allocator.Temp); writer.WriteValueSafe(data); Send(type, targets, writer, delivery); writer.Dispose(); } } public void SendFloat(string type, IReadOnlyList targets, float data, NetworkDelivery delivery) { if (IsServer) { FastBufferWriter writer = new FastBufferWriter(4, Allocator.Temp); writer.WriteValueSafe(data); Send(type, targets, writer, delivery); writer.Dispose(); } } public void SendObject(string type, IReadOnlyList targets, T data, NetworkDelivery delivery) where T : INetworkSerializable { if (IsServer) { FastBufferWriter writer = new FastBufferWriter(1024, Allocator.Temp, TcgNetwork.MsgSizeMax); writer.WriteNetworkSerializable(data); Send(type, targets, writer, delivery); writer.Dispose(); } } //--------- Send All ---------- public void SendEmptyAll(string type, NetworkDelivery delivery) { if (IsServer) { FastBufferWriter writer = new FastBufferWriter(0, Allocator.Temp); SendAll(type, writer, delivery); writer.Dispose(); } } public void SendStringAll(string type, string msg, NetworkDelivery delivery) { if (IsServer) { FastBufferWriter writer = new FastBufferWriter(msg.Length, Allocator.Temp, TcgNetwork.MsgSizeMax); writer.WriteValueSafe(msg); SendAll(type, writer, delivery); writer.Dispose(); } } public void SendIntAll(string type, int data, NetworkDelivery delivery) { if (IsServer) { FastBufferWriter writer = new FastBufferWriter(4, Allocator.Temp); writer.WriteValueSafe(data); SendAll(type, writer, delivery); writer.Dispose(); } } public void SendUInt64All(string type, ulong data, NetworkDelivery delivery) { if (IsServer) { FastBufferWriter writer = new FastBufferWriter(8, Allocator.Temp); writer.WriteValueSafe(data); SendAll(type, writer, delivery); writer.Dispose(); } } public void SendFloatAll(string type, float data, NetworkDelivery delivery) { if (IsServer) { FastBufferWriter writer = new FastBufferWriter(4, Allocator.Temp); writer.WriteValueSafe(data); SendAll(type, writer, delivery); writer.Dispose(); } } public void SendBytesAll(string type, byte[] msg, NetworkDelivery delivery) { if (IsServer) { FastBufferWriter writer = new FastBufferWriter(msg.Length, Allocator.Temp); writer.WriteBytesSafe(msg, msg.Length); SendAll(type, writer, delivery); writer.Dispose(); } } public void SendObjectAll(string type, T data, NetworkDelivery delivery) where T : INetworkSerializable { if (IsServer) { FastBufferWriter writer = new FastBufferWriter(1024, Allocator.Temp, TcgNetwork.MsgSizeMax); writer.WriteNetworkSerializable(data); SendAll(type, writer, delivery); writer.Dispose(); } } //-------- Generic Send ---------- public void Send(string type, ulong target, FastBufferWriter writer, NetworkDelivery delivery) { Debug.Log("=== Send 方法开始 ==="); Debug.Log("Send 步骤1: 检查网络状态 - IsOnline: " + IsOnline + ", target: " + target + ", ClientID: " + ClientID); if (IsOnline) { Debug.Log("Send 步骤2: 在线模式,调用 SendOnline"); SendOnline(type, target, writer, delivery); } else if (target == ClientID && ClientID != 0) { Debug.Log("Send 步骤2: 离线模式且目标是自己,调用 SendOffline"); SendOffline(type, writer); } else { Debug.Log("Send 步骤2: 离线模式但目标不是自己,跳过发送"); } Debug.Log("=== Send 方法结束 ==="); } public void Send(string type, IReadOnlyList targets, FastBufferWriter writer, NetworkDelivery delivery) { if (IsOnline) SendOnline(type, targets, writer, delivery); else if (Contains(targets, ClientID)) SendOffline(type, writer); } public void SendAll(string type, FastBufferWriter writer, NetworkDelivery delivery) { Send(type, ClientList, writer, delivery); } private void SendOnline(string type, ulong target, FastBufferWriter writer, NetworkDelivery delivery) { Debug.Log("=== SendOnline 方法开始 ==="); Debug.Log("SendOnline 步骤1: 参数验证 - type: " + type + " target: " + target + " delivery: " + delivery); Debug.Log("SendOnline 步骤2: 检查 NetworkManager 状态 - 是否为 null: " + (network.NetworkManager == null)); Debug.Log("SendOnline 步骤3: 检查 CustomMessagingManager 状态 - 是否为 null: " + (network.NetworkManager?.CustomMessagingManager == null)); Debug.Log("SendOnline 步骤4: 准备发送消息,writer 长度: " + writer.Length); try { Debug.Log("SendOnline 步骤5: 调用 Unity Netcode 的 SendNamedMessage"); network.NetworkManager.CustomMessagingManager.SendNamedMessage(type, target, writer, delivery); Debug.Log("SendOnline 步骤6: 消息发送成功"); } catch (System.Exception e) { Debug.LogError("SendOnline 步骤6: 消息发送失败 - " + e.Message); } Debug.Log("=== SendOnline 方法结束 ==="); } private void SendOnline(string type, IReadOnlyList targets, FastBufferWriter writer, NetworkDelivery delivery) { network.NetworkManager.CustomMessagingManager.SendNamedMessage(type, targets, writer, delivery); } //Just copy the message from writer to reader locally and call the callback immediately private void SendOffline(string type, FastBufferWriter writer) { Debug.Log("=== SendOffline 方法开始 ==="); Debug.Log("SendOffline 步骤1: 查找消息类型 '" + type + "' 的监听器"); bool found = msg_dict.TryGetValue(type, out System.Action callback); Debug.Log("SendOffline 步骤2: 监听器查找结果 - 找到: " + found); if (found) { Debug.Log("SendOffline 步骤3: 创建 FastBufferReader 从 writer 复制数据"); FastBufferReader reader = new FastBufferReader(writer, Allocator.Temp); Debug.Log("SendOffline 步骤4: 调用回调函数,ClientID: " + ClientID + ", reader 长度: " + reader.Length); callback?.Invoke(ClientID, reader); Debug.Log("SendOffline 步骤5: 释放 reader 资源"); reader.Dispose(); Debug.Log("SendOffline 步骤6: 离线消息处理完成"); } else { Debug.Log("SendOffline 步骤3: 未找到消息类型 '" + type + "' 的监听器,跳过处理"); } Debug.Log("=== SendOffline 方法结束 ==="); } //--------- Forward msgs ---------- //Forward a client message to one client //Make sure you finished reading the reader before forwarding public void Forward(string type, ulong target, FastBufferReader reader, NetworkDelivery delivery) { if (IsServer && IsOnline) { reader.Seek(0); //Reset reader reader.ReadValueSafe(out ulong header); //Ignore header byte[] bytes = new byte[reader.Length - reader.Position]; reader.ReadBytesSafe(ref bytes, reader.Length - reader.Position); FastBufferWriter writer = new FastBufferWriter(bytes.Length, Allocator.Temp); writer.WriteBytesSafe(bytes, bytes.Length); network.NetworkManager.CustomMessagingManager.SendNamedMessage(type, target, writer, delivery); writer.Dispose(); } } //Forward a client message to all target clients //Make sure you finished reading the reader before forwarding public void Forward(string type, IReadOnlyList targets, FastBufferReader reader, NetworkDelivery delivery) { if (IsServer && IsOnline) { reader.Seek(0); //Reset reader reader.ReadValueSafe(out ulong header); //Ignore header byte[] bytes = new byte[reader.Length - reader.Position]; reader.ReadBytesSafe(ref bytes, reader.Length - reader.Position); FastBufferWriter writer = new FastBufferWriter(bytes.Length, Allocator.Temp); writer.WriteBytesSafe(bytes, bytes.Length); network.NetworkManager.CustomMessagingManager.SendNamedMessage(type, targets, writer, delivery); writer.Dispose(); } } //Forward a client message to all other clients (other than the source) //Make sure you finished reading the reader before forwarding public void ForwardAll(string type, ulong source_client, FastBufferReader reader, NetworkDelivery delivery) { if (IsServer && IsOnline) { reader.Seek(0); //Reset reader reader.ReadValueSafe(out ulong header); //Ignore header byte[] bytes = new byte[reader.Length - reader.Position]; reader.ReadBytesSafe(ref bytes, reader.Length - reader.Position); FastBufferWriter writer = new FastBufferWriter(bytes.Length, Allocator.Temp); writer.WriteBytesSafe(bytes, bytes.Length); foreach (ulong client in ClientList) { if (client != source_client && client != ClientID) network.NetworkManager.CustomMessagingManager.SendNamedMessage(type, client, writer, delivery); } writer.Dispose(); } } private bool Contains(IReadOnlyList list, ulong client_id) { foreach (ulong cid in list) { if (cid == client_id) return true; } return false; } public IReadOnlyList ClientList { get { return network.GetClientsIds(); } } public bool IsOnline { get { return network.IsOnline && network.ClientID != 0; } } public bool IsServer { get { return network.IsServer; } } public ulong ServerID { get { return network.ServerID; } } public ulong ClientID { get { return network.ClientID; } } public static NetworkMessaging Get() { return TcgNetwork.Get().Messaging; } } }