BITKit/Packages/Common~/Extensions/GameDesigner/BITNet.cs

253 lines
8.5 KiB
C#

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<object> 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<object> 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<IProgress>(new ProgressInfo()
{
Progress = 0.1f,
Message = message,
});
Debug.Log(message);
await webProvider
.GetAsync<Package>(GetApiUrl(address),this.GetCancellationTokenOnDestroy());
message = $"已获取到服务器信息,正在连接到服务器";
Data.Set<IProgress>(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<IProgress>(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<IProgress>(new ProgressInfo()
{
Progress = 0.1f + i*0.1f,
Message = "正在尝试重新连接到服务器",
});
}
}
if(isConnected)
{
Data.Set<IProgress>(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<BITNet>
{
}
#endif
}