完善插件模组系统 (#68)

* 添加GameModeServer

* Addon系列大修改

* RuntimeController添加发送结束游戏反馈的方法

* 将GamingMessageHandler返回值修改为Hashtable

* 添加马甲方法,隐藏委托

* 更新AddonController注释

---------

Co-authored-by: yeziuku <53083103+yeziuku@users.noreply.github.com>
Co-authored-by: yeziuku <yezi@wrss.org>
This commit is contained in:
milimoe 2023-12-09 01:40:46 +08:00 committed by GitHub
parent 0672d839bb
commit 5c89bafffd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 832 additions and 116 deletions

View File

@ -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
{
/// <summary>
/// 适用于客户端的模组集
/// </summary>
public Dictionary<string, GameMode> Modes { get; } = [];
/// <summary>
/// 适用于服务器的模组集
/// </summary>
public Dictionary<string, GameModeServer> ServerModes { get; } = [];
/// <summary>
/// 游戏地图集
/// </summary>
public Dictionary<string, GameMap> Maps { get; } = [];
/// <summary>
/// 角色表
/// </summary>
public List<Character> Characters { get; } = [];
/// <summary>
/// 技能表
/// </summary>
public List<Skill> Skills { get; } = [];
/// <summary>
/// 物品表
/// </summary>
public List<Item> Items { get; } = [];
private GameModeLoader()
@ -17,14 +42,38 @@ namespace Milimoe.FunGame.Core.Api.Utility
}
public static GameModeLoader LoadGameModes(params object[] objs)
/// <summary>
/// 传入 <see cref="FunGameInfo.FunGame"/> 类型来创建指定端的模组读取器
/// <para>runtime = <see cref="FunGameInfo.FunGame.FunGame_Desktop"/> 时,仅读取 <seealso cref="Modes"/></para>
/// <para>runtime = <see cref="FunGameInfo.FunGame.FunGame_Server"/> 时,仅读取 <seealso cref="ServerModes"/></para>
/// <seealso cref="Maps"/> 都会读取
/// </summary>
/// <param name="runtime">传入 <see cref="FunGameInfo.FunGame"/> 类型来创建指定端的模组读取器</param>
/// <param name="delegates">用于构建 <see cref="Controller.AddonController"/></param>
/// <param name="otherobjs">其他需要传入给插件初始化的对象</param>
/// <returns></returns>
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;
}
/// <summary>
/// 获取对应名称的模组实例
/// <para>如果需要取得服务器模组的实例,请调用 <see cref="GetServerMode"/></para>
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public GameMode this[string name]
{
get
@ -37,6 +86,21 @@ namespace Milimoe.FunGame.Core.Api.Utility
}
}
/// <summary>
/// 获取对应名称的服务器模组实例
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public GameModeServer GetServerMode(string name)
{
return ServerModes[name];
}
/// <summary>
/// 获取对应名称的游戏地图
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public GameMap GetGameMap(string name)
{
return Maps[name];

View File

@ -6,6 +6,10 @@ namespace Milimoe.FunGame.Core.Api.Utility
{
public class PluginLoader
{
/// <summary>
/// 已读取的插件列表
/// <para>key 是 <see cref="Plugin.Name"/></para>
/// </summary>
public Dictionary<string, Plugin> Plugins { get; } = [];
private PluginLoader()
@ -13,10 +17,16 @@ namespace Milimoe.FunGame.Core.Api.Utility
}
public static PluginLoader LoadPlugins(params object[] objs)
/// <summary>
/// 构建一个插件读取器并读取插件
/// </summary>
/// <param name="delegates">用于构建 <see cref="Controller.AddonController"/></param>
/// <param name="otherobjs">其他需要传入给插件初始化的对象</param>
/// <returns></returns>
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;
}

View File

@ -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; }
/// <summary>
/// 输出系统消息
/// </summary>
private Action<string> MaskMethod_WriteLine { get; set; } = new(msg => Console.Write("\r" + msg + "\n\r> "));
/// <summary>
/// 基于本地已连接的Socket创建新的数据请求
/// </summary>
private Func<DataRequestType, DataRequest> MaskMethod_NewDataRequest { get; set; }
/// <summary>
/// 基于本地已连接的Socket创建长时间运行的数据请求
/// </summary>
private Func<DataRequestType, DataRequest> MaskMethod_NewLongRunningDataRequest { get; set; }
/// <summary>
/// 输出系统消息
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
public void WriteLine(string msg) => MaskMethod_WriteLine(msg);
/// <summary>
/// 基于本地已连接的Socket创建新的数据请求
/// <para>请勿在 <see cref="Library.Common.Addon.GameModeServer"/> 中调用此方法</para>
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public DataRequest NewDataRequest(DataRequestType type) => MaskMethod_NewDataRequest(type);
/// <summary>
/// 基于本地已连接的Socket创建长时间运行的数据请求
/// <para>请勿在 <see cref="Library.Common.Addon.GameModeServer"/> 中调用此方法</para>
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public DataRequest NewLongRunningDataRequest(DataRequestType type) => MaskMethod_NewLongRunningDataRequest(type);
/// <summary>
/// 新建一个AddonController
/// </summary>
/// <param name="Addon"></param>
/// <param name="delegates"></param>
public AddonController(IAddon Addon, Delegate[] delegates)
{
this.Addon = Addon;
if (delegates.Length > 0) MaskMethod_WriteLine = (Action<string>)delegates[0];
if (delegates.Length > 1) MaskMethod_NewDataRequest = (Func<DataRequestType, DataRequest>)delegates[1];
if (delegates.Length > 2) MaskMethod_NewLongRunningDataRequest = (Func<DataRequestType, DataRequest>)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();
}
}
}

