完善 HTTPClient;添加日志级别;添加匿名服务器模组;修复不同时间多客户端连接游戏模组时可能产生的线程安全问题 (#106)

* 完善 HTTPClient;添加日志级别;添加匿名服务器模组(此模组不强制要求登录、客户端安装)

* 添加参数

* 添加 null 检查

* 修复不同时间多客户端连接游戏模组时可能产生的线程安全问题
This commit is contained in:
milimoe 2025-01-17 18:58:51 +08:00 committed by GitHub
parent ce0c933b35
commit d23c6597d1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 410 additions and 134 deletions

View File

@ -70,13 +70,13 @@ namespace Milimoe.FunGame.Core.Api.Transmittal
/// 插件则使用 <see cref="RunTimeController"/> 中的 <see cref="RunTimeController.NewDataRequestForAddon(DataRequestType)"/> 创建一个新的请求<para/> /// 插件则使用 <see cref="RunTimeController"/> 中的 <see cref="RunTimeController.NewDataRequestForAddon(DataRequestType)"/> 创建一个新的请求<para/>
/// 此数据请求只能调用异步方法 <see cref="SendRequestAsync"/> 请求数据 /// 此数据请求只能调用异步方法 <see cref="SendRequestAsync"/> 请求数据
/// </summary> /// </summary>
/// <param name="WebSocket"></param> /// <param name="HTTPClient"></param>
/// <param name="RequestType"></param> /// <param name="RequestType"></param>
/// <param name="IsLongRunning"></param> /// <param name="IsLongRunning"></param>
/// <param name="RuntimeType"></param> /// <param name="RuntimeType"></param>
internal DataRequest(HTTPClient WebSocket, DataRequestType RequestType, bool IsLongRunning = false, SocketRuntimeType RuntimeType = SocketRuntimeType.Client) internal DataRequest(HTTPClient HTTPClient, DataRequestType RequestType, bool IsLongRunning = false, SocketRuntimeType RuntimeType = SocketRuntimeType.Client)
{ {
Worker = new(WebSocket, RequestType, Guid.NewGuid(), IsLongRunning, RuntimeType); Worker = new(HTTPClient, RequestType, Guid.NewGuid(), IsLongRunning, RuntimeType);
} }
/// <summary> /// <summary>
@ -99,13 +99,13 @@ namespace Milimoe.FunGame.Core.Api.Transmittal
/// 此构造方法是给 <see cref="Library.Common.Addon.GameModule"/> 提供的<para/> /// 此构造方法是给 <see cref="Library.Common.Addon.GameModule"/> 提供的<para/>
/// 此数据请求只能调用异步方法 <see cref="SendRequestAsync"/> 请求数据 /// 此数据请求只能调用异步方法 <see cref="SendRequestAsync"/> 请求数据
/// </summary> /// </summary>
/// <param name="WebSocket"></param> /// <param name="Client"></param>
/// <param name="GamingType"></param> /// <param name="GamingType"></param>
/// <param name="IsLongRunning"></param> /// <param name="IsLongRunning"></param>
/// <param name="RuntimeType"></param> /// <param name="RuntimeType"></param>
internal DataRequest(HTTPClient WebSocket, GamingType GamingType, bool IsLongRunning = false, SocketRuntimeType RuntimeType = SocketRuntimeType.Client) internal DataRequest(HTTPClient Client, GamingType GamingType, bool IsLongRunning = false, SocketRuntimeType RuntimeType = SocketRuntimeType.Client)
{ {
GamingWorker = new(WebSocket, GamingType, Guid.NewGuid(), IsLongRunning, RuntimeType); GamingWorker = new(Client, GamingType, Guid.NewGuid(), IsLongRunning, RuntimeType);
} }
/// <summary> /// <summary>
@ -194,7 +194,7 @@ namespace Milimoe.FunGame.Core.Api.Transmittal
public string Error => _Error; public string Error => _Error;
private readonly Socket? Socket = null; private readonly Socket? Socket = null;
private readonly HTTPClient? WebSocket = null; private readonly HTTPClient? HTTPClient = null;
private readonly DataRequestType RequestType = DataRequestType.UnKnown; private readonly DataRequestType RequestType = DataRequestType.UnKnown;
private readonly Guid RequestID = Guid.Empty; private readonly Guid RequestID = Guid.Empty;
private readonly bool IsLongRunning = false; private readonly bool IsLongRunning = false;
@ -212,9 +212,9 @@ namespace Milimoe.FunGame.Core.Api.Transmittal
this.RuntimeType = RuntimeType; this.RuntimeType = RuntimeType;
} }
public SocketRequest(HTTPClient? WebSocket, DataRequestType RequestType, Guid RequestID, bool IsLongRunning = false, SocketRuntimeType RuntimeType = SocketRuntimeType.Client) : base(WebSocket) public SocketRequest(HTTPClient? HTTPClient, DataRequestType RequestType, Guid RequestID, bool IsLongRunning = false, SocketRuntimeType RuntimeType = SocketRuntimeType.Client) : base(HTTPClient)
{ {
this.WebSocket = WebSocket; this.HTTPClient = HTTPClient;
this.RequestType = RequestType; this.RequestType = RequestType;
this.RequestID = RequestID; this.RequestID = RequestID;
this.IsLongRunning = IsLongRunning; this.IsLongRunning = IsLongRunning;
@ -236,7 +236,7 @@ namespace Milimoe.FunGame.Core.Api.Transmittal
{ {
WaitForWorkDone(); WaitForWorkDone();
} }
else if (WebSocket != null) else if (HTTPClient != null)
{ {
throw new AsyncSendException(); throw new AsyncSendException();
} }
@ -265,7 +265,7 @@ namespace Milimoe.FunGame.Core.Api.Transmittal
{ {
await WaitForWorkDoneAsync(); await WaitForWorkDoneAsync();
} }
else if (WebSocket != null && await WebSocket.Send(SocketMessageType.DataRequest, RequestType, RequestID, RequestData) == SocketResult.Success) else if (HTTPClient != null && await HTTPClient.Send(SocketMessageType.DataRequest, RequestType, RequestID, RequestData) == SocketResult.Success)
{ {
await WaitForWorkDoneAsync(); await WaitForWorkDoneAsync();
} }
@ -317,7 +317,7 @@ namespace Milimoe.FunGame.Core.Api.Transmittal
public string Error => _Error; public string Error => _Error;
private readonly Socket? Socket = null; private readonly Socket? Socket = null;
private readonly HTTPClient? WebSocket = null; private readonly HTTPClient? HTTPClient = null;
private readonly GamingType GamingType = GamingType.None; private readonly GamingType GamingType = GamingType.None;
private readonly Guid RequestID = Guid.Empty; private readonly Guid RequestID = Guid.Empty;
private readonly bool IsLongRunning = false; private readonly bool IsLongRunning = false;
@ -335,9 +335,9 @@ namespace Milimoe.FunGame.Core.Api.Transmittal
this.RuntimeType = RuntimeType; this.RuntimeType = RuntimeType;
} }
public GamingRequest(HTTPClient? WebSocket, GamingType GamingType, Guid RequestID, bool IsLongRunning = false, SocketRuntimeType RuntimeType = SocketRuntimeType.Client) : base(WebSocket) public GamingRequest(HTTPClient? HTTPClient, GamingType GamingType, Guid RequestID, bool IsLongRunning = false, SocketRuntimeType RuntimeType = SocketRuntimeType.Client) : base(HTTPClient)
{ {
this.WebSocket = WebSocket; this.HTTPClient = HTTPClient;
this.GamingType = GamingType; this.GamingType = GamingType;
this.RequestID = RequestID; this.RequestID = RequestID;
this.IsLongRunning = IsLongRunning; this.IsLongRunning = IsLongRunning;
@ -359,7 +359,7 @@ namespace Milimoe.FunGame.Core.Api.Transmittal
{ {
WaitForWorkDone(); WaitForWorkDone();
} }
else if (WebSocket != null) else if (HTTPClient != null)
{ {
throw new AsyncSendException(); throw new AsyncSendException();
} }
@ -388,7 +388,7 @@ namespace Milimoe.FunGame.Core.Api.Transmittal
{ {
await WaitForWorkDoneAsync(); await WaitForWorkDoneAsync();
} }
else if (WebSocket != null && await WebSocket.Send(SocketMessageType.GamingRequest, GamingType, RequestID, RequestData) == SocketResult.Success) else if (HTTPClient != null && await HTTPClient.Send(SocketMessageType.GamingRequest, GamingType, RequestID, RequestData) == SocketResult.Success)
{ {
await WaitForWorkDoneAsync(); await WaitForWorkDoneAsync();
} }

View File

@ -443,7 +443,7 @@ namespace Milimoe.FunGame.Core.Api.Utility
byte[] key_bytes = General.DefaultEncoding.GetBytes(key); byte[] key_bytes = General.DefaultEncoding.GetBytes(key);
HMACSHA512 hmacsha512 = new(key_bytes); HMACSHA512 hmacsha512 = new(key_bytes);
byte[] hash_bytes = hmacsha512.ComputeHash(text_bytes); byte[] hash_bytes = hmacsha512.ComputeHash(text_bytes);
string hmac = BitConverter.ToString(hash_bytes).Replace("-", ""); string hmac = Convert.ToHexString(hash_bytes);
return hmac.ToLower(); return hmac.ToLower();
} }
@ -452,12 +452,12 @@ namespace Milimoe.FunGame.Core.Api.Utility
/// </summary> /// </summary>
/// <param name="file_path">要计算哈希值的文件路径</param> /// <param name="file_path">要计算哈希值的文件路径</param>
/// <returns>文件的 SHA-256 哈希值</returns> /// <returns>文件的 SHA-256 哈希值</returns>
public static string FileSha512(string file_path) public static string FileSha256(string file_path)
{ {
using SHA256 sha256 = SHA256.Create(); using SHA256 sha256 = SHA256.Create();
using FileStream stream = File.OpenRead(file_path); using FileStream stream = File.OpenRead(file_path);
byte[] hash = sha256.ComputeHash(stream); byte[] hash = sha256.ComputeHash(stream);
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); return Convert.ToHexStringLower(hash);
} }
/// <summary> /// <summary>
@ -471,7 +471,7 @@ namespace Milimoe.FunGame.Core.Api.Utility
byte[] plain = General.DefaultEncoding.GetBytes(plain_text); byte[] plain = General.DefaultEncoding.GetBytes(plain_text);
using RSACryptoServiceProvider rsa = new(); using RSACryptoServiceProvider rsa = new();
rsa.FromXmlString(plublic_key); rsa.FromXmlString(plublic_key);
byte[] encrypted = rsa.Encrypt(plain, false); byte[] encrypted = rsa.Encrypt(plain, true);
return Convert.ToBase64String(encrypted); return Convert.ToBase64String(encrypted);
} }
@ -486,7 +486,7 @@ namespace Milimoe.FunGame.Core.Api.Utility
byte[] secret = Convert.FromBase64String(secret_text); byte[] secret = Convert.FromBase64String(secret_text);
using RSACryptoServiceProvider rsa = new(); using RSACryptoServiceProvider rsa = new();
rsa.FromXmlString(private_key); rsa.FromXmlString(private_key);
byte[] decrypted = rsa.Decrypt(secret, false); byte[] decrypted = rsa.Decrypt(secret, true);
return General.DefaultEncoding.GetString(decrypted); return General.DefaultEncoding.GetString(decrypted);
} }
} }

