using System; using System.Threading; using System.Threading.Tasks; using UnityEngine; using Cysharp.Threading.Tasks; namespace BITKit.Net.Kcp { public class MonoKcpClient : MonoBehaviour,INetClient,INetProvider { internal static MonoKcpClient Singleton { get; private set; } [SerializeField] private string m_host; [SerializeField] private ushort m_port; [SerializeField] private bool connectOnStart; [SerializeField] private bool autoReconnect; #if UNITY_EDITOR [SerializeField] private Optional allowDebugHost; [SerializeField] private Optional allowDebugPort; #endif private KcpNetClient client; private INetClient _netClientImplementation=>client; private INetProvider _netProviderImplementation=>client; private CancellationTokenSource _cancellationTokenSource; public event Action OnStartConnect { add => _netClientImplementation.OnStartConnect += value; remove => _netClientImplementation.OnStartConnect -= value; } public event Action OnConnected { add => _netClientImplementation.OnConnected += value; remove => _netClientImplementation.OnConnected -= value; } public event Action OnDisconnected { add => _netClientImplementation.OnDisconnected += value; remove => _netClientImplementation.OnDisconnected -= value; } public event Action OnConnectedFailed { add => _netClientImplementation.OnConnectedFailed += value; remove => _netClientImplementation.OnConnectedFailed -= value; } public bool IsConnected => _netClientImplementation.IsConnected; public int Ping => _netClientImplementation.Ping; public int Id => _netClientImplementation.Id; public void Disconnect() { _netClientImplementation.Disconnect(); } public UniTask Connect(string address = "localhost", ushort port = 27014) { return _netClientImplementation.Connect(address, port); } public void SendServerMessage(string message) { _netClientImplementation.SendServerMessage(message); } public void ServerCommand(T command = default) { _netProviderImplementation.ServerCommand(command); } public void AllClientCommand(T command = default) { _netProviderImplementation.AllClientCommand(command); } public void ClientCommand(int id, T command) { _netProviderImplementation.ClientCommand(id, command); } public UniTask GetFromServer(string addressablePath = Constant.System.Internal) { return _netProviderImplementation.GetFromServer(addressablePath); } public UniTask GetFromClient(int id, string addressablePath = Constant.System.Internal) { return _netProviderImplementation.GetFromClient(id, addressablePath); } public void AddRpcHandle(object rpcHandle) { _netProviderImplementation.AddRpcHandle(rpcHandle); } public void AddCommandListener(Action handle) { _netProviderImplementation.AddCommandListener(handle); } public void RemoveCommandListener(Action handle) { _netProviderImplementation.RemoveCommandListener(handle); } public void SendRT(string rpcName, params object[] pars) { _netProviderImplementation.SendRT(rpcName, pars); } public void SendTargetRT(int id, string rpcName, params object[] pars) { _netProviderImplementation.SendTargetRT(id, rpcName, pars); } public void SendAllRT(string rpcName, params object[] pars) { _netProviderImplementation.SendAllRT(rpcName, pars); } public void Tick() { _netProviderImplementation.Tick(); } public void HandShake() { _netProviderImplementation.HandShake(); } private void Awake() { Singleton = this; _cancellationTokenSource = new CancellationTokenSource(); client = new KcpNetClient(); client.OnConnectedFailed += Reconnect; client.OnDisconnected += Reconnect; } private async void Reconnect() { if (autoReconnect is false) return; try { await Task.Delay(1000, _cancellationTokenSource.Token); if (client.IsConnected is false) { await client.Connect(m_host, m_port); } } catch (OperationCanceledException) { } } private void Start() { if (!connectOnStart) return; #if UNITY_EDITOR var _host = allowDebugHost.Allow ? allowDebugHost.Value : m_host; var _port = allowDebugPort.Allow ? allowDebugPort.Value : m_port; Connect(_host, _port).Forget(); #else Connect(m_host, m_port).Forget(); #endif } private void OnDestroy() { _cancellationTokenSource.Cancel(); if (client.IsConnected) { client.Disconnect(); } } } }