View File

@ -58,6 +58,26 @@ namespace Milimoe.FunGame.Core.Controller
return result;
}
/// <summary>
/// 发送结束游戏反馈
/// </summary>
/// <returns></returns>
public bool EndGame()
{
bool result = false;
try
{
result = _Socket?.Send(SocketMessageType.EndGame, "") == SocketResult.Success;
}
catch (Exception e)
{
WritelnSystemInfo(e.GetErrorInfo());
}
return result;
}
/// <summary>
/// 连接服务器
/// </summary>

View File

@ -331,6 +331,70 @@
<param name="dr"></param>
<returns></returns>
</member>
<member name="P:Milimoe.FunGame.Core.Api.Utility.GameModeLoader.Modes">
<summary>
适用于客户端的模组集
</summary>
</member>
<member name="P:Milimoe.FunGame.Core.Api.Utility.GameModeLoader.ServerModes">
<summary>
适用于服务器的模组集
</summary>
</member>
<member name="P:Milimoe.FunGame.Core.Api.Utility.GameModeLoader.Maps">
<summary>
游戏地图集
</summary>
</member>
<member name="P:Milimoe.FunGame.Core.Api.Utility.GameModeLoader.Characters">
<summary>
角色表
</summary>
</member>
<member name="P:Milimoe.FunGame.Core.Api.Utility.GameModeLoader.Skills">
<summary>
技能表
</summary>
</member>
<member name="P:Milimoe.FunGame.Core.Api.Utility.GameModeLoader.Items">
<summary>
物品表
</summary>
</member>
<member name="M:Milimoe.FunGame.Core.Api.Utility.GameModeLoader.LoadGameModes(Milimoe.FunGame.Core.Library.Constant.FunGameInfo.FunGame,System.Delegate[],System.Object[])">
<summary>
传入 <see cref="T:Milimoe.FunGame.Core.Library.Constant.FunGameInfo.FunGame"/> 类型来创建指定端的模组读取器
<para>runtime = <see cref="F:Milimoe.FunGame.Core.Library.Constant.FunGameInfo.FunGame.FunGame_Desktop"/> 时,仅读取 <seealso cref="P:Milimoe.FunGame.Core.Api.Utility.GameModeLoader.Modes"/></para>
<para>runtime = <see cref="F:Milimoe.FunGame.Core.Library.Constant.FunGameInfo.FunGame.FunGame_Server"/> 时,仅读取 <seealso cref="P:Milimoe.FunGame.Core.Api.Utility.GameModeLoader.ServerModes"/></para>
<seealso cref="P:Milimoe.FunGame.Core.Api.Utility.GameModeLoader.Maps"/> 都会读取
</summary>
<param name="runtime">传入 <see cref="T:Milimoe.FunGame.Core.Library.Constant.FunGameInfo.FunGame"/> 类型来创建指定端的模组读取器</param>
<param name="delegates">用于构建 <see cref="T:Milimoe.FunGame.Core.Controller.AddonController"/></param>
<param name="otherobjs">其他需要传入给插件初始化的对象</param>
<returns></returns>
</member>
<member name="P:Milimoe.FunGame.Core.Api.Utility.GameModeLoader.Item(System.String)">
<summary>
获取对应名称的模组实例
<para>如果需要取得服务器模组的实例,请调用 <see cref="M:Milimoe.FunGame.Core.Api.Utility.GameModeLoader.GetServerMode(System.String)"/></para>
</summary>
<param name="name"></param>
<returns></returns>
</member>
<member name="M:Milimoe.FunGame.Core.Api.Utility.GameModeLoader.GetServerMode(System.String)">
<summary>
获取对应名称的服务器模组实例
</summary>
<param name="name"></param>
<returns></returns>
</member>
<member name="M:Milimoe.FunGame.Core.Api.Utility.GameModeLoader.GetGameMap(System.String)">
<summary>
获取对应名称的游戏地图
</summary>
<param name="name"></param>
<returns></returns>
</member>
<member name="T:Milimoe.FunGame.Core.Api.Utility.NetworkUtility">
<summary>
网络服务工具箱
@ -698,6 +762,20 @@
Private JsonSerializerOptions
</summary>
</member>
<member name="P:Milimoe.FunGame.Core.Api.Utility.PluginLoader.Plugins">
<summary>
已读取的插件列表
<para>key 是 <see cref="P:Milimoe.FunGame.Core.Library.Common.Addon.Plugin.Name"/></para>
</summary>
</member>
<member name="M:Milimoe.FunGame.Core.Api.Utility.PluginLoader.LoadPlugins(System.Delegate[],System.Object[])">
<summary>
构建一个插件读取器并读取插件
</summary>
<param name="delegates">用于构建 <see cref="T:Milimoe.FunGame.Core.Controller.AddonController"/></param>
<param name="otherobjs">其他需要传入给插件初始化的对象</param>
<returns></returns>
</member>
<member name="T:Milimoe.FunGame.Core.Api.Utility.Singleton">
<summary>
单例表表中的对象以类名作为Key保存并以Key获取该对象Key具有唯一约束
@ -882,6 +960,51 @@
<param name="strs"></param>
<returns></returns>
</member>
<member name="P:Milimoe.FunGame.Core.Controller.AddonController.MaskMethod_WriteLine">
<summary>
输出系统消息
</summary>
</member>
<member name="P:Milimoe.FunGame.Core.Controller.AddonController.MaskMethod_NewDataRequest">
<summary>
基于本地已连接的Socket创建新的数据请求
</summary>
</member>
<member name="P:Milimoe.FunGame.Core.Controller.AddonController.MaskMethod_NewLongRunningDataRequest">
<summary>
基于本地已连接的Socket创建长时间运行的数据请求
</summary>
</member>
<member name="M:Milimoe.FunGame.Core.Controller.AddonController.WriteLine(System.String)">
<summary>
输出系统消息
</summary>
<param name="msg"></param>
<returns></returns>
</member>
<member name="M:Milimoe.FunGame.Core.Controller.AddonController.NewDataRequest(Milimoe.FunGame.Core.Library.Constant.DataRequestType)">
<summary>
基于本地已连接的Socket创建新的数据请求
<para>请勿在 <see cref="T:Milimoe.FunGame.Core.Library.Common.Addon.GameModeServer"/> 中调用此方法</para>
</summary>
<param name="type"></param>
<returns></returns>
</member>
<member name="M:Milimoe.FunGame.Core.Controller.AddonController.NewLongRunningDataRequest(Milimoe.FunGame.Core.Library.Constant.DataRequestType)">
<summary>
基于本地已连接的Socket创建长时间运行的数据请求
<para>请勿在 <see cref="T:Milimoe.FunGame.Core.Library.Common.Addon.GameModeServer"/> 中调用此方法</para>
</summary>
<param name="type"></param>
<returns></returns>
</member>
<member name="M:Milimoe.FunGame.Core.Controller.AddonController.#ctor(Milimoe.FunGame.Core.Interface.IAddon,System.Delegate[])">
<summary>
新建一个AddonController
</summary>
<param name="Addon"></param>
<param name="delegates"></param>
</member>
<member name="T:Milimoe.FunGame.Core.Controller.RunTimeController">
<summary>
此类实现服务器连接、断开连接、心跳检测、创建数据请求等功能
@ -919,6 +1042,12 @@
</summary>
<returns></returns>
</member>
<member name="M:Milimoe.FunGame.Core.Controller.RunTimeController.EndGame">
<summary>
发送结束游戏反馈
</summary>
<returns></returns>
</member>
<member name="M:Milimoe.FunGame.Core.Controller.RunTimeController.Connect(System.String,System.Int32)">
<summary>
连接服务器
@ -1138,6 +1267,70 @@
Key为赛季(long)每个key代表第key赛季key = 0时为生涯数据。
</summary>
</member>
<member name="P:Milimoe.FunGame.Core.Interface.Base.IServerModel.Running">
<summary>
服务器实例是否在运行
</summary>
</member>
<member name="P:Milimoe.FunGame.Core.Interface.Base.IServerModel.Socket">
<summary>
客户端的套接字实例
</summary>
</member>
<member name="P:Milimoe.FunGame.Core.Interface.Base.IServerModel.User">
<summary>
客户端的用户实例,在用户登录后有效
</summary>
</member>
<member name="P:Milimoe.FunGame.Core.Interface.Base.IServerModel.ClientName">
<summary>
客户端的名称默认是客户端的IP地址
</summary>
</member>
<member name="P:Milimoe.FunGame.Core.Interface.Base.IServerModel.IsDebugMode">
<summary>
客户端是否启动了开发者模式
</summary>
</member>
<member name="M:Milimoe.FunGame.Core.Interface.Base.IServerModel.Send(Milimoe.FunGame.Core.Library.Common.Network.ClientSocket,Milimoe.FunGame.Core.Library.Constant.SocketMessageType,System.Object[])">
<summary>
向客户端发送消息
</summary>
<param name="socket"></param>
<param name="type"></param>
<param name="objs"></param>
<returns></returns>
</member>
<member name="M:Milimoe.FunGame.Core.Interface.Base.IServerModel.SendSystemMessage(Milimoe.FunGame.Core.Library.Constant.ShowMessageType,System.String,System.String,System.Int32,System.String[])">
<summary>
向客户端发送系统消息
</summary>
<param name="showtype"></param>
<param name="msg"></param>
<param name="title"></param>
<param name="autoclose"></param>
<param name="usernames"></param>
</member>
<member name="M:Milimoe.FunGame.Core.Interface.Base.IServerModel.GetClientName">
<summary>
获取客户端的名称通常未登录时显示为客户端的IP地址登录后显示为账号名
</summary>
<returns></returns>
</member>
<member name="M:Milimoe.FunGame.Core.Interface.Base.IServerModel.Read(Milimoe.FunGame.Core.Library.Common.Network.ClientSocket)">
<summary>
开始接收客户端消息
<para>请勿在 <see cref="T:Milimoe.FunGame.Core.Library.Common.Addon.GameModeServer"/> 中调用此方法</para>
</summary>
<param name="socket"></param>
<returns></returns>
</member>
<member name="M:Milimoe.FunGame.Core.Interface.Base.IServerModel.Start">
<summary>
启动对客户端的监听
<para>请勿在 <see cref="T:Milimoe.FunGame.Core.Library.Common.Addon.GameModeServer"/> 中调用此方法</para>
</summary>
</member>
<member name="T:Milimoe.FunGame.Core.Interface.IEventHandler">
<summary>
窗体继承这些接口便能实现事件,或为插件预留。
@ -1298,6 +1491,16 @@
模组所使用的地图
</summary>
</member>
<member name="P:Milimoe.FunGame.Core.Library.Common.Addon.GameMode.Controller">
<summary>
包含了一些常用方法的控制器
</summary>
</member>
<member name="F:Milimoe.FunGame.Core.Library.Common.Addon.GameMode._Controller">
<summary>
控制器内部变量
</summary>
</member>
<member name="M:Milimoe.FunGame.Core.Library.Common.Addon.GameMode.StartUI(System.Object[])">
<summary>
如模组有界面,请重写此方法
@ -1332,21 +1535,6 @@
传递委托以便让模组调用
</summary>
</member>
<member name="F:Milimoe.FunGame.Core.Library.Common.Addon.GameMode.WritelnSystemInfo">
<summary>
输出系统消息
</summary>
</member>
<member name="F:Milimoe.FunGame.Core.Library.Common.Addon.GameMode.NewDataRequest">
<summary>
基于本地已连接的Socket创建新的数据请求
</summary>
</member>
<member name="F:Milimoe.FunGame.Core.Library.Common.Addon.GameMode.NewLongRunningDataRequest">
<summary>
基于本地已连接的Socket创建长时间运行的数据请求
</summary>
</member>
<member name="F:Milimoe.FunGame.Core.Library.Common.Addon.GameMode.Session">
<summary>
Session对象
@ -1362,6 +1550,88 @@
绑定事件。在<see cref="M:Milimoe.FunGame.Core.Library.Common.Addon.GameMode.BeforeLoad"/>后触发
</summary>
</member>
<member name="P:Milimoe.FunGame.Core.Library.Common.Addon.GameModeServer.Name">
<summary>
模组名称
</summary>
</member>
<member name="P:Milimoe.FunGame.Core.Library.Common.Addon.GameModeServer.Description">
<summary>
模组描述
</summary>
</member>
<member name="P:Milimoe.FunGame.Core.Library.Common.Addon.GameModeServer.Version">
<summary>
模组版本
</summary>
</member>
<member name="P:Milimoe.FunGame.Core.Library.Common.Addon.GameModeServer.Author">
<summary>
模组作者
</summary>
</member>
<member name="P:Milimoe.FunGame.Core.Library.Common.Addon.GameModeServer.DefaultMap">
<summary>
默认地图
</summary>
</member>
<member name="P:Milimoe.FunGame.Core.Library.Common.Addon.GameModeServer.Maps">
<summary>
模组所使用的地图
</summary>
</member>
<member name="P:Milimoe.FunGame.Core.Library.Common.Addon.GameModeServer.Controller">
<summary>
包含了一些常用方法的控制器
</summary>
</member>
<member name="F:Milimoe.FunGame.Core.Library.Common.Addon.GameModeServer._Controller">
<summary>
控制器内部变量
</summary>
</member>
<member name="M:Milimoe.FunGame.Core.Library.Common.Addon.GameModeServer.StartServer(System.String,Milimoe.FunGame.Core.Entity.Room,System.Collections.Generic.List{Milimoe.FunGame.Core.Entity.User},Milimoe.FunGame.Core.Interface.Base.IServerModel,System.Collections.Generic.Dictionary{System.String,Milimoe.FunGame.Core.Interface.Base.IServerModel},System.Object[])">
<summary>
启动服务器监听 请在此处实现服务器逻辑
</summary>
<param name="GameMode"></param>
<param name="Room"></param>
<param name="Users"></param>
<param name="RoomMasterServerModel"></param>
<param name="OthersServerModel"></param>
<param name="Args"></param>
<returns></returns>
</member>
<member name="M:Milimoe.FunGame.Core.Library.Common.Addon.GameModeServer.GamingMessageHandler(System.String,Milimoe.FunGame.Core.Library.Constant.GamingType,System.Collections.Hashtable)">
<summary>
接收并处理GamingMessage
</summary>
<param name="username">发送此消息的账号</param>
<param name="type">消息类型</param>
<param name="data">消息参数</param>
<returns>底层会将哈希表中的数据发送给客户端</returns>
</member>
<member name="F:Milimoe.FunGame.Core.Library.Common.Addon.GameModeServer.IsLoaded">
<summary>
加载标记
</summary>
</member>
<member name="M:Milimoe.FunGame.Core.Library.Common.Addon.GameModeServer.Load(System.Object[])">
<summary>
加载模组
</summary>
</member>
<member name="M:Milimoe.FunGame.Core.Library.Common.Addon.GameModeServer.AfterLoad">
<summary>
模组加载后需要做的事
</summary>
</member>
<member name="M:Milimoe.FunGame.Core.Library.Common.Addon.GameModeServer.BeforeLoad">
<summary>
允许返回false来阻止加载此模组
</summary>
<returns></returns>
</member>
<member name="P:Milimoe.FunGame.Core.Library.Common.Addon.ItemMode.Name">
<summary>
模组名称
@ -1428,6 +1698,16 @@
插件作者
</summary>
</member>
<member name="P:Milimoe.FunGame.Core.Library.Common.Addon.Plugin.Controller">
<summary>
包含了一些常用方法的控制器
</summary>
</member>
<member name="F:Milimoe.FunGame.Core.Library.Common.Addon.Plugin._Controller">
<summary>
控制器内部变量
</summary>
</member>
<member name="F:Milimoe.FunGame.Core.Library.Common.Addon.Plugin.IsLoaded">
<summary>
加载标记
@ -1454,21 +1734,6 @@
传递委托以便让插件调用
</summary>
</member>
<member name="F:Milimoe.FunGame.Core.Library.Common.Addon.Plugin.WritelnSystemInfo">
<summary>
输出系统消息
</summary>
</member>
<member name="F:Milimoe.FunGame.Core.Library.Common.Addon.Plugin.NewDataRequest">
<summary>
基于本地已连接的Socket创建新的数据请求
</summary>
</member>
<member name="F:Milimoe.FunGame.Core.Library.Common.Addon.Plugin.NewLongRunningDataRequest">
<summary>
基于本地已连接的Socket创建长时间运行的数据请求
</summary>
</member>
<member name="F:Milimoe.FunGame.Core.Library.Common.Addon.Plugin.Session">
<summary>
Session对象
@ -2043,23 +2308,37 @@
所处的房间
</summary>
</member>
<member name="M:Milimoe.FunGame.Core.Service.AddonManager.LoadPlugins(System.Collections.Generic.Dictionary{System.String,Milimoe.FunGame.Core.Library.Common.Addon.Plugin},System.Object[])">
<member name="M:Milimoe.FunGame.Core.Service.AddonManager.LoadPlugins(System.Collections.Generic.Dictionary{System.String,Milimoe.FunGame.Core.Library.Common.Addon.Plugin},System.Delegate[],System.Object[])">
<summary>
从plugins目录加载所有插件
</summary>
<param name="plugins"></param>
<param name="objs"></param>
<param name="delegates"></param>
<param name="otherobjs"></param>
<returns></returns>
</member>
<member name="M:Milimoe.FunGame.Core.Service.AddonManager.LoadGameModes(System.Collections.Generic.Dictionary{System.String,Milimoe.FunGame.Core.Library.Common.Addon.GameMode},System.Collections.Generic.List{Milimoe.FunGame.Core.Entity.Character},System.Collections.Generic.List{Milimoe.FunGame.Core.Entity.Skill},System.Collections.Generic.List{Milimoe.FunGame.Core.Entity.Item},System.Object[])">
<member name="M:Milimoe.FunGame.Core.Service.AddonManager.LoadGameModes(System.Collections.Generic.Dictionary{System.String,Milimoe.FunGame.Core.Library.Common.Addon.GameMode},System.Collections.Generic.List{Milimoe.FunGame.Core.Entity.Character},System.Collections.Generic.List{Milimoe.FunGame.Core.Entity.Skill},System.Collections.Generic.List{Milimoe.FunGame.Core.Entity.Item},System.Delegate[],System.Object[])">
<summary>
从gamemodes目录加载所有模组
</summary>
<param name="gamemodes"></param>
<param name="Characters"></param>
<param name="Skills"></param>
<param name="Items"></param>
<param name="objs"></param>
<param name="characters"></param>
<param name="skills"></param>
<param name="items"></param>
<param name="delegates"></param>
<param name="otherobjs"></param>
<returns></returns>
</member>
<member name="M:Milimoe.FunGame.Core.Service.AddonManager.LoadGameModesForServer(System.Collections.Generic.Dictionary{System.String,Milimoe.FunGame.Core.Library.Common.Addon.GameModeServer},System.Collections.Generic.List{Milimoe.FunGame.Core.Entity.Character},System.Collections.Generic.List{Milimoe.FunGame.Core.Entity.Skill},System.Collections.Generic.List{Milimoe.FunGame.Core.Entity.Item},System.Delegate[],System.Object[])">
<summary>
从gamemodes目录加载所有适用于服务器的模组
</summary>
<param name="gamemodes"></param>
<param name="characters"></param>
<param name="skills"></param>
<param name="items"></param>
<param name="delegates"></param>
<param name="otherobjs"></param>
<returns></returns>
</member>
<member name="M:Milimoe.FunGame.Core.Service.AddonManager.LoadGameMaps(System.Collections.Generic.Dictionary{System.String,Milimoe.FunGame.Core.Library.Common.Addon.GameMap},System.Object[])">

