插件间通信与事件广播
ToolDelta 的插件之间可以互相调用与通信,主要有两种方式:
- 前置插件(API 插件):把一个插件注册为 API,供其他插件获取并直接调用其方法。
- 事件广播:插件向全局广播一个事件,其他插件监听并可选返回数据。
注册一个 API 插件
在 plugin_entry 中额外传入 api_name(API 名,可为字符串或字符串列表)与 api_version(API 版本),即可将该插件同时注册为 API 插件:
python
from tooldelta import plugin_entry, Plugin
class MyPlugin(Plugin):
name = "示例 api 插件"
version = (0, 0, 1)
def greet(self, msg: str):
print("hello,", msg)
# 第二个参数为 API 名,第三个参数为 API 版本
entry = plugin_entry(MyPlugin, "example-api", (0, 0, 1))1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
plugin_entry 的签名为:
python
def plugin_entry(
plugin_cls: type[Plugin],
api_name: str | list[str] = [],
api_version: tuple[int, int, int] | None = None
) -> Plugin1
2
3
4
5
2
3
4
5
api_name:注册的 API 名,可以有多个。api_version:API 版本,不填则默认使用插件主类的version。
获取其他插件的 API
在插件中通过 self.GetPluginAPI(api_name, min_version=(0, 0, 0), force=True) 获取其他 API 插件的实例:
python
from tooldelta import Plugin
class MyPlugin2(Plugin):
name = "另一个插件"
def __init__(self, frame):
super().__init__(frame)
self.ListenPreload(self.on_preload)
def on_preload(self):
api = self.GetPluginAPI("example-api")
api.greet("world")
# 终端输出:hello, world
entry = plugin_entry(MyPlugin2)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- 参数:
参数名 类型 说明 api_name str API 名 min_version tuple[int, int, int] 要求的最低版本,默认为 (0, 0, 0)force bool 为 False时找不到 API 插件返回None,而不是报错 - 引发异常:
类型 说明 PluginAPINotFoundError 无法找到对应 API 插件( force=True时)PluginAPIVersionError API 插件版本低于 min_version
原理
GetPluginAPI() 返回的是对应 Plugin 对象的实例,因此你可以直接调用该插件里的所有公开方法。
如果你希望 IDE 对获取到的 API 对象进行类型提示与高亮,可在 TYPE_CHECKING 代码块下使用 self.get_typecheck_plugin_api(api_cls),详见 前置插件。
事件的广播
插件可以通过 self.BroadcastEvent(evt) 向全局广播一个 InternalBroadcast 事件:
python
from tooldelta import InternalBroadcast
result_list = self.BroadcastEvent(
InternalBroadcast("my.evt", {"k": 1})
)1
2
3
4
5
2
3
4
5
- 参数:一个
InternalBroadcast实例,包含字段:成员 类型 说明 evt_name str 广播事件名 data Any 附加数据 - 返回:
list[Any],收集了所有监听回调返回的非 None 结果。
监听广播
插件可以通过 self.ListenInternalBroadcast(broadcast_name, cb, priority=0) 监听指定名字的广播事件;回调的返回值会回传给广播的发送者:
python
from tooldelta import InternalBroadcast
class AnotherPlugin(Plugin):
name = "监听者"
def __init__(self, frame):
super().__init__(frame)
self.ListenInternalBroadcast("my.evt", self.on_my_evt)
def on_my_evt(self, evt: InternalBroadcast):
self.print_inf(f"收到广播 {evt.evt_name}: {evt.data}")
return "已收到"
entry = plugin_entry(AnotherPlugin)1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
提示
InternalBroadcast 已由顶层 tooldelta 导出;Death、Attack 等事件类型则需从 tooldelta.internal.types 导入。