MCDRpost API--自定义 Handler

一般来说,MCDRpost 已经能够适应大多数服务端,但是对于某些特殊情况(比如 1.9 版本) [1],MCDRpost 可能无法满足需求, 考虑到插件对 Minecraft 的兼容性,插件暴露了一定的 API 用于 Minecraft 一些特殊服务端的适配

核心 API 有:

你可以在导入的时候使用下面的方式:

from mcdrpost.api import *

当然如果不希望污染全局变量也可以这样:

from mcdrpost import api as mp

详细文档

处理器

class mcdrpost.api.AbstractVersionHandler[源代码]

版本处理器

server

psi 实例

Type:

PluginServerInterface

sound_player

音效播放器

Type:

AbstractSoundPlayer

final classmethod is_builtin() bool[源代码]

此处理器是否为 MCDRpost 内置的处理器

abstractmethod replace(player: str, item: Item) None[源代码]

替换玩家副手物品

参数:
  • player (str) -- 玩家名

  • item (Item) -- 物品字符串

abstractmethod get_offhand_item(player: str) Item[源代码]

获取玩家副手物品

参数:

player (str) -- 玩家 id

property play_sound: AbstractSoundPlayer

播放提示音

你可以重写这个 property 来更换音效,但请注意刚实例化的 Handler 的 sound_player 属性 是 None,要判断一下并赋值

class mcdrpost.api.DefaultVersionHandler[源代码]

这是对 Minecraft 1.17~1.20.5 的简易 Handler

mcdrpost.api.register_handler(handler: type[AbstractVersionHandler], checker: Callable[[Environment], bool]) None[源代码]

向 MCDRpost 注册 Handler

参数:

声音播放器

class mcdrpost.api.AbstractSoundPlayer(server: PluginServerInterface)[源代码]

音效播放

server

MCDR 服务器接口

Type:

PluginServerInterface

abstractmethod successfully_receive(player: str)[源代码]

播放音效: 当成功接受订单时

参数:

player (str) -- 玩家 id

abstractmethod successfully_post(sender: str, receiver: str)[源代码]

播放音效: 当成功发送订单时

请给收件人和发件人播放音效

参数:
  • sender (str) -- 发件人

  • receiver (str) -- 收件人

Returns:

abstractmethod has_something_to_receive(player: str)[源代码]

播放音效: 登陆后发现有订单未接受时

参数:

player (str) -- 玩家 id

class mcdrpost.api.NewSoundPlayer(server: PluginServerInterface)[源代码]

1.13 及以上版本的音效播放器

class mcdrpost.api.OldSoundPlayer(server: PluginServerInterface)[源代码]

1.13 以下版本的音效播放器

类型

class mcdrpost.api.Item(**kwargs)[源代码]

物品数据类,表示 Minecraft 中的物品

备注

Minecraft 1.20.5 之后的 components 数据和之前的 tag 标签都存放在 components中

在 3.4.1 版本加入: 新增验证功能

id: str

物品的唯一标识符

count: int

物品数量

components: dict

物品的组件信息或标签

class mcdrpost.api.Environment(server: PluginServerInterface)[源代码]
property server_version: MinecraftVersion

Minecraft 服务器版本

property mcdr_handler: str

MCDR 正在使用的 handler

class mcdrpost.api.MinecraftVersion(original_version_str: str)[源代码]

Minecraft 版本, 主要目的是兼容新版本号系统

如果是普通的 1.x 版本, 那么它相当于语义化版本号

如果是新的版本命名系统, 那么 major 会储存年份, minor 会储存版本号, 快照版本会在 patch 和 pre_release 中储存, 其中的 pre_release 是 str 类型并且会保留 snapshot

version: SemanticVersion

语义化版本号

major: int

主版本号

minor: int

次版本号

patch: int

补丁版本号, 或快照版本号(snapshot后的数字)

pre_release: str | None = None

预发布版本号

build_metadata: str | None = None

构建元数据

class mcdrpost.api.SemanticVersion(version_str: str)[源代码]

语义化版本号

该类生成的实例支持不同的比较方法, 不仅可以和自己比较, 还可以和 str, tuple 类型比较, 只需要它确实是一个语义化版本号的样子

备注

tuple 的比较按 (major, minor, patch, prerelease, build_metadata) 进行比较

pre_release: str | None = None

