From 5c89bafffdc7bb925fadff4da19f9e267cd5d485 Mon Sep 17 00:00:00 2001 From: milimoe <110188673+milimoe@users.noreply.github.com> Date: Sat, 9 Dec 2023 01:40:46 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=8F=92=E4=BB=B6=E6=A8=A1?= =?UTF-8?q?=E7=BB=84=E7=B3=BB=E7=BB=9F=20(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 添加GameModeServer * Addon系列大修改 * RuntimeController添加发送结束游戏反馈的方法 * 将GamingMessageHandler返回值修改为Hashtable * 添加马甲方法,隐藏委托 * 更新AddonController注释 --------- Co-authored-by: yeziuku <53083103+yeziuku@users.noreply.github.com> Co-authored-by: yeziuku --- Api/Utility/GameModeLoader.cs | 70 ++++- Api/Utility/PluginLoader.cs | 14 +- Controller/AddonController.cs | 70 +++++ Controller/RunTimeController.cs | 20 ++ Docs/FunGame.Core.xml | 353 ++++++++++++++++++++++--- Interface/Base/IAddon.cs | 4 +- Interface/Base/IAddonController.cs | 9 + Interface/Base/IGameMode.cs | 6 +- Interface/Base/IGameModeServer.cs | 14 + Interface/Base/IPlugin.cs | 6 +- Interface/Base/IServerModel.cs | 63 ++++- Interface/Event/GamingEvents.cs | 16 +- Library/Common/Addon/GameMode.cs | 39 ++- Library/Common/Addon/GameModeServer.cs | 119 +++++++++ Library/Common/Addon/Plugin.cs | 37 ++- Library/Constant/TypeEnum.cs | 13 + Service/AddonManager.cs | 95 +++++-- 17 files changed, 832 insertions(+), 116 deletions(-) create mode 100644 Controller/AddonController.cs create mode 100644 Interface/Base/IAddonController.cs create mode 100644 Interface/Base/IGameModeServer.cs create mode 100644 Library/Common/Addon/GameModeServer.cs diff --git a/Api/Utility/GameModeLoader.cs b/Api/Utility/GameModeLoader.cs index aec5b31..3ccd0b1 100644 --- a/Api/Utility/GameModeLoader.cs +++ b/Api/Utility/GameModeLoader.cs @@ -1,15 +1,40 @@ using Milimoe.FunGame.Core.Entity; using Milimoe.FunGame.Core.Library.Common.Addon; +using Milimoe.FunGame.Core.Library.Constant; using Milimoe.FunGame.Core.Service; namespace Milimoe.FunGame.Core.Api.Utility { public class GameModeLoader { + /// + /// 适用于客户端的模组集 + /// public Dictionary Modes { get; } = []; + + /// + /// 适用于服务器的模组集 + /// + public Dictionary ServerModes { get; } = []; + + /// + /// 游戏地图集 + /// public Dictionary Maps { get; } = []; + + /// + /// 角色表 + /// public List Characters { get; } = []; + + /// + /// 技能表 + /// public List Skills { get; } = []; + + /// + /// 物品表 + /// public List Items { get; } = []; private GameModeLoader() @@ -17,14 +42,38 @@ namespace Milimoe.FunGame.Core.Api.Utility } - public static GameModeLoader LoadGameModes(params object[] objs) + /// + /// 传入 类型来创建指定端的模组读取器 + /// runtime = 时,仅读取 + /// runtime = 时,仅读取 + /// 都会读取 + /// + /// 传入 类型来创建指定端的模组读取器 + /// 用于构建 + /// 其他需要传入给插件初始化的对象 + /// + public static GameModeLoader LoadGameModes(FunGameInfo.FunGame runtime, Delegate[] delegates, params object[] otherobjs) { GameModeLoader loader = new(); - AddonManager.LoadGameModes(loader.Modes, loader.Characters, loader.Skills, loader.Items, objs); - AddonManager.LoadGameMaps(loader.Maps, objs); + if (runtime == FunGameInfo.FunGame.FunGame_Desktop) + { + AddonManager.LoadGameModes(loader.Modes, loader.Characters, loader.Skills, loader.Items, delegates, otherobjs); + AddonManager.LoadGameMaps(loader.Maps, otherobjs); + } + else if (runtime == FunGameInfo.FunGame.FunGame_Server) + { + AddonManager.LoadGameModesForServer(loader.ServerModes, loader.Characters, loader.Skills, loader.Items, delegates, otherobjs); + AddonManager.LoadGameMaps(loader.Maps, otherobjs); + } return loader; } + /// + /// 获取对应名称的模组实例 + /// 如果需要取得服务器模组的实例,请调用 + /// + /// + /// public GameMode this[string name] { get @@ -37,6 +86,21 @@ namespace Milimoe.FunGame.Core.Api.Utility } } + /// + /// 获取对应名称的服务器模组实例 + /// + /// + /// + public GameModeServer GetServerMode(string name) + { + return ServerModes[name]; + } + + /// + /// 获取对应名称的游戏地图 + /// + /// + /// public GameMap GetGameMap(string name) { return Maps[name]; diff --git a/Api/Utility/PluginLoader.cs b/Api/Utility/PluginLoader.cs index a211bcd..b13738e 100644 --- a/Api/Utility/PluginLoader.cs +++ b/Api/Utility/PluginLoader.cs @@ -6,6 +6,10 @@ namespace Milimoe.FunGame.Core.Api.Utility { public class PluginLoader { + /// + /// 已读取的插件列表 + /// key 是 + /// public Dictionary Plugins { get; } = []; private PluginLoader() @@ -13,10 +17,16 @@ namespace Milimoe.FunGame.Core.Api.Utility } - public static PluginLoader LoadPlugins(params object[] objs) + /// + /// 构建一个插件读取器并读取插件 + /// + /// 用于构建 + /// 其他需要传入给插件初始化的对象 + /// + public static PluginLoader LoadPlugins(Delegate[] delegates, params object[] otherobjs) { PluginLoader loader = new(); - AddonManager.LoadPlugins(loader.Plugins, objs); + AddonManager.LoadPlugins(loader.Plugins, delegates, otherobjs); return loader; } diff --git a/Controller/AddonController.cs b/Controller/AddonController.cs new file mode 100644 index 0000000..5021e50 --- /dev/null +++ b/Controller/AddonController.cs @@ -0,0 +1,70 @@ +using Milimoe.FunGame.Core.Api.Transmittal; +using Milimoe.FunGame.Core.Interface; +using Milimoe.FunGame.Core.Library.Constant; + +namespace Milimoe.FunGame.Core.Controller +{ + public class AddonController + { + private IAddon Addon { get; } + + /// + /// 输出系统消息 + /// + private Action MaskMethod_WriteLine { get; set; } = new(msg => Console.Write("\r" + msg + "\n\r> ")); + + /// + /// 基于本地已连接的Socket创建新的数据请求 + /// + private Func MaskMethod_NewDataRequest { get; set; } + + /// + /// 基于本地已连接的Socket创建长时间运行的数据请求 + /// + private Func MaskMethod_NewLongRunningDataRequest { get; set; } + + /// + /// 输出系统消息 + /// + /// + /// + public void WriteLine(string msg) => MaskMethod_WriteLine(msg); + + /// + /// 基于本地已连接的Socket创建新的数据请求 + /// 请勿在 中调用此方法 + /// + /// + /// + public DataRequest NewDataRequest(DataRequestType type) => MaskMethod_NewDataRequest(type); + + /// + /// 基于本地已连接的Socket创建长时间运行的数据请求 + /// 请勿在 中调用此方法 + /// + /// + /// + public DataRequest NewLongRunningDataRequest(DataRequestType type) => MaskMethod_NewLongRunningDataRequest(type); + + /// + /// 新建一个AddonController + /// + /// + /// + public AddonController(IAddon Addon, Delegate[] delegates) + { + this.Addon = Addon; + if (delegates.Length > 0) MaskMethod_WriteLine = (Action)delegates[0]; + if (delegates.Length > 1) MaskMethod_NewDataRequest = (Func)delegates[1]; + if (delegates.Length > 2) MaskMethod_NewLongRunningDataRequest = (Func)delegates[2]; + MaskMethod_NewDataRequest ??= new(DefaultNewDataRequest); + MaskMethod_NewLongRunningDataRequest ??= new(DefaultNewDataRequest); + } + + private DataRequest DefaultNewDataRequest(DataRequestType type) + { + if (Addon is IGameModeServer) throw new NotSupportedException("请勿在GameModeServer类中调用此方法"); + else throw new ConnectFailedException(); + } + } +} diff --git a/Controller/RunTimeController.cs b/Controller/RunTimeController.cs index 1357a52..baf9449 100644 --- a/Controller/RunTimeController.cs +++ b/Controller/RunTimeController.cs @@ -57,6 +57,26 @@ namespace Milimoe.FunGame.Core.Controller return result; } + + /// + /// 发送结束游戏反馈 + /// + /// + public bool EndGame() + { + bool result = false; + + try + { + result = _Socket?.Send(SocketMessageType.EndGame, "") == SocketResult.Success; + } + catch (Exception e) + { + WritelnSystemInfo(e.GetErrorInfo()); + } + + return result; + } /// /// 连接服务器 diff --git a/Docs/FunGame.Core.xml b/Docs/FunGame.Core.xml index 16a4b25..8cb4136 100644 --- a/Docs/FunGame.Core.xml +++ b/Docs/FunGame.Core.xml @@ -331,6 +331,70 @@ + + + 适用于客户端的模组集 + + + + + 适用于服务器的模组集 + + + + + 游戏地图集 + + + + + 角色表 + + + + + 技能表 + + + + + 物品表 + + + + + 传入 类型来创建指定端的模组读取器 + runtime = 时,仅读取 + runtime = 时,仅读取 + 都会读取 + + 传入 类型来创建指定端的模组读取器 + 用于构建 + 其他需要传入给插件初始化的对象 + + + + + 获取对应名称的模组实例 + 如果需要取得服务器模组的实例,请调用 + + + + + + + 获取对应名称的服务器模组实例 + + + + + + + 获取对应名称的游戏地图 + + + + 网络服务工具箱 @@ -698,6 +762,20 @@ Private JsonSerializerOptions + + + 已读取的插件列表 + key 是 + + + + + 构建一个插件读取器并读取插件 + + 用于构建 + 其他需要传入给插件初始化的对象 + + 单例表:表中的对象以类名作为Key保存,并以Key获取该对象,Key具有唯一约束 @@ -882,6 +960,51 @@ + + + 输出系统消息 + + + + + 基于本地已连接的Socket创建新的数据请求 + + + + + 基于本地已连接的Socket创建长时间运行的数据请求 + + + + + 输出系统消息 + + + + + + + 基于本地已连接的Socket创建新的数据请求 + 请勿在 中调用此方法 + + + + + + + 基于本地已连接的Socket创建长时间运行的数据请求 + 请勿在 中调用此方法 + + + + + + + 新建一个AddonController + + + + 此类实现服务器连接、断开连接、心跳检测、创建数据请求等功能 @@ -919,6 +1042,12 @@ + + + 发送结束游戏反馈 + + + 连接服务器 @@ -1138,6 +1267,70 @@ Key为赛季(long),每个key代表第key赛季,key = 0时为生涯数据。 + + + 服务器实例是否在运行 + + + + + 客户端的套接字实例 + + + + + 客户端的用户实例,在用户登录后有效 + + + + + 客户端的名称,默认是客户端的IP地址 + + + + + 客户端是否启动了开发者模式 + + + + + 向客户端发送消息 + + + + + + + + + 向客户端发送系统消息 + + + + + + + + + + 获取客户端的名称,通常未登录时显示为客户端的IP地址,登录后显示为账号名 + + + + + + 开始接收客户端消息 + 请勿在 中调用此方法 + + + + + + + 启动对客户端的监听 + 请勿在 中调用此方法 + + 窗体继承这些接口便能实现事件,或为插件预留。 @@ -1298,6 +1491,16 @@ 模组所使用的地图 + + + 包含了一些常用方法的控制器 + + + + + 控制器内部变量 + + 如模组有界面,请重写此方法 @@ -1332,21 +1535,6 @@ 传递委托以便让模组调用 - - - 输出系统消息 - - - - - 基于本地已连接的Socket创建新的数据请求 - - - - - 基于本地已连接的Socket创建长时间运行的数据请求 - - Session对象 @@ -1362,6 +1550,88 @@ 绑定事件。在后触发 + + + 模组名称 + + + + + 模组描述 + + + + + 模组版本 + + + + + 模组作者 + + + + + 默认地图 + + + + + 模组所使用的地图 + + + + + 包含了一些常用方法的控制器 + + + + + 控制器内部变量 + + + + + 启动服务器监听 请在此处实现服务器逻辑 + + + + + + + + + + + + 接收并处理GamingMessage + + 发送此消息的账号 + 消息类型 + 消息参数 + 底层会将哈希表中的数据发送给客户端 + + + + 加载标记 + + + + + 加载模组 + + + + + 模组加载后需要做的事 + + + + + 允许返回false来阻止加载此模组 + + + 模组名称 @@ -1428,6 +1698,16 @@ 插件作者 + + + 包含了一些常用方法的控制器 + + + + + 控制器内部变量 + + 加载标记 @@ -1454,21 +1734,6 @@ 传递委托以便让插件调用 - - - 输出系统消息 - - - - - 基于本地已连接的Socket创建新的数据请求 - - - - - 基于本地已连接的Socket创建长时间运行的数据请求 - - Session对象 @@ -2043,23 +2308,37 @@ 所处的房间 - + 从plugins目录加载所有插件 - + + - + 从gamemodes目录加载所有模组 - - - - + + + + + + + + + + 从gamemodes目录加载所有适用于服务器的模组 + + + + + + + diff --git a/Interface/Base/IAddon.cs b/Interface/Base/IAddon.cs index d27ab52..c612d24 100644 --- a/Interface/Base/IAddon.cs +++ b/Interface/Base/IAddon.cs @@ -1,4 +1,6 @@ -namespace Milimoe.FunGame.Core.Interface +using Milimoe.FunGame.Core.Controller; + +namespace Milimoe.FunGame.Core.Interface { public interface IAddon { diff --git a/Interface/Base/IAddonController.cs b/Interface/Base/IAddonController.cs new file mode 100644 index 0000000..1ac82bb --- /dev/null +++ b/Interface/Base/IAddonController.cs @@ -0,0 +1,9 @@ +using Milimoe.FunGame.Core.Controller; + +namespace Milimoe.FunGame.Core.Interface.Base +{ + public interface IAddonController + { + public AddonController Controller { get; set; } + } +} diff --git a/Interface/Base/IGameMode.cs b/Interface/Base/IGameMode.cs index 3d84e97..a6d0830 100644 --- a/Interface/Base/IGameMode.cs +++ b/Interface/Base/IGameMode.cs @@ -1,6 +1,8 @@ -namespace Milimoe.FunGame.Core.Interface +using Milimoe.FunGame.Core.Interface.Base; + +namespace Milimoe.FunGame.Core.Interface { - public interface IGameMode : IAddon, IGamingConnectEventHandler, IGamingDisconnectEventHandler, IGamingReconnectEventHandler, IGamingBanCharacterEventHandler, IGamingPickCharacterEventHandler, + public interface IGameMode : IAddon, IAddonController, IGamingConnectEventHandler, IGamingDisconnectEventHandler, IGamingReconnectEventHandler, IGamingBanCharacterEventHandler, IGamingPickCharacterEventHandler, IGamingRandomEventHandler, IGamingRoundEventHandler, IGamingLevelUpEventHandler, IGamingMoveEventHandler, IGamingAttackEventHandler, IGamingSkillEventHandler, IGamingItemEventHandler, IGamingMagicEventHandler, IGamingBuyEventHandler, IGamingSuperSkillEventHandler, IGamingPauseEventHandler, IGamingUnpauseEventHandler, IGamingSurrenderEventHandler, IGamingUpdateInfoEventHandler, IGamingPunishEventHandler { diff --git a/Interface/Base/IGameModeServer.cs b/Interface/Base/IGameModeServer.cs new file mode 100644 index 0000000..a2b6ca7 --- /dev/null +++ b/Interface/Base/IGameModeServer.cs @@ -0,0 +1,14 @@ +using System.Collections; +using Milimoe.FunGame.Core.Entity; +using Milimoe.FunGame.Core.Interface.Base; +using Milimoe.FunGame.Core.Library.Constant; + +namespace Milimoe.FunGame.Core.Interface +{ + public interface IGameModeServer : IAddon, IAddonController + { + public bool StartServer(string GameMode, Room Room, List Users, IServerModel RoomMasterServerModel, Dictionary OthersServerModel, params object[] args); + + public Hashtable GamingMessageHandler(string username, GamingType type, Hashtable data); + } +} diff --git a/Interface/Base/IPlugin.cs b/Interface/Base/IPlugin.cs index 415a436..658b657 100644 --- a/Interface/Base/IPlugin.cs +++ b/Interface/Base/IPlugin.cs @@ -1,6 +1,8 @@ -namespace Milimoe.FunGame.Core.Interface +using Milimoe.FunGame.Core.Interface.Base; + +namespace Milimoe.FunGame.Core.Interface { - public interface IPlugin : IAddon, IConnectEventHandler, IDisconnectEventHandler, ILoginEventHandler, ILogoutEventHandler, IRegEventHandler, IIntoRoomEventHandler, ISendTalkEventHandler, + public interface IPlugin : IAddon, IAddonController, IConnectEventHandler, IDisconnectEventHandler, ILoginEventHandler, ILogoutEventHandler, IRegEventHandler, IIntoRoomEventHandler, ISendTalkEventHandler, ICreateRoomEventHandler, IQuitRoomEventHandler, IChangeRoomSettingEventHandler, IStartMatchEventHandler, IStartGameEventHandler, IChangeProfileEventHandler, IChangeAccountSettingEventHandler, IOpenInventoryEventHandler, ISignInEventHandler, IOpenStoreEventHandler, IBuyItemEventHandler, IShowRankingEventHandler, IUseItemEventHandler, IEndGameEventHandler { diff --git a/Interface/Base/IServerModel.cs b/Interface/Base/IServerModel.cs index 6b59bb8..849cfdb 100644 --- a/Interface/Base/IServerModel.cs +++ b/Interface/Base/IServerModel.cs @@ -1,4 +1,5 @@ using Milimoe.FunGame.Core.Entity; +using Milimoe.FunGame.Core.Library.Common.Addon; using Milimoe.FunGame.Core.Library.Common.Network; using Milimoe.FunGame.Core.Library.Constant; @@ -6,14 +7,68 @@ namespace Milimoe.FunGame.Core.Interface.Base { public interface IServerModel { + /// + /// 服务器实例是否在运行 + /// public abstract bool Running { get; } + + /// + /// 客户端的套接字实例 + /// public abstract ClientSocket? Socket { get; } - public abstract Task? Task { get; } + + /// + /// 客户端的用户实例,在用户登录后有效 + /// public abstract User User { get; } + + /// + /// 客户端的名称,默认是客户端的IP地址 + /// public abstract string ClientName { get; } - public abstract bool Read(ClientSocket socket); - public abstract bool Send(ClientSocket socket, SocketMessageType type, params object[] objs); - public abstract void Start(); + /// + /// 客户端是否启动了开发者模式 + /// + public bool IsDebugMode { get; } + + /// + /// 向客户端发送消息 + /// + /// + /// + /// + /// + public bool Send(ClientSocket socket, SocketMessageType type, params object[] objs); + + /// + /// 向客户端发送系统消息 + /// + /// + /// + /// + /// + /// + public void SendSystemMessage(ShowMessageType showtype, string msg, string title, int autoclose, params string[] usernames); + + /// + /// 获取客户端的名称,通常未登录时显示为客户端的IP地址,登录后显示为账号名 + /// + /// + public string GetClientName(); + + /// + /// 开始接收客户端消息 + /// 请勿在 中调用此方法 + /// + /// + /// + public bool Read(ClientSocket socket); + + /// + /// 启动对客户端的监听 + /// 请勿在 中调用此方法 + /// + public void Start(); } } diff --git a/Interface/Event/GamingEvents.cs b/Interface/Event/GamingEvents.cs index 871ae84..8e4c074 100644 --- a/Interface/Event/GamingEvents.cs +++ b/Interface/Event/GamingEvents.cs @@ -52,14 +52,6 @@ namespace Milimoe.FunGame.Core.Interface public void FailedGamingRandomEvent(object sender, GamingEventArgs e, Hashtable data); } - public interface IGamingLevelUpEvent - { - public void BeforeGamingLevelUpEvent(object sender, GamingEventArgs e, Hashtable data); - public void AfterGamingLevelUpEvent(object sender, GamingEventArgs e, Hashtable data); - public void SucceedGamingLevelUpEvent(object sender, GamingEventArgs e, Hashtable data); - public void FailedGamingLevelUpEvent(object sender, GamingEventArgs e, Hashtable data); - } - public interface IGamingRoundEvent { public void BeforeGamingRoundEvent(object sender, GamingEventArgs e, Hashtable data); @@ -68,6 +60,14 @@ namespace Milimoe.FunGame.Core.Interface public void FailedGamingRoundEvent(object sender, GamingEventArgs e, Hashtable data); } + public interface IGamingLevelUpEvent + { + public void BeforeGamingLevelUpEvent(object sender, GamingEventArgs e, Hashtable data); + public void AfterGamingLevelUpEvent(object sender, GamingEventArgs e, Hashtable data); + public void SucceedGamingLevelUpEvent(object sender, GamingEventArgs e, Hashtable data); + public void FailedGamingLevelUpEvent(object sender, GamingEventArgs e, Hashtable data); + } + public interface IGamingMoveEvent { public void BeforeGamingMoveEvent(object sender, GamingEventArgs e, Hashtable data); diff --git a/Library/Common/Addon/GameMode.cs b/Library/Common/Addon/GameMode.cs index 7e1c199..73140d1 100644 --- a/Library/Common/Addon/GameMode.cs +++ b/Library/Common/Addon/GameMode.cs @@ -1,8 +1,7 @@ using System.Collections; -using Milimoe.FunGame.Core.Api.Transmittal; +using Milimoe.FunGame.Core.Controller; using Milimoe.FunGame.Core.Interface; using Milimoe.FunGame.Core.Library.Common.Event; -using Milimoe.FunGame.Core.Library.Constant; using Milimoe.FunGame.Core.Model; namespace Milimoe.FunGame.Core.Library.Common.Addon @@ -39,6 +38,20 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon /// public abstract string[] Maps { get; } + /// + /// 包含了一些常用方法的控制器 + /// + public AddonController Controller + { + get => _Controller ?? throw new NotImplementedException(); + set => _Controller = value; + } + + /// + /// 控制器内部变量 + /// + protected AddonController? _Controller; + /// /// 如模组有界面,请重写此方法 /// 此方法会在StartGame时调用 @@ -101,28 +114,10 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon /// private void Init(params object[] objs) { - if (objs.Length > 0) WritelnSystemInfo = (Action)objs[0]; - if (objs.Length > 1) NewDataRequest = (Func)objs[1]; - if (objs.Length > 2) NewLongRunningDataRequest = (Func)objs[2]; - if (objs.Length > 3) Session = (Session)objs[3]; - if (objs.Length > 4) Config = (FunGameConfig)objs[4]; + if (objs.Length > 0) Session = (Session)objs[0]; + if (objs.Length > 1) Config = (FunGameConfig)objs[1]; } - /// - /// 输出系统消息 - /// - protected Action WritelnSystemInfo = new(msg => Console.Write("\r" + msg + "\n\r> ")); - - /// - /// 基于本地已连接的Socket创建新的数据请求 - /// - protected Func NewDataRequest = new(type => throw new ConnectFailedException()); - - /// - /// 基于本地已连接的Socket创建长时间运行的数据请求 - /// - protected Func NewLongRunningDataRequest = new(type => throw new ConnectFailedException()); - /// /// Session对象 /// diff --git a/Library/Common/Addon/GameModeServer.cs b/Library/Common/Addon/GameModeServer.cs new file mode 100644 index 0000000..f7b57e1 --- /dev/null +++ b/Library/Common/Addon/GameModeServer.cs @@ -0,0 +1,119 @@ +using System.Collections; +using Milimoe.FunGame.Core.Controller; +using Milimoe.FunGame.Core.Entity; +using Milimoe.FunGame.Core.Interface; +using Milimoe.FunGame.Core.Interface.Base; +using Milimoe.FunGame.Core.Library.Constant; + +namespace Milimoe.FunGame.Core.Library.Common.Addon +{ + public abstract class GameModeServer : IGameModeServer + { + /// + /// 模组名称 + /// + public abstract string Name { get; } + + /// + /// 模组描述 + /// + public abstract string Description { get; } + + /// + /// 模组版本 + /// + public abstract string Version { get; } + + /// + /// 模组作者 + /// + public abstract string Author { get; } + + /// + /// 默认地图 + /// + public abstract string DefaultMap { get; } + + /// + /// 模组所使用的地图 + /// + public abstract string[] Maps { get; } + + /// + /// 包含了一些常用方法的控制器 + /// + public AddonController Controller + { + get => _Controller ?? throw new NotImplementedException(); + set => _Controller = value; + } + + /// + /// 控制器内部变量 + /// + protected AddonController? _Controller; + + /// + /// 启动服务器监听 请在此处实现服务器逻辑 + /// + /// + /// + /// + /// + /// + /// + /// + public abstract bool StartServer(string GameMode, Room Room, List Users, IServerModel RoomMasterServerModel, Dictionary OthersServerModel, params object[] Args); + + /// + /// 接收并处理GamingMessage + /// + /// 发送此消息的账号 + /// 消息类型 + /// 消息参数 + /// 底层会将哈希表中的数据发送给客户端 + public abstract Hashtable GamingMessageHandler(string username, GamingType type, Hashtable data); + + /// + /// 加载标记 + /// + private bool IsLoaded = false; + + /// + /// 加载模组 + /// + public bool Load(params object[] objs) + { + if (IsLoaded) + { + return false; + } + // BeforeLoad可以阻止加载此模组 + if (BeforeLoad()) + { + // 模组加载后,不允许再次加载此模组 + IsLoaded = true; + // 如果加载后需要执行代码,请重写AfterLoad方法 + AfterLoad(); + } + return IsLoaded; + } + + /// + /// 模组加载后需要做的事 + /// + protected virtual void AfterLoad() + { + // override + } + + /// + /// 允许返回false来阻止加载此模组 + /// + /// + protected virtual bool BeforeLoad() + { + return true; + } + } +} diff --git a/Library/Common/Addon/Plugin.cs b/Library/Common/Addon/Plugin.cs index ae189c1..1829e87 100644 --- a/Library/Common/Addon/Plugin.cs +++ b/Library/Common/Addon/Plugin.cs @@ -1,4 +1,5 @@ using Milimoe.FunGame.Core.Api.Transmittal; +using Milimoe.FunGame.Core.Controller; using Milimoe.FunGame.Core.Interface; using Milimoe.FunGame.Core.Library.Common.Event; using Milimoe.FunGame.Core.Library.Constant; @@ -28,6 +29,20 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon /// public abstract string Author { get; } + /// + /// 包含了一些常用方法的控制器 + /// + public AddonController Controller + { + get => _Controller ?? throw new NotImplementedException(); + set => _Controller = value; + } + + /// + /// 控制器内部变量 + /// + protected AddonController? _Controller; + /// /// 加载标记 /// @@ -79,28 +94,10 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon /// private void Init(params object[] objs) { - if (objs.Length > 0) WritelnSystemInfo = (Action)objs[0]; - if (objs.Length > 1) NewDataRequest = (Func)objs[1]; - if (objs.Length > 2) NewLongRunningDataRequest = (Func)objs[2]; - if (objs.Length > 3) Session = (Session)objs[3]; - if (objs.Length > 4) Config = (FunGameConfig)objs[4]; + if (objs.Length > 0) Session = (Session)objs[0]; + if (objs.Length > 1) Config = (FunGameConfig)objs[1]; } - /// - /// 输出系统消息 - /// - protected Action WritelnSystemInfo = new(msg => Console.Write("\r" + msg + "\n\r> ")); - - /// - /// 基于本地已连接的Socket创建新的数据请求 - /// - protected Func NewDataRequest = new(type => throw new ConnectFailedException()); - - /// - /// 基于本地已连接的Socket创建长时间运行的数据请求 - /// - protected Func NewLongRunningDataRequest = new(type => throw new ConnectFailedException()); - /// /// Session对象 /// diff --git a/Library/Constant/TypeEnum.cs b/Library/Constant/TypeEnum.cs index f74a027..2066da2 100644 --- a/Library/Constant/TypeEnum.cs +++ b/Library/Constant/TypeEnum.cs @@ -380,4 +380,17 @@ namespace Milimoe.FunGame.Core.Library.Constant Column, Username } + + public enum InvokeMessageType + { + None, + Core, + Error, + System, + Api, + Interface, + DataRequest, + Plugin, + GameMode + } } diff --git a/Service/AddonManager.cs b/Service/AddonManager.cs index 13fe8e8..75abb9b 100644 --- a/Service/AddonManager.cs +++ b/Service/AddonManager.cs @@ -11,9 +11,10 @@ namespace Milimoe.FunGame.Core.Service /// 从plugins目录加载所有插件 /// /// - /// + /// + /// /// - internal static Dictionary LoadPlugins(Dictionary plugins, params object[] objs) + internal static Dictionary LoadPlugins(Dictionary plugins, Delegate[] delegates, params object[] otherobjs) { if (!Directory.Exists(ReflectionSet.PluginFolderPath)) return plugins; @@ -28,8 +29,9 @@ namespace Milimoe.FunGame.Core.Service foreach (Type type in assembly.GetTypes().AsEnumerable().Where(type => type.IsSubclassOf(typeof(Plugin)))) { Plugin? instance = (Plugin?)Activator.CreateInstance(type); - if (instance != null && instance.Load(objs) && instance.Name.Trim() != "") + if (instance != null && instance.Load(otherobjs) && instance.Name.Trim() != "") { + instance.Controller = new(instance, delegates); plugins.TryAdd(instance.Name, instance); } } @@ -42,12 +44,13 @@ namespace Milimoe.FunGame.Core.Service /// 从gamemodes目录加载所有模组 /// /// - /// - /// - /// - /// + /// + /// + /// + /// + /// /// - internal static Dictionary LoadGameModes(Dictionary gamemodes, List Characters, List Skills, List Items, params object[] objs) + internal static Dictionary LoadGameModes(Dictionary gamemodes, List characters, List skills, List items, Delegate[] delegates, params object[] otherobjs) { if (!Directory.Exists(ReflectionSet.GameModeFolderPath)) return gamemodes; @@ -60,8 +63,9 @@ namespace Milimoe.FunGame.Core.Service foreach (Type type in assembly.GetTypes().AsEnumerable().Where(type => type.IsSubclassOf(typeof(GameMode)))) { GameMode? instance = (GameMode?)Activator.CreateInstance(type); - if (instance != null && instance.Load(objs) && instance.Name.Trim() != "") + if (instance != null && instance.Load(otherobjs) && instance.Name.Trim() != "") { + instance.Controller = new(instance, delegates); gamemodes.TryAdd(instance.Name, instance); } } @@ -69,27 +73,88 @@ namespace Milimoe.FunGame.Core.Service foreach (Type type in assembly.GetTypes().AsEnumerable().Where(type => type.IsSubclassOf(typeof(Character)))) { Character? instance = (Character?)Activator.CreateInstance(type); - if (instance != null && instance.Name.Trim() != "" && !Characters.Contains(instance)) + if (instance != null && instance.Name.Trim() != "" && !characters.Contains(instance)) { - Characters.Add(instance); + characters.Add(instance); } } foreach (Type type in assembly.GetTypes().AsEnumerable().Where(type => type.IsSubclassOf(typeof(Skill)))) { Skill? instance = (Skill?)Activator.CreateInstance(type); - if (instance != null && instance.Name.Trim() != "" && !Skills.Contains(instance)) + if (instance != null && instance.Name.Trim() != "" && !skills.Contains(instance)) { - Skills.Add(instance); + skills.Add(instance); } } foreach (Type type in assembly.GetTypes().AsEnumerable().Where(type => type.IsSubclassOf(typeof(Item)))) { Item? instance = (Item?)Activator.CreateInstance(type); - if (instance != null && instance.Name.Trim() != "" && !Items.Contains(instance)) + if (instance != null && instance.Name.Trim() != "" && !items.Contains(instance)) { - Items.Add(instance); + items.Add(instance); + } + } + } + + return gamemodes; + } + + /// + /// 从gamemodes目录加载所有适用于服务器的模组 + /// + /// + /// + /// + /// + /// + /// + /// + internal static Dictionary LoadGameModesForServer(Dictionary gamemodes, List characters, List skills, List items, Delegate[] delegates, params object[] otherobjs) + { + if (!Directory.Exists(ReflectionSet.GameModeFolderPath)) return gamemodes; + + string[] dlls = Directory.GetFiles(ReflectionSet.GameModeFolderPath, "*.dll"); + + foreach (string dll in dlls) + { + Assembly assembly = Assembly.LoadFrom(dll); + + foreach (Type type in assembly.GetTypes().AsEnumerable().Where(type => type.IsSubclassOf(typeof(GameModeServer)))) + { + GameModeServer? instance = (GameModeServer?)Activator.CreateInstance(type); + if (instance != null && instance.Load(otherobjs) && instance.Name.Trim() != "") + { + instance.Controller = new(instance, delegates); + gamemodes.TryAdd(instance.Name, instance); + } + } + + foreach (Type type in assembly.GetTypes().AsEnumerable().Where(type => type.IsSubclassOf(typeof(Character)))) + { + Character? instance = (Character?)Activator.CreateInstance(type); + if (instance != null && instance.Name.Trim() != "" && !characters.Contains(instance)) + { + characters.Add(instance); + } + } + + foreach (Type type in assembly.GetTypes().AsEnumerable().Where(type => type.IsSubclassOf(typeof(Skill)))) + { + Skill? instance = (Skill?)Activator.CreateInstance(type); + if (instance != null && instance.Name.Trim() != "" && !skills.Contains(instance)) + { + skills.Add(instance); + } + } + + foreach (Type type in assembly.GetTypes().AsEnumerable().Where(type => type.IsSubclassOf(typeof(Item)))) + { + Item? instance = (Item?)Activator.CreateInstance(type); + if (instance != null && instance.Name.Trim() != "" && !items.Contains(instance)) + { + items.Add(instance); } } }