View File

@ -76,12 +76,16 @@ namespace Milimoe.FunGame.Core.Api.Utility
WriteINI("Account", "AutoKey", ""); WriteINI("Account", "AutoKey", "");
break; break;
case FunGameInfo.FunGame.FunGame_Server: case FunGameInfo.FunGame.FunGame_Server:
/**
* Console
*/
WriteINI("Console", "LogLevel", "INFO");
/** /**
* Server * Server
*/ */
WriteINI("Server", "Name", "FunGame Server"); WriteINI("Server", "Name", "FunGame Server");
WriteINI("Server", "Password", ""); WriteINI("Server", "Password", "");
WriteINI("Server", "Describe", "Just Another FunGame Server."); WriteINI("Server", "Description", "Just Another FunGame Server.");
WriteINI("Server", "Notice", "This is the FunGame Server's Notice."); WriteINI("Server", "Notice", "This is the FunGame Server's Notice.");
WriteINI("Server", "Key", ""); WriteINI("Server", "Key", "");
WriteINI("Server", "Status", "1"); WriteINI("Server", "Status", "1");

View File

@ -1,5 +1,6 @@
using Milimoe.FunGame.Core.Interface.Addons; using Milimoe.FunGame.Core.Interface.Addons;
using Milimoe.FunGame.Core.Library.Common.Addon; using Milimoe.FunGame.Core.Library.Common.Addon;
using Milimoe.FunGame.Core.Library.Constant;
namespace Milimoe.FunGame.Core.Controller namespace Milimoe.FunGame.Core.Controller
{ {
@ -17,7 +18,7 @@ namespace Milimoe.FunGame.Core.Controller
/// <summary> /// <summary>
/// 输出系统消息 /// 输出系统消息
/// </summary> /// </summary>
protected Action<string> MaskMethod_WriteLine { get; set; } protected Action<string, string, LogLevel, bool> MaskMethod_WriteLine { get; set; }
/// <summary> /// <summary>
/// 输出错误消息 /// 输出错误消息
@ -28,8 +29,10 @@ namespace Milimoe.FunGame.Core.Controller
/// 输出系统消息 /// 输出系统消息
/// </summary> /// </summary>
/// <param name="msg"></param> /// <param name="msg"></param>
/// <param name="level"></param>
/// <param name="useLevel"></param>
/// <returns></returns> /// <returns></returns>
public void WriteLine(string msg) => MaskMethod_WriteLine(msg); public void WriteLine(string msg, LogLevel level = LogLevel.Info, bool useLevel = true) => MaskMethod_WriteLine(Addon.Name, msg, level, useLevel);
/// <summary> /// <summary>
/// 输出错误消息 /// 输出错误消息
@ -46,7 +49,7 @@ namespace Milimoe.FunGame.Core.Controller
public BaseAddonController(IAddon addon, Dictionary<string, object> delegates) public BaseAddonController(IAddon addon, Dictionary<string, object> delegates)
{ {
Addon = (T)addon; Addon = (T)addon;
if (delegates.TryGetValue("WriteLine", out object? value)) MaskMethod_WriteLine = value != null ? (Action<string>)value : new(DefaultPrint); if (delegates.TryGetValue("WriteLine", out object? value)) MaskMethod_WriteLine = value != null ? (Action<string, string, LogLevel, bool>)value : new(DefaultPrint);
if (delegates.TryGetValue("Error", out value)) MaskMethod_Error = value != null ? (Action<Exception>)value : new(DefaultPrint); if (delegates.TryGetValue("Error", out value)) MaskMethod_Error = value != null ? (Action<Exception>)value : new(DefaultPrint);
MaskMethod_WriteLine ??= new(DefaultPrint); MaskMethod_WriteLine ??= new(DefaultPrint);
MaskMethod_Error ??= new(DefaultPrint); MaskMethod_Error ??= new(DefaultPrint);
@ -55,15 +58,22 @@ namespace Milimoe.FunGame.Core.Controller
/// <summary> /// <summary>
/// 默认的输出错误消息方法 /// 默认的输出错误消息方法
/// </summary> /// </summary>
/// <param name="name"></param>
/// <param name="msg"></param> /// <param name="msg"></param>
/// <param name="level"></param>
/// <param name="useLevel"></param>
/// <returns></returns> /// <returns></returns>
private void DefaultPrint(string msg) => Console.Write("\r" + msg + "\n\r> "); private void DefaultPrint(string name, string msg, LogLevel level = LogLevel.Info, bool useLevel = true)
{
DateTime now = DateTime.Now;
Console.Write("\r" + now.AddMilliseconds(-now.Millisecond).ToString() + $" {CommonSet.GetLogLevelPrefix(level)}/[Addon] {Addon.Name}\n\r> ");
}
/// <summary> /// <summary>
/// 输出错误消息 /// 输出错误消息
/// </summary> /// </summary>
/// <param name="e"></param> /// <param name="e"></param>
/// <returns></returns> /// <returns></returns>
private void DefaultPrint(Exception e) => DefaultPrint(e.ToString()); private void DefaultPrint(Exception e) => DefaultPrint(Addon.Name, e.ToString(), LogLevel.Error);
} }
} }

