MCDRpost API--自定义 Handler
一般来说,MCDRpost 已经能够适应大多数服务端,但是对于某些特殊情况(比如 1.9 版本) [1],MCDRpost 可能无法满足需求, 考虑到插件对 Minecraft 的兼容性,插件暴露了一定的 API 用于 Minecraft 一些特殊服务端的适配
核心 API 有:
- functions
- types
- constants
你可以在导入的时候使用下面的方式:
from mcdrpost.api import *
当然如果不希望污染全局变量也可以这样:
from mcdrpost import api as mp
详细文档
处理器
- class mcdrpost.api.AbstractVersionHandler[源代码]
版本处理器
- server
psi 实例
- Type:
PluginServerInterface
- sound_player
音效播放器
- Type:
- property play_sound: AbstractSoundPlayer
播放提示音
你可以重写这个 property 来更换音效,但请注意刚实例化的 Handler 的 sound_player 属性 是 None,要判断一下并赋值
- mcdrpost.api.register_handler(handler: type[AbstractVersionHandler], checker: Callable[[Environment], bool]) None[源代码]
向 MCDRpost 注册 Handler
- 参数:
handler (type[AbstractVersionHandler]) -- Handler 类
checker (Callable[[Environment], bool]) -- 检查器
声音播放器
- class mcdrpost.api.AbstractSoundPlayer(server: PluginServerInterface)[源代码]
音效播放
- server
MCDR 服务器接口
- Type:
PluginServerInterface
- 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 版本加入: 新增验证功能
- class mcdrpost.api.Environment(server: PluginServerInterface)[源代码]
- property server_version: MinecraftVersion
Minecraft 服务器版本
- class mcdrpost.api.MinecraftVersion(original_version_str: str)[源代码]
Minecraft 版本, 主要目的是兼容新版本号系统
如果是普通的 1.x 版本, 那么它相当于语义化版本号
如果是新的版本命名系统, 那么 major 会储存年份, minor 会储存版本号, 快照版本会在 patch 和 pre_release 中储存, 其中的 pre_release 是 str 类型并且会保留
snapshot- version: SemanticVersion
语义化版本号
常量
- mcdrpost.api.OFFHAND_CODE: str
副手的位置, 在使用
/data获取数据时使用例如:
server.execute(f"/data get entity @s {OFFHAND_CODE}")
- 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 - 音效名
示例
我们建议使用插件定义你的 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'
)
脚注