结构化协议事件
比手工 pkt.unpack 更省事的一条路:让 C++ 侧把包解析成 dict 再交给你。
注册事件
python
import engine
def on_packet(event):
print(event["packet_id"], event["packet_name"], event["size"])
if event["parsed"]:
print(event["data"])
elif event["error"] is not None:
print("parse failed:", event["error"])
engine.register_structured_protocol_event(56, on_packet)第三个参数不要传 True
is_kernel 默认为 False。内核事件只应由框架自身注册 —— 插件传 True 会与框架抢注册。
事件结构
每次回调接收一个字典:
| 字段 | 类型 | 含义 |
|---|---|---|
packet_id | int | Bedrock 协议包 ID |
packet_name | str | 已知包名,未知时为 Unknown |
payload | bytes | 不含包 ID 的原始负载 |
size | int | 原始负载长度 |
parsed | bool | 是否已可靠解析为 data |
data | dict | None | 已解析字段,不支持解析时为 None |
error | str | None | 解析错误,没有错误时为 None |
支持结构化解析的包
MovePlayer、ContainerOpen、InventoryContent、BlockActorData、 PlayStatus、Text、CommandOutput、PlayerList
其他包仍会提供完整事件信封和原始负载,但 parsed 为 False。
解析失败不会中断别的回调
解析异常会保留在 error 字段中,不会影响其他协议回调的执行。
原有的 register_protocol_event 保持不变,回调仍只接收 bytes。
示例:从 BlockActorData 里取命令方块指令
python
def on_block_actor(event):
if not event["parsed"]:
return
tag = event["data"]["nbt"]
command = tag.Get("Command")
if command is not None:
print(command.GetValue())
engine.register_structured_protocol_event(56, on_block_actor)该用哪个接口?
| 场景 | 用 |
|---|---|
| 上表 8 个包,只要字段 | register_structured_protocol_event |
| 其他包 / 需要原始字节 | register_protocol_event + pkt |
| 聊天消息 | OnTextPacket 事件(见事件系统) |
