正在载入

等待时间过长时请刷新页面

编写于

最近更新

交互式命令

交互式命令允许参数通过玩家接下来的游戏操作取得。例如,命令可以等待玩家点击一个方块,再把对应的 Block 交给执行器。

交互参数由 Bukkit Runtime 提供,只能由玩家触发。Core 在解析到交互参数时保存当前命令节点、已解析变量、参数位置和输入位置;Bukkit Runtime 收到目标事件后把结果交还 Core,Core 从下一个参数继续解析并最终执行同一个叶子处理器。

点击方块

声明交互参数:

commands.register(
        "rs select block <selection:event:block>",
        ctx -> {
            Player player = ctx.requirePlayer("Only players can select blocks");
            Block block = ctx.get("selection");
            selectionService.select(player, block);
        },
        CommandOptions.options()
                .permission("rainbowedit.select.block")
                .player()
                .i18n(i18n)
);

当前交互参数仍然占用一个命令 token。玩家需要输入一段用于进入该参数位置的内容,例如:

/rs select block begin

begin 的文本不会用于选择方块。解析器到达 selection:event:block 后挂起命令并提示玩家点击,随后用实际点击的 Block 替换这个参数。

交互参数之前的普通参数会被保存,之后的参数会在交互完成后继续解析:

rs region point <index:int(1..2)> <block:event:block> [name:string=default]

交互完成后,执行器可以同时读取 indexblockname

支持的交互类型

Bukkit Runtime 当前注册以下类型:

  1. event:block:等待玩家点击方块,返回 Block
  2. break:block:等待玩家破坏方块,返回 Block
  3. place:block:等待玩家放置方块,返回放置后的 Block
  4. event:entity:等待玩家右键实体,返回 Entity
  5. damage:entity:等待玩家攻击实体,返回被攻击的 Entity
  6. kill:entity:等待玩家击杀实体,返回死亡的实体。
  7. event:item:等待玩家点击容器中的物品,返回 ItemStack
  8. shoot:block:等待玩家发射的抛射物命中方块,返回 Block

交互类型会检查发送者是否为 Bukkit Player。即使叶子使用默认的 ALL,控制台解析交互参数时仍然会失败;交互命令应通过 CommandOptions.player() 明确限制为玩家执行。

挂起与恢复

sequenceDiagram
    participant Player as 玩家
    participant Command as 命令服务
    participant Hub as InteractionHub
    participant Bukkit as Bukkit 事件

    Player->>Command: 输入包含交互参数的命令
    Command->>Command: 解析前置参数并保存游标
    Command->>Hub: 等待指定交互
    Hub-->>Player: 显示交互提示
    Player->>Bukkit: 点击、破坏或攻击
    Bukkit->>Hub: 发送目标事件
    Hub->>Command: 返回 Block、Entity 或 ItemStack
    Command->>Command: 恢复后续参数解析
    Command->>Player: 执行叶子处理器

恢复过程继续使用原命令服务中已经安装的全部解析器,不会另外建立一套基础参数解析器。一个命令包含多个交互参数时,前一个完成后可以再次挂起并等待下一个交互。

权限和执行目标在首次参数解析前完成检查,因此无权限玩家不会进入等待状态。

使用限制

使用交互式命令时,需要注意:

  1. 每名玩家同时只保存一个待处理交互;新的等待会覆盖旧等待。
  2. 交互事件被其他插件取消时,Linlang 不会用该事件完成参数选择。
  3. Linlang 不会主动取消点击、破坏、放置、攻击或容器事件,原本的游戏行为仍会继续。
  4. event:item 点击空槽位时可能得到 null,业务代码必须检查结果。
  5. 玩家退出服务器时没有单独的失败回调,待处理状态会在命令服务关闭时统一清除。
  6. 只有收到对应事件时才会检查交互是否过期,不会在到期时主动发送超时消息。
  7. CommandFailure.Reason 预留了 INTERACTION_TIMEOUTINTERACTION_CANCELLED,当前 Bukkit Runtime 尚未把超时和取消通知给命令组失败回调。
  8. 交互参数的 Tab 提示当前由 Bukkit Runtime 提供固定文本,不属于命令参数的 LangText 标签。

交互处理器执行的业务代码仍位于普通叶子执行器中,因此成功、参数失败和业务执行失败会继续触发所属命令组的结果回调。尚未产生通知的超时与取消不在此范围内。

讨论

请登录账号