View File

@ -21,7 +21,7 @@ namespace Milimoe.FunGame.Core.Controller
/// <summary> /// <summary>
/// 与服务器的连接套接字实例WebSocket /// 与服务器的连接套接字实例WebSocket
/// </summary> /// </summary>
public HTTPClient? WebSocket => _WebSocket; public HTTPClient? HTTPClient => _HTTPClient;
/// <summary> /// <summary>
/// 套接字是否已经连接 /// 套接字是否已经连接
@ -41,7 +41,7 @@ namespace Milimoe.FunGame.Core.Controller
/// <summary> /// <summary>
/// 用于类内赋值 /// 用于类内赋值
/// </summary> /// </summary>
protected HTTPClient? _WebSocket; protected HTTPClient? _HTTPClient;
/// <summary> /// <summary>
/// 是否正在接收服务器信息 /// 是否正在接收服务器信息
@ -204,6 +204,7 @@ namespace Milimoe.FunGame.Core.Controller
} }
} }
}); });
_Socket.ConnectionLost += Error;
} }
} }
} }
@ -231,12 +232,12 @@ namespace Milimoe.FunGame.Core.Controller
string serverName = ""; string serverName = "";
string notice = ""; string notice = "";
_WebSocket?.Close(); _HTTPClient?.Close();
_WebSocket = await HTTPClient.Connect(address, ssl, port, subUrl, connectArgs.Cast<object>().ToArray()); _HTTPClient = await HTTPClient.Connect(address, ssl, port, subUrl, connectArgs.Cast<object>().ToArray());
if (_WebSocket.Connected) if (_HTTPClient.Connected)
{ {
bool webSocketConnected = false; bool webSocketConnected = false;
_WebSocket.AddSocketObjectHandler(obj => _HTTPClient.AddSocketObjectHandler(obj =>
{ {
try try
{ {
@ -247,7 +248,7 @@ namespace Milimoe.FunGame.Core.Controller
result = success ? ConnectResult.Success : ConnectResult.ConnectFailed; result = success ? ConnectResult.Success : ConnectResult.ConnectFailed;
if (success) if (success)
{ {
_WebSocket.Token = obj.GetParam<Guid>(2); _HTTPClient.Token = obj.GetParam<Guid>(2);
serverName = obj.GetParam<string>(3) ?? ""; serverName = obj.GetParam<string>(3) ?? "";
notice = obj.GetParam<string>(4) ?? ""; notice = obj.GetParam<string>(4) ?? "";
} }
@ -265,10 +266,11 @@ namespace Milimoe.FunGame.Core.Controller
{ {
await Task.Delay(100); await Task.Delay(100);
} }
_HTTPClient.ConnectionLost += Error;
} }
else else
{ {
_WebSocket?.Close(); _HTTPClient?.Close();
result = ConnectResult.ConnectFailed; result = ConnectResult.ConnectFailed;
} }
@ -370,10 +372,10 @@ namespace Milimoe.FunGame.Core.Controller
{ {
try try
{ {
if (_WebSocket != null) if (_HTTPClient != null)
{ {
_WebSocket.Close(); _HTTPClient.Close();
_WebSocket = null; _HTTPClient = null;
} }
} }
catch (Exception e) catch (Exception e)
@ -388,7 +390,9 @@ namespace Milimoe.FunGame.Core.Controller
/// 输出消息 /// 输出消息
/// </summary> /// </summary>
/// <param name="msg"></param> /// <param name="msg"></param>
public abstract void WritelnSystemInfo(string msg); /// <param name="level"></param>
/// <param name="useLevel"></param>
public abstract void WritelnSystemInfo(string msg, LogLevel level = LogLevel.Info, bool useLevel = true);
/// <summary> /// <summary>
/// 自定处理异常的方法 /// 自定处理异常的方法
@ -410,9 +414,9 @@ namespace Milimoe.FunGame.Core.Controller
DataRequest request = new(_Socket, RequestType); DataRequest request = new(_Socket, RequestType);
return request; return request;
} }
else if (_WebSocket != null) else if (_HTTPClient != null)
{ {
DataRequest request = new(_WebSocket, RequestType); DataRequest request = new(_HTTPClient, RequestType);
return request; return request;
} }
throw new ConnectFailedException(); throw new ConnectFailedException();
@ -431,9 +435,9 @@ namespace Milimoe.FunGame.Core.Controller
DataRequest request = new(_Socket, RequestType, true); DataRequest request = new(_Socket, RequestType, true);
return request; return request;
} }
else if (_WebSocket != null) else if (_HTTPClient != null)
{ {
DataRequest request = new(_WebSocket, RequestType, true); DataRequest request = new(_HTTPClient, RequestType, true);
return request; return request;
} }
throw new ConnectFailedException(); throw new ConnectFailedException();
@ -453,9 +457,9 @@ namespace Milimoe.FunGame.Core.Controller
DataRequest request = new(_Socket, RequestType, false, SocketRuntimeType.Addon); DataRequest request = new(_Socket, RequestType, false, SocketRuntimeType.Addon);
return request; return request;
} }
else if (_WebSocket != null) else if (_HTTPClient != null)
{ {
DataRequest request = new(_WebSocket, RequestType, false, SocketRuntimeType.Addon); DataRequest request = new(_HTTPClient, RequestType, false, SocketRuntimeType.Addon);
return request; return request;
} }
throw new ConnectFailedException(); throw new ConnectFailedException();
@ -475,9 +479,9 @@ namespace Milimoe.FunGame.Core.Controller
DataRequest request = new(_Socket, RequestType, true, SocketRuntimeType.Addon); DataRequest request = new(_Socket, RequestType, true, SocketRuntimeType.Addon);
return request; return request;
} }
else if (_WebSocket != null) else if (_HTTPClient != null)
{ {
DataRequest request = new(_WebSocket, RequestType, true, SocketRuntimeType.Addon); DataRequest request = new(_HTTPClient, RequestType, true, SocketRuntimeType.Addon);
return request; return request;
} }
throw new ConnectFailedException(); throw new ConnectFailedException();
@ -497,9 +501,9 @@ namespace Milimoe.FunGame.Core.Controller
DataRequest request = new(_Socket, GamingType, false, SocketRuntimeType.Addon); DataRequest request = new(_Socket, GamingType, false, SocketRuntimeType.Addon);
return request; return request;
} }
else if (_WebSocket != null) else if (_HTTPClient != null)
{ {
DataRequest request = new(_WebSocket, GamingType, false, SocketRuntimeType.Addon); DataRequest request = new(_HTTPClient, GamingType, false, SocketRuntimeType.Addon);
return request; return request;
} }
throw new ConnectFailedException(); throw new ConnectFailedException();
@ -519,9 +523,9 @@ namespace Milimoe.FunGame.Core.Controller
DataRequest request = new(_Socket, GamingType, true, SocketRuntimeType.Addon); DataRequest request = new(_Socket, GamingType, true, SocketRuntimeType.Addon);
return request; return request;
} }
else if (_WebSocket != null) else if (_HTTPClient != null)
{ {
DataRequest request = new(_WebSocket, GamingType, true, SocketRuntimeType.Addon); DataRequest request = new(_HTTPClient, GamingType, true, SocketRuntimeType.Addon);
return request; return request;
} }
throw new ConnectFailedException(); throw new ConnectFailedException();
@ -576,8 +580,8 @@ namespace Milimoe.FunGame.Core.Controller
} }
catch (Exception e) catch (Exception e)
{ {
// 报错中断服务器连接 _Socket?.OnConnectionLost(e);
Error(e); Close_Socket();
} }
return result; return result;
} }
@ -642,6 +646,10 @@ namespace Milimoe.FunGame.Core.Controller
SocketHandler_Gaming(obj); SocketHandler_Gaming(obj);
break; break;
case SocketMessageType.AnonymousGameServer:
SocketHandler_AnonymousGameServer(obj);
break;
case SocketMessageType.Unknown: case SocketMessageType.Unknown:
default: default:
break; break;
@ -735,5 +743,14 @@ namespace Milimoe.FunGame.Core.Controller
{ {
} }
/// <summary>
/// 客户端接收并处理匿名服务器的消息
/// </summary>
/// <param name="ServerMessage"></param>
protected virtual void SocketHandler_AnonymousGameServer(SocketObject ServerMessage)
{
}
} }
} }

