插件事件

插件事件是插件与控制台和服务器交互的重要方式

当服务器触发某一事件时,MCDR 会以触发的参数传递至注册该事件的事件监听器,然后调用该监听器的回调函数

事件监听器是具有优先级的,默认优先级为 1000,插件可以在手动注册事件监听器时设置优先级,MCDR会根据优先级按升序来执行事件监听器

注册事件监听器

MCDR 插件 文档中的 事件监听器 章节

MCDR 事件

默认的事件监听器

所有的 MCDR 事件监听器都有一个 “默认函数名称”。当你在插件文件内创建一个函数名称与“默认函数名称”相同的函数时,该函数会自动注册为相应的事件监听器

这些事件监听器的优先级始终是默认的优先级(1000

MCDR 事件列表

为了助于理解,一些 MCDR 的事件可被划分为三个生命周期流程

插件被加载

插件被加载事件将在插件加载后被触发一次,若你需要注册一些事件监听器/命令/帮助消息,以及初始化参数,那么你应该将它们置于这个函数里

def on_load(server: PluginServerInterface, prev_module):
    server.register_command(...)
    server.register_event_listener(...)
    server.register_help_message(...)

插件重载时,prev_module 参数会代表之前的插件模块实例。若第一次加载插件,则 prev_module 为 None。你使用该参数时,可让插件继承以前的插件实例中的内容,例如:

def on_load(server: PluginServerInterface, prev_module):
    global reload_counter
    if prev_module is not None:
        reload_counter = prev_module.reload_counter + 1
    else:
        reload_counter = 0

由于它是插件生命周期中的第一个事件,因此只能使用默认事件侦听器注册该事件,因此 on_load 函数是插件的入口点

注意:你不应该在 on_load 函数中分发自定义事件,否则它将无效。 MCDR的事件侦听器存储此时尚未初始化

事件 ID:

mcdr.plugin_loaded

回调参数:

PluginServerInterface, Any (之前的模块)

默认函数名称:

on_load

插件被卸载

当 MCDR 卸载插件实例时,将派发该事件。这可能是由插件重载或卸载引起的

除此之外,在 MCDR 关闭过程中,该事件也将被派发,因此这非常适合用于执行清理操作

事件 ID:

mcdr.plugin_unloaded

回调参数:

PluginServerInterface

默认函数名称:

on_unload

标准信息

服务器输出新一行文本,或者从控制台中输入文本时,触发此事件。 MCDR 将把文本解析为 Info 对象。在这种情况下,插件可以响应信息

以下是一个示例用法:

def on_info(server: PluginServerInterface, info: Info):
    if not info.is_user and re.fullmatch(r'Starting Minecraft server on \S*', info.content):
        server.logger.info('Minecraft is starting at address {}'.format(info.content.rsplit(' ', 1)[1]))
事件 ID:

mcdr.general_info

回调参数:

PluginServerInterface, Info

默认函数名称:

on_info

用户信息

用户信息 事件与 标准信息 事件非常相似,但仅在用户发送信息时——更准确地说,info.is_userTrue 时——才会触发

如果你需要一种简单的方式来处理用户输入,则可以使用此事件

以下是一个示例用法:

def on_user_info(server: PluginServerInterface, info: Info):
    if info.content == 'Restart the server!':
        server.reply(info, 'Roger that. Server restarting...')
        server.restart()

如果你想要更复杂的命令系统,而不是在用户信息事件中手动解析它们,则建议你为插件注册一个命令树。参见插件的 指令注册 文档

事件 ID:

mcdr.user_info

回调参数:

PluginServerInterface, Info

默认函数名称:

on_user_info

服务端启动

服务端进程刚被 MCDR 启动时触发

事件 ID:

mcdr.server_start

回调参数:

PluginServerInterface

默认函数名称:

on_server_start

服务端启动完成

服务器已完全启动时——例如,原版 Minecraft 服务器输出 Done (1.0s)! For help, type "help" 时——被触发

事件 ID:

mcdr.server_startup

回调参数:

PluginServerInterface

默认函数名称:

on_server_startup

服务端终止

服务端进程终止。你可以通过判断进程的返回码执行不同操作

MCDR 将等待所有派发的事件触发的回调函数运行完成,再继续运行下去

例如:

def on_server_stop(server: PluginServerInterface, server_return_code: int):
    if server_return_code != 0:
        server.logger.info('Is it a server crash?')
事件 ID:

mcdr.server_stop

回调参数:

PluginServerInterface, int

默认函数名称:

on_server_stop

MCDR 启动

MCDR 正在启动。只有成功加载的插件才能接收此事件

事件 ID:

mcdr.mcdr_start

回调参数:

PluginServerInterface

默认函数名称:

on_mcdr_start

MCDR 终止

MCDR 正在关闭,该做一些清理工作了

MCDR 将等待所有派发的事件触发的回调函数运行完成,再继续运行下去

Watchdog 在这个过程中将会被临时禁用,因此你可以放心地在这里阻塞 MCDR 至你的清理操作结束

事件 ID:

mcdr.mcdr_stop

回调参数:

PluginServerInterface

默认函数名称:

on_mcdr_stop

玩家加入

一名玩家加入了游戏。 MCDR 仅将玩家的名称解析为字符串,插件可以使用返回的 Info 实例进行更多自定义信息解析

例如:

def on_player_joined(server: PluginServerInterface, player: str, info: Info):
    server.say('Welcome {}'.format(player))
事件 ID:

mcdr.player_joined

回调参数:

PluginServerInterface, str, Info

默认函数名称:

on_player_joined

玩家离开

一名玩家离开了游戏。插件可以清理与玩家相关的对象

事件 ID:

mcdr.player_left

回调参数:

PluginServerInterface, str

默认函数名称:

on_player_left

自定义事件

除了 MCDR 本身,插件还可以分发自己的事件。你需要做的就是调用带有事件和一些参数的 ServerInterface.dispatch_event API

自定义事件是在插件之间传递消息的好办法。这也是一种不错的间接让插件响应其他插件请求的方式