This commit is contained in:
CortexCore 2024-06-08 10:07:40 +08:00
parent ccc9957809
commit b9731c20a1
11 changed files with 231 additions and 44 deletions

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Timers;
using Cysharp.Threading.Tasks;
@ -38,6 +39,10 @@ namespace BITKit.Net
private readonly GenericEvent _events = new();
private readonly ValidHandle _isConnected = new();
private int _index = 1001;
private readonly ConcurrentDictionary<int, object> _p2p = new();
private readonly ConcurrentDictionary<string,object> _rpc = new();
public KcpNetClient()
{
client = new KcpClient(
@ -161,6 +166,11 @@ namespace BITKit.Net
case NetCommandType.Ping:
Ping = (int)(DateTime.Now - _lastPingTime).TotalMilliseconds;
break;
case NetCommandType.ReturnToClient:
var id = reader.ReadInt32();
var value = BITBinary.Read(reader);
_p2p.TryAdd(id,value);
break;
default:
BIT4Log.Log<KcpClient>($"未知消息类型:{type},字节:{(byte)type}");
if (bytes.Array != null)
@ -217,15 +227,36 @@ namespace BITKit.Net
Send(NetCommandType.TargetCommand,id,command);
}
public UniTask<T> GetFromServer<T>(string addressablePath = Constant.System.Internal)
public async UniTask<T> GetFromServer<T>(T command = default)
{
var id = _index++;
using var ms = new MemoryStream();
await using var writer = new BinaryWriter(ms);
writer.Write((byte)NetCommandType.GetFromServer);
writer.Write(id);
BITBinary.Write(writer,command);
var bytes = ms.ToArray();
commandQueue.Enqueue(bytes);
var startTime = DateTime.Now;
while (true)
{
if(DateTime.Now-startTime>TimeSpan.FromSeconds(5) || IsConnected is false)
throw new TimeoutException();
if (_p2p.TryRemove(id, out var value))
{
return (T)value;
}
await Task.Delay(100);
}
}
public UniTask<T> GetFromClient<T>(int id, T command = default)
{
throw new NotImplementedException();
}
public UniTask<T> GetFromClient<T>(int id, string addressablePath = Constant.System.Internal)
{
throw new NotImplementedException();
}
public void AddRpcHandle(object rpcHandle)
{
@ -237,9 +268,19 @@ namespace BITKit.Net
_events.AddListener<T>(handle);
}
public void AddCommandListener<T>(Func<T, T> func)
{
_rpc.GetOrAdd(typeof(T).FullName, func);
}
public void RemoveCommandListener<T>(Func<T, T> func)
{
_rpc.TryRemove(typeof(T).FullName, out _);
}
public void RemoveCommandListener<T>(Action<T> handle)
{
throw new NotImplementedException();
_events.RemoveListener<T>(handle);
}
public void SendRT(string rpcName, params object[] pars)

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Timers;
using Cysharp.Threading.Tasks;
@ -26,6 +27,11 @@ namespace BITKit.Net
AutoReset = true
};
private int _index = 1001;
private readonly ConcurrentDictionary<int, object> _p2p = new();
private readonly ConcurrentDictionary<string,Func<object,object>> _rpc = new();
public KCPNetServer()
{
server = new KcpServer(
@ -37,6 +43,12 @@ namespace BITKit.Net
);
_timer.Elapsed += Tick;
BIT4Log.Log<KCPNetServer>("已创建KCP服务器");
AddCommandListener<SimplePing>(x =>
{
x.EndTime = DateTime.Now;
return x;
});
}
private void Tick(object sender, ElapsedEventArgs e)
@ -161,6 +173,35 @@ namespace BITKit.Net
case NetCommandType.Ping:
server.Send(Id,new byte[]{(byte)NetCommandType.Ping},channel);
break;
case NetCommandType.GetFromServer:
try
{
var requestId = reader.ReadInt32();
var commandObj = BITBinary.Read(reader);
BIT4Log.Log<KCPNetServer>($"已收到请求:{commandObj},请求ID:{requestId}");
if (_rpc.TryGetValue(commandObj.GetType().FullName, out var func) is false)
{
throw new NotImplementedException($"未找到对应的方法:{commandObj.GetType().FullName}");
}
var value = func.As<Func<object,object>>().Invoke(commandObj);
using var _ms = new MemoryStream();
using var _writer = new BinaryWriter(_ms);
_writer.Write((byte)NetCommandType.ReturnToClient);
_writer.Write(requestId);
BITBinary.Write(_writer,value);
var _bytes = _ms.ToArray();
server.Send(Id,_bytes,KcpChannel.Reliable);
}
catch (Exception e)
{
BIT4Log.LogException(e);
Send(Id,NetCommandType.ReturnToClient,-1,0);
}
break;
default:
BIT4Log.Log<KCPNetServer>($"未知消息类型:{type},字节:{(byte)type}");
BIT4Log.Log<KCPNetServer>($"已收到:({Id}, {BitConverter.ToString(bytes.Array, bytes.Offset, bytes.Count)} @ {channel})");
@ -190,12 +231,12 @@ namespace BITKit.Net
Send(id,NetCommandType.Command,command);
}
public UniTask<T> GetFromServer<T>(string addressablePath = Constant.System.Internal)
public UniTask<T> GetFromServer<T>(T command = default)
{
throw new NotImplementedException();
}
public UniTask<T> GetFromClient<T>(int id, string addressablePath = Constant.System.Internal)
public UniTask<T> GetFromClient<T>(int id, T command = default)
{
throw new NotImplementedException();
}
@ -209,7 +250,21 @@ namespace BITKit.Net
{
_events.AddListener<T>(handle);
}
public void AddCommandListener<T>(Func<T, T> func)
{
_rpc.TryAdd(typeof(T).FullName, F);
return;
object F(object o)
{
return func.Invoke((T)o);
}
}
public void RemoveCommandListener<T>(Func<T, T> func)
{
_rpc.TryRemove(typeof(T).FullName, out _);
}
public void AddCommandListenerWithId<T>(Action<int, T> handle)
{
_events.AddListenerDirect(typeof(T).FullName, Callback);
@ -233,6 +288,11 @@ namespace BITKit.Net
_events.RemoveListener<T>(handle);
}
public void RemoveCommandListener<T>(Func<string, T> func)
{
throw new NotImplementedException();
}
public void SendRT(string rpcName, params object[] pars)
{
throw new NotImplementedException();

View File

@ -1,11 +1,13 @@
using System;
using System.Data;
namespace BITKit.Net.Examples
{
public struct LogTime
{
public Guid Id;
public DateTime CreateTime;
#if NET5_0_OR_GREATER
#if NET5_0_OR_GREATER
public LogTime()
{
CreateTime=DateTime.Now;
@ -13,5 +15,10 @@ namespace BITKit.Net.Examples
}
#endif
}
public struct SimplePing
{
public DateTime StartTime;
public DateTime EndTime;
}
}

View File

@ -29,6 +29,11 @@ namespace BITKit
Message=6,
Heartbeat=7,
Ping=8,
GetFromServer=9,
GetFromClient=10,
ReciveFile=11,
ReturnToServer=12,
ReturnToClient=13,
}
/// <summary>
/// 网络提供服务包括了基础网络服务e.g
@ -67,10 +72,9 @@ namespace BITKit
/// <summary>
/// 从服务端获取数据
/// </summary>
/// <param name="addressablePath">可寻址路劲 e.g. Key</param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
UniTask<T> GetFromServer<T>(string addressablePath = Constant.System.Internal);
UniTask<T> GetFromServer<T>(T command = default);
/// <summary>
/// 从客户端获取数据
@ -79,7 +83,7 @@ namespace BITKit
/// <param name="addressablePath">可寻址路劲 e.g. Key</param>
/// <typeparam name="T">远程指令类型</typeparam>
/// <returns></returns>
UniTask<T> GetFromClient<T>(int id, string addressablePath = Constant.System.Internal);
UniTask<T> GetFromClient<T>(int id,T command = default);
/// <summary>
/// 添加RPC远程服务服务类型为需要的方法标记[RPC]
@ -93,13 +97,19 @@ namespace BITKit
/// <param name="handle">远程指令回调</param>
/// <typeparam name="T">远程指令类型</typeparam>
void AddCommandListener<T>(Action<T> handle);
/// <summary>
/// 监听远程func
/// </summary>
/// <param name="func"></param>
/// <typeparam name="T"></typeparam>
void AddCommandListener<T>(Func<T,T> func);
/// <summary>
/// 取消监听远程指令
/// </summary>
/// <param name="handle">远程指令回调</param>
/// <typeparam name="T">远程指令类型</typeparam>
void RemoveCommandListener<T>(Action<T> handle);
void RemoveCommandListener<T>(Func<T,T> func);
/// <summary>
/// 向服务端发送Rpc