View File

@ -72,7 +72,7 @@ namespace Milimoe.FunGame.Core.Controller
} }
else else
{ {
WriteLine("已经创建过 SQLHelper 实例。"); WriteLine("已经创建过 SQLHelper 实例。", Library.Constant.LogLevel.Warning);
} }
} }
@ -87,7 +87,7 @@ namespace Milimoe.FunGame.Core.Controller
} }
else else
{ {
WriteLine("已经创建过 MailSender 实例。"); WriteLine("已经创建过 MailSender 实例。", Library.Constant.LogLevel.Warning);
} }
} }

View File

@ -8,6 +8,6 @@ namespace Milimoe.FunGame.Core.Interface.Addons
{ {
public bool StartServer(string GameModule, Room Room, List<User> Users, IServerModel RoomMasterServerModel, Dictionary<string, IServerModel> ServerModels, params object[] args); public bool StartServer(string GameModule, Room Room, List<User> Users, IServerModel RoomMasterServerModel, Dictionary<string, IServerModel> ServerModels, params object[] args);
public Task<Dictionary<string, object>> GamingMessageHandler(string username, GamingType type, Dictionary<string, object> data); public Task<Dictionary<string, object>> GamingMessageHandler(IServerModel model, GamingType type, Dictionary<string, object> data);
} }
} }

View File