View File

@ -1,4 +1,6 @@
namespace Milimoe.FunGame.Core.Interface
using Milimoe.FunGame.Core.Controller;
namespace Milimoe.FunGame.Core.Interface
{
public interface IAddon
{

View File

@ -0,0 +1,9 @@
using Milimoe.FunGame.Core.Controller;
namespace Milimoe.FunGame.Core.Interface.Base
{
public interface IAddonController
{
public AddonController Controller { get; set; }
}
}

View File

@ -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
{

View File

@ -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<User> Users, IServerModel RoomMasterServerModel, Dictionary<string, IServerModel> OthersServerModel, params object[] args);
public Hashtable GamingMessageHandler(string username, GamingType type, Hashtable data);
}
}

View File

@ -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
{

View File

@ -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
{
/// <summary>
/// 服务器实例是否在运行
/// </summary>
public abstract bool Running { get; }
/// <summary>
/// 客户端的套接字实例
/// </summary>
public abstract ClientSocket? Socket { get; }
public abstract Task? Task { get; }
/// <summary>
/// 客户端的用户实例,在用户登录后有效
/// </summary>
public abstract User User { get; }
/// <summary>
/// 客户端的名称默认是客户端的IP地址
/// </summary>
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();
/// <summary>
/// 客户端是否启动了开发者模式
/// </summary>
public bool IsDebugMode { get; }
/// <summary>
/// 向客户端发送消息
/// </summary>
/// <param name="socket"></param>
/// <param name="type"></param>
/// <param name="objs"></param>
/// <returns></returns>
public bool Send(ClientSocket socket, SocketMessageType type, params object[] objs);
/// <summary>
/// 向客户端发送系统消息
/// </summary>
/// <param name="showtype"></param>
/// <param name="msg"></param>
/// <param name="title"></param>
/// <param name="autoclose"></param>
/// <param name="usernames"></param>
public void SendSystemMessage(ShowMessageType showtype, string msg, string title, int autoclose, params string[] usernames);
/// <summary>
/// 获取客户端的名称通常未登录时显示为客户端的IP地址登录后显示为账号名
/// </summary>
/// <returns></returns>
public string GetClientName();
/// <summary>
/// 开始接收客户端消息
/// <para>请勿在 <see cref="GameModeServer"/> 中调用此方法</para>
/// </summary>
/// <param name="socket"></param>
/// <returns></returns>
public bool Read(ClientSocket socket);
/// <summary>
/// 启动对客户端的监听
/// <para>请勿在 <see cref="GameModeServer"/> 中调用此方法</para>
/// </summary>
public void Start();
}
}

