跳转到正文

按任务开发 ​

从要做的功能选择入口,用配套工具包运行示例。中文命令、玩家动作和一次提交等常用写法见作者便利接口。组合多个动作、解释 typed 协议字段或设计共享 provider,见用 Python 组合能力。

找到起点 ​

想做什么从哪里开始先确认什么
做第一个插件、保存配置与启动次数第一个插件Python 3.10+、工具包和目标 Host 版本
玩家输入指令后计数、查询或触发业务下方聊天示例 · 事件聊天事件源、名单权限、输入规则与 ACK
查询玩家、发送通知或执行命令玩家 · 通知 · 命令精确身份、对应操作权限和回执含义
保存奖励记录、定时处理或插件协作事务与服务 · 生命周期重复触发、持久状态、停止及恢复规则
操作方块、BDX、背包或机器人能力总览目标版本、连接证据、最小权限和实际读回

聊天命令计数 ​

制作一个 !计数 命令,保留 !count 别名:已识别玩家每发送一次,插件将全局计数增加一并记录日志。计数与事件确认一起保存;它不向游戏发消息,也不发放物品。

1. 创建与修改 ​

在解压后的工具包目录运行:

sh
python3 runtime-plugins.py --directory plugins --id example.chatcounter --template event-counter new chatcounter

在生成的 plugins/chatcounter/manifest.json 中保留 chat.received 订阅,将 host_api.min_minor 从 0 改为 1,再将 permissions 改为下方内容。名单权限要求 Host API 至少 1.1,用于核对聊天身份;订阅和权限仍需管理员授权。

text
"permissions": {
  "operations": [],
  "services": [],
  "players": ["list"]
}

将生成的 main.py 替换为:

python
from dataclasses import dataclass, field
from neomega_runtime import Plugin, ChatArgumentError


@dataclass
class Settings:
    greeting: str = field(
        default="你好",
        metadata={"title": "启动问候语", "description": "插件启动时记录的问候语。"},
    )


class MyPlugin(Plugin):
    config_type = Settings

    async def on_validate(self, ctx):
        count = await ctx.storage.get("count", 0)
        if type(count) is not int or count < 0:
            raise ValueError("count must be a nonnegative integer")

    async def on_start(self, ctx):
        ctx.log.info("%s; 输入 !计数 可增加计数", ctx.config.greeting)

        @ctx.chat.command("计数", aliases=("count",),
                          description="增加全局计数", usage="!计数", max_args=0)
        async def count_command(command):
            tx = await command.event.transaction()
            count = tx.increment("count")
            await tx.save()
            ctx.log.info("persisted command count=%d", count)

    async def on_event(self, ctx, event):
        try:
            handled = await ctx.chat.dispatch(event)
        except ChatArgumentError as exc:
            ctx.log.info("用法:%s,不需要参数", exc.command.usage)
            await event.ack()
            return
        if not handled:
            await event.ack()


if __name__ == "__main__":
    MyPlugin().run()

此例沿用模板配置类型,不需要修改 schema 或发布清单;同步修改生成的 README,说明 !计数 与 !count 触发同一命令。max_args=0 自动拒绝多余参数,description/usage 可用于制作帮助菜单。参数支持引号,名称与别名区分大小写。

路由器会核对聊天姓名及非空 XUID 与缓存名单。无法解析的引号、身份冲突或处理器错误向上传递,本例不吞掉异常;日志与恢复方法见事件和错误。保存超时后先查原提交,不能重新计数。

2. 检查与打包 ​

sh
python3 runtime-plugins.py lint plugins/chatcounter --json
python3 runtime-plugins.py pack plugins/chatcounter chatcounter.zip
python3 runtime-plugins.py check chatcounter.zip

检查通过后得到 chatcounter.zip。lint 与制品检查不执行聊天业务;实际安装按第一个插件,将安装名换为 chatcounter。

3. 在目标实例验收 ​

由管理员配置、授权并启动后,用真实玩家聊天触发以下情况:

输入或操作预期结果
发送 !计数 或 !count插件日志计数增加一;游戏内不显示回复。
发送普通聊天或未知命令不增加计数,事件完成确认。
发送 !count extra记录用法,不增加计数。
重载当前制品,再发送 !count原计数保留并继续增加。

初始名单缺失时不能靠伪造聊天或机器人 say 替代真实玩家输入。日志符合预期才算该场景运行通过;后续加入通知或奖励时,还需单独检查游戏动作回执和实际效果。

直接使用两个能力组合示例 ​

工具包的 examples/native-feedback 在收到 !feedback 时为已核对玩家准备标题和声音,把动作接纳与事件 ACK 一起保存。它演示组合现有 helper、保留原始意图,以及遇到 unknown 后查询原动作。

examples/typed-radius-observer 只读观察入站 NetworkChunkPublisherUpdate,把 Radius 解释为方块半径,并保留连接和源序列;流中断时停止推断。这两例的检查、打包与运行步骤见用 Python 组合能力。

从示例扩展到业务 ​

保持触发、授权、状态提交和结果验收可分别检查。需要玩家可见回复时使用通知;需要奖励或其他写入时,在事件事务中登记动作,并按回执流程核对最终结果。等待超时或 unknown 保留原意图与标识,不自动重放。

将需求交给 AI 时使用AI 开发说明。交付与故障定位见调试与验收,更换源码后按插件更新安装新制品;reload 只重启已安装版本。

Neomega · 使用、开发与参考文档