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);
}
}
}