View File

@ -53,6 +53,10 @@ namespace BITKit
private static Type SearchType(string fullName)
{
if (string.IsNullOrWhiteSpace(fullName))
{
throw new ArgumentException("fullName is null or empty", nameof(fullName));
}
assemblies ??= AppDomain.CurrentDomain.GetAssemblies();
return assemblies.Select(assembly => assembly.GetType(fullName, false)).FirstOrDefault(type => type is not null);
}

View File

@ -2,13 +2,37 @@
namespace BITKit
{
/// <summary>
/// 循环
/// </summary>
public interface ITicker
{
/// <summary>
/// 总帧数
/// </summary>
ulong TickCount { get; }
/// <summary>
/// 在下一次循环时执行,仅执行一次
/// </summary>
/// <param name="action"></param>
void Add(Action action);
/// <summary>
/// 注册在下一次循环时执行,每次循环都会执行
/// </summary>
/// <param name="action"></param>
void Add(Action<float> action);
/// <summary>
/// 移除循环
/// </summary>
/// <param name="action"></param>
void Remove(Action<float> action);
}
/// <summary>
/// 主线程循环
/// </summary>
public interface IMainTicker : ITicker { }
/// <summary>
/// 线程池循环
/// </summary>
public interface IThreadTicker : ITicker { }
}