@ -1,3 +1,4 @@
using System.Collections.Concurrent;
using Milimoe.FunGame.Core.Api.Transmittal; using Milimoe.FunGame.Core.Api.Transmittal;
using Milimoe.FunGame.Core.Api.Utility; using Milimoe.FunGame.Core.Api.Utility;
using Milimoe.FunGame.Core.Entity; using Milimoe.FunGame.Core.Entity;
@ -128,29 +129,31 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon.Example
public override GameModuleDepend GameModuleDepend => ExampleGameModuleConstant.GameModuleDepend; public override GameModuleDepend GameModuleDepend => ExampleGameModuleConstant.GameModuleDepend;
protected Room Room = General.HallInstance; private readonly struct ModuleServerWorker(Room room, List<User> users, IServerModel roomMaster, Dictionary<string, IServerModel> serverModels)
protected List<User> Users = []; {
protected IServerModel? RoomMaster; public Room Room { get; } = room;
protected Dictionary<string, IServerModel> All = []; public List<User> Users { get; } = users;
public IServerModel RoomMaster { get; } = roomMaster;
public Dictionary<string, IServerModel> All { get; } = serverModels;
public List<User> ConnectedUser { get; } = [];
public Dictionary<string, Dictionary<string, object>> UserData { get; } = [];
}
private ConcurrentDictionary<string, ModuleServerWorker> Workers { get; } = [];
public override bool StartServer(string GameModule, Room Room, List<User> Users, IServerModel RoomMasterServerModel, Dictionary<string, IServerModel> ServerModels, params object[] Args) public override bool StartServer(string GameModule, Room Room, List<User> Users, IServerModel RoomMasterServerModel, Dictionary<string, IServerModel> ServerModels, params object[] Args)
{ {
// 将参数转为本地属性 // 因为模组是单例的,需要为这个房间创建一个工作类接收参数,不能直接用本地变量处理
this.Room = Room; ModuleServerWorker worker = new(Room, Users, RoomMasterServerModel, ServerModels);
this.Users = Users; Workers[Room.Roomid] = worker;
RoomMaster = RoomMasterServerModel;
All = ServerModels;
// 创建一个线程执行Test() // 创建一个线程执行Test()
TaskUtility.NewTask(Test).OnError(Controller.Error); TaskUtility.NewTask(async () => await Test(worker)).OnError(Controller.Error);
return true; return true;
} }
private readonly List<User> ConnectedUser = []; private async Task Test(ModuleServerWorker worker)
private readonly Dictionary<string, Dictionary<string, object>> UserData = [];
private async Task Test()
{ {
Controller.WriteLine("欢迎各位玩家进入房间 " + Room.Roomid + " 。"); Controller.WriteLine("欢迎各位玩家进入房间 " + worker.Room.Roomid + " 。");
// 通常,我们可以对客户端的连接状态进行确认,此方法展示如何确认客户端的连接 // 通常,我们可以对客户端的连接状态进行确认,此方法展示如何确认客户端的连接
// 有两种确认的方式1是服务器主动确认2是客户端发起确认 // 有两种确认的方式1是服务器主动确认2是客户端发起确认
@ -165,33 +168,36 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon.Example
data.Add("connect_token", token); data.Add("connect_token", token);
// 我们保存到字典UserData中这样可以方便跨方法检查变量 // 我们保存到字典UserData中这样可以方便跨方法检查变量
foreach (string username in Users.Select(u => u.Username).Distinct()) foreach (string username in worker.Users.Select(u => u.Username).Distinct())
{ {
if (UserData.TryGetValue(username, out Dictionary<string, object>? value)) if (worker.UserData.TryGetValue(username, out Dictionary<string, object>? value))
{ {
value.Add("connect_token", token); value.Add("connect_token", token);
} }
else else
{ {
UserData.Add(username, []); worker.UserData.Add(username, []);
UserData[username].Add("connect_token", token); worker.UserData[username].Add("connect_token", token);
} }
} }
await SendGamingMessage(All.Values, GamingType.UpdateInfo, data); await SendGamingMessage(worker.All.Values, GamingType.UpdateInfo, data);
// 新建一个线程等待所有玩家确认 // 新建一个线程等待所有玩家确认
while (true) while (true)
{ {
if (ConnectedUser.Count == Users.Count) break; if (worker.ConnectedUser.Count == worker.Users.Count) break;
// 每200ms确认一次不需要太频繁 // 每200ms确认一次不需要太频繁
await Task.Delay(200); await Task.Delay(200);
} }
Controller.WriteLine("所有玩家都已经连接。"); Controller.WriteLine("所有玩家都已经连接。");
} }
public override async Task<Dictionary<string, object>> GamingMessageHandler(string username, GamingType type, Dictionary<string, object> data) public override async Task<Dictionary<string, object>> GamingMessageHandler(IServerModel model, GamingType type, Dictionary<string, object> data)
{ {
Dictionary<string, object> result = []; Dictionary<string, object> result = [];
// 获取model所在的房间工作类
ModuleServerWorker worker = Workers[model.InRoom.Roomid];
string username = model.User.Username;
switch (type) switch (type)
{ {
@ -200,12 +206,12 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon.Example
// 如果需要处理客户端传递的参数获取与客户端约定好的参数key对应的值 // 如果需要处理客户端传递的参数获取与客户端约定好的参数key对应的值
string un = NetworkUtility.JsonDeserializeFromDictionary<string>(data, "username") ?? ""; string un = NetworkUtility.JsonDeserializeFromDictionary<string>(data, "username") ?? "";
Guid token = NetworkUtility.JsonDeserializeFromDictionary<Guid>(data, "connect_token"); Guid token = NetworkUtility.JsonDeserializeFromDictionary<Guid>(data, "connect_token");
if (un == username && UserData.TryGetValue(username, out Dictionary<string, object>? value) && value != null && (value["connect_token"]?.Equals(token) ?? false)) if (un == username && worker.UserData.TryGetValue(username, out Dictionary<string, object>? value) && value != null && (value["connect_token"]?.Equals(token) ?? false))
{ {
ConnectedUser.Add(Users.Where(u => u.Username == username).First()); worker.ConnectedUser.Add(worker.Users.Where(u => u.Username == username).First());
Controller.WriteLine(username + " 已经连接。"); Controller.WriteLine(username + " 已经连接。");
} }
else Controller.WriteLine(username + " 确认连接失败!"); else Controller.WriteLine(username + " 确认连接失败!", LogLevel.Warning);
break; break;
default: default:
await Task.Delay(1); await Task.Delay(1);
@ -214,6 +220,53 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon.Example
return result; return result;
} }
protected HashSet<IServerModel> _clientModels = [];
/// <summary>
/// 匿名服务器示例
/// </summary>
/// <param name="model"></param>
/// <param name="data"></param>
/// <returns></returns>
public override bool StartAnonymousServer(IServerModel model, Dictionary<string, object> data)
{
// 可以做验证处理
string access_token = NetworkUtility.JsonDeserializeFromDictionary<string>(data, "access_token") ?? "";
if (access_token == "approval_access_token")
{
// 接收连接匿名服务器的客户端
_clientModels.Add(model);
return true;
}
return false;
}
public override void CloseAnonymousServer(IServerModel model)
{
// 移除客户端
_clientModels.Remove(model);
}
/// <summary>
/// 接收并处理匿名服务器消息
/// </summary>
/// <param name="model"></param>
/// <param name="data"></param>
/// <returns></returns>
public override async Task<Dictionary<string, object>> AnonymousGameServerHandler(IServerModel model, Dictionary<string, object> data)
{
Dictionary<string, object> result = [];
// 根据服务器和客户端的数据传输约定,自行处理 data并返回。
if (data.Count > 0)
{
await Task.Delay(1);
}
result.Add("msg", "匿名服务器已经收到消息了");
return result;
}
} }
/// <summary> /// <summary>

