mirror of
https://github.com/project-redbud/FunGame-Core.git
synced 2026-04-20 05:24:59 +00:00
添加插件之间的数据请求;补全插件示例 (#150)
This commit is contained in:
parent
5194fe39e9
commit
47fb717651
@ -1,4 +1,5 @@
|
||||
using Milimoe.FunGame.Core.Library.Common.Addon;
|
||||
using Milimoe.FunGame.Core.Library.Common.Event;
|
||||
using Milimoe.FunGame.Core.Library.Constant;
|
||||
using Milimoe.FunGame.Core.Service;
|
||||
|
||||
@ -196,6 +197,29 @@ namespace Milimoe.FunGame.Core.Api.Utility
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理服务器广播的非标准 DataRequest 请求
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="e"></param>
|
||||
/// <returns></returns>
|
||||
public Dictionary<string, object> HandleDataRequest(Dictionary<string, object> data, AddonDataRequestEventArgs e)
|
||||
{
|
||||
Dictionary<string, object> result = [];
|
||||
if (ModuleServers.Count > 0)
|
||||
{
|
||||
foreach (GameModuleServer module in ModuleServers.Values)
|
||||
{
|
||||
Dictionary<string, object> moduleResult = module.HandleDataRequest(data, e);
|
||||
foreach (string key in moduleResult.Keys)
|
||||
{
|
||||
result[key] = moduleResult[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取对应名称的模组实例
|
||||
/// <para>如果需要取得服务器模组的实例,请调用 <see cref="GetServerMode"/></para>
|
||||
|
||||
@ -81,6 +81,26 @@ namespace Milimoe.FunGame.Core.Api.Utility
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理服务器广播的非标准 DataRequest 请求
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="e"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Dictionary<string, object> HandleDataRequest(Dictionary<string, object> data, AddonDataRequestEventArgs e)
|
||||
{
|
||||
Dictionary<string, object> result = [];
|
||||
foreach (ServerPlugin plugin in Plugins.Values)
|
||||
{
|
||||
Dictionary<string, object> pluginResult = plugin.HandleDataRequest(data, e);
|
||||
foreach (string key in pluginResult.Keys)
|
||||
{
|
||||
result[key] = pluginResult[key];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public ServerPlugin this[string name]
|
||||
{
|
||||
get
|
||||
|
||||
@ -81,6 +81,26 @@ namespace Milimoe.FunGame.Core.Api.Utility
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理服务器广播的非标准 DataRequest 请求
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="e"></param>
|
||||
/// <returns></returns>
|
||||
public Dictionary<string, object> HandleDataRequest(Dictionary<string, object> data, AddonDataRequestEventArgs e)
|
||||
{
|
||||
Dictionary<string, object> result = [];
|
||||
foreach (WebAPIPlugin plugin in Plugins.Values)
|
||||
{
|
||||
Dictionary<string, object> pluginResult = plugin.HandleDataRequest(data, e);
|
||||
foreach (string key in pluginResult.Keys)
|
||||
{
|
||||
result[key] = pluginResult[key];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public WebAPIPlugin this[string name]
|
||||
{
|
||||
get
|
||||
|
||||
@ -98,6 +98,58 @@ namespace Milimoe.FunGame.Core.Controller
|
||||
return MaskMethod_NewLongRunningGamingRequest(type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 基于本地已连接的Socket创建非标准的数据请求(<see cref="DataRequestType.Addon_Module"/> 或 <see cref="DataRequestType.Addon_Plugin"/>,具体类型由 <see cref="BaseAddonController{T}.Addon"/> 决定)
|
||||
/// <para/>可以指定 <paramref name="targetAddon"/>,以便发送给一个已知的服务器模组或服务器插件
|
||||
/// </summary>
|
||||
/// <param name="targetAddon"></param>
|
||||
/// <param name="longRunning"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ConnectFailedException"></exception>
|
||||
public DataRequest NewDataRequest(string targetAddon = "", bool longRunning = false)
|
||||
{
|
||||
if (Addon is IPlugin)
|
||||
{
|
||||
DataRequest request;
|
||||
if (longRunning)
|
||||
{
|
||||
request = NewLongRunningDataRequest(DataRequestType.Addon_Plugin);
|
||||
}
|
||||
else
|
||||
{
|
||||
request = NewDataRequest(DataRequestType.Addon_Plugin);
|
||||
}
|
||||
request.AddRequestData(SocketSet.AddonDataRequestMark_FromPlugin, Addon.Name);
|
||||
request.AddRequestData(SocketSet.AddonDataRequestMark_TargetPlugin, targetAddon);
|
||||
return request;
|
||||
}
|
||||
else if (Addon is IGameModule)
|
||||
{
|
||||
DataRequest request;
|
||||
if (longRunning)
|
||||
{
|
||||
request = NewLongRunningDataRequest(DataRequestType.Addon_Module);
|
||||
}
|
||||
else
|
||||
{
|
||||
request = NewDataRequest(DataRequestType.Addon_Module);
|
||||
}
|
||||
request.AddRequestData(SocketSet.AddonDataRequestMark_FromModule, Addon.Name);
|
||||
request.AddRequestData(SocketSet.AddonDataRequestMark_TargetModule, targetAddon);
|
||||
return request;
|
||||
}
|
||||
throw new ConnectFailedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 基于本地已连接的Socket创建长时间运行的、非标准的数据请求(<see cref="DataRequestType.Addon_Module"/> 或 <see cref="DataRequestType.Addon_Plugin"/>,具体类型由 <see cref="BaseAddonController{T}.Addon"/> 决定)
|
||||
/// <para/>可以指定 <paramref name="targetAddon"/>,以便发送给一个已知的服务器模组或服务器插件
|
||||
/// </summary>
|
||||
/// <param name="targetAddon"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ConnectFailedException"></exception>
|
||||
public DataRequest NewLongRunningDataRequest(string targetAddon = "") => NewDataRequest(targetAddon, true);
|
||||
|
||||
/// <summary>
|
||||
/// 新建一个AddonController
|
||||
/// </summary>
|
||||
|
||||
@ -1,13 +1,18 @@
|
||||
using Milimoe.FunGame.Core.Interface;
|
||||
using System.Data;
|
||||
using Milimoe.FunGame.Core.Api.Transmittal;
|
||||
using Milimoe.FunGame.Core.Api.Utility;
|
||||
using Milimoe.FunGame.Core.Interface;
|
||||
using Milimoe.FunGame.Core.Library.Common.Event;
|
||||
using Milimoe.FunGame.Core.Library.Constant;
|
||||
using Milimoe.FunGame.Core.Library.SQLScript.Entity;
|
||||
|
||||
namespace Milimoe.FunGame.Core.Library.Common.Addon.Example
|
||||
{
|
||||
/// <summary>
|
||||
/// 必须继承基类:<see cref="Plugin"/><para/>
|
||||
/// 继承事件接口并实现其方法来使插件生效。例如继承:<seealso cref="ILoginEvent"/>
|
||||
/// 客户端插件,必须继承基类:<see cref="Plugin"/><para/>
|
||||
/// 继承事件接口并实现其方法来使插件生效。例如继承:<seealso cref="IConnectEvent"/>
|
||||
/// </summary>
|
||||
public class ExamplePlugin : Plugin, ILoginEvent
|
||||
public class ExamplePlugin : Plugin, IConnectEvent
|
||||
{
|
||||
public override string Name => "fungame.example.plugin";
|
||||
|
||||
@ -17,6 +22,77 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon.Example
|
||||
|
||||
public override string Author => "FunGamer";
|
||||
|
||||
public void AfterConnectEvent(object sender, ConnectEventArgs e)
|
||||
{
|
||||
// 每个事件接口都有 Before/After 两个介入点,根据自身需求实现即可
|
||||
// 可以在连接服务器完毕后做一些处理...
|
||||
}
|
||||
|
||||
public void BeforeConnectEvent(object sender, ConnectEventArgs e)
|
||||
{
|
||||
// 和服务器插件的联动示例
|
||||
// 假设服务器上有个名为“fungame.example.serverplugin”的服务器插件,当然也可以不指定,不指定时服务器会广播所有插件,性能可能较低
|
||||
DataRequest request = Controller.NewDataRequest(targetAddon: "fungame.example.serverplugin");
|
||||
long tick = DateTime.Now.Ticks;
|
||||
request.AddRequestData("event", "ping");
|
||||
request.AddRequestData("tick", tick);
|
||||
request.SendRequest();
|
||||
if (request.Result == RequestResult.Success)
|
||||
{
|
||||
long newTick = request.GetResult<long>("tick");
|
||||
Controller.WriteLine($"服务器延迟:{Math.Min(999, new TimeSpan(newTick - tick).TotalMilliseconds)}ms");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 服务器插件,必须继承基类:<see cref="ServerPlugin"/><para/>
|
||||
/// 同样需继承事件接口并实现其方法来使插件生效。例如继承:<seealso cref="ILoginEvent"/>
|
||||
/// </summary>
|
||||
public class ExampleServerPlugin : ServerPlugin, ILoginEvent
|
||||
{
|
||||
public override string Name => "fungame.example.serverplugin";
|
||||
|
||||
public override string Description => "My First Server Plugin";
|
||||
|
||||
public override string Version => "1.0.0";
|
||||
|
||||
public override string Author => "FunGamer";
|
||||
|
||||
public override void ProcessInput(string input)
|
||||
{
|
||||
// 该方法用于接收服务器控制台的输入并处理
|
||||
if (input.Equals("info", StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
// 使用PluginController的输出方式
|
||||
Controller.WriteLine($"This is {nameof(ExampleServerPlugin)}!!");
|
||||
}
|
||||
}
|
||||
|
||||
public override void AfterLoad(ServerPluginLoader loader, params object[] objs)
|
||||
{
|
||||
// 该方法可在插件加载完毕后执行代码
|
||||
}
|
||||
|
||||
public override Dictionary<string, object> HandleDataRequest(Dictionary<string, object> data, AddonDataRequestEventArgs e)
|
||||
{
|
||||
// 此方法接收并处理数据请求,我们先前在客户端插件中发送了数据请求,这里就要处理它
|
||||
// 需要注意,data 是通用的,如果服务器将数据请求广播到所有的插件,这些插件是无法区分客户端的请求类型是什么的,所以这一部分更偏向于“约定”
|
||||
// 可以约定好插件的名称,也可以约定好event,一切都完全由插件开发者掌控
|
||||
if (e.From == "fungame.example.plugin" && e.Target == Name)
|
||||
{
|
||||
string ent = NetworkUtility.JsonDeserializeFromDictionary<string>(data, "event") ?? "";
|
||||
if (ent.Equals("ping", StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
return new()
|
||||
{
|
||||
{ "tick", DateTime.Now.Ticks }
|
||||
};
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
public void AfterLoginEvent(object sender, LoginEventArgs e)
|
||||
{
|
||||
|
||||
@ -24,8 +100,18 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon.Example
|
||||
|
||||
public void BeforeLoginEvent(object sender, LoginEventArgs e)
|
||||
{
|
||||
// 如果这里设置Cancel = true,将终止登录
|
||||
e.Cancel = true;
|
||||
// 如果这里设置Cancel = true,将终止登录(可以加入自定义的验证机制等)
|
||||
// 例如SQLHelper的使用:
|
||||
if (Controller.SQLHelper != null)
|
||||
{
|
||||
// 服务器的标准功能会有登录检查,这里仅做一个示例
|
||||
DataRow? row = Controller.SQLHelper.ExecuteDataRow(UserQuery.Select_UserByUsername(Controller.SQLHelper, e.Username));
|
||||
if (row is null)
|
||||
{
|
||||
e.Cancel = true;
|
||||
e.EventMsg = "用户名不存在。";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ using Milimoe.FunGame.Core.Api.Utility;
|
||||
using Milimoe.FunGame.Core.Controller;
|
||||
using Milimoe.FunGame.Core.Interface.Addons;
|
||||
using Milimoe.FunGame.Core.Interface.Base;
|
||||
using Milimoe.FunGame.Core.Library.Common.Event;
|
||||
using Milimoe.FunGame.Core.Library.Constant;
|
||||
|
||||
namespace Milimoe.FunGame.Core.Library.Common.Addon
|
||||
@ -129,6 +130,19 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon
|
||||
return [];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 此方法为可选实现,接收并处理非标准 DataRequest 请求<para/>
|
||||
/// 此方法效率可能低于匿名服务器<para/>
|
||||
/// <para/>请使用 <see cref="NetworkUtility.JsonDeserializeFromDictionary{T}(Dictionary{string, object}, string)"/> 方法获取 <paramref name="data"/> 成员
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="e"></param>
|
||||
/// <returns>返回一个无需对成员序列化的字典</returns>
|
||||
public virtual Dictionary<string, object> HandleDataRequest(Dictionary<string, object> data, AddonDataRequestEventArgs e)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载标记
|
||||
/// </summary>
|
||||
|
||||
@ -96,6 +96,18 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon
|
||||
/// <param name="input"></param>
|
||||
public abstract void ProcessInput(string input);
|
||||
|
||||
/// <summary>
|
||||
/// 处理服务器广播的非标准 DataRequest 请求
|
||||
/// <para/>请使用 <see cref="NetworkUtility.JsonDeserializeFromDictionary{T}(Dictionary{string, object}, string)"/> 方法获取 <paramref name="data"/> 成员
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="e"></param>
|
||||
/// <returns>返回一个无需对成员序列化的字典</returns>
|
||||
public virtual Dictionary<string, object> HandleDataRequest(Dictionary<string, object> data, AddonDataRequestEventArgs e)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 插件完全加载后需要做的事
|
||||
/// </summary>
|
||||
|
||||
@ -96,6 +96,18 @@ namespace Milimoe.FunGame.Core.Library.Common.Addon
|
||||
/// <param name="input"></param>
|
||||
public abstract void ProcessInput(string input);
|
||||
|
||||
/// <summary>
|
||||
/// 处理服务器广播的非标准 DataRequest 请求
|
||||
/// <para/>请使用 <see cref="NetworkUtility.JsonDeserializeFromDictionary{T}(Dictionary{string, object}, string)"/> 方法获取 <paramref name="data"/> 成员
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="e"></param>
|
||||
/// <returns>返回一个无需对成员序列化的字典</returns>
|
||||
public virtual Dictionary<string, object> HandleDataRequest(Dictionary<string, object> data, AddonDataRequestEventArgs e)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 插件完全加载后需要做的事
|
||||
/// </summary>
|
||||
|
||||
11
Library/Common/Event/AddonDataRequestEventArgs.cs
Normal file
11
Library/Common/Event/AddonDataRequestEventArgs.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using Milimoe.FunGame.Core.Interface.Base;
|
||||
|
||||
namespace Milimoe.FunGame.Core.Library.Common.Event
|
||||
{
|
||||
public class AddonDataRequestEventArgs(IServerModel client, string from, string target) : GeneralEventArgs
|
||||
{
|
||||
public IServerModel Client { get; set; } = client;
|
||||
public string From { get; set; } = from;
|
||||
public string Target { get; set; } = target;
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
using System.Text;
|
||||
using Milimoe.FunGame.Core.Interface.Addons;
|
||||
using Milimoe.FunGame.Core.Model;
|
||||
|
||||
/**
|
||||
@ -104,7 +105,11 @@ namespace Milimoe.FunGame.Core.Library.Constant
|
||||
public const int MaxConnection_1C2G = 10;
|
||||
public const int MaxConnection_2C2G = 20;
|
||||
public const int MaxConnection_4C4G = 40;
|
||||
public const string Plugins_Mark = "plugins_mark";
|
||||
public const string Plugins_Mark = "$*plugins_mark*";
|
||||
public const string AddonDataRequestMark_FromPlugin = "$*from_plugin*";
|
||||
public const string AddonDataRequestMark_TargetPlugin = "$*target_plugin*";
|
||||
public const string AddonDataRequestMark_FromModule = "$*from_module*";
|
||||
public const string AddonDataRequestMark_TargetModule = "$*target_module*";
|
||||
|
||||
public const string Socket = "Socket";
|
||||
public const string Unknown = "Unknown";
|
||||
@ -211,6 +216,11 @@ namespace Milimoe.FunGame.Core.Library.Constant
|
||||
public const string Inventory_MakeOffer = "Inventory::MakeOffer";
|
||||
public const string Inventory_ReviseOffer = "Inventory::ReviseOffer";
|
||||
public const string Inventory_RespondOffer = "Inventory::RespondOffer";
|
||||
/**
|
||||
* Addon
|
||||
*/
|
||||
public const string Addon_Plugin = "Addon::Plugin";
|
||||
public const string Addon_Module = "Addon::Module";
|
||||
|
||||
/// <summary>
|
||||
/// 获取Type的等效字符串
|
||||
@ -256,6 +266,8 @@ namespace Milimoe.FunGame.Core.Library.Constant
|
||||
DataRequestType.Inventory_MakeOffer => Inventory_MakeOffer,
|
||||
DataRequestType.Inventory_ReviseOffer => Inventory_ReviseOffer,
|
||||
DataRequestType.Inventory_RespondOffer => Inventory_RespondOffer,
|
||||
DataRequestType.Addon_Module => Addon_Module,
|
||||
DataRequestType.Addon_Plugin => Addon_Plugin,
|
||||
_ => UnKnown
|
||||
};
|
||||
}
|
||||
|
||||
@ -122,6 +122,8 @@ namespace Milimoe.FunGame.Core.Library.Constant
|
||||
Inventory_MakeOffer,
|
||||
Inventory_ReviseOffer,
|
||||
Inventory_RespondOffer,
|
||||
Addon_Plugin,
|
||||
Addon_Module
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -1118,4 +1120,13 @@ namespace Milimoe.FunGame.Core.Library.Constant
|
||||
NumberInput,
|
||||
Custom
|
||||
}
|
||||
|
||||
public enum PositionType
|
||||
{
|
||||
Center,
|
||||
Left,
|
||||
Right,
|
||||
Top,
|
||||
Bottom
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user