服务端处理器

服务端处理器是分析服务器输出并提供命令接口来控制服务器的对象

MCDR 本身已经包含许多广泛使用的 Minecraft 服务端的处理器,但如果你有需要自定义输出格式的服务端,你可以编写自己的服务端处理器,并让 MCDR 使用它

要设计服务端处理器,你需要从现有的服务端处理器类或 AbstractMinecraftHandler 基类继承

建议首先查看 MCDR 中服务端处理器的实现,并尝试理解它们

为了更方便的使用、管理以及后续可能的分发,建议创建一个 MCDR 插件,并使用 register_server_handler() API,来提供服务端处理器

示例

假设我们有一个原版服务器,但某些玩家的用户名加有前缀,这将导致玩家聊天消息的消息格式发生一些更改。例如,具有 ID Steve 和前缀 [Builder] 的玩家可能有以下聊天消息:

<[Builder]Steve> Hello
<[Builder]Steve> !!MCDR status

对于默认的原版服务端处理器,[Builder]Steve 是一个非法的玩家名称。幸运的是,服务器中所有可能的玩家前缀都遵循相同的格式,即 [前缀]玩家名称。因此,可以为之创建专用的处理器

例如,我们创建一个 MCDR 插件,并编写以下代码作为其入口点,以在此服务器中正确处理玩家名称:

import re

from mcdreforged.handler.impl import VanillaHandler


class MyHandler(VanillaHandler):
    def get_name(self) -> str:
        return 'the_handler_for_my_server'

    def parse_server_stdout(self, text: str):
        info = super().parse_server_stdout(text)
        if info.player is None:
            m = re.fullmatch(r'<\[\w+](?P<name>[^>]+)> (?P<message>.*)', info.content)
            if m is not None and self._verify_player_name(m['name']):
                info.player, info.content = m['name'], m['message']
        return info


def on_load(server, prev_module):
    server.register_server_handler(MyHandler())

然后,你可以加载或重载你刚刚创建的这个插件,来开始使用这个自定义处理器

快速指南:创建一个提供自定义处理器的单文件插件

创建一个插件最简单的方法,是创建一个由单个 .py 文件组成的 单文件插件

  1. 假设配置项 plugin_directories 包含 plugins/ 目录,那么你可以通过创建并编辑文件 plugins/handler_for_my_server.py 来创建一个新的单文件插件

    import re
    
    from mcdreforged.handler.impl import VanillaHandler
    
    PLUGIN_METADATA = {
        'id': 'handler_for_my_server',
        'version': '0.0.0',
    }
    
    class MyHandler(VanillaHandler):
        def get_name(self) -> str:
            return 'the_handler_for_my_server'
    
        def parse_server_stdout(self, text: str):
            info = super().parse_server_stdout(text)
            if info.player is None:
                m = re.fullmatch(r'<\[\w+](?P<name>[^>]+)> (?P<message>.*)', info.content)
                if m is not None and self._verify_player_name(m['name']):
                    info.player, info.content = m['name'], m['message']
            return info
    
    
    def on_load(server, prev_module):
        server.register_server_handler(MyHandler())
    

    注意,以下代码与上面代码的唯一区别,是它在全局作用域内声明了一个 PLUGIN_METADATA 字段,作为单文件插件的元数据字段

    参见

    元数据 文档

  2. 使用命令 !!MCDR plugin load handler_for_my_server.py 加载你新创建的插件

  3. 你的自定义服务端处理器已被加载,去看看它是否按照预期工作吧

  4. (可选)若其效果不符合预期,继续编辑 .py 插件文件以满足你的需求

  5. (可选)使用命令 !!MCDR plugin reload handler_for_my_server 重新加载插件


除此之外,还有一种不推荐的方式,你可以通过一个 .py 文件来提供服务端处理器

将上述代码(不包括 on_load 方法)放入一个 .py 文件,例如 my_handler.py,然后按以下步骤使用:

  1. 将其放入 MCDR 工作目录里的一个有效 Python 包中,例如:

        my_mcdr_server/
    ++  ├─ handlers/
    ++  │   ├─ __init__.py
    ++  │   └─ my_handler.py
         ├─ server/
        ├─ config.yml
        └─ permission.yml
    

    如此一来,你就可以通过 from handlers.my_handler import MyHandler 来访问该处理器类

  2. 将路径添加到 custom_handlers 选项中,然后把 handler 选项设置为自定义处理器 get_name() 方法的返回值,例如:

    handler: the_handler_for_my_server
    
    custom_handlers:
    - handlers.my_handler.MyHandler