View File

@ -39,6 +39,11 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon
/// </summary> /// </summary>
public abstract GameModuleDepend GameModuleDepend { get; } public abstract GameModuleDepend GameModuleDepend { get; }
/// <summary>
/// 是否是匿名服务器
/// </summary>
public virtual bool IsAnonymous { get; set; } = false;
/// <summary> /// <summary>
/// 包含了一些常用方法的控制器 /// 包含了一些常用方法的控制器
/// </summary> /// </summary>
@ -77,11 +82,45 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon
/// <summary> /// <summary>
/// 接收并处理GamingMessage /// 接收并处理GamingMessage
/// </summary> /// </summary>
/// <param name="username">发送此消息的账号</param> /// <param name="model">发送此消息的客户端</param>
/// <param name="type">消息类型</param> /// <param name="type">消息类型</param>
/// <param name="data">消息参数</param> /// <param name="data">消息参数</param>
/// <returns>底层会将字典中的数据发送给客户端</returns> /// <returns>底层会将字典中的数据发送给客户端</returns>
public abstract Task<Dictionary<string, object>> GamingMessageHandler(string username, GamingType type, Dictionary<string, object> data); public abstract Task<Dictionary<string, object>> GamingMessageHandler(IServerModel model, GamingType type, Dictionary<string, object> data);
/// <summary>
/// 启动匿名服务器监听
/// </summary>
/// <param name="model"></param>
/// <param name="data"></param>
/// <returns></returns>
public virtual bool StartAnonymousServer(IServerModel model, Dictionary<string, object> data)
{
return true;
}
/// <summary>
/// 结束匿名服务器监听
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public virtual void CloseAnonymousServer(IServerModel model)
{
}
/// <summary>
/// 接收并处理匿名服务器监听消息<para/>
/// 此方法为可选实现,可以帮助 RESTful API 处理不需要验证的 WebSocket 请求
/// </summary>
/// <param name="model">发送此消息的客户端</param>
/// <param name="data">消息参数</param>
/// <returns>底层会将字典中的数据发送给客户端</returns>
public virtual async Task<Dictionary<string, object>> AnonymousGameServerHandler(IServerModel model, Dictionary<string, object> data)
{
await Task.Delay(1);
return [];
}
/// <summary> /// <summary>
/// 加载标记 /// 加载标记
@ -129,13 +168,24 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon
/// <param name="clients"></param> /// <param name="clients"></param>
/// <param name="type"></param> /// <param name="type"></param>
/// <param name="data"></param> /// <param name="data"></param>
protected virtual async Task SendGamingMessage(IEnumerable<IServerModel> clients, GamingType type, Dictionary<string, object> data) /// <returns>发送失败的客户端</returns>
protected virtual async Task<List<IServerModel>> SendGamingMessage(IEnumerable<IServerModel> clients, GamingType type, Dictionary<string, object> data)
{ {
// 发送局内消息 // 发送局内消息
List<IServerModel> failedModels = [];
foreach (IServerModel s in clients) foreach (IServerModel s in clients)
{
try
{ {
await s.Send(SocketMessageType.Gaming, type, data); await s.Send(SocketMessageType.Gaming, type, data);
} }
catch (System.Exception e)
{
Controller.Error(e);
failedModels.Add(s);
}
}
return failedModels;
} }
/// <summary> /// <summary>
@ -144,13 +194,48 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon
/// <param name="clients"></param> /// <param name="clients"></param>
/// <param name="type"></param> /// <param name="type"></param>
/// <param name="args"></param> /// <param name="args"></param>
protected virtual async Task Send(IEnumerable<IServerModel> clients, SocketMessageType type, params object[] args) /// <returns>发送失败的客户端</returns>
protected virtual async Task<List<IServerModel>> Send(IEnumerable<IServerModel> clients, SocketMessageType type, params object[] args)
{ {
// 发送消息 // 发送消息
List<IServerModel> failedModels = [];
foreach (IServerModel s in clients) foreach (IServerModel s in clients)
{
try
{ {
await s.Send(type, args); await s.Send(type, args);
} }
catch (System.Exception e)
{
Controller.Error(e);
failedModels.Add(s);
}
}
return failedModels;
}
/// <summary>
/// 给客户端发送匿名服务器消息
/// </summary>
/// <param name="clients"></param>
/// <param name="data"></param>
/// <returns>发送失败的客户端</returns>
protected virtual async Task<List<IServerModel>> SendAnonymousGameServerMessage(IEnumerable<IServerModel> clients, Dictionary<string, object> data)
{
List<IServerModel> failedModels = [];
foreach (IServerModel s in clients)
{
try
{
await s.Send(SocketMessageType.AnonymousGameServer, data);
}
catch (System.Exception e)
{
Controller.Error(e);
failedModels.Add(s);
}
}
return failedModels;
} }
} }
} }

View File

