using Milimoe.FunGame.Core.Controller; using Milimoe.FunGame.Core.Library.Common.Network; using Milimoe.FunGame.Core.Library.Constant; using Milimoe.FunGame.Core.Library.Exception; namespace Milimoe.FunGame.Core.Api.Transmittal { /// /// 需要配合 使用 /// 如果是 的数据请求,则配合 使用 /// 确保已添加对应的枚举 /// public class DataRequest : IDisposable { /// /// 数据请求结果 /// public RequestResult Result => _worker != null ? _worker.Result : (_gamingWorker != null ? _gamingWorker.Result : RequestResult.Missing); /// /// 详细错误信息 /// public string Error => _worker != null ? _worker.Error : (_gamingWorker != null ? _gamingWorker.Error : ""); /// /// 是否已经关闭 /// public bool IsDisposed => _isDisposed; // 获取ResultData中key值对应的Json字符串 // -- 此索引器仅返回Json字符串,对象类型请使用反序列化方法GetResult() -- // -- 当然也可以自己反序列化 -- // -- 基本类型可能有效,但仍建议使用反序列化方法 -- public object? this[string key] { get { if (_worker != null) return _worker.ResultData[key]; else if (_gamingWorker != null) return _gamingWorker.ResultData[key]; return null; } set { if (value != null) AddRequestData(key, value); } } /// /// 私有的实现类 /// private readonly SocketRequest? _worker; /// /// 私有的实现类(这是局内请求的) /// private readonly GamingRequest? _gamingWorker; /// /// 指示关闭的变量 /// private bool _isDisposed = false; /// /// 基于本地已连接的 创建新的数据请求 /// 使用 中的 创建一个新的请求 /// 插件则使用 中的 创建一个新的请求 /// /// /// /// /// internal DataRequest(Socket socket, DataRequestType type, bool longRunning = false, SocketRuntimeType runtime = SocketRuntimeType.Client) { _worker = new(socket, type, Guid.NewGuid(), longRunning, runtime); } /// /// 基于本地已连接的 创建新的数据请求 /// 使用 中的 创建一个新的请求 /// 插件则使用 中的 创建一个新的请求 /// 此数据请求只能调用异步方法 请求数据 /// /// /// /// /// internal DataRequest(HTTPClient client, DataRequestType type, bool longRunning = false, SocketRuntimeType runtime = SocketRuntimeType.Client) { _worker = new(client, type, Guid.NewGuid(), longRunning, runtime); } /// /// 基于本地已连接的 创建新的局内()数据请求 /// 使用 中的 创建一个新的请求 /// 此构造方法是给 提供的 /// /// /// /// /// internal DataRequest(Socket socket, GamingType type, bool longRunning = false, SocketRuntimeType runtime = SocketRuntimeType.Client) { _gamingWorker = new(socket, type, Guid.NewGuid(), longRunning, runtime); } /// /// 基于本地已连接的 创建新的局内()数据请求 /// 使用 中的 创建一个新的请求 /// 此构造方法是给 提供的 /// 此数据请求只能调用异步方法 请求数据 /// /// /// /// /// internal DataRequest(HTTPClient client, GamingType type, bool longRunning = false, SocketRuntimeType runtime = SocketRuntimeType.Client) { _gamingWorker = new(client, type, Guid.NewGuid(), longRunning, runtime); } /// /// 添加数据 /// /// /// public void AddRequestData(string key, object value) { if (_worker != null) { if (!_worker.RequestData.TryAdd(key, value)) _worker.RequestData[key] = value; } else if (_gamingWorker != null) { if (!_gamingWorker.RequestData.TryAdd(key, value)) _gamingWorker.RequestData[key] = value; } } /// /// 长时间运行的数据请求需要在使用完毕后自行关闭 /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// 关闭时 /// /// protected void Dispose(bool disposing) { if (!_isDisposed) { if (disposing) { _worker?.Dispose(); _gamingWorker?.Dispose(); } } _isDisposed = true; } /// /// 向服务器发送数据请求 /// 警告: 调用此方法将抛出异常。请调用并等待 /// /// /// public RequestResult SendRequest() { _worker?.SendRequest(); _gamingWorker?.SendRequest(); return Result; } /// /// 异步向服务器发送数据请求 /// /// public async Task SendRequestAsync() { if (_worker != null) { await _worker.SendRequestAsync(); } else if (_gamingWorker != null) { await _gamingWorker.SendRequestAsync(); } return Result; } /// /// 获取指定key对应的反序列化对象 /// /// /// /// public T? GetResult(string key) { if (_worker != null) { return GetDictionaryJsonObject(_worker.ResultData, key); } else if (_gamingWorker != null) { return GetDictionaryJsonObject(_gamingWorker.ResultData, key); } return default; } /// /// 常规数据请求 /// private class SocketRequest : SocketHandlerController { public Dictionary RequestData { get; } = []; public Dictionary ResultData => _ResultData; public RequestResult Result => _Result; public string Error => _Error; private readonly Socket? Socket = null; private readonly HTTPClient? HTTPClient = null; private readonly DataRequestType RequestType = DataRequestType.UnKnown; private readonly Guid RequestID = Guid.Empty; private readonly bool IsLongRunning = false; private readonly SocketRuntimeType RuntimeType = SocketRuntimeType.Client; private Dictionary _ResultData = []; private RequestResult _Result = RequestResult.Missing; private string _Error = ""; public SocketRequest(Socket? socket, DataRequestType type, Guid requestId, bool longRunning = false, SocketRuntimeType runtime = SocketRuntimeType.Client) : base(socket) { Socket = socket; RequestType = type; RequestID = requestId; IsLongRunning = longRunning; RuntimeType = runtime; } public SocketRequest(HTTPClient? client, DataRequestType type, Guid requestId, bool longRunning = false, SocketRuntimeType runtime = SocketRuntimeType.Client) : base(client) { HTTPClient = client; RequestType = type; RequestID = requestId; IsLongRunning = longRunning; RuntimeType = runtime; } public void SendRequest() { try { SetWorking(); if (RuntimeType == SocketRuntimeType.Addon) { if (RequestData.ContainsKey(SocketSet.Plugins_Mark)) RequestData[SocketSet.Plugins_Mark] = "true"; else RequestData.Add(SocketSet.Plugins_Mark, true); } else RequestData.Remove(SocketSet.Plugins_Mark); if (Socket != null && Socket.Send(SocketMessageType.DataRequest, RequestType, RequestID, RequestData) == SocketResult.Success) { WaitForWorkDone(); } else if (HTTPClient != null) { throw new AsyncSendException(); } else throw new ConnectFailedException(); } catch (Exception e) { Working = false; _Result = RequestResult.Fail; _Error = e.GetErrorInfo(); } } public async Task SendRequestAsync() { try { SetWorking(); if (RuntimeType == SocketRuntimeType.Addon) { if (RequestData.ContainsKey(SocketSet.Plugins_Mark)) RequestData[SocketSet.Plugins_Mark] = "true"; else RequestData.Add(SocketSet.Plugins_Mark, true); } else RequestData.Remove(SocketSet.Plugins_Mark); if (Socket != null && Socket.Send(SocketMessageType.DataRequest, RequestType, RequestID, RequestData) == SocketResult.Success) { await WaitForWorkDoneAsync(); } else if (HTTPClient != null && await HTTPClient.Send(SocketMessageType.DataRequest, RequestType, RequestID, RequestData) == SocketResult.Success) { await WaitForWorkDoneAsync(); } else throw new ConnectFailedException(); } catch (Exception e) { Working = false; _Result = RequestResult.Fail; _Error = e.GetErrorInfo(); } } public override void SocketHandler(SocketObject obj) { try { if (obj.SocketType == SocketMessageType.DataRequest) { DataRequestType type = obj.GetParam(0); Guid id = obj.GetParam(1); if (type == RequestType && id == RequestID) { if (!IsLongRunning) Dispose(); ReceivedObject = obj; Working = false; _ResultData = obj.GetParam>(2) ?? []; _Result = RequestResult.Success; } } } catch (Exception e) { Working = false; _Result = RequestResult.Fail; _Error = e.GetErrorInfo(); } } } /// /// 游戏局内请求 /// private class GamingRequest : SocketHandlerController { public Dictionary RequestData { get; } = []; public Dictionary ResultData => _ResultData; public RequestResult Result => _Result; public string Error => _Error; private readonly Socket? Socket = null; private readonly HTTPClient? HTTPClient = null; private readonly GamingType GamingType = GamingType.None; private readonly Guid RequestID = Guid.Empty; private readonly bool IsLongRunning = false; private readonly SocketRuntimeType RuntimeType = SocketRuntimeType.Client; private Dictionary _ResultData = []; private RequestResult _Result = RequestResult.Missing; private string _Error = ""; public GamingRequest(Socket? socket, GamingType type, Guid requestId, bool longRunning = false, SocketRuntimeType runtime = SocketRuntimeType.Client) : base(socket) { Socket = socket; GamingType = type; RequestID = requestId; IsLongRunning = longRunning; RuntimeType = runtime; } public GamingRequest(HTTPClient? client, GamingType type, Guid requestId, bool longRunning = false, SocketRuntimeType runtime = SocketRuntimeType.Client) : base(client) { HTTPClient = client; GamingType = type; RequestID = requestId; IsLongRunning = longRunning; RuntimeType = runtime; } public void SendRequest() { try { SetWorking(); if (RuntimeType == SocketRuntimeType.Addon) { if (RequestData.ContainsKey(SocketSet.Plugins_Mark)) RequestData[SocketSet.Plugins_Mark] = "true"; else RequestData.Add(SocketSet.Plugins_Mark, true); } else RequestData.Remove(SocketSet.Plugins_Mark); if (Socket != null && Socket.Send(SocketMessageType.GamingRequest, GamingType, RequestID, RequestData) == SocketResult.Success) { WaitForWorkDone(); } else if (HTTPClient != null) { throw new AsyncSendException(); } else throw new ConnectFailedException(); } catch (Exception e) { Working = false; _Result = RequestResult.Fail; _Error = e.GetErrorInfo(); } } public async Task SendRequestAsync() { try { SetWorking(); if (RuntimeType == SocketRuntimeType.Addon) { if (RequestData.ContainsKey(SocketSet.Plugins_Mark)) RequestData[SocketSet.Plugins_Mark] = "true"; else RequestData.Add(SocketSet.Plugins_Mark, true); } else RequestData.Remove(SocketSet.Plugins_Mark); if (Socket != null && Socket.Send(SocketMessageType.GamingRequest, GamingType, RequestID, RequestData) == SocketResult.Success) { await WaitForWorkDoneAsync(); } else if (HTTPClient != null && await HTTPClient.Send(SocketMessageType.GamingRequest, GamingType, RequestID, RequestData) == SocketResult.Success) { await WaitForWorkDoneAsync(); } else throw new ConnectFailedException(); } catch (Exception e) { Working = false; _Result = RequestResult.Fail; _Error = e.GetErrorInfo(); } } public override void SocketHandler(SocketObject obj) { try { if (obj.SocketType == SocketMessageType.GamingRequest) { GamingType type = obj.GetParam(0); Guid id = obj.GetParam(1); if (type == GamingType && id == RequestID) { if (!IsLongRunning) Dispose(); ReceivedObject = obj; Working = false; _ResultData = obj.GetParam>(2) ?? []; _Result = RequestResult.Success; } } } catch (Exception e) { Working = false; _Result = RequestResult.Fail; _Error = e.GetErrorInfo(); } } } /// /// 反序列化Dictionary中的Json对象 /// /// /// /// /// public static T? GetDictionaryJsonObject(Dictionary dict, string key) { return Service.JsonManager.GetObject(dict, key); } } }