From 3c81cf7217d6588e8f09e58d309a535dcc4a1c5d Mon Sep 17 00:00:00 2001 From: milimoe <110188673+milimoe@users.noreply.github.com> Date: Wed, 8 Apr 2026 01:20:38 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E6=8E=A7=E5=88=B6=E5=8F=B0?= =?UTF-8?q?=E6=8C=87=E4=BB=A4=E7=B3=BB=E7=BB=9F=EF=BC=9B=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=20CORS=20=E9=85=8D=E7=BD=AE=EF=BC=9B=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=E9=A1=B9=E8=AF=BB=E5=8F=96=20(#57)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 重构控制台指令系统;添加 CORS 配置;添加启动项读取 * 修改BUG --- FunGame.Server/Main.cs | 67 ++--- FunGame.Server/Models/ConsoleModel.cs | 243 +++++++++++++----- FunGame.Server/Others/Config.cs | 5 + FunGame.Server/Others/OrderDictionary.cs | 21 +- FunGame.Server/Services/FunGameSystem.cs | 32 ++- FunGame.Server/Services/General.cs | 10 - FunGame.WebAPI/Program.cs | 60 +++-- FunGame.WebAPI/Properties/launchSettings.json | 35 +-- FunGame.WebAPI/appsettings.Development.json | 7 +- FunGame.WebAPI/appsettings.json | 4 + 10 files changed, 316 insertions(+), 168 deletions(-) diff --git a/FunGame.Server/Main.cs b/FunGame.Server/Main.cs index 0f341cb..37cd2c8 100644 --- a/FunGame.Server/Main.cs +++ b/FunGame.Server/Main.cs @@ -30,8 +30,8 @@ else Console.Title = Config.ServerName + " - FunGame Server Port: " + Config.ServerPort; } -// 初始化命令菜单 -ServerHelper.InitOrderList(); +// 读取启动项 +FunGameSystem.GetStartupArguments(args); // 初始化SQLHelper FunGameSystem.InitSQLHelper(); @@ -86,41 +86,44 @@ FunGameSystem.CloseListener += async () => } }; +// 初始化命令菜单 +if (SocketListener != null) +{ + ConsoleModel.InitOrders(SocketListener); +} +else +{ + ConsoleModel.InitOrders(WebSocketListener); +} while (Running) { - string order = Console.ReadLine() ?? ""; + string input = Console.ReadLine()?.Trim() ?? ""; ServerHelper.Type(); - if (order != "" && Running) + if (input != "" && Running) { - order = order.ToLower(); - if (FunGameSystem.OrderList.TryGetValue(order, out Action? action) && action != null) + string[] strings = input.Split(' ', StringSplitOptions.RemoveEmptyEntries); + if (strings.Length > 0) { - action(order); - } - switch (order) - { - case OrderDictionary.Quit: - case OrderDictionary.Exit: - case OrderDictionary.Close: - CloseServer(); - break; - case OrderDictionary.Restart: - if (SocketListener is null || WebSocketListener is null) - { - StartServerListening(); - } - else ServerHelper.WriteLine("服务器正在运行,请手动结束服务器进程再启动!"); - break; - default: - if (SocketListener != null) - { - await ConsoleModel.Order(SocketListener, order); - } - else - { - await ConsoleModel.Order(WebSocketListener, order); - } - break; + string order = strings[0].ToLower(); + string[] inputArgs = [.. strings.Skip(1)]; + switch (order) + { + case OrderDictionary.Quit: + case OrderDictionary.Exit: + case OrderDictionary.Close: + CloseServer(); + break; + case OrderDictionary.Restart: + if (SocketListener is null || WebSocketListener is null) + { + StartServerListening(); + } + else ServerHelper.WriteLine("服务器正在运行,请手动结束服务器进程再启动!"); + break; + default: + await ConsoleModel.Order(order, inputArgs); + break; + } } } } diff --git a/FunGame.Server/Models/ConsoleModel.cs b/FunGame.Server/Models/ConsoleModel.cs index 175b485..8905962 100644 --- a/FunGame.Server/Models/ConsoleModel.cs +++ b/FunGame.Server/Models/ConsoleModel.cs @@ -13,85 +13,188 @@ namespace Milimoe.FunGame.Server.Model { public class ConsoleModel { - public static async Task Order(ISocketListener? server, string order) where T : ISocketMessageProcessor + public static void InitOrders(ISocketListener? server) where T : ISocketMessageProcessor + { + FunGameSystem.OrderList[OrderDictionary.Kick] = async (args) => + { + if (args.Length == 0 || args[0] is not string client) + { + ServerHelper.Write("输入需要踢出的客户端名称:"); + client = await Console.In.ReadLineAsync() ?? ""; + } + if (client != "" && server != null && server.ClientList.ContainsKey(client)) + { + await Kick(server.ClientList[client]); + } + else + { + ServerHelper.WriteLine("未找到指定的客户端。"); + } + }; + FunGameSystem.OrderList[OrderDictionary.Logout] = async (args) => + { + if (args.Length == 0 || args[0] is not string user) + { + ServerHelper.Write("输入需要强制下线的玩家ID:"); + user = await Console.In.ReadLineAsync() ?? ""; + } + if (user != "" && server != null && server.UserList.ContainsKey(user)) + { + await ForceLogOut(server.UserList[user]); + } + else + { + ServerHelper.WriteLine("未找到指定的玩家。"); + } + }; + FunGameSystem.OrderList[OrderDictionary.Show] = async (args) => + { + if (args.Length > 0 && args[0] is string type) + { + switch (type) + { + case "clients": + case "-c": + ShowClients(server); + break; + case "users": + case "-u": + ShowUsers(server); + break; + default: + ServerHelper.WriteLine($"指令 '{OrderDictionary.Show}' 的参数 '{type}' 无效。", InvokeMessageType.Warning); + ShowClients(server); + ShowUsers(server); + break; + } + } + else + { + ShowClients(server); + ShowUsers(server); + } + }; + FunGameSystem.OrderList[OrderDictionary.ShowClients] = async (args) => + { + ShowClients(server); + }; + FunGameSystem.OrderList[OrderDictionary.ShowUsers] = async (args) => + { + ShowUsers(server); + }; + FunGameSystem.OrderList[OrderDictionary.Reload] = async (args) => + { + if (args.Length > 0 && args[0] is string type) + { + switch (type) + { + case "addons": + case "-a": + FunGameSystem.HotReloadServerPlugins(); + FunGameSystem.HotReloadWebAPIPlugins(); + FunGameSystem.HotReloadGameModuleList(); + break; + case "modules": + case "-m": + FunGameSystem.HotReloadGameModuleList(); + break; + case "plugins": + case "-p": + FunGameSystem.HotReloadServerPlugins(); + FunGameSystem.HotReloadWebAPIPlugins(); + break; + case "serverplugins": + case "-sp": + FunGameSystem.HotReloadServerPlugins(); + break; + case "webapiplugins": + case "-wp": + FunGameSystem.HotReloadWebAPIPlugins(); + break; + default: + ServerHelper.WriteLine($"指令 '{OrderDictionary.Reload}' 的参数 '{type}' 无效。", InvokeMessageType.Error); + break; + } + } + }; + FunGameSystem.OrderList[OrderDictionary.Help] = async (args) => + { + ServerHelper.WriteLine($"可用指令:{string.Join(",", FunGameSystem.OrderList.Keys.Select(c => $"{c}{GetOrderAliases(c)}"))}"); + }; + FunGameSystem.OrderList[OrderDictionary.Ban] = async (args) => + { + if (args.Length > 0 && args[0] is string type) + { + if (args.Length == 1 || args[1] is not string banned) + { + ServerHelper.WriteLine($"没有提供指令 '{OrderDictionary.Ban}' 所需的第二个参数 'banned ip' 值。", InvokeMessageType.Error); + return; + } + if (!NetworkUtility.IsIP(banned)) + { + ServerHelper.WriteLine($"指令 '{OrderDictionary.Ban}' 的参数 '{banned}' 不是一个 IP 地址。", InvokeMessageType.Error); + return; + } + switch (type) + { + case "add": + case "-a": + Config.ServerBannedList.Add(banned); + ServerHelper.WriteLine($"将 {banned} 添加入黑名单成功。"); + break; + case "remove": + case "-r": + Config.ServerBannedList.Remove(banned); + ServerHelper.WriteLine($"将 {banned} 移出黑名单成功。"); + break; + default: + ServerHelper.WriteLine($"指令 '{OrderDictionary.Ban}' 的参数 '{type}' 无效。", InvokeMessageType.Error); + break; + } + } + else + { + ServerHelper.WriteLine($"没有提供指令 '{OrderDictionary.Ban}' 所需的参数。", InvokeMessageType.Error); + } + }; + } + + public static void AddOrderAlias(string order, params string[] aliases) + { + foreach (string alias in aliases) + { + FunGameSystem.OrderAliasList[alias] = order; + } + } + + public static async Task Order(string order, string[] args) { try { - switch (order) + if (FunGameSystem.OrderList.TryGetValue(order, out Func? func) && func != null) { - case OrderDictionary.Kick: - { - ServerHelper.Write("输入需要踢出的客户端名称:"); - string client = Console.ReadLine() ?? ""; - if (client != "" && server != null) - { - await Kick(server.ClientList[client]); - } - break; - } - case OrderDictionary.Logout: - { - ServerHelper.Write("输入需要强制下线的玩家ID:"); - string user = Console.ReadLine() ?? ""; - if (user != "" && server != null) - { - await ForceLogOut(server.UserList[user]); - } - break; - } - case OrderDictionary.ShowList: - ShowClients(server); - ShowUsers(server); - break; - case OrderDictionary.ShowClients1: - case OrderDictionary.ShowClients2: - ShowClients(server); - break; - case OrderDictionary.ShowUsers1: - case OrderDictionary.ShowUsers2: - ShowUsers(server); - break; - case OrderDictionary.ReloadAddons: - FunGameSystem.HotReloadServerPlugins(); - FunGameSystem.HotReloadWebAPIPlugins(); - FunGameSystem.HotReloadGameModuleList(); - break; - case OrderDictionary.ReloadPlugins1: - FunGameSystem.HotReloadServerPlugins(); - FunGameSystem.HotReloadWebAPIPlugins(); - break; - case OrderDictionary.ReloadPlugins2: - FunGameSystem.HotReloadServerPlugins(); - FunGameSystem.HotReloadWebAPIPlugins(); - break; - case OrderDictionary.ReloadPlugins3: - FunGameSystem.HotReloadServerPlugins(); - break; - case OrderDictionary.ReloadPlugins4: - FunGameSystem.HotReloadWebAPIPlugins(); - break; - case OrderDictionary.ReloadModules1: - FunGameSystem.HotReloadGameModuleList(); - break; - case OrderDictionary.ReloadModules2: - FunGameSystem.HotReloadGameModuleList(); - break; - default: - break; + await func.Invoke(args); + } + else if (FunGameSystem.OrderAliasList.TryGetValue(order, out string? actualOrder) && actualOrder != null) + { + if (FunGameSystem.OrderList.TryGetValue(actualOrder, out Func? func2) && func2 != null) + { + await func2.Invoke(args); + } } // 广播到插件 if (FunGameSystem.ServerPluginLoader != null) { foreach (ServerPlugin plugin in FunGameSystem.ServerPluginLoader.Plugins.Values) { - plugin.ProcessInput(order); + plugin.ProcessInput(order, args); } } if (FunGameSystem.WebAPIPluginLoader != null) { foreach (WebAPIPlugin plugin in FunGameSystem.WebAPIPluginLoader.Plugins.Values) { - plugin.ProcessInput(order); + plugin.ProcessInput(order, args); } } } @@ -101,17 +204,23 @@ namespace Milimoe.FunGame.Server.Model } } - public static async Task Kick(IServerModel clientModel) + public static string GetOrderAliases(string order) + { + string[] alias = [.. FunGameSystem.OrderAliasList.Where(kv => kv.Value == order).Select(kv => kv.Key)]; + return alias.Length > 0 ? $"(替代:{string.Join(",", alias)})" : ""; + } + + private static async Task Kick(IServerModel clientModel) { await clientModel.Kick("您已被服务器管理员踢出此服务器。"); } - public static async Task ForceLogOut(IServerModel clientModel) + private static async Task ForceLogOut(IServerModel clientModel) { await clientModel.ForceLogOut("您已被服务器管理员强制下线。"); } - public static void ShowClients(ISocketListener? server) where T : ISocketMessageProcessor + private static void ShowClients(ISocketListener? server) where T : ISocketMessageProcessor { if (server != null) { @@ -124,7 +233,7 @@ namespace Milimoe.FunGame.Server.Model } } - public static void ShowUsers(ISocketListener? server) where T : ISocketMessageProcessor + private static void ShowUsers(ISocketListener? server) where T : ISocketMessageProcessor { if (server != null) { diff --git a/FunGame.Server/Others/Config.cs b/FunGame.Server/Others/Config.cs index 5e28820..bbdc5ac 100644 --- a/FunGame.Server/Others/Config.cs +++ b/FunGame.Server/Others/Config.cs @@ -154,6 +154,11 @@ namespace Milimoe.FunGame.Server.Others /// public static SQLMode SQLMode { get; set; } = SQLMode.None; + /// + /// CORS:允许所有来源 + /// + public static bool AllowAnyOrigin { get; set; } = false; + /// /// 未Loadmodules时,此属性表示至少需要安装的模组 /// diff --git a/FunGame.Server/Others/OrderDictionary.cs b/FunGame.Server/Others/OrderDictionary.cs index 60c4477..fc4399b 100644 --- a/FunGame.Server/Others/OrderDictionary.cs +++ b/FunGame.Server/Others/OrderDictionary.cs @@ -7,23 +7,12 @@ public const string Exit = "exit"; public const string Close = "close"; public const string Restart = "restart"; - public const string AddBanned1 = "ban add"; - public const string AddBanned2 = "ban -a"; - public const string RemoveBanned1 = "ban remove"; - public const string RemoveBanned2 = "ban -r"; + public const string Ban = "ban"; public const string Kick = "kick"; public const string Logout = "logout"; - public const string ShowList = "showlist"; - public const string ShowClients1 = "show clients"; - public const string ShowClients2 = "clients"; - public const string ShowUsers1 = "show users"; - public const string ShowUsers2 = "users"; - public const string ReloadAddons = "reload addons"; - public const string ReloadPlugins1 = "reload plugins"; - public const string ReloadPlugins2 = "reload -p"; - public const string ReloadPlugins3 = "reload -sp"; - public const string ReloadPlugins4 = "reload -wp"; - public const string ReloadModules1 = "reload modules"; - public const string ReloadModules2 = "reload -m"; + public const string Show = "show"; + public const string ShowClients = "clients"; + public const string ShowUsers = "users"; + public const string Reload = "reload"; } } diff --git a/FunGame.Server/Services/FunGameSystem.cs b/FunGame.Server/Services/FunGameSystem.cs index be6fe9a..136cb52 100644 --- a/FunGame.Server/Services/FunGameSystem.cs +++ b/FunGame.Server/Services/FunGameSystem.cs @@ -20,7 +20,12 @@ namespace Milimoe.FunGame.Server.Services /// /// 服务器指令列表 /// - public static Dictionary> OrderList { get; } = []; + public static Dictionary> OrderList { get; } = []; + + /// + /// 服务器指令的别名列表 + /// + public static Dictionary OrderAliasList { get; } = []; /// /// 在线房间列表 @@ -72,6 +77,31 @@ namespace Milimoe.FunGame.Server.Services /// public const string APISecretFileName = ".apisecret"; + /// + /// 读取启动项 + /// + /// + /// + public static void GetStartupArguments(string[] args) + { + foreach (string arg in args) + { + switch (arg) + { + case "--debug": + case "-d": + FunGameInfo.FunGame_DebugMode = true; + break; + case "--allowanyorigin": + case "-aao": + Config.AllowAnyOrigin = true; + break; + default: + break; + } + } + } + /// /// 初始化数据库连接器 /// diff --git a/FunGame.Server/Services/General.cs b/FunGame.Server/Services/General.cs index bee0ece..b3b5b7a 100644 --- a/FunGame.Server/Services/General.cs +++ b/FunGame.Server/Services/General.cs @@ -245,16 +245,6 @@ namespace Milimoe.FunGame.Server.Services Error(e); } } - - public static void InitOrderList() - { - FunGameSystem.OrderList.Clear(); - FunGameSystem.OrderList.Add(OrderDictionary.Help, s => WriteLine("Milimoe -> 帮助")); - FunGameSystem.OrderList.Add(OrderDictionary.Quit, s => WriteLine("关闭服务器")); - FunGameSystem.OrderList.Add(OrderDictionary.Exit, s => WriteLine("关闭服务器")); - FunGameSystem.OrderList.Add(OrderDictionary.Close, s => WriteLine("关闭服务器")); - FunGameSystem.OrderList.Add(OrderDictionary.Restart, s => WriteLine("重启服务器")); - } } public class SmtpHelper diff --git a/FunGame.WebAPI/Program.cs b/FunGame.WebAPI/Program.cs index 434a572..f103ee7 100644 --- a/FunGame.WebAPI/Program.cs +++ b/FunGame.WebAPI/Program.cs @@ -52,8 +52,8 @@ try ServerHelper.GetServerSettings(); } - // 初始化命令菜单 - ServerHelper.InitOrderList(); + // 读取启动项 + FunGameSystem.GetStartupArguments(args); // 初始化 SQLHelper FunGameSystem.InitSQLHelper(); @@ -132,7 +132,16 @@ try { options.AddPolicy("AllowSpecificOrigin", policy => { - policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod(); + if (Config.AllowAnyOrigin) + { + ServerHelper.WriteLine($"已允许所有来源跨域访问", InvokeMessageType.Warning); + policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod(); + } + else + { + string[] allowedOrigins = builder.Configuration.GetSection("AllowOrigins").Get() ?? ["http://localhost:12099", "https://localhost:12099"]; + policy.WithOrigins(allowedOrigins).AllowAnyHeader().AllowAnyMethod().AllowCredentials(); + } }); }); // 添加 JWT 认证 @@ -279,30 +288,33 @@ catch (Exception e) async Task GetConsoleOrder() { + // 初始化命令菜单 + ConsoleModel.InitOrders(listener); while (true) { - string order = await Console.In.ReadLineAsync() ?? ""; + string input = (await Console.In.ReadLineAsync())?.Trim() ?? ""; ServerHelper.Type(); - if (order != "") + if (input != "") { - order = order.ToLower(); - if (FunGameSystem.OrderList.TryGetValue(order, out Action? action) && action != null) + string[] strings = input.Split(' ', StringSplitOptions.RemoveEmptyEntries); + if (strings.Length > 0) { - action(order); - } - switch (order) - { - case OrderDictionary.Quit: - case OrderDictionary.Exit: - case OrderDictionary.Close: - CloseServer(); - break; - case OrderDictionary.Restart: - ServerHelper.WriteLine("服务器正在运行,请手动结束服务器进程再启动!"); - break; - default: - await ConsoleModel.Order(listener, order); - break; + string order = strings[0].ToLower(); + string[] args = [.. strings.Skip(1)]; + switch (order) + { + case OrderDictionary.Quit: + case OrderDictionary.Exit: + case OrderDictionary.Close: + CloseServer(); + break; + case OrderDictionary.Restart: + ServerHelper.WriteLine("服务器正在运行,请手动结束服务器进程再启动!"); + break; + default: + await ConsoleModel.Order(order, args); + break; + } } } } @@ -360,8 +372,8 @@ async Task WebSocketConnectionHandler(HttpContext context) { Config.DecrementConnectingPlayerCount(); ConnectEventArgs eventArgs = new(clientip, Config.ServerPort, ConnectResult.CanNotConnect); - FunGameSystem.ServerPluginLoader?.OnAfterConnectEvent(context, eventArgs); - FunGameSystem.WebAPIPluginLoader?.OnAfterConnectEvent(context, eventArgs); + FunGameSystem.ServerPluginLoader?.OnAfterConnectEvent(socket, eventArgs); + FunGameSystem.WebAPIPluginLoader?.OnAfterConnectEvent(socket, eventArgs); ServerHelper.WriteLine(ServerHelper.MakeClientName(clientip) + " 中断连接!", InvokeMessageType.Core); ServerHelper.Error(e); } diff --git a/FunGame.WebAPI/Properties/launchSettings.json b/FunGame.WebAPI/Properties/launchSettings.json index 88622e2..00206a3 100644 --- a/FunGame.WebAPI/Properties/launchSettings.json +++ b/FunGame.WebAPI/Properties/launchSettings.json @@ -1,33 +1,25 @@ -{ - "$schema": "http://json.schemastore.org/launchsettings.json", - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:45590", - "sslPort": 44356 - } - }, +{ "profiles": { "http": { "commandName": "Project", - "dotnetRunMessages": true, "launchBrowser": true, "launchUrl": "scalar", - "applicationUrl": "http://localhost:5117", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5117" }, "https": { "commandName": "Project", - "dotnetRunMessages": true, + "commandLineArgs": "-aao", "launchBrowser": true, "launchUrl": "scalar", - "applicationUrl": "https://localhost:7162;http://localhost:5117", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7162;http://localhost:5117" }, "IIS Express": { "commandName": "IISExpress", @@ -37,5 +29,14 @@ "ASPNETCORE_ENVIRONMENT": "Development" } } + }, + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:45590", + "sslPort": 44356 + } } -} +} \ No newline at end of file diff --git a/FunGame.WebAPI/appsettings.Development.json b/FunGame.WebAPI/appsettings.Development.json index 0c208ae..c6ee44d 100644 --- a/FunGame.WebAPI/appsettings.Development.json +++ b/FunGame.WebAPI/appsettings.Development.json @@ -1,8 +1,13 @@ { "Logging": { "LogLevel": { - "Default": "Information", + "Default": "Debug", "Microsoft.AspNetCore": "Warning" } + }, + "Jwt": { + "Key": "166afec8ff6e0c3a647c7230294ea10be39d5d217f37aa5195f795017403da730ce6313790335b4975d7387c14aaa06c52d1cd90b5ef47d1831b6d7d524a12bf", + "Issuer": "FunGame", + "Audience": "FunGame Web API" } } diff --git a/FunGame.WebAPI/appsettings.json b/FunGame.WebAPI/appsettings.json index 3701d01..1c1c5d7 100644 --- a/FunGame.WebAPI/appsettings.json +++ b/FunGame.WebAPI/appsettings.json @@ -11,6 +11,10 @@ "Protocols": "Http1AndHttp2AndHttp3" } }, + "AllowOrigins": [ + "http://localhost:12099", + "https://localhost:12099" + ], "Jwt": { "Key": "166afec8ff6e0c3a647c7230294ea10be39d5d217f37aa5195f795017403da730ce6313790335b4975d7387c14aaa06c52d1cd90b5ef47d1831b6d7d524a12bf", "Issuer": "FunGame",