@ -51,6 +51,8 @@ namespace Milimoe.FunGame.Core.Library.Common.Architecture
} }
private async Task SendHeartBeat() private async Task SendHeartBeat()
{
try
{ {
await Task.Delay(100); await Task.Delay(100);
if (_Socket != null) if (_Socket != null)
@ -71,7 +73,7 @@ namespace Milimoe.FunGame.Core.Library.Common.Architecture
} }
else if (_HTTPClient != null) else if (_HTTPClient != null)
{ {
while (_HTTPClient.Instance?.State == System.Net.WebSockets.WebSocketState.Open) while (_HTTPClient.WebSocket?.State == System.Net.WebSockets.WebSocketState.Open)
{ {
if (!SendingHeartBeat) _SendingHeartBeat = true; if (!SendingHeartBeat) _SendingHeartBeat = true;
// 发送心跳包 // 发送心跳包
@ -86,6 +88,20 @@ namespace Milimoe.FunGame.Core.Library.Common.Architecture
} }
_SendingHeartBeat = false; _SendingHeartBeat = false;
} }
catch (System.Exception e)
{
if (_Socket != null)
{
_Socket.OnConnectionLost(e);
_Socket.Close();
}
if (_HTTPClient != null)
{
_HTTPClient.OnConnectionLost(e);
_HTTPClient.Close();
}
}
}
private void AddHeartBeatFaileds() private void AddHeartBeatFaileds()
{ {

View File

@ -1,4 +1,5 @@
using System.Net.WebSockets; using System.Net.WebSockets;
using Milimoe.FunGame.Core.Api.Utility;
using Milimoe.FunGame.Core.Interface.HTTP; using Milimoe.FunGame.Core.Interface.HTTP;
using Milimoe.FunGame.Core.Library.Common.Architecture; using Milimoe.FunGame.Core.Library.Common.Architecture;
using Milimoe.FunGame.Core.Library.Constant; using Milimoe.FunGame.Core.Library.Constant;
@ -9,23 +10,28 @@ namespace Milimoe.FunGame.Core.Library.Common.Network
{ {
public class HTTPClient : IHTTPClient public class HTTPClient : IHTTPClient
{ {
public System.Net.WebSockets.ClientWebSocket? Instance { get; } = null; public HttpClient Instance { get; }
public ClientWebSocket? WebSocket { get; } = null;
public SocketRuntimeType Runtime => SocketRuntimeType.Client; public SocketRuntimeType Runtime => SocketRuntimeType.Client;
public Guid Token { get; set; } = Guid.Empty; public Guid Token { get; set; } = Guid.Empty;
public string ServerAddress { get; } = ""; public string ServerAddress { get; } = "";
public int ServerPort { get; } = 0; public int ServerPort { get; } = 0;
public string ServerName { get; } = ""; public string ServerName { get; } = "";
public string ServerNotice { get; } = ""; public string ServerNotice { get; } = "";
public bool Connected => Instance != null && Instance.State == WebSocketState.Open; public bool Connected => WebSocket != null && WebSocket.State == WebSocketState.Open;
public bool Receiving => _receiving; public bool Receiving => _receiving;
private HeartBeat HeartBeat { get; } private HeartBeat HeartBeat { get; }
public event Action<System.Exception>? ConnectionLost;
public event Action? Closed;
private bool _receiving = false; private bool _receiving = false;
private readonly HashSet<Action<SocketObject>> _boundEvents = []; private readonly HashSet<Action<SocketObject>> _boundEvents = [];
private HTTPClient(ClientWebSocket instance, string serverAddress, int serverPort, params object[] args) private HTTPClient(ClientWebSocket websocket, string serverAddress, int serverPort, params object[] args)
{ {
Instance = instance; Instance = new();
WebSocket = websocket;
ServerAddress = serverAddress; ServerAddress = serverAddress;
ServerPort = serverPort; ServerPort = serverPort;
HeartBeat = new(this); HeartBeat = new(this);
@ -55,8 +61,9 @@ namespace Milimoe.FunGame.Core.Library.Common.Network
} }
catch (System.Exception e) catch (System.Exception e)
{ {
OnConnectionLost(e);
Close(); Close();
Api.Utility.TXTHelper.AppendErrorLog(e.GetErrorInfo()); TXTHelper.AppendErrorLog(e.GetErrorInfo());
throw new SocketWrongInfoException(); throw new SocketWrongInfoException();
} }
} }
@ -64,13 +71,46 @@ namespace Milimoe.FunGame.Core.Library.Common.Network
public async Task<SocketResult> Send(SocketMessageType type, params object[] objs) public async Task<SocketResult> Send(SocketMessageType type, params object[] objs)
{ {
if (Instance != null) if (WebSocket != null)
{ {
return await HTTPManager.Send(Instance, new(type, Token, objs)); return await HTTPManager.Send(WebSocket, new(type, Token, objs));
} }
return SocketResult.NotSent; return SocketResult.NotSent;
} }
/// <summary>
/// 发送 GET 请求
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public async Task<T?> HttpGet<T>(string url)
{
HttpResponseMessage response = await Instance.GetAsync(url);
response.EnsureSuccessStatusCode();
string content = await response.Content.ReadAsStringAsync();
T? result = NetworkUtility.JsonDeserialize<T>(content);
return result;
}
/// <summary>
/// 发送 POST 请求
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="url"></param>
/// <param name="json"></param>
/// <returns></returns>
public async Task<T?> HttpPost<T>(string url, string json)
{
HttpContent content = new StringContent(json, General.DefaultEncoding, "application/json");
HttpResponseMessage response = await Instance.PostAsync(url, content);
response.EnsureSuccessStatusCode();
string read = await response.Content.ReadAsStringAsync();
T? result = NetworkUtility.JsonDeserialize<T>(read);
return result;
}
public void AddSocketObjectHandler(Action<SocketObject> method) public void AddSocketObjectHandler(Action<SocketObject> method)
{ {
if (_boundEvents.Add(method)) if (_boundEvents.Add(method))
@ -85,23 +125,32 @@ namespace Milimoe.FunGame.Core.Library.Common.Network
SocketManager.SocketReceive -= new SocketManager.SocketReceiveHandler(method); SocketManager.SocketReceive -= new SocketManager.SocketReceiveHandler(method);
} }
public void OnConnectionLost(System.Exception e)
{
ConnectionLost?.Invoke(e);
}
public void Close() public void Close()
{ {
Instance.Dispose();
_receiving = false; _receiving = false;
HeartBeat.StopSendingHeartBeat(); HeartBeat.StopSendingHeartBeat();
Instance?.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None); WebSocket?.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None);
Instance?.Dispose(); WebSocket?.Dispose();
foreach (Action<SocketObject> method in _boundEvents.ToList()) foreach (Action<SocketObject> method in _boundEvents.ToList())
{ {
RemoveSocketObjectHandler(method); RemoveSocketObjectHandler(method);
} }
Closed?.Invoke();
ConnectionLost = null;
Closed = null;
} }
private async Task StartListening(params object[] args) private async Task StartListening(params object[] args)
{ {
if (Instance != null && Instance.State == WebSocketState.Open) if (WebSocket != null && WebSocket.State == WebSocketState.Open)
{ {
if (await HTTPManager.Send(Instance, new(SocketMessageType.Connect, Guid.Empty, args)) == SocketResult.Success && await HTTPManager.ReceiveMessage(this)) if (await HTTPManager.Send(WebSocket, new(SocketMessageType.Connect, Guid.Empty, args)) == SocketResult.Success && await HTTPManager.ReceiveMessage(this))
{ {
_receiving = true; _receiving = true;
await Receive(); await Receive();

View File

@ -19,6 +19,9 @@ namespace Milimoe.FunGame.Core.Library.Common.Network
public bool Receiving => _receiving; public bool Receiving => _receiving;
private HeartBeat HeartBeat { get; } private HeartBeat HeartBeat { get; }
public event Action<System.Exception>? ConnectionLost;
public event Action? Closed;
private Task? _receivingTask; private Task? _receivingTask;
private bool _receiving = false; private bool _receiving = false;
private readonly HashSet<Action<SocketObject>> _boundEvents = []; private readonly HashSet<Action<SocketObject>> _boundEvents = [];
@ -61,6 +64,8 @@ namespace Milimoe.FunGame.Core.Library.Common.Network
} }
catch (System.Exception e) catch (System.Exception e)
{ {
OnConnectionLost(e);
Close();
Api.Utility.TXTHelper.AppendErrorLog(e.GetErrorInfo()); Api.Utility.TXTHelper.AppendErrorLog(e.GetErrorInfo());
throw new SocketWrongInfoException(); throw new SocketWrongInfoException();
} }
@ -80,6 +85,11 @@ namespace Milimoe.FunGame.Core.Library.Common.Network
SocketManager.SocketReceive -= new SocketManager.SocketReceiveHandler(method); SocketManager.SocketReceive -= new SocketManager.SocketReceiveHandler(method);
} }
public void OnConnectionLost(System.Exception e)
{
ConnectionLost?.Invoke(e);
}
public void Close() public void Close()
{ {
HeartBeat.StopSendingHeartBeat(); HeartBeat.StopSendingHeartBeat();
@ -89,6 +99,9 @@ namespace Milimoe.FunGame.Core.Library.Common.Network
{ {
RemoveSocketObjectHandler(method); RemoveSocketObjectHandler(method);
} }
Closed?.Invoke();
ConnectionLost = null;
Closed = null;
} }
public void StartReceiving(Task t) public void StartReceiving(Task t)

View File

@ -3,6 +3,23 @@
*/ */
namespace Milimoe.FunGame.Core.Library.Constant namespace Milimoe.FunGame.Core.Library.Constant
{ {
public class CommonSet
{
public static string GetLogLevelPrefix(LogLevel level)
{
return level switch
{
LogLevel.Trace => "T/",
LogLevel.Debug => "D/",
LogLevel.Info => "I/",
LogLevel.Warning => "W/",
LogLevel.Error => "E/",
LogLevel.Critical => "C/",
_ => "I/"
};
}
}
/// <summary> /// <summary>
/// 配合 <see cref="InterfaceMethod"/> <see cref="InterfaceType"/> 使用,也别忘了修改 <see cref="Api.Utility.Implement"/> /// 配合 <see cref="InterfaceMethod"/> <see cref="InterfaceType"/> 使用,也别忘了修改 <see cref="Api.Utility.Implement"/>
/// </summary> /// </summary>
@ -49,6 +66,7 @@ namespace Milimoe.FunGame.Core.Library.Constant
public const string StartGame = "StartGame"; public const string StartGame = "StartGame";
public const string EndGame = "EndGame"; public const string EndGame = "EndGame";
public const string Gaming = "Gaming"; public const string Gaming = "Gaming";
public const string AnonymousGameServer = "AnonymousGameServer";
/// <summary> /// <summary>
/// 将通信类型的枚举转换为字符串 /// 将通信类型的枚举转换为字符串

View File

@ -77,7 +77,8 @@ namespace Milimoe.FunGame.Core.Library.Constant
MatchRoom, MatchRoom,
StartGame, StartGame,
EndGame, EndGame,
Gaming Gaming,
AnonymousGameServer
} }
/// <summary> /// <summary>
@ -809,4 +810,14 @@ namespace Milimoe.FunGame.Core.Library.Constant
Immediate, Immediate,
Progressive Progressive
} }
public enum LogLevel
{
Trace,
Debug,
Info,
Warning,
Error,
Critical
}
} }

