174 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C#
		
	
	
			
		
		
	
	
			174 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C#
		
	
	
| using System;
 | ||
| using System.Net;
 | ||
| using System.IO;
 | ||
| using dotNetty_kcp;
 | ||
| using DotNetty.Buffers;
 | ||
| using UnityEngine;
 | ||
| using Guru;
 | ||
| using Dof;
 | ||
| 
 | ||
| namespace DofLibrary
 | ||
| {
 | ||
| 
 | ||
|     public class GameKcpClient : KcpListener
 | ||
|     {
 | ||
|         public Action OnConnected;
 | ||
| 
 | ||
|         private KcpClient _kcpClient;
 | ||
|         public IMessageSender sender { get; private set; } = new MessageSender();
 | ||
|         private IMessageReceiver _receiver;
 | ||
|         private bool _running;
 | ||
| 
 | ||
|         public GameKcpClient(DotNetty.Unity.Level level = DotNetty.Unity.Level.ALL)
 | ||
|         {
 | ||
|             // 指定DotNetty日志的显示级别
 | ||
|             DotNetty.Unity.UnityLoggerFactory.Default.Level = level;
 | ||
|         }
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 当前 Client 是否处于连接状态
 | ||
|         /// </summary>
 | ||
|         public bool Running => _running;
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 创建一个到 Dof GameServer 的连接
 | ||
|         /// </summary>
 | ||
|         /// <param name="serverAddress">Dof GameServer 的地址,形如 xxx.xxx.xxx.xxx</param>
 | ||
|         /// <param name="port">房间ID</param>
 | ||
|         /// <param name="receiver">事件回调接口</param>
 | ||
|         public async void Connect(string serverAddress, int port, IMessageReceiver receiver)
 | ||
|         {
 | ||
|             _receiver = receiver;
 | ||
|             _receiver.MessageSender = sender;
 | ||
|             _running = true;
 | ||
| 
 | ||
|             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(serverAddress), port);
 | ||
|             var task = _kcpClient.BindLocal();
 | ||
|             await task;
 | ||
|             var channel = task.Result;
 | ||
|             _kcpClient.connect(channel, remoteAddress, channelConfig, this);
 | ||
|         }
 | ||
| 
 | ||
|         private void ProcessMessage(ServerMessage serverMessage)
 | ||
|         {
 | ||
|             Debug.Log("[ProcessMessage]");
 | ||
|             if (serverMessage.PlayerEntered != null)
 | ||
|             {
 | ||
|                 //Debug.Log("[ProcessMessage]PlayerEntered");
 | ||
|                 var cid = serverMessage.PlayerEntered.Cid;
 | ||
|                 sender.Cid = cid;
 | ||
|                 _receiver.OnPlayerEntered(cid);
 | ||
|             }
 | ||
|             else if (serverMessage.GameStart != null)
 | ||
|             {
 | ||
|                 //Debug.Log("[ProcessMessage]GameStart");
 | ||
|                 _receiver.OnGameStart(serverMessage.GameStart);
 | ||
|             }
 | ||
|             else if (serverMessage.LevelStart != null)
 | ||
|             {
 | ||
|                 //Debug.Log("[ProcessMessage]LevelStart");
 | ||
|                 _receiver.OnLevelStart(serverMessage.LevelStart);
 | ||
|             }
 | ||
|             else if (serverMessage.PointFound != null)
 | ||
|             {
 | ||
|                 //Debug.Log("[ProcessMessage]PointFound");
 | ||
|                 _receiver.OnPointFound(serverMessage.PointFound);
 | ||
|             }
 | ||
|             else if (serverMessage.GameFinish != null)
 | ||
|             {
 | ||
|                 //Debug.Log("[ProcessMessage]GameFinish");
 | ||
|                 _receiver.OnGameFinish(serverMessage.GameFinish);
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// kcp 连接后的回调函数
 | ||
|         /// </summary>
 | ||
|         /// <param name="ukcp">kcp连接</param>
 | ||
|         public void onConnected(Ukcp ukcp)
 | ||
|         {
 | ||
|             Debug.Log($"[GameKcpClient]onConnected: conv = {ukcp.getConv()}");
 | ||
|             sender.Client = ukcp;
 | ||
| 
 | ||
|             if (OnConnected != null)
 | ||
|             {
 | ||
|                 Loom.QueueOnMainThread(() =>
 | ||
|                 {
 | ||
|                     OnConnected.Invoke();
 | ||
|                 });
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// kcp 接收到消息的回调函数
 | ||
|         /// </summary>
 | ||
|         /// <param name="byteBuf">接收到的消息buffer</param>
 | ||
|         /// <param name="ukcp">kcp连接</param>
 | ||
|         public void handleReceive(IByteBuffer byteBuf, Ukcp ukcp)
 | ||
|         {
 | ||
|             Debug.Log("[GameKcpClient]handleReceive");
 | ||
| 
 | ||
|             var ms = new MemoryStream(1024 * 1024 * 1);
 | ||
|             var data_len = byteBuf.ReadableBytes;
 | ||
|             byteBuf.ReadBytes(ms, data_len);
 | ||
|             var msg = ProtobufHelper.FromBytes(typeof(ServerMessage), ms.GetBuffer(), 0, data_len);
 | ||
| 
 | ||
|             if (msg is ServerMessage server_msg)
 | ||
|             {
 | ||
|                 Loom.QueueOnMainThread(() =>
 | ||
|                 {
 | ||
|                     ProcessMessage(server_msg);
 | ||
|                 });
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 Debug.LogError("[GameKcpClient]handleReceive: Fail to Deserialize ServerMessage");
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// kcp 连接或者接收消息出错的回调函数
 | ||
|         /// </summary>
 | ||
|         /// <param name="ex">异常</param>
 | ||
|         /// <param name="ukcp">kcp连接</param>
 | ||
|         public void handleException(Exception ex, Ukcp ukcp)
 | ||
|         {
 | ||
|             Debug.LogError($"[GameKcpClient]handleException: {ex}");
 | ||
|         }
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// kcp 连接关闭时的回调函数
 | ||
|         /// </summary>
 | ||
|         /// <param name="ukcp">kcp连接</param>
 | ||
|         public void handleClose(Ukcp ukcp)
 | ||
|         {
 | ||
|             Debug.Log("[GameKcpClient]: Connection closed");
 | ||
|         }
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 关闭 Client,应该在游戏结束时调用
 | ||
|         /// </summary>
 | ||
|         public void Close()
 | ||
|         {
 | ||
|             _kcpClient?.stop();
 | ||
|             _running = false;
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
| } |