This commit is contained in:
parent
ccc9957809
commit
b9731c20a1
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 { }
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue