From 59253948cbb531900cd334b4751979d9b94e7c2d Mon Sep 17 00:00:00 2001 From: milimoe <110188673+milimoe@users.noreply.github.com> Date: Tue, 15 Oct 2024 20:13:48 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=BA=E6=9C=8D=E5=8A=A1=E5=99=A8=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=8F=92=E4=BB=B6=20(#94)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 添加 WebAPIPlugin 和 Loader * 添加 接收服务器控制台的输入 * 添加 ServerPlugin,添加控制器 * 更新 SocketObejct --- Api/Utility/GameModuleLoader.cs | 8 +- Api/Utility/JsonTool.cs | 1 + Api/Utility/PluginLoader.cs | 10 +- Api/Utility/ServerPluginLoader.cs | 54 ++ Api/Utility/WebAPIPluginLoader.cs | 54 ++ Controller/AddonController.cs | 2 +- Controller/BaseAddonController.cs | 11 +- Library/Common/Addon/Plugin.cs | 12 +- Library/Common/Addon/ServerPlugin.cs | 792 +++++++++++++++++++++++++ Library/Common/Addon/WebAPIPlugin.cs | 88 +++ Library/Common/Network/SocketObject.cs | 8 +- Service/AddonManager.cs | 84 ++- Service/JsonManager.cs | 1 + 13 files changed, 1097 insertions(+), 28 deletions(-) create mode 100644 Api/Utility/ServerPluginLoader.cs create mode 100644 Api/Utility/WebAPIPluginLoader.cs create mode 100644 Library/Common/Addon/ServerPlugin.cs create mode 100644 Library/Common/Addon/WebAPIPlugin.cs diff --git a/Api/Utility/GameModuleLoader.cs b/Api/Utility/GameModuleLoader.cs index a64c030..f162434 100644 --- a/Api/Utility/GameModuleLoader.cs +++ b/Api/Utility/GameModuleLoader.cs @@ -54,26 +54,26 @@ namespace Milimoe.FunGame.Core.Api.Utility /// 用于构建 /// 其他需要传入给插件初始化的对象 /// - public static GameModuleLoader LoadGameModules(FunGameInfo.FunGame runtime, Hashtable delegates, params object[] otherobjs) + public static GameModuleLoader LoadGameModules(FunGameInfo.FunGame runtime, Dictionary delegates, params object[] otherobjs) { GameModuleLoader loader = new(); if (runtime == FunGameInfo.FunGame.FunGame_Desktop) { AddonManager.LoadGameModules(loader.Modules, loader.Characters, loader.Skills, loader.Items, delegates, otherobjs); AddonManager.LoadGameMaps(loader.Maps, otherobjs); - foreach (GameModule module in loader.Modules.Values) + foreach (GameModule module in loader.Modules.Values.ToList()) { // 读取模组的依赖集合 module.GameModuleDepend.GetDependencies(loader); // 如果模组加载后需要执行代码,请重写AfterLoad方法 - module.AfterLoad(runtime, loader); + module.AfterLoad(loader); } } else if (runtime == FunGameInfo.FunGame.FunGame_Server) { AddonManager.LoadGameModulesForServer(loader.ModuleServers, loader.Characters, loader.Skills, loader.Items, delegates, otherobjs); AddonManager.LoadGameMaps(loader.Maps, otherobjs); - foreach (GameModuleServer server in loader.ModuleServers.Values) + foreach (GameModuleServer server in loader.ModuleServers.Values.ToList()) { server.GameModuleDepend.GetDependencies(loader); server.AfterLoad(loader); diff --git a/Api/Utility/JsonTool.cs b/Api/Utility/JsonTool.cs index e3f2479..36ac012 100644 --- a/Api/Utility/JsonTool.cs +++ b/Api/Utility/JsonTool.cs @@ -108,6 +108,7 @@ namespace Milimoe.FunGame.Core.Api.Utility private readonly JsonSerializerOptions options = new() { WriteIndented = true, + PropertyNameCaseInsensitive = true, ReferenceHandler = ReferenceHandler.IgnoreCycles, Converters = { new DateTimeConverter(), new DataTableConverter(), new DataSetConverter(), new UserConverter(), new RoomConverter(), new CharacterConverter(), new MagicResistanceConverter(), new EquipSlotConverter(), new SkillConverter(), new EffectConverter(), new ItemConverter() } diff --git a/Api/Utility/PluginLoader.cs b/Api/Utility/PluginLoader.cs index a17aaf2..9a02066 100644 --- a/Api/Utility/PluginLoader.cs +++ b/Api/Utility/PluginLoader.cs @@ -1,5 +1,4 @@ -using System.Collections; -using Milimoe.FunGame.Core.Library.Common.Addon; +using Milimoe.FunGame.Core.Library.Common.Addon; using Milimoe.FunGame.Core.Library.Common.Event; using Milimoe.FunGame.Core.Service; @@ -29,10 +28,15 @@ namespace Milimoe.FunGame.Core.Api.Utility /// 用于构建 /// 其他需要传入给插件初始化的对象 /// - public static PluginLoader LoadPlugins(Hashtable delegates, params object[] otherobjs) + public static PluginLoader LoadPlugins(Dictionary delegates, params object[] otherobjs) { PluginLoader loader = new(); AddonManager.LoadPlugins(loader.Plugins, delegates, otherobjs); + foreach (Plugin plugin in loader.Plugins.Values.ToList()) + { + // 如果插件加载后需要执行代码,请重写AfterLoad方法 + plugin.AfterLoad(loader); + } return loader; } diff --git a/Api/Utility/ServerPluginLoader.cs b/Api/Utility/ServerPluginLoader.cs new file mode 100644 index 0000000..4525076 --- /dev/null +++ b/Api/Utility/ServerPluginLoader.cs @@ -0,0 +1,54 @@ +using Milimoe.FunGame.Core.Library.Common.Addon; +using Milimoe.FunGame.Core.Service; + +namespace Milimoe.FunGame.Core.Api.Utility +{ + public class ServerPluginLoader + { + /// + /// 已读取的插件列表 + /// key 是 + /// + public Dictionary Plugins { get; } = []; + + /// + /// 已加载的插件DLL名称对应的路径 + /// + public static Dictionary PluginFilePaths => new(AddonManager.PluginFilePaths); + + private ServerPluginLoader() + { + + } + + /// + /// 构建一个插件读取器并读取插件 + /// + /// 用于构建 + /// 其他需要传入给插件初始化的对象 + /// + public static ServerPluginLoader LoadPlugins(Dictionary delegates, params object[] otherobjs) + { + ServerPluginLoader loader = new(); + AddonManager.LoadServerPlugins(loader.Plugins, delegates, otherobjs); + foreach (ServerPlugin plugin in loader.Plugins.Values.ToList()) + { + // 如果插件加载后需要执行代码,请重写AfterLoad方法 + plugin.AfterLoad(loader); + } + return loader; + } + + public ServerPlugin this[string name] + { + get + { + return Plugins[name]; + } + set + { + Plugins.TryAdd(name, value); + } + } + } +} diff --git a/Api/Utility/WebAPIPluginLoader.cs b/Api/Utility/WebAPIPluginLoader.cs new file mode 100644 index 0000000..8309984 --- /dev/null +++ b/Api/Utility/WebAPIPluginLoader.cs @@ -0,0 +1,54 @@ +using Milimoe.FunGame.Core.Library.Common.Addon; +using Milimoe.FunGame.Core.Service; + +namespace Milimoe.FunGame.Core.Api.Utility +{ + public class WebAPIPluginLoader + { + /// + /// 已读取的插件列表 + /// key 是 + /// + public Dictionary Plugins { get; } = []; + + /// + /// 已加载的插件DLL名称对应的路径 + /// + public static Dictionary PluginFilePaths => new(AddonManager.PluginFilePaths); + + private WebAPIPluginLoader() + { + + } + + /// + /// 构建一个插件读取器并读取插件 + /// + /// 用于构建 + /// 其他需要传入给插件初始化的对象 + /// + public static WebAPIPluginLoader LoadPlugins(Dictionary delegates, params object[] otherobjs) + { + WebAPIPluginLoader loader = new(); + AddonManager.LoadWebAPIPlugins(loader.Plugins, delegates, otherobjs); + foreach (WebAPIPlugin plugin in loader.Plugins.Values.ToList()) + { + // 如果插件加载后需要执行代码,请重写AfterLoad方法 + plugin.AfterLoad(loader); + } + return loader; + } + + public WebAPIPlugin this[string name] + { + get + { + return Plugins[name]; + } + set + { + Plugins.TryAdd(name, value); + } + } + } +} diff --git a/Controller/AddonController.cs b/Controller/AddonController.cs index 2d6b6a9..40fe3ce 100644 --- a/Controller/AddonController.cs +++ b/Controller/AddonController.cs @@ -104,7 +104,7 @@ namespace Milimoe.FunGame.Core.Controller /// /// /// - public AddonController(IAddon addon, Hashtable delegates) : base(addon, delegates) + public AddonController(IAddon addon, Dictionary delegates) : base(addon, delegates) { if (delegates.ContainsKey("NewDataRequest")) MaskMethod_NewDataRequest = delegates["NewDataRequest"] != null ? (Func)delegates["NewDataRequest"]! : new(DefaultNewDataRequest); if (delegates.ContainsKey("NewLongRunningDataRequest")) MaskMethod_NewLongRunningDataRequest = delegates["NewLongRunningDataRequest"] != null ? (Func)delegates["NewLongRunningDataRequest"]! : new(DefaultNewDataRequest); diff --git a/Controller/BaseAddonController.cs b/Controller/BaseAddonController.cs index 20767c2..4824c47 100644 --- a/Controller/BaseAddonController.cs +++ b/Controller/BaseAddonController.cs @@ -1,5 +1,4 @@ -using System.Collections; -using Milimoe.FunGame.Core.Interface.Addons; +using Milimoe.FunGame.Core.Interface.Addons; using Milimoe.FunGame.Core.Library.Common.Addon; namespace Milimoe.FunGame.Core.Controller @@ -7,7 +6,7 @@ namespace Milimoe.FunGame.Core.Controller /// /// 这是通用的控制器,仅提供基本功能 /// - /// Addon的类型,如或者 + /// Addon的类型,如 或者 / / public class BaseAddonController where T : IAddon { /// @@ -44,11 +43,11 @@ namespace Milimoe.FunGame.Core.Controller /// /// /// - public BaseAddonController(IAddon addon, Hashtable delegates) + public BaseAddonController(IAddon addon, Dictionary delegates) { Addon = (T)addon; - if (delegates.ContainsKey("WriteLine")) MaskMethod_WriteLine = delegates["WriteLine"] != null ? (Action)delegates["WriteLine"]! : new(DefaultPrint); - if (delegates.ContainsKey("Error")) MaskMethod_Error = delegates["Error"] != null ? (Action)delegates["Error"]! : new(DefaultPrint); + if (delegates.TryGetValue("WriteLine", out object? value)) MaskMethod_WriteLine = value != null ? (Action)value : new(DefaultPrint); + if (delegates.TryGetValue("Error", out value)) MaskMethod_Error = value != null ? (Action)value : new(DefaultPrint); MaskMethod_WriteLine ??= new(DefaultPrint); MaskMethod_Error ??= new(DefaultPrint); } diff --git a/Library/Common/Addon/Plugin.cs b/Library/Common/Addon/Plugin.cs index edbb5c3..71dbe4c 100644 --- a/Library/Common/Addon/Plugin.cs +++ b/Library/Common/Addon/Plugin.cs @@ -66,7 +66,7 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon return false; } // BeforeLoad可以阻止加载此插件 - if (BeforeLoad()) + if (BeforeLoad(objs)) { // 插件加载后,不允许再次加载此插件 IsLoaded = true; @@ -74,16 +74,14 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon Init(objs); // 触发绑定事件 BindEvent(); - // 如果加载后需要执行代码,请重写AfterLoad方法 - AfterLoad(); } return IsLoaded; } /// - /// 插件加载后需要做的事 + /// 插件完全加载后需要做的事 /// - protected virtual void AfterLoad() + public virtual void AfterLoad(params object[] objs) { // override } @@ -92,13 +90,13 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon /// 允许返回false来阻止加载此插件 /// /// - protected virtual bool BeforeLoad() + protected virtual bool BeforeLoad(params object[] objs) { return true; } /// - /// 传递委托以便让插件调用 + /// 传递一些插件可以用参数 /// private void Init(params object[] objs) { diff --git a/Library/Common/Addon/ServerPlugin.cs b/Library/Common/Addon/ServerPlugin.cs new file mode 100644 index 0000000..3430e86 --- /dev/null +++ b/Library/Common/Addon/ServerPlugin.cs @@ -0,0 +1,792 @@ +using Milimoe.FunGame.Core.Controller; +using Milimoe.FunGame.Core.Interface; +using Milimoe.FunGame.Core.Interface.Addons; +using Milimoe.FunGame.Core.Library.Common.Event; + +namespace Milimoe.FunGame.Core.Library.Common.Addon +{ + public abstract class ServerPlugin : IPlugin + { + /// + /// 插件名称 + /// + public abstract string Name { get; } + + /// + /// 插件描述 + /// + public abstract string Description { get; } + + /// + /// 插件版本 + /// + public abstract string Version { get; } + + /// + /// 插件作者 + /// + public abstract string Author { get; } + + /// + /// 包含了一些常用方法的控制器 + /// + public BaseAddonController Controller + { + get => _Controller ?? throw new NotImplementedException(); + set => _Controller = value; + } + + /// + /// 控制器内部变量 + /// + private BaseAddonController? _Controller; + + /// + /// 加载标记 + /// + private bool IsLoaded = false; + + /// + /// 加载插件 + /// + public bool Load(params object[] objs) + { + if (IsLoaded) + { + return false; + } + // BeforeLoad可以阻止加载此插件 + if (BeforeLoad(objs)) + { + // 插件加载后,不允许再次加载此插件 + IsLoaded = true; + // 触发绑定事件 + BindEvent(); + } + return IsLoaded; + } + + /// + /// 接收服务器控制台的输入 + /// + /// + public abstract void ProcessInput(string input); + + /// + /// 插件完全加载后需要做的事 + /// + public virtual void AfterLoad(params object[] objs) + { + // override + } + + /// + /// 允许返回false来阻止加载此插件 + /// + /// + protected virtual bool BeforeLoad(params object[] objs) + { + return true; + } + + /// + /// 绑定事件。在后触发 + /// + private void BindEvent() + { + if (this is IConnectEvent) + { + IConnectEvent bind = (IConnectEvent)this; + BeforeConnect += bind.BeforeConnectEvent; + AfterConnect += bind.AfterConnectEvent; + SucceedConnect += bind.SucceedConnectEvent; + FailedConnect += bind.FailedConnectEvent; + } + + if (this is IDisconnectEvent) + { + IDisconnectEvent bind = (IDisconnectEvent)this; + BeforeDisconnect += bind.BeforeDisconnectEvent; + AfterDisconnect += bind.AfterDisconnectEvent; + SucceedDisconnect += bind.SucceedDisconnectEvent; + FailedDisconnect += bind.FailedDisconnectEvent; + } + + if (this is ILoginEvent) + { + ILoginEvent bind = (ILoginEvent)this; + BeforeLogin += bind.BeforeLoginEvent; + AfterLogin += bind.AfterLoginEvent; + SucceedLogin += bind.SucceedLoginEvent; + FailedLogin += bind.FailedLoginEvent; + } + + if (this is ILogoutEvent) + { + ILogoutEvent bind = (ILogoutEvent)this; + BeforeLogout += bind.BeforeLogoutEvent; + AfterLogout += bind.AfterLogoutEvent; + SucceedLogout += bind.SucceedLogoutEvent; + FailedLogout += bind.FailedLogoutEvent; + } + + if (this is IRegEvent) + { + IRegEvent bind = (IRegEvent)this; + BeforeReg += bind.BeforeRegEvent; + AfterReg += bind.AfterRegEvent; + SucceedReg += bind.SucceedRegEvent; + FailedReg += bind.FailedRegEvent; + } + + if (this is IIntoRoomEvent) + { + IIntoRoomEvent bind = (IIntoRoomEvent)this; + BeforeIntoRoom += bind.BeforeIntoRoomEvent; + AfterIntoRoom += bind.AfterIntoRoomEvent; + SucceedIntoRoom += bind.SucceedIntoRoomEvent; + FailedIntoRoom += bind.FailedIntoRoomEvent; + } + + if (this is ISendTalkEvent) + { + ISendTalkEvent bind = (ISendTalkEvent)this; + BeforeSendTalk += bind.BeforeSendTalkEvent; + AfterSendTalk += bind.AfterSendTalkEvent; + SucceedSendTalk += bind.SucceedSendTalkEvent; + FailedSendTalk += bind.FailedSendTalkEvent; + } + + if (this is ICreateRoomEvent) + { + ICreateRoomEvent bind = (ICreateRoomEvent)this; + BeforeCreateRoom += bind.BeforeCreateRoomEvent; + AfterCreateRoom += bind.AfterCreateRoomEvent; + SucceedCreateRoom += bind.SucceedCreateRoomEvent; + FailedCreateRoom += bind.FailedCreateRoomEvent; + } + + if (this is IQuitRoomEvent) + { + IQuitRoomEvent bind = (IQuitRoomEvent)this; + BeforeQuitRoom += bind.BeforeQuitRoomEvent; + AfterQuitRoom += bind.AfterQuitRoomEvent; + SucceedQuitRoom += bind.SucceedQuitRoomEvent; + FailedQuitRoom += bind.FailedQuitRoomEvent; + } + + if (this is IChangeRoomSettingEvent) + { + IChangeRoomSettingEvent bind = (IChangeRoomSettingEvent)this; + BeforeChangeRoomSetting += bind.BeforeChangeRoomSettingEvent; + AfterChangeRoomSetting += bind.AfterChangeRoomSettingEvent; + SucceedChangeRoomSetting += bind.SucceedChangeRoomSettingEvent; + FailedChangeRoomSetting += bind.FailedChangeRoomSettingEvent; + } + + if (this is IStartMatchEvent) + { + IStartMatchEvent bind = (IStartMatchEvent)this; + BeforeStartMatch += bind.BeforeStartMatchEvent; + AfterStartMatch += bind.AfterStartMatchEvent; + SucceedStartMatch += bind.SucceedStartMatchEvent; + FailedStartMatch += bind.FailedStartMatchEvent; + } + + if (this is IStartGameEvent) + { + IStartGameEvent bind = (IStartGameEvent)this; + BeforeStartGame += bind.BeforeStartGameEvent; + AfterStartGame += bind.AfterStartGameEvent; + SucceedStartGame += bind.SucceedStartGameEvent; + FailedStartGame += bind.FailedStartGameEvent; + } + + if (this is IChangeProfileEvent) + { + IChangeProfileEvent bind = (IChangeProfileEvent)this; + BeforeChangeProfile += bind.BeforeChangeProfileEvent; + AfterChangeProfile += bind.AfterChangeProfileEvent; + SucceedChangeProfile += bind.SucceedChangeProfileEvent; + FailedChangeProfile += bind.FailedChangeProfileEvent; + } + + if (this is IChangeAccountSettingEvent) + { + IChangeAccountSettingEvent bind = (IChangeAccountSettingEvent)this; + BeforeChangeAccountSetting += bind.BeforeChangeAccountSettingEvent; + AfterChangeAccountSetting += bind.AfterChangeAccountSettingEvent; + SucceedChangeAccountSetting += bind.SucceedChangeAccountSettingEvent; + FailedChangeAccountSetting += bind.FailedChangeAccountSettingEvent; + } + + if (this is IOpenInventoryEvent) + { + IOpenInventoryEvent bind = (IOpenInventoryEvent)this; + BeforeOpenInventory += bind.BeforeOpenInventoryEvent; + AfterOpenInventory += bind.AfterOpenInventoryEvent; + SucceedOpenInventory += bind.SucceedOpenInventoryEvent; + FailedOpenInventory += bind.FailedOpenInventoryEvent; + } + + if (this is ISignInEvent) + { + ISignInEvent bind = (ISignInEvent)this; + BeforeSignIn += bind.BeforeSignInEvent; + AfterSignIn += bind.AfterSignInEvent; + SucceedSignIn += bind.SucceedSignInEvent; + FailedSignIn += bind.FailedSignInEvent; + } + + if (this is IOpenStoreEvent) + { + IOpenStoreEvent bind = (IOpenStoreEvent)this; + BeforeOpenStore += bind.BeforeOpenStoreEvent; + AfterOpenStore += bind.AfterOpenStoreEvent; + SucceedOpenStore += bind.SucceedOpenStoreEvent; + FailedOpenStore += bind.FailedOpenStoreEvent; + } + + if (this is IBuyItemEvent) + { + IBuyItemEvent bind = (IBuyItemEvent)this; + BeforeBuyItem += bind.BeforeBuyItemEvent; + AfterBuyItem += bind.AfterBuyItemEvent; + SucceedBuyItem += bind.SucceedBuyItemEvent; + FailedBuyItem += bind.FailedBuyItemEvent; + } + + if (this is IShowRankingEvent) + { + IShowRankingEvent bind = (IShowRankingEvent)this; + BeforeShowRanking += bind.BeforeShowRankingEvent; + AfterShowRanking += bind.AfterShowRankingEvent; + SucceedShowRanking += bind.SucceedShowRankingEvent; + FailedShowRanking += bind.FailedShowRankingEvent; + } + + if (this is IUseItemEvent) + { + IUseItemEvent bind = (IUseItemEvent)this; + BeforeUseItem += bind.BeforeUseItemEvent; + AfterUseItem += bind.AfterUseItemEvent; + SucceedUseItem += bind.SucceedUseItemEvent; + FailedUseItem += bind.FailedUseItemEvent; + } + + if (this is IEndGameEvent) + { + IEndGameEvent bind = (IEndGameEvent)this; + BeforeEndGame += bind.BeforeEndGameEvent; + AfterEndGame += bind.AfterEndGameEvent; + SucceedEndGame += bind.SucceedEndGameEvent; + FailedEndGame += bind.FailedEndGameEvent; + } + } + + public event IConnectEventHandler.BeforeEventHandler? BeforeConnect; + public event IConnectEventHandler.AfterEventHandler? AfterConnect; + public event IConnectEventHandler.SucceedEventHandler? SucceedConnect; + public event IConnectEventHandler.FailedEventHandler? FailedConnect; + public event IEventHandler.BeforeEventHandler? BeforeDisconnect; + public event IEventHandler.AfterEventHandler? AfterDisconnect; + public event IEventHandler.SucceedEventHandler? SucceedDisconnect; + public event IEventHandler.FailedEventHandler? FailedDisconnect; + public event ILoginEventHandler.BeforeEventHandler? BeforeLogin; + public event ILoginEventHandler.AfterEventHandler? AfterLogin; + public event ILoginEventHandler.SucceedEventHandler? SucceedLogin; + public event ILoginEventHandler.FailedEventHandler? FailedLogin; + public event IEventHandler.BeforeEventHandler? BeforeLogout; + public event IEventHandler.AfterEventHandler? AfterLogout; + public event IEventHandler.SucceedEventHandler? SucceedLogout; + public event IEventHandler.FailedEventHandler? FailedLogout; + public event IRegEventHandler.BeforeEventHandler? BeforeReg; + public event IRegEventHandler.AfterEventHandler? AfterReg; + public event IRegEventHandler.SucceedEventHandler? SucceedReg; + public event IRegEventHandler.FailedEventHandler? FailedReg; + public event IIntoRoomEventHandler.BeforeEventHandler? BeforeIntoRoom; + public event IIntoRoomEventHandler.AfterEventHandler? AfterIntoRoom; + public event IIntoRoomEventHandler.SucceedEventHandler? SucceedIntoRoom; + public event IIntoRoomEventHandler.FailedEventHandler? FailedIntoRoom; + public event ISendTalkEventHandler.BeforeEventHandler? BeforeSendTalk; + public event ISendTalkEventHandler.AfterEventHandler? AfterSendTalk; + public event ISendTalkEventHandler.SucceedEventHandler? SucceedSendTalk; + public event ISendTalkEventHandler.FailedEventHandler? FailedSendTalk; + public event ICreateRoomEventHandler.BeforeEventHandler? BeforeCreateRoom; + public event ICreateRoomEventHandler.AfterEventHandler? AfterCreateRoom; + public event ICreateRoomEventHandler.SucceedEventHandler? SucceedCreateRoom; + public event ICreateRoomEventHandler.FailedEventHandler? FailedCreateRoom; + public event IQuitRoomEventHandler.BeforeEventHandler? BeforeQuitRoom; + public event IQuitRoomEventHandler.AfterEventHandler? AfterQuitRoom; + public event IQuitRoomEventHandler.SucceedEventHandler? SucceedQuitRoom; + public event IQuitRoomEventHandler.FailedEventHandler? FailedQuitRoom; + public event IEventHandler.BeforeEventHandler? BeforeChangeRoomSetting; + public event IEventHandler.AfterEventHandler? AfterChangeRoomSetting; + public event IEventHandler.SucceedEventHandler? SucceedChangeRoomSetting; + public event IEventHandler.FailedEventHandler? FailedChangeRoomSetting; + public event IEventHandler.BeforeEventHandler? BeforeStartMatch; + public event IEventHandler.AfterEventHandler? AfterStartMatch; + public event IEventHandler.SucceedEventHandler? SucceedStartMatch; + public event IEventHandler.FailedEventHandler? FailedStartMatch; + public event IEventHandler.BeforeEventHandler? BeforeStartGame; + public event IEventHandler.AfterEventHandler? AfterStartGame; + public event IEventHandler.SucceedEventHandler? SucceedStartGame; + public event IEventHandler.FailedEventHandler? FailedStartGame; + public event IEventHandler.BeforeEventHandler? BeforeChangeProfile; + public event IEventHandler.AfterEventHandler? AfterChangeProfile; + public event IEventHandler.SucceedEventHandler? SucceedChangeProfile; + public event IEventHandler.FailedEventHandler? FailedChangeProfile; + public event IEventHandler.BeforeEventHandler? BeforeChangeAccountSetting; + public event IEventHandler.AfterEventHandler? AfterChangeAccountSetting; + public event IEventHandler.SucceedEventHandler? SucceedChangeAccountSetting; + public event IEventHandler.FailedEventHandler? FailedChangeAccountSetting; + public event IEventHandler.BeforeEventHandler? BeforeOpenInventory; + public event IEventHandler.AfterEventHandler? AfterOpenInventory; + public event IEventHandler.SucceedEventHandler? SucceedOpenInventory; + public event IEventHandler.FailedEventHandler? FailedOpenInventory; + public event IEventHandler.BeforeEventHandler? BeforeSignIn; + public event IEventHandler.AfterEventHandler? AfterSignIn; + public event IEventHandler.SucceedEventHandler? SucceedSignIn; + public event IEventHandler.FailedEventHandler? FailedSignIn; + public event IEventHandler.BeforeEventHandler? BeforeOpenStore; + public event IEventHandler.AfterEventHandler? AfterOpenStore; + public event IEventHandler.SucceedEventHandler? SucceedOpenStore; + public event IEventHandler.FailedEventHandler? FailedOpenStore; + public event IEventHandler.BeforeEventHandler? BeforeBuyItem; + public event IEventHandler.AfterEventHandler? AfterBuyItem; + public event IEventHandler.SucceedEventHandler? SucceedBuyItem; + public event IEventHandler.FailedEventHandler? FailedBuyItem; + public event IEventHandler.BeforeEventHandler? BeforeShowRanking; + public event IEventHandler.AfterEventHandler? AfterShowRanking; + public event IEventHandler.SucceedEventHandler? SucceedShowRanking; + public event IEventHandler.FailedEventHandler? FailedShowRanking; + public event IEventHandler.BeforeEventHandler? BeforeUseItem; + public event IEventHandler.AfterEventHandler? AfterUseItem; + public event IEventHandler.SucceedEventHandler? SucceedUseItem; + public event IEventHandler.FailedEventHandler? FailedUseItem; + public event IEventHandler.BeforeEventHandler? BeforeEndGame; + public event IEventHandler.AfterEventHandler? AfterEndGame; + public event IEventHandler.SucceedEventHandler? SucceedEndGame; + public event IEventHandler.FailedEventHandler? FailedEndGame; + + public void OnBeforeConnectEvent(object sender, ConnectEventArgs e) + { + BeforeConnect?.Invoke(sender, e); + } + + public void OnAfterConnectEvent(object sender, ConnectEventArgs e) + { + AfterConnect?.Invoke(sender, e); + } + + public void OnSucceedConnectEvent(object sender, ConnectEventArgs e) + { + SucceedConnect?.Invoke(sender, e); + } + + public void OnFailedConnectEvent(object sender, ConnectEventArgs e) + { + FailedConnect?.Invoke(sender, e); + } + + public void OnBeforeDisconnectEvent(object sender, GeneralEventArgs e) + { + BeforeDisconnect?.Invoke(sender, e); + } + + public void OnAfterDisconnectEvent(object sender, GeneralEventArgs e) + { + AfterDisconnect?.Invoke(sender, e); + } + + public void OnSucceedDisconnectEvent(object sender, GeneralEventArgs e) + { + SucceedDisconnect?.Invoke(sender, e); + } + + public void OnFailedDisconnectEvent(object sender, GeneralEventArgs e) + { + FailedDisconnect?.Invoke(sender, e); + } + + public void OnBeforeLoginEvent(object sender, LoginEventArgs e) + { + BeforeLogin?.Invoke(sender, e); + } + + public void OnAfterLoginEvent(object sender, LoginEventArgs e) + { + AfterLogin?.Invoke(sender, e); + } + + public void OnSucceedLoginEvent(object sender, LoginEventArgs e) + { + SucceedLogin?.Invoke(sender, e); + } + + public void OnFailedLoginEvent(object sender, LoginEventArgs e) + { + FailedLogin?.Invoke(sender, e); + } + + public void OnBeforeLogoutEvent(object sender, GeneralEventArgs e) + { + BeforeLogout?.Invoke(sender, e); + } + + public void OnAfterLogoutEvent(object sender, GeneralEventArgs e) + { + AfterLogout?.Invoke(sender, e); + } + + public void OnSucceedLogoutEvent(object sender, GeneralEventArgs e) + { + SucceedLogout?.Invoke(sender, e); + } + + public void OnFailedLogoutEvent(object sender, GeneralEventArgs e) + { + FailedLogout?.Invoke(sender, e); + } + + public void OnBeforeRegEvent(object sender, RegisterEventArgs e) + { + BeforeReg?.Invoke(sender, e); + } + + public void OnAfterRegEvent(object sender, RegisterEventArgs e) + { + AfterReg?.Invoke(sender, e); + } + + public void OnSucceedRegEvent(object sender, RegisterEventArgs e) + { + SucceedReg?.Invoke(sender, e); + } + + public void OnFailedRegEvent(object sender, RegisterEventArgs e) + { + FailedReg?.Invoke(sender, e); + } + + public void OnBeforeIntoRoomEvent(object sender, RoomEventArgs e) + { + BeforeIntoRoom?.Invoke(sender, e); + } + + public void OnAfterIntoRoomEvent(object sender, RoomEventArgs e) + { + AfterIntoRoom?.Invoke(sender, e); + } + + public void OnSucceedIntoRoomEvent(object sender, RoomEventArgs e) + { + SucceedIntoRoom?.Invoke(sender, e); + } + + public void OnFailedIntoRoomEvent(object sender, RoomEventArgs e) + { + FailedIntoRoom?.Invoke(sender, e); + } + + public void OnBeforeSendTalkEvent(object sender, SendTalkEventArgs e) + { + BeforeSendTalk?.Invoke(sender, e); + } + + public void OnAfterSendTalkEvent(object sender, SendTalkEventArgs e) + { + AfterSendTalk?.Invoke(sender, e); + } + + public void OnSucceedSendTalkEvent(object sender, SendTalkEventArgs e) + { + SucceedSendTalk?.Invoke(sender, e); + } + + public void OnFailedSendTalkEvent(object sender, SendTalkEventArgs e) + { + FailedSendTalk?.Invoke(sender, e); + } + + public void OnBeforeCreateRoomEvent(object sender, RoomEventArgs e) + { + BeforeCreateRoom?.Invoke(sender, e); + } + + public void OnAfterCreateRoomEvent(object sender, RoomEventArgs e) + { + AfterCreateRoom?.Invoke(sender, e); + } + + public void OnSucceedCreateRoomEvent(object sender, RoomEventArgs e) + { + SucceedCreateRoom?.Invoke(sender, e); + } + + public void OnFailedCreateRoomEvent(object sender, RoomEventArgs e) + { + FailedCreateRoom?.Invoke(sender, e); + } + + public void OnBeforeQuitRoomEvent(object sender, RoomEventArgs e) + { + BeforeQuitRoom?.Invoke(sender, e); + } + + public void OnAfterQuitRoomEvent(object sender, RoomEventArgs e) + { + AfterQuitRoom?.Invoke(sender, e); + } + + public void OnSucceedQuitRoomEvent(object sender, RoomEventArgs e) + { + SucceedQuitRoom?.Invoke(sender, e); + } + + public void OnFailedQuitRoomEvent(object sender, RoomEventArgs e) + { + FailedQuitRoom?.Invoke(sender, e); + } + + public void OnBeforeChangeRoomSettingEvent(object sender, GeneralEventArgs e) + { + BeforeChangeRoomSetting?.Invoke(sender, e); + } + + public void OnAfterChangeRoomSettingEvent(object sender, GeneralEventArgs e) + { + AfterChangeRoomSetting?.Invoke(sender, e); + } + + public void OnSucceedChangeRoomSettingEvent(object sender, GeneralEventArgs e) + { + SucceedChangeRoomSetting?.Invoke(sender, e); + } + + public void OnFailedChangeRoomSettingEvent(object sender, GeneralEventArgs e) + { + FailedChangeRoomSetting?.Invoke(sender, e); + } + + public void OnBeforeStartMatchEvent(object sender, GeneralEventArgs e) + { + BeforeStartMatch?.Invoke(sender, e); + } + + public void OnAfterStartMatchEvent(object sender, GeneralEventArgs e) + { + AfterStartMatch?.Invoke(sender, e); + } + + public void OnSucceedStartMatchEvent(object sender, GeneralEventArgs e) + { + SucceedStartMatch?.Invoke(sender, e); + } + + public void OnFailedStartMatchEvent(object sender, GeneralEventArgs e) + { + FailedStartMatch?.Invoke(sender, e); + } + + public void OnBeforeStartGameEvent(object sender, GeneralEventArgs e) + { + BeforeStartGame?.Invoke(sender, e); + } + + public void OnAfterStartGameEvent(object sender, GeneralEventArgs e) + { + AfterStartGame?.Invoke(sender, e); + } + + public void OnSucceedStartGameEvent(object sender, GeneralEventArgs e) + { + SucceedStartGame?.Invoke(sender, e); + } + + public void OnFailedStartGameEvent(object sender, GeneralEventArgs e) + { + FailedStartGame?.Invoke(sender, e); + } + + public void OnBeforeChangeProfileEvent(object sender, GeneralEventArgs e) + { + BeforeChangeProfile?.Invoke(sender, e); + } + + public void OnAfterChangeProfileEvent(object sender, GeneralEventArgs e) + { + AfterChangeProfile?.Invoke(sender, e); + } + + public void OnSucceedChangeProfileEvent(object sender, GeneralEventArgs e) + { + SucceedChangeProfile?.Invoke(sender, e); + } + + public void OnFailedChangeProfileEvent(object sender, GeneralEventArgs e) + { + FailedChangeProfile?.Invoke(sender, e); + } + + public void OnBeforeChangeAccountSettingEvent(object sender, GeneralEventArgs e) + { + BeforeChangeAccountSetting?.Invoke(sender, e); + } + + public void OnAfterChangeAccountSettingEvent(object sender, GeneralEventArgs e) + { + AfterChangeAccountSetting?.Invoke(sender, e); + } + + public void OnSucceedChangeAccountSettingEvent(object sender, GeneralEventArgs e) + { + SucceedChangeAccountSetting?.Invoke(sender, e); + } + + public void OnFailedChangeAccountSettingEvent(object sender, GeneralEventArgs e) + { + FailedChangeAccountSetting?.Invoke(sender, e); + } + + public void OnBeforeOpenInventoryEvent(object sender, GeneralEventArgs e) + { + BeforeOpenInventory?.Invoke(sender, e); + } + + public void OnAfterOpenInventoryEvent(object sender, GeneralEventArgs e) + { + AfterOpenInventory?.Invoke(sender, e); + } + + public void OnSucceedOpenInventoryEvent(object sender, GeneralEventArgs e) + { + SucceedOpenInventory?.Invoke(sender, e); + } + + public void OnFailedOpenInventoryEvent(object sender, GeneralEventArgs e) + { + FailedOpenInventory?.Invoke(sender, e); + } + + public void OnBeforeSignInEvent(object sender, GeneralEventArgs e) + { + BeforeSignIn?.Invoke(sender, e); + } + + public void OnAfterSignInEvent(object sender, GeneralEventArgs e) + { + AfterSignIn?.Invoke(sender, e); + } + + public void OnSucceedSignInEvent(object sender, GeneralEventArgs e) + { + SucceedSignIn?.Invoke(sender, e); + } + + public void OnFailedSignInEvent(object sender, GeneralEventArgs e) + { + FailedSignIn?.Invoke(sender, e); + } + + public void OnBeforeOpenStoreEvent(object sender, GeneralEventArgs e) + { + BeforeOpenStore?.Invoke(sender, e); + } + + public void OnAfterOpenStoreEvent(object sender, GeneralEventArgs e) + { + AfterOpenStore?.Invoke(sender, e); + } + + public void OnSucceedOpenStoreEvent(object sender, GeneralEventArgs e) + { + SucceedOpenStore?.Invoke(sender, e); + } + + public void OnFailedOpenStoreEvent(object sender, GeneralEventArgs e) + { + FailedOpenStore?.Invoke(sender, e); + } + + public void OnBeforeBuyItemEvent(object sender, GeneralEventArgs e) + { + BeforeBuyItem?.Invoke(sender, e); + } + + public void OnAfterBuyItemEvent(object sender, GeneralEventArgs e) + { + AfterBuyItem?.Invoke(sender, e); + } + + public void OnSucceedBuyItemEvent(object sender, GeneralEventArgs e) + { + SucceedBuyItem?.Invoke(sender, e); + } + + public void OnFailedBuyItemEvent(object sender, GeneralEventArgs e) + { + FailedBuyItem?.Invoke(sender, e); + } + + public void OnBeforeShowRankingEvent(object sender, GeneralEventArgs e) + { + BeforeShowRanking?.Invoke(sender, e); + } + + public void OnAfterShowRankingEvent(object sender, GeneralEventArgs e) + { + AfterShowRanking?.Invoke(sender, e); + } + + public void OnSucceedShowRankingEvent(object sender, GeneralEventArgs e) + { + SucceedShowRanking?.Invoke(sender, e); + } + + public void OnFailedShowRankingEvent(object sender, GeneralEventArgs e) + { + FailedShowRanking?.Invoke(sender, e); + } + + public void OnBeforeUseItemEvent(object sender, GeneralEventArgs e) + { + BeforeUseItem?.Invoke(sender, e); + } + + public void OnAfterUseItemEvent(object sender, GeneralEventArgs e) + { + AfterUseItem?.Invoke(sender, e); + } + + public void OnSucceedUseItemEvent(object sender, GeneralEventArgs e) + { + SucceedUseItem?.Invoke(sender, e); + } + + public void OnFailedUseItemEvent(object sender, GeneralEventArgs e) + { + FailedUseItem?.Invoke(sender, e); + } + + public void OnBeforeEndGameEvent(object sender, GeneralEventArgs e) + { + BeforeEndGame?.Invoke(sender, e); + } + + public void OnAfterEndGameEvent(object sender, GeneralEventArgs e) + { + AfterEndGame?.Invoke(sender, e); + } + + public void OnSucceedEndGameEvent(object sender, GeneralEventArgs e) + { + SucceedEndGame?.Invoke(sender, e); + } + + public void OnFailedEndGameEvent(object sender, GeneralEventArgs e) + { + FailedEndGame?.Invoke(sender, e); + } + } +} diff --git a/Library/Common/Addon/WebAPIPlugin.cs b/Library/Common/Addon/WebAPIPlugin.cs new file mode 100644 index 0000000..0e6d7c2 --- /dev/null +++ b/Library/Common/Addon/WebAPIPlugin.cs @@ -0,0 +1,88 @@ +using Milimoe.FunGame.Core.Controller; +using Milimoe.FunGame.Core.Interface.Addons; + +namespace Milimoe.FunGame.Core.Library.Common.Addon +{ + public abstract class WebAPIPlugin : IAddon, IAddonController + { + /// + /// 插件名称 + /// + public abstract string Name { get; } + + /// + /// 插件描述 + /// + public abstract string Description { get; } + + /// + /// 插件版本 + /// + public abstract string Version { get; } + + /// + /// 插件作者 + /// + public abstract string Author { get; } + + /// + /// 包含了一些常用方法的控制器 + /// + public BaseAddonController Controller + { + get => _Controller ?? throw new NotImplementedException(); + set => _Controller = value; + } + + /// + /// 控制器内部变量 + /// + private BaseAddonController? _Controller; + + /// + /// 加载标记 + /// + private bool IsLoaded = false; + + /// + /// 加载插件 + /// + public bool Load(params object[] objs) + { + if (IsLoaded) + { + return false; + } + // BeforeLoad可以阻止加载此插件 + if (BeforeLoad(objs)) + { + // 插件加载后,不允许再次加载此插件 + IsLoaded = true; + } + return IsLoaded; + } + + /// + /// 接收服务器控制台的输入 + /// + /// + public abstract void ProcessInput(string input); + + /// + /// 插件完全加载后需要做的事 + /// + public virtual void AfterLoad(params object[] objs) + { + // override + } + + /// + /// 允许返回false来阻止加载此插件 + /// + /// + protected virtual bool BeforeLoad(params object[] objs) + { + return true; + } + } +} diff --git a/Library/Common/Network/SocketObject.cs b/Library/Common/Network/SocketObject.cs index aef6476..e5bd0ba 100644 --- a/Library/Common/Network/SocketObject.cs +++ b/Library/Common/Network/SocketObject.cs @@ -10,6 +10,8 @@ namespace Milimoe.FunGame.Core.Library.Common.Network public SocketMessageType SocketType { get; } = SocketMessageType.Unknown; public Guid Token { get; } = Guid.Empty; public object[] Parameters { get; } = []; + + [JsonIgnore] public int Length => Parameters.Length; // 从参数列表中获取指定索引的参数的Json字符串 @@ -27,11 +29,11 @@ namespace Milimoe.FunGame.Core.Library.Common.Network } [JsonConstructor] - public SocketObject(SocketMessageType type, Guid token, params object[] args) + public SocketObject(SocketMessageType socketType, Guid token, params object[] parameters) { - SocketType = type; + SocketType = socketType; Token = token; - if (args != null && args.Length > 0) Parameters = args; + if (parameters != null && parameters.Length > 0) Parameters = parameters; } /// diff --git a/Service/AddonManager.cs b/Service/AddonManager.cs index 21f453b..6dfef1e 100644 --- a/Service/AddonManager.cs +++ b/Service/AddonManager.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System; using System.Reflection; using Milimoe.FunGame.Core.Interface.Addons; using Milimoe.FunGame.Core.Library.Common.Addon; @@ -25,7 +25,7 @@ namespace Milimoe.FunGame.Core.Service /// /// /// - internal static Dictionary LoadPlugins(Dictionary plugins, Hashtable delegates, params object[] otherobjs) + internal static Dictionary LoadPlugins(Dictionary plugins, Dictionary delegates, params object[] otherobjs) { if (!Directory.Exists(ReflectionSet.PluginFolderPath)) return plugins; @@ -56,6 +56,82 @@ namespace Milimoe.FunGame.Core.Service return plugins; } + /// + /// 从plugins目录加载所有Server插件 + /// + /// + /// + /// + /// + internal static Dictionary LoadServerPlugins(Dictionary plugins, Dictionary delegates, params object[] otherobjs) + { + if (!Directory.Exists(ReflectionSet.PluginFolderPath)) return plugins; + + string[] dlls = Directory.GetFiles(ReflectionSet.PluginFolderPath, "*.dll"); + + foreach (string dll in dlls) + { + // 加载目录下所有的DLL + Assembly assembly = Assembly.LoadFrom(dll); + + foreach (Type type in assembly.GetTypes().AsEnumerable().Where(type => type.IsSubclassOf(typeof(ServerPlugin)))) + { + if (AddAddonInstances(type, plugins, (instance) => + { + if (instance.Load(otherobjs)) + { + instance.Controller = new(instance, delegates); + return true; + } + return false; + })) + { + AddDictionary(PluginFilePaths, assembly, dll); + } + } + } + + return plugins; + } + + /// + /// 从plugins目录加载所有WebAPI插件 + /// + /// + /// + /// + /// + internal static Dictionary LoadWebAPIPlugins(Dictionary plugins, Dictionary delegates, params object[] otherobjs) + { + if (!Directory.Exists(ReflectionSet.PluginFolderPath)) return plugins; + + string[] dlls = Directory.GetFiles(ReflectionSet.PluginFolderPath, "*.dll"); + + foreach (string dll in dlls) + { + // 加载目录下所有的DLL + Assembly assembly = Assembly.LoadFrom(dll); + + foreach (Type type in assembly.GetTypes().AsEnumerable().Where(type => type.IsSubclassOf(typeof(WebAPIPlugin)))) + { + if (AddAddonInstances(type, plugins, (instance) => + { + if (instance.Load(otherobjs)) + { + instance.Controller = new(instance, delegates); + return true; + } + return false; + })) + { + AddDictionary(PluginFilePaths, assembly, dll); + } + } + } + + return plugins; + } + /// /// 从modules目录加载所有模组 /// @@ -66,7 +142,7 @@ namespace Milimoe.FunGame.Core.Service /// /// /// - internal static Dictionary LoadGameModules(Dictionary modules, Dictionary characters, Dictionary skills, Dictionary items, Hashtable delegates, params object[] otherobjs) + internal static Dictionary LoadGameModules(Dictionary modules, Dictionary characters, Dictionary skills, Dictionary items, Dictionary delegates, params object[] otherobjs) { if (!Directory.Exists(ReflectionSet.GameModuleFolderPath)) return modules; @@ -125,7 +201,7 @@ namespace Milimoe.FunGame.Core.Service /// /// /// - internal static Dictionary LoadGameModulesForServer(Dictionary servers, Dictionary characters, Dictionary skills, Dictionary items, Hashtable delegates, params object[] otherobjs) + internal static Dictionary LoadGameModulesForServer(Dictionary servers, Dictionary characters, Dictionary skills, Dictionary items, Dictionary delegates, params object[] otherobjs) { if (!Directory.Exists(ReflectionSet.GameModuleFolderPath)) return servers; diff --git a/Service/JsonManager.cs b/Service/JsonManager.cs index a32c62e..429f5a4 100644 --- a/Service/JsonManager.cs +++ b/Service/JsonManager.cs @@ -16,6 +16,7 @@ namespace Milimoe.FunGame.Core.Service private readonly static JsonSerializerOptions GeneralOptions = new() { WriteIndented = true, + PropertyNameCaseInsensitive = true, Encoder = JavaScriptEncoder.Create(UnicodeRanges.All), ReferenceHandler = ReferenceHandler.IgnoreCycles, Converters = { new DateTimeConverter(), new DataTableConverter(), new DataSetConverter(), new UserConverter(), new RoomConverter(),