预发布版本号

build_metadata: str | None = None

构建元数据

major: int

主版本号

minor: int

次版本号

patch: int

补丁版本号

property is_pre_release: bool

是否是预发布版本

常量

mcdrpost.api.OFFHAND_CODE: str

副手的位置, 在使用 /data 获取数据时使用

例如:

server.execute(f"/data get entity @s {OFFHAND_CODE}")
mcdrpost.api.AIR: Item

空气方块

class mcdrpost.api.Commands[源代码]

原版命令集合

REPLACE_OLD = 'replaceitem entity {0} weapon.offhand {1}'

旧版命令 replaceitem

Format:
  • 0 - 玩家名

  • 1 - 物品命名空间 ID

REPLACE_NEW = 'item replace entity {0} weapon.offhand with {1}'

新版本命令 item replace

Format:
  • 0 - 玩家名

  • 1 - 物品命名空间 ID

GET_ITEM = 'data get entity {0} Inventory[{Slot:-106b}]'

获取副手物品

Format:
  • 0 - 玩家名

PLAY_SOUND_NEW = 'execute at {0} run {1} player {0}'

新版本音效播放 execute

Format:
  • 0 - 玩家名

  • 1 - 音效名

PLAY_SOUND_OLD = 'execute {0} ~ ~ ~ playsound {1} player {0}'

旧版本音效播放 execute

Format:
  • 0 - 玩家名

  • 1 - 音效名

class mcdrpost.api.Sounds[源代码]

默认音效

示例

我们建议使用插件定义你的 Handler,下面是一个单文件插件的例子

PLUGIN_METADATA = {
    'id': 'example_handler',
    'version': '1.0.0',
    'name': 'Example Handler',
    'author': 'xieyuen',
    'description': 'An example of custom handler',
    'dependencies': {
        'mcdrpost': '>=3.3.2-beta5'
    }
}


def on_load(_server, _old):
    import minecraft_data_api as api
    from mcdrpost.api import AbstractVersionHandler, Item, OFFHAND_CODE, register_handler

    class ExampleHandler(AbstractVersionHandler):
        def replace(self, player: str, item: Item) -> None:
            self.server.execute(f'item replace entity {player} with {self.item2str(item)}')

        @staticmethod
        def item2str(item: Item) -> str:
            return f'{item.id}{item.components} {item.count}'

        @staticmethod
        def dict2item(item: dict) -> Item:
            return Item(
                id=item['id'],
                count=item['Count'],
                components=item.get('tag', {})
            )

        def get_offhand_item(self, player: str) -> Item:
            item = api.convert_minecraft_json(
                self.server.rcon_query(
                    f'data get entity {player} {OFFHAND_CODE}'
                )
            )

            return self.dict2item(item)

    register_handler(
        ExampleHandler,
        lambda env: '1.20.5' > env.server_version >= '1.17'
    )

备注

on_load() 函数中定义是为了保证 MCDR 能正确加载插件, 因为 MCDR 要先读取 Metadata 才知道插件依赖 MCDRpost,而此时 MCDRpost 不一定已经被加载 放在函数中先不运行就可以避免没有优先加载 MCDRpost 导致的问题

注意:如果是多文件插件就没有这种问题,放在外面定义就好

如果是用多文件插件的话,你甚至不需要定义 on_load, 只需要在入口点内定义 Handler 并注册就好

example_handler/entry.py 文件内

import minecraft_data_api as api
from mcdrpost.api import AbstractVersionHandler, Item, OFFHAND_CODE, register_handler


class ExampleHandler(AbstractVersionHandler):
    def replace(self, player: str, item: Item) -> None:
        self.server.execute(f'item replace entity {player} with {self.item2str(item)}')

    @staticmethod
    def item2str(item: Item) -> str:
        return f'{item.id}{item.components} {item.count}'

    @staticmethod
    def dict2item(item: dict) -> Item:
        return Item(
            id=item['id'],
            count=item['Count'],
            components=item.get('tag', {})
        )

    def get_offhand_item(self, player: str) -> Item:
        item = api.convert_minecraft_json(
            self.server.rcon_query(
                f'data get entity {player} {OFFHAND_CODE}'
            )
        )

        return self.dict2item(item)


register_handler(
    ExampleHandler,
    lambda env: '1.20.5' > env.server_version >= '1.17'
)

脚注