View File

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

View File

@ -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
/// </summary>
public abstract string[] Maps { get; }
/// <summary>
/// 包含了一些常用方法的控制器
/// </summary>
public AddonController Controller
{
get => _Controller ?? throw new NotImplementedException();
set => _Controller = value;
}
/// <summary>
/// 控制器内部变量
/// </summary>
protected AddonController? _Controller;
/// <summary>
/// 如模组有界面,请重写此方法
/// 此方法会在StartGame时调用
@ -101,28 +114,10 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon
/// </summary>
private void Init(params object[] objs)
{
if (objs.Length > 0) WritelnSystemInfo = (Action<string>)objs[0];
if (objs.Length > 1) NewDataRequest = (Func<DataRequestType, DataRequest>)objs[1];
if (objs.Length > 2) NewLongRunningDataRequest = (Func<DataRequestType, DataRequest>)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];
}
/// <summary>
/// 输出系统消息
/// </summary>
protected Action<string> WritelnSystemInfo = new(msg => Console.Write("\r" + msg + "\n\r> "));
/// <summary>
/// 基于本地已连接的Socket创建新的数据请求
/// </summary>
protected Func<DataRequestType, DataRequest> NewDataRequest = new(type => throw new ConnectFailedException());
/// <summary>
/// 基于本地已连接的Socket创建长时间运行的数据请求
/// </summary>
protected Func<DataRequestType, DataRequest> NewLongRunningDataRequest = new(type => throw new ConnectFailedException());
/// <summary>
/// Session对象
/// </summary>

