using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using BITKit; using BITKit.UX; using BITKit.HttpNet; using Cysharp.Threading.Tasks; using Net.Client; using UnityEngine.UIElements; using System.Text; using Net.Share; using Object = System.Object; namespace BITKit { public interface INetClientProvider { ClientBase GetClient(); } [CreateOnStart(BITAppForUnity.Path.Services,nameof(BITNet))] public class BITNet : MonoBehaviour { [UnityEngine.RuntimeInitializeOnLoadMethod] static void Reload() { OnStartConnect = null; OnConnected = null; OnConnectFailed = null; OnTryToConnect = null; OnTryToConnectFailed = null; OnDisconnect = null; OnConnectLost = null; OnConnection = null; OnReconnect = null; OnOnWhenQueuing = null; OnOnQueueCancellation = null; RpcHandles.Clear(); } public static event Action OnStartConnect; public static event Action OnConnected; public static event Action OnConnectFailed; public static event Action OnTryToConnect; public static event Action OnTryToConnectFailed; public static event Action OnDisconnect; public static event Action OnConnectLost; public static event Action OnConnection; public static event Action OnReconnect; public static event Action OnOnWhenQueuing; public static event Action OnOnQueueCancellation; private static BITNet Singleton; private static readonly List RpcHandles = new(); private static readonly Queue<(string name,Object[] pars)> Rpcs = new(); [BITCommand] public static void Connect(string address, int port) { Singleton.ConnectInternal(address, port); } public static Action AddRpcHandle => RpcHandles.Add; public static void SendRT(string rpcName, params object[] pars) { Rpcs.Enqueue(new() { name = rpcName, pars = pars }); } [Header(Constant.Header.Settings)] public string address = "localhost"; public int port = 666; public int apiPort = 27014; [Header(Constant.Header.Settings)] [SerializeReference, SubclassSelector] public IWebProvider webProvider; [SerializeReference, SubclassSelector] public INetClientProvider clientProvider; [Header(Constant.Header.InternalVariables)] ClientBase client; private string GetApiUrl(string address) => $"http://{address}:{apiPort}/api"; public string GetAPI(params string[] path) { return GetApiUrl(address) + "/" + String.Join("/", path); } [BIT] public void ConnectToServer() { ConnectInternal(address, port); } [BIT] public void ConnectToLocal() { ConnectInternal("localhost", port); } [BIT] public void Disconnect() { client.Close(); //clientManager.client.Close(); } async void ConnectInternal(string address, int port) { try { foreach (var x in RpcHandles) { client.AddRpcHandle(x); } OnStartConnect?.Invoke(); var message = $"正在获取api:{GetApiUrl(address)}"; Data.Set(new ProgressInfo() { Progress = 0.1f, Message = message, }); Debug.Log(message); await webProvider .GetAsync(GetApiUrl(address),this.GetCancellationTokenOnDestroy()); message = $"已获取到服务器信息,正在连接到服务器"; Data.Set(new ProgressInfo() { Progress = 0.2f, Message = message, }); client.host = address; client.port = port; //client.ip=address; //clientManager.port=port; if (await client.Connect()) { Data.Set(new ProgressInfo() { Progress = 0.1f, Message = "已获取到在线服务器", }); } else { bool isConnected = false; for (int i = 0; i < 3; i++) { if(await client.Connect()) { isConnected=true; break; } else { Data.Set(new ProgressInfo() { Progress = 0.1f + i*0.1f, Message = "正在尝试重新连接到服务器", }); } } if(isConnected) { Data.Set(new ProgressInfo() { Progress = 0.5f, Message = "已连接,正在加载中...", }); } else { Alert.Print(new() { title = "连接失败", message = "已找到服务端但未找到服务器", }); OnConnectFailed?.Invoke(); } } } catch (System.Net.Http.HttpRequestException e) { Alert.Print(new AlertMessage() { title = "未找到服务端:", message = e.Message, }); OnConnectFailed?.Invoke(); } catch (System.Exception e) { Alert.Print(new AlertMessage() { title = "无法连接到服务端", message = e.Message, }); Debug.Log(e.GetType().FullName); BIT4Log.LogException(e); OnConnectFailed?.Invoke(); } } void Awake() { Singleton = this; DI.Register(this); client = clientProvider.GetClient(); DI.Register(client); } void Start() { /* * None, Connected, ConnectFailed, TryToConnect, TryToConnectFailed, Disconnect, ConnectLost, ConnectClosed, Connection, Reconnect, OnWhenQueuing, OnQueueCancellation, */ client.AddStateHandler(NetworkState.Connected,OnConnected); client.AddStateHandler(NetworkState.ConnectFailed,OnConnectFailed); client.AddStateHandler(NetworkState.TryToConnect,OnTryToConnect); client.AddStateHandler(NetworkState.TryToConnectFailed,OnTryToConnectFailed); client.AddStateHandler(NetworkState.Disconnect,OnDisconnect); client.AddStateHandler(NetworkState.ConnectLost,OnConnectLost); client.AddStateHandler(NetworkState.ConnectClosed,OnConnectLost); client.AddStateHandler(NetworkState.Connection,OnConnection); client.AddStateHandler(NetworkState.Reconnect,OnReconnect); client.AddStateHandler(NetworkState.OnWhenQueuing,OnOnWhenQueuing); client.AddStateHandler(NetworkState.OnQueueCancellation,OnOnQueueCancellation); } void Update() { if (client is null || client.Client is null || client.Client.Connected is false) return; while (Rpcs.TryDequeue(out var rpc)) { client.SendRT(rpc.name,rpc.pars); } } } #if UNITY_EDITOR [UnityEditor.CustomEditor(typeof(BITNet))] public class BITNetInspector : BITInspector { } #endif }