View File

@ -89,15 +89,9 @@ namespace BITKit.Net
_netProviderImplementation.ClientCommand(id, command);
}
public UniTask<T> GetFromServer<T>(string addressablePath = Constant.System.Internal)
{
return _netProviderImplementation.GetFromServer<T>(addressablePath);
}
public UniTask<T> GetFromServer<T>(T command = default)=>_netProviderImplementation.GetFromServer<T>(command);
public UniTask<T> GetFromClient<T>(int id, string addressablePath = Constant.System.Internal)
{
return _netProviderImplementation.GetFromClient<T>(id, addressablePath);
}
public UniTask<T> GetFromClient<T>(int id, T command = default)=>_netProviderImplementation.GetFromClient(id, command);
public void AddRpcHandle(object rpcHandle)
{
@ -109,11 +103,15 @@ namespace BITKit.Net
_netProviderImplementation.AddCommandListener(handle);
}
public void RemoveCommandListener<T>(Action<T> handle)
public void AddCommandListener<T>(Func<T, T> func)
{
_netProviderImplementation.RemoveCommandListener(handle);
throw new NotImplementedException();
}
public void RemoveCommandListener<T>(Func<T, T> func)
{
throw new NotImplementedException();
}
public void SendRT(string rpcName, params object[] pars)
{
_netProviderImplementation.SendRT(rpcName, pars);

View File

@ -1,6 +1,7 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using BITKit.Net.Examples;
using UnityEngine;
using Cysharp.Threading.Tasks;
namespace BITKit.Net.Kcp
@ -95,16 +96,15 @@ namespace BITKit.Net.Kcp
_netProviderImplementation.ClientCommand(id, command);
}
public UniTask<T> GetFromServer<T>(string addressablePath = Constant.System.Internal)
public UniTask<T> GetFromServer<T>(T command = default)
{
return _netProviderImplementation.GetFromServer<T>(addressablePath);
return _netProviderImplementation.GetFromServer<T>(command);
}
public UniTask<T> GetFromClient<T>(int id, string addressablePath = Constant.System.Internal)
public UniTask<T> GetFromClient<T>(int id, T command = default)
{
return _netProviderImplementation.GetFromClient<T>(id, addressablePath);
return _netProviderImplementation.GetFromClient<T>(id, command);
}
public void AddRpcHandle(object rpcHandle)
{
_netProviderImplementation.AddRpcHandle(rpcHandle);
@ -115,11 +115,15 @@ namespace BITKit.Net.Kcp
_netProviderImplementation.AddCommandListener(handle);
}
public void RemoveCommandListener<T>(Action<T> handle)
public void AddCommandListener<T>(Func<T, T> func)
{
_netProviderImplementation.RemoveCommandListener(handle);
throw new NotImplementedException();
}
public void RemoveCommandListener<T>(Func<T, T> func)
{
throw new NotImplementedException();
}
public void SendRT(string rpcName, params object[] pars)
{
_netProviderImplementation.SendRT(rpcName, pars);
@ -214,6 +218,16 @@ namespace BITKit.Net.Kcp
BITAppForUnity.ThrowIfNotPlaying();
Disconnect();
}
[BIT]
private async void Hello()
{
BITAppForUnity.ThrowIfNotPlaying();
var value =await GetFromServer(new SimplePing()
{
StartTime = DateTime.Now
});
BIT4Log.Log<MonoKcpClient>($"已返回\n开始:{value.StartTime}\n结束:{value.EndTime}\n延迟:{(value.EndTime-value.StartTime).TotalMilliseconds}ms");
}
}
}