View File

@ -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
{
/// <summary>
/// 模组名称
/// </summary>
public abstract string Name { get; }
/// <summary>
/// 模组描述
/// </summary>
public abstract string Description { get; }
/// <summary>
/// 模组版本
/// </summary>
public abstract string Version { get; }
/// <summary>
/// 模组作者
/// </summary>
public abstract string Author { get; }
/// <summary>
/// 默认地图
/// </summary>
public abstract string DefaultMap { get; }
/// <summary>
/// 模组所使用的地图
/// </summary>
public abstract string[] Maps { get; }
/// <summary>
/// 包含了一些常用方法的控制器
/// </summary>
public AddonController Controller
{
get => _Controller ?? throw new NotImplementedException();
set => _Controller = value;
}
/// <summary>
/// 控制器内部变量
/// </summary>
protected AddonController? _Controller;
/// <summary>
/// 启动服务器监听 请在此处实现服务器逻辑
/// </summary>
/// <param name="GameMode"></param>
/// <param name="Room"></param>
/// <param name="Users"></param>
/// <param name="RoomMasterServerModel"></param>
/// <param name="OthersServerModel"></param>
/// <param name="Args"></param>
/// <returns></returns>
public abstract bool StartServer(string GameMode, Room Room, List<User> Users, IServerModel RoomMasterServerModel, Dictionary<string, IServerModel> OthersServerModel, params object[] Args);
/// <summary>
/// 接收并处理GamingMessage
/// </summary>
/// <param name="username">发送此消息的账号</param>
/// <param name="type">消息类型</param>
/// <param name="data">消息参数</param>
/// <returns>底层会将哈希表中的数据发送给客户端</returns>
public abstract Hashtable GamingMessageHandler(string username, GamingType type, Hashtable data);
/// <summary>
/// 加载标记
/// </summary>
private bool IsLoaded = false;
/// <summary>
/// 加载模组
/// </summary>
public bool Load(params object[] objs)
{
if (IsLoaded)
{
return false;
}
// BeforeLoad可以阻止加载此模组
if (BeforeLoad())
{
// 模组加载后,不允许再次加载此模组
IsLoaded = true;
// 如果加载后需要执行代码请重写AfterLoad方法
AfterLoad();
}
return IsLoaded;
}
/// <summary>
/// 模组加载后需要做的事
/// </summary>
protected virtual void AfterLoad()
{
// override
}
/// <summary>
/// 允许返回false来阻止加载此模组
/// </summary>
/// <returns></returns>
protected virtual bool BeforeLoad()
{
return true;
}
}
}

