upm_guru_dof_lib/Runtime/GameKcpClient.cs

189 lines
6.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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;
public Action OnDisConnected;
private KcpClient _kcpClient;
public IMessageSender sender { get; private set; } = new MessageSender();
private IMessageReceiver _receiver;
private bool _running;
private int? _timeoutMillis;
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);
if(_timeoutMillis.hasValue)
channelConfig.TimeoutMillis = _timeoutMillis.Value;
_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");
if (OnDisConnected != null)
{
Loom.QueueOnMainThread(() =>
{
OnDisConnected.Invoke();
});
}
}
public void setTimeoutMillis(int timeoutMillis)
{
_timeoutMillis = timeoutMillis;
}
/// <summary>
/// 关闭 Client应该在游戏结束时调用
/// </summary>
public void Close()
{
_kcpClient?.stop();
_running = false;
}
}
}