using System; using System.IO; using System.Net; using DotNetty.Buffers; using dotNetty_kcp; using UnityEngine; using Guru; using Dof; public class KcpDofClient : KcpListener { public Action OnConnected; public Action OnServerMessage; private Ukcp _ukcp; private KcpClient _kcpClient; private MemoryStream _localRecvMs = new MemoryStream(1024 * 1024 * 1); private MemoryStream _localSendMs = new MemoryStream(1024 * 1024 * 1); public long Cid { get; private set; } public KcpDofClient() { // 指定DotNetty日志的显示级别 DotNetty.Unity.UnityLoggerFactory.Default.Level = DotNetty.Unity.Level.ERROR; } public async void Connect(string ip_str, int port) { var channelConfig = new ChannelConfig(); channelConfig.initNodelay(true, 40, 2, true); channelConfig.Sndwnd = 512; channelConfig.Rcvwnd = 512; channelConfig.Mtu = 512; channelConfig.FecDataShardCount = 10; channelConfig.FecParityShardCount = 3; channelConfig.AckNoDelay = true; channelConfig.Crc32Check = false; channelConfig.UseConvChannel = true; //channelConfig.Conv = UnityEngine.Random.Range(1, int.MaxValue); channelConfig.TimeoutMillis = 10000; _kcpClient = new KcpClient(); _kcpClient.init(channelConfig); var remoteAddress = new IPEndPoint(IPAddress.Parse(ip_str), port); var task = _kcpClient.BindLocal(); await task; var channel = task.Result; _ukcp = _kcpClient.connect(channel, remoteAddress, channelConfig, this); } public void Send(ClientMessage msg) { _localSendMs.SetLength(0); _localSendMs.Position = 0; ProtobufHelper.ToStream(msg, _localSendMs); var dataBuf = Unpooled.DirectBuffer(1024 * 1024 * 1); dataBuf.WriteBytes(_localSendMs.GetBuffer(), 0, (int)_localSendMs.Length); _ukcp.write(dataBuf); dataBuf.Release(); } public void onConnected(Ukcp ukcp) { Debug.Log($"[KcpDofClient]onConnected"); if (OnConnected != null) { Loom.QueueOnMainThread(() => { OnConnected.Invoke(); }); } } /// /// kcp 接收到消息的回调函数 /// /// 接收到的消息buffer /// kcp连接 public void handleReceive(IByteBuffer byteBuf, Ukcp ukcp) { Debug.Log("[KcpDofClient]handleReceive"); _localRecvMs.SetLength(0); _localRecvMs.Position = 0; var data_len = byteBuf.ReadableBytes; byteBuf.ReadBytes(_localRecvMs, data_len); var msg = ProtobufHelper.FromBytes(typeof(ServerMessage), _localRecvMs.GetBuffer(), 0, data_len); var server_msg = msg as ServerMessage; if (server_msg != null) { ServerMessageHandler(server_msg); } else { Debug.LogError("[KcpDofClient]handleReceive: Fail to Deserialize ServerMessage"); } } public void handleException(Exception ex, Ukcp ukcp) { Debug.LogError($"[KcpDofClient]{ex}"); } public void handleClose(Ukcp ukcp) { } void ServerMessageHandler(ServerMessage msg) { if (msg.PlayerEntered != null) { Cid = msg.PlayerEntered.Cid; Debug.Log($"Player Enter cid: {Cid}"); } else if (msg.GameStart != null) { Debug.Log($"Game Start"); } else if (msg.LevelStart != null) { Debug.Log($"Level Start"); } else if (msg.PointFound != null) { Debug.Log($"Point Found"); } else if (msg.GameFinish != null) { Debug.Log($"Game Finish"); } else { Debug.LogError($"Unhandled ServerMessage"); } if (OnServerMessage != null) { Loom.QueueOnMainThread(() => { OnServerMessage.Invoke(msg); }); } } }