View File

@ -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
/// </summary>
public abstract string Author { get; }
/// <summary>
/// 包含了一些常用方法的控制器
/// </summary>
public AddonController Controller
{
get => _Controller ?? throw new NotImplementedException();
set => _Controller = value;
}
/// <summary>
/// 控制器内部变量
/// </summary>
protected AddonController? _Controller;
/// <summary>
/// 加载标记
/// </summary>
@ -79,28 +94,10 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon
/// </summary>
private void Init(params object[] objs)
{
if (objs.Length > 0) WritelnSystemInfo = (Action<string>)objs[0];
if (objs.Length > 1) NewDataRequest = (Func<DataRequestType, DataRequest>)objs[1];
if (objs.Length > 2) NewLongRunningDataRequest = (Func<DataRequestType, DataRequest>)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];
}
/// <summary>
/// 输出系统消息
/// </summary>
protected Action<string> WritelnSystemInfo = new(msg => Console.Write("\r" + msg + "\n\r> "));
/// <summary>
/// 基于本地已连接的Socket创建新的数据请求
/// </summary>
protected Func<DataRequestType, DataRequest> NewDataRequest = new(type => throw new ConnectFailedException());
/// <summary>
/// 基于本地已连接的Socket创建长时间运行的数据请求
/// </summary>
protected Func<DataRequestType, DataRequest> NewLongRunningDataRequest = new(type => throw new ConnectFailedException());
/// <summary>
/// Session对象
/// </summary>