View File

@ -38,9 +38,9 @@ namespace Milimoe.FunGame.Core.Service
/// </summary> /// </summary>
/// <param name="uri"></param> /// <param name="uri"></param>
/// <returns></returns> /// <returns></returns>
internal static async Task<System.Net.WebSockets.ClientWebSocket?> Connect(Uri uri) internal static async Task<ClientWebSocket?> Connect(Uri uri)
{ {
System.Net.WebSockets.ClientWebSocket socket = new(); ClientWebSocket socket = new();
await socket.ConnectAsync(uri, CancellationToken.None); await socket.ConnectAsync(uri, CancellationToken.None);
if (socket.State == WebSocketState.Open) if (socket.State == WebSocketState.Open)
{ {
@ -55,7 +55,7 @@ namespace Milimoe.FunGame.Core.Service
/// <param name="socket"></param> /// <param name="socket"></param>
/// <param name="obj"></param> /// <param name="obj"></param>
/// <returns></returns> /// <returns></returns>
internal static async Task<SocketResult> Send(System.Net.WebSockets.ClientWebSocket socket, SocketObject obj) internal static async Task<SocketResult> Send(ClientWebSocket socket, SocketObject obj)
{ {
if (socket != null) if (socket != null)
{ {
@ -176,12 +176,12 @@ namespace Milimoe.FunGame.Core.Service
/// <returns></returns> /// <returns></returns>
internal static async Task<bool> ReceiveMessage(HTTPClient client) internal static async Task<bool> ReceiveMessage(HTTPClient client)
{ {
if (client.Instance is null) return false; if (client.WebSocket is null) return false;
byte[] buffer = new byte[General.SocketByteSize]; byte[] buffer = new byte[General.SocketByteSize];
WebSocketReceiveResult result = await client.Instance.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None); WebSocketReceiveResult result = await client.WebSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
string msg = General.DefaultEncoding.GetString(buffer).Replace("\0", "").Trim(); string msg = General.DefaultEncoding.GetString(buffer).Replace("\0", "").Trim();
SocketObject[] objs = await GetSocketObjects(client.Instance, result, msg); SocketObject[] objs = await GetSocketObjects(client.WebSocket, result, msg);
foreach (SocketObject obj in objs) foreach (SocketObject obj in objs)
{ {
@ -192,7 +192,7 @@ namespace Milimoe.FunGame.Core.Service
} }
else if (obj.SocketType == SocketMessageType.Disconnect) else if (obj.SocketType == SocketMessageType.Disconnect)
{ {
await client.Instance.CloseAsync(result.CloseStatus ?? WebSocketCloseStatus.NormalClosure, result.CloseStatusDescription, CancellationToken.None); await client.WebSocket.CloseAsync(result.CloseStatus ?? WebSocketCloseStatus.NormalClosure, result.CloseStatusDescription, CancellationToken.None);
return true; return true;
} }
} }