外观
命令、计分板与查询
原生插件通过 ctx.commands、ctx.scoreboard 和 ctx.queries 创建动作意图,再用 ctx.operations 提交、等待和查询。它们不是外部 HTTP 工具,也不接收 HTTP token。
实例连接游戏并授予插件相应操作权限后,即可提交意图。权限页说明 manifest 声明方法。
所有意图共同的调用规则
以下所有 builder 都返回 OperationIntent,调用本身没有游戏效果。每次都需要关键字参数 idempotency_key: str 和 deadline: str;为简洁,表格中不重复列出。deadline 是带时区的绝对时间,不是秒数。
python
from datetime import datetime, timedelta, timezone
# 以下是已启动插件回调内的片段。
# business_key 由业务为这个独立动作分配,提交前与原意图一起持久保存。
deadline = (datetime.now(timezone.utc) + timedelta(seconds=30)).isoformat()
intent = ctx.commands.prepare(
"say hello", idempotency_key=business_key, deadline=deadline
)
operation_id = await ctx.operations.submit(intent)
receipt = await ctx.operations.wait(operation_id, timeout=35)
completion = receipt.get("result") or {}
if receipt["state"] == "succeeded":
output = completion.get("result")
else:
ctx.log.info("动作状态=%s 原因=%s", receipt["state"], completion.get("reason"))业务返回值在 receipt["result"]["result"],不要把外层 OperationReceipt 与内层 ActionResult 混用。wait() 等到终态也可能返回 failed、cancelled 或 unknown。提交超时不证明动作没有入队;保留原意图核对,不能换键重做。详见动作与结果及错误处理。
Commands:执行一条命令
text
ctx.commands.prepare(command: str, *, idempotency_key: str, deadline: str,
identity: str = 'ws', wait: bool = True,
timeout: float = 30) -> OperationIntent操作权限为 framework.command.execute。command 必须非空,最多 32768 UTF-8 字节,不能含 NUL、回车或换行。identity 接受 player、ws、wo、ai;它选择机器人发送命令的通道,不是指定某位玩家的身份。
| 参数/结果 | 含义 |
|---|---|
identity='ws', wait=True | 默认请求服务端命令输出;适合需要判断执行结果的调用。 |
identity='wo' 或 wait=False | 没有可用输出保证;发送后通常为 unknown / response_omitted。 |
timeout | Host 等待命令响应的预算,最多 300 秒;非正值由 Host 使用 30 秒默认值。不要与绝对 deadline 或 SDK 的等待超时混为一谈。 |
succeeded / acknowledged | 收到报告成功的命令响应;不保证后续世界状态不变。 |
failed / command_unsuccessful | 收到服务端未成功的响应,仍应检查消息内容。 |
正常输出含 success_count: int、output_type: int、data_set: int、messages: list。每条消息有 success: bool、message: str 和 parameters: list[str];message 可能是语言键,不是已翻译的人类文字。可选 protocol_output 保留原始协议输出;不要假定始终存在。输出超限可替换成 {"output_omitted": true, "reason": "output_limit"}。
传输异常可能返回 unknown / command_transport_error,缺少输出可返回 unknown / dispatch_unverified;这些都不能直接重放。不要拼接未经检查的玩家聊天;使用 SDK 入门中的精确身份解析和 player_target()。
一次提交并读取结果
ctx.commands.execute(...) 组合准备、一次提交和等待,返回原始回执;ctx.commands.result(receipt) 解析命令结果。
python
receipt = await ctx.commands.execute(
"say hello", idempotency_key=business_key, deadline=deadline,
command_timeout=30, submit_timeout=10, timeout=35,
)
result = ctx.commands.result(receipt)
if result.is_success:
ctx.log.info("命令成功,成功项=%d", result.output.success_count)
else:
ctx.log.info("命令状态=%s 原因=%s", result.state, result.reason)result.is_success 同时检查成功状态、服务端确认、正的成功计数以及无错误或部分效果;result.message_texts 保留响应文字或语言键,参数在各消息的 parameters 中。无输出时 result.output 为 None。超时不会自动重试或取消,异常附带原 intent/operation_id,恢复步骤见运行上下文。
命令查询与常加载区
ctx.command_queries 把常见查询准备成命令意图,使用 framework.command.execute 权限和服务端命令输出。方法均需 idempotency_key、deadline,由调用方提交对应意图,再把它的回执交给对应解析器。
| 查询 | 解析器与返回值 |
|---|---|
item_count(name, item, *, data=-1, ...) | parse_item_count(receipt) 返回物品数量;通过 clear 的 maxCount=0 查询,不移除物品。 |
tags(name, ...) | parse_tags(receipt) 返回 TagList,含服务端数量和展示文字;展示文字不能当作精确标签 ID 列表。 |
scores(name, ...) | parse_scores(receipt) 返回 ScoreList,各项含 objective/display_name/value。 |
testfor(selector, ...) | parse_testfor(receipt) 返回 TestForMatch 的展示文字,不提供玩家身份列表或实体数量。 |
python
intent = ctx.command_queries.item_count(
"ExamplePlayer", "minecraft:diamond",
idempotency_key=business_key, deadline=deadline,
)
receipt = await ctx.operations.execute(intent)
answer = ctx.command_queries.parse_item_count(receipt)
if answer.known:
ctx.log.info("匹配物品数=%d", answer.value)
else:
ctx.log.info("数量未知,原因=%s", answer.reason)解析结果保留 answer.command。只有已识别的输出格式才令 known=True;value=None 表示未知,不能替换为 0。解析器不替你核对意图与回执的业务归属。
ctx.tickingareas 也使用命令权限,提供 add_box(name, start, end, *, preload=False, ...)、add_circle(name, center, radius, *, preload=False, ...)、remove(name, ...) 和 list(*, all_dimensions=False, ...)。这些方法准备意图,仍需公共的键和截止时间;使用 ctx.commands.result(receipt) 读取结果。新增和移除会修改世界,坐标及移除作用于执行者维度;命令成功不代表区块已经加载。
Scoreboard:精确对象的分数
计分板方法使用明确的 holder 和 objective,每种方法申请自己的权限,不需要额外申请宽泛的命令执行权限。
Builder(另需 idempotency_key、deadline) | 操作权限 | 行为与业务结果 |
|---|---|---|
prepare_get(holder, objective) | framework.scoreboard.get | 读分;返回 holder, objective, found,仅 found=true 时有 value。 |
prepare_set(holder, objective, value) | framework.scoreboard.set | 设分;返回本次响应解析出的 holder、objective、found、value。 |
prepare_add(holder, objective, delta) | framework.scoreboard.add | 加分,负数扣分,0 合法;结果同上。 |
prepare_reset(holder, objective) | framework.scoreboard.reset | 只移除指定计分项中的该 holder,不删除整个计分项。 |
prepare_operation(holder, objective, operator, source_holder, source_objective) | framework.scoreboard.operation | 用源对象计算目标对象;交换会修改两边。 |
holder 可以是玩家名或假名,1–128 UTF-8 字节,不允许首尾空白、@、*、双引号、反斜杠或控制字符;不能传选择器。objective 必须匹配 [A-Za-z0-9_.-]{1,16}。SDK 对这些参数做本地校验,不合格会抛 ValueError。
value 范围为 -2147483648 至 2147483647;delta 为 -2147483647 至 2147483647。operator 接受 =、+=、-=、*=、/=、%=、><、<、>;>< 交换,< 取较小值,> 取较大值。运算的源 holder/objective 也遵守相同校验;不存在的分数、除零等由服务端响应决定。
python
intent = ctx.scoreboard.prepare_get(
"ExamplePlayer", "coins", idempotency_key=business_key, deadline=deadline
)
receipt = await ctx.operations.wait(await ctx.operations.submit(intent))
if receipt["state"] == "succeeded":
score = receipt["result"]["result"]
if score["found"]:
ctx.log.info("本次查询分数=%s", score["value"])计分项与显示槽
| Builder(另需公共关键字参数) | 操作权限 | 参数与返回 |
|---|---|---|
prepare_objective_add(objective, *, display_name=None) | framework.scoreboard.objectives.add | 新建 dummy 计分项。可选显示名 1–128 UTF-8 字节,无首尾空白、双引号、反斜杠及控制字符。 |
prepare_objective_remove(objective) | framework.scoreboard.objectives.remove | 删除计分项及其分数。 |
prepare_objective_list() | framework.scoreboard.objectives.list | 返回 {"objectives": [{"name": ..., "display_name": ..., "criteria": ...}]}。 |
prepare_objective_setdisplay(slot, objective=None, *, sort_order=None) | framework.scoreboard.objectives.setdisplay | slot 为 list/sidebar/belowname;省略 objective 清空该显示槽。 |
sort_order 只接受 ascending 或 descending,必须同时指定 objective,且不能用于 belowname。除分数读取/设定/加减和列表外,成功结果为 {"operation": ..., "acknowledged": true}。例如下面只准备清空侧栏的动作:
python
intent = ctx.scoreboard.prepare_objective_setdisplay(
"sidebar", idempotency_key=business_key, deadline=deadline
)计分板的证据是这次服务端命令的确认,不是永久有效的分数快照。响应不可用或无法解析会保留 unknown,常见原因为 scoreboard_response_unavailable、scoreboard_output_unrecognized;服务端失败为 command_unsuccessful。
Queries:实体、方块和物品栏
实体查询
text
ctx.queries.entities(*, idempotency_key: str, deadline: str,
target: str = 'players', name: str | None = None,
entity_type: str | None = None, tag: str | None = None,
origin=None, radius: float | None = None,
limit: int = 64) -> OperationIntent需要 framework.entities.query。target 为 players 或 entities;name、entity_type、tag 各最多 128 UTF-8 字节,不能含双引号、反斜杠或控制字符;实体类型还必须是合法的命名空间标识。origin 为三个数,每轴 ±30000000;radius 范围 0–1024,指定半径必须同时提供 origin。limit 为 1–64。
python
intent = ctx.queries.entities(
target="entities", entity_type="minecraft:zombie",
origin=(0, 64, 0), radius=16, limit=16,
idempotency_key=business_key, deadline=deadline,
)成功数据为 {"entities": [...], "count": n, "limit": n, "complete": bool}。实体项保留 id、uniqueId、dimension、yRot、position: {x,y,z}。没有匹配目标返回空列表。complete 仅按返回数量小于 limit 判定;达到上限时不能认为已枚举全部实体。证据来自这次 querytarget 输出,不是整个世界的原子快照,也不是持久玩家身份库。
方块与区域
| Builder(另需公共关键字参数) | 操作权限 | 参数/结果 |
|---|---|---|
ctx.queries.block(pos) | framework.world.block.read | 整数世界坐标三元组;返回一个 BlockEntry。 |
ctx.queries.region(pos, size) | framework.world.region.read | size 三轴各 1–32,乘积不超过 4096;返回 pos,size,origin,blocks。 |
世界坐标每轴在 ±30000000 内。读回请求使用服务端结构数据,不会为调用方自动传送机器人或加载远处区块。未加载或来源不完整时不能把缺失项当作空气。结果有 128 KiB 上限,应按业务需要缩小区域;大规模缓存读取见世界快照。
BlockEntry 包含 rel、abs、foreground、background、entity_data,可带 name。前景/背景层是 null 或 {name, states, val, version};应保留两层和方块实体数据。缺少层、读回失败或不完整都与“观察到空气”不同。
自身物品栏读取
| Builder(另需公共关键字参数) | 操作权限 | 参数与证据 |
|---|---|---|
ctx.queries.inventory(window_id, slot) | framework.inventory.read | 旧的单槽缓存接口:window 0–4294967295、slot 0–255。数据为 {window_id,slot,cached:true,item},不是刷新。 |
ctx.queries.observe_inventory(window_id) | framework.self.inventory.observe | window 为主背包 0、副手 119、护甲 120,读取原生包观察,保留连接、revision、unknown 槽位。 |
ctx.queries.item_stack_responses(*, after=None, limit=8) | framework.self.inventory.stack_responses.read | 读取部分入站事务响应历史,limit 1–32;不是完整 NBT 或完成证明。 |
after 是 {"connection_id": "...", "revision": "123"};revision 必须是无前导零的 uint64 十进制字符串("0" 合法)。使用响应返回的游标,不能沿用旧连接的游标。响应明确保留 full_nbt_available=false、completion_proven=false。读取失败可出现 not_in_game、stack_responses_unavailable、stack_responses_packet_too_large 或 stack_responses_result_too_large。
以上均只观察机器人自身,不读取其他玩家的背包。新业务优先使用完整原生观察;缓存无记录不等于空槽,读取不更新原始观察的时间。物品结构、typed NBT 和事务核对见物品栏与容器。