View File

@ -76,16 +76,15 @@ namespace BITKit.Net.Kcp
_netProviderImplementation.ClientCommand(id, command);
}
public UniTask<T> GetFromServer<T>(string addressablePath = Constant.System.Internal)
public UniTask<T> GetFromServer<T>(T command = default)
{
return _netProviderImplementation.GetFromServer<T>(addressablePath);
return _netProviderImplementation.GetFromServer<T>(command);
}
public UniTask<T> GetFromClient<T>(int id, string addressablePath = Constant.System.Internal)
public UniTask<T> GetFromClient<T>(int id, T command = default)
{
return _netProviderImplementation.GetFromClient<T>(id, addressablePath);
return _netProviderImplementation.GetFromClient<T>(id, command);
}
public void AddRpcHandle(object rpcHandle)
{
_netProviderImplementation.AddRpcHandle(rpcHandle);
@ -96,11 +95,15 @@ namespace BITKit.Net.Kcp
_netProviderImplementation.AddCommandListener(handle);
}
public void RemoveCommandListener<T>(Action<T> handle)
public void AddCommandListener<T>(Func<T, T> func)
{
_netProviderImplementation.RemoveCommandListener(handle);
throw new NotImplementedException();
}
public void RemoveCommandListener<T>(Func<T, T> func)
{
throw new NotImplementedException();
}
public void SendRT(string rpcName, params object[] pars)
{
_netProviderImplementation.SendRT(rpcName, pars);

View File

@ -108,16 +108,15 @@ namespace BITKit.Net.Kcp
_server.ClientCommand(id, command);
}
public UniTask<T> GetFromServer<T>(string addressablePath = Constant.System.Internal)
public UniTask<T> GetFromServer<T>(T command = default)
{
return _server.GetFromServer<T>(addressablePath);
return _serverInstance.GetFromServer(command);
}
public UniTask<T> GetFromClient<T>(int id, string addressablePath = Constant.System.Internal)
public UniTask<T> GetFromClient<T>(int id, T command = default)
{
return _server.GetFromClient<T>(id, addressablePath);
return _serverInstance.GetFromClient(id, command);
}
public void AddRpcHandle(object rpcHandle)
{
_server.AddRpcHandle(rpcHandle);
@ -128,6 +127,16 @@ namespace BITKit.Net.Kcp
_server.AddCommandListener(handle);
}
public void AddCommandListener<T>(Func<T, T> func)
{
_serverInstance.AddCommandListener(func);
}
public void RemoveCommandListener<T>(Func<T, T> func)
{
_serverInstance.RemoveCommandListener(func);
}
public void RemoveCommandListener<T>(Action<T> handle)
{
_server.RemoveCommandListener(handle);

View File

@ -50,6 +50,10 @@ namespace BITKit.GameEditor
var listViewContainer = container.Create<VisualElement>();
var createContainer = listViewContainer.Create<VisualElement>();
var exportButton = leftSlider.Create<Button>();
exportButton.text = "导出";
exportButton.clicked += ExportData;
createContainer.style.flexDirection = FlexDirection.Row;
@ -99,6 +103,19 @@ namespace BITKit.GameEditor
$"{GetType().Name} 已初始化,从{AssetsPath}获取到{List.Count}个{typeof(T).Name}");
}
private void ExportData()
{
var exportPath = EditorUtility.OpenFolderPanel("select path", "",typeof(T).FullName);
if(string.IsNullOrEmpty(exportPath))return;
ExportData(exportPath);
}
protected virtual void ExportData(string path)
{
}
protected virtual void ItemsChosen(IEnumerable<object> obj)
{
var selected = obj.FirstOrDefault() as Object;