View File

@ -380,4 +380,17 @@ namespace Milimoe.FunGame.Core.Library.Constant
Column,
Username
}
public enum InvokeMessageType
{
None,
Core,
Error,
System,
Api,
Interface,
DataRequest,
Plugin,
GameMode
}
}

View File

@ -11,9 +11,10 @@ namespace Milimoe.FunGame.Core.Service
/// 从plugins目录加载所有插件
/// </summary>
/// <param name="plugins"></param>
/// <param name="objs"></param>
/// <param name="delegates"></param>
/// <param name="otherobjs"></param>
/// <returns></returns>
internal static Dictionary<string, Plugin> LoadPlugins(Dictionary<string, Plugin> plugins, params object[] objs)
internal static Dictionary<string, Plugin> LoadPlugins(Dictionary<string, Plugin> 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目录加载所有模组
/// </summary>
/// <param name="gamemodes"></param>
/// <param name="Characters"></param>
/// <param name="Skills"></param>
/// <param name="Items"></param>
/// <param name="objs"></param>
/// <param name="characters"></param>
/// <param name="skills"></param>
/// <param name="items"></param>
/// <param name="delegates"></param>
/// <param name="otherobjs"></param>
/// <returns></returns>
internal static Dictionary<string, GameMode> LoadGameModes(Dictionary<string, GameMode> gamemodes, List<Character> Characters, List<Skill> Skills, List<Item> Items, params object[] objs)
internal static Dictionary<string, GameMode> LoadGameModes(Dictionary<string, GameMode> gamemodes, List<Character> characters, List<Skill> skills, List<Item> 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;
}
/// <summary>
/// 从gamemodes目录加载所有适用于服务器的模组
/// </summary>
/// <param name="gamemodes"></param>
/// <param name="characters"></param>
/// <param name="skills"></param>
/// <param name="items"></param>
/// <param name="delegates"></param>
/// <param name="otherobjs"></param>
/// <returns></returns>
internal static Dictionary<string, GameModeServer> LoadGameModesForServer(Dictionary<string, GameModeServer> gamemodes, List<Character> characters, List<Skill> skills, List<Item> 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);
}
}
}