⚙️ 全局设置 (Settings)¶
Settings 节点用于配置菜单的全局行为参数,包括关闭方式、动作执行后的行为等。
配置项总览¶
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
can_escape |
Boolean |
true |
是否允许玩家通过 ESC 键关闭菜单 |
after_action |
String |
CLOSE |
点击按钮执行动作后的客户端行为 |
lifetime |
Long |
300 |
菜单最大存在时间,单位为秒 |
need_placeholder |
List<String> |
null |
菜单所需的 PlaceholderAPI 扩展列表 |
can_escape 参数¶
功能说明¶
控制菜单的关闭方式,决定玩家是否可以通过 ESC 键关闭菜单。
可选值¶
| 值 | 说明 |
|---|---|
true(默认) |
玩家可通过 ESC 键关闭菜单,并触发底部按钮对应的动作 |
false |
玩家必须点击指定按钮才能关闭菜单,禁用 ESC 退出功能 |
配置示例¶
使用场景¶
推荐使用 true(默认):
- 普通菜单,允许玩家随时退出
- 需要灵活关闭的场景
推荐使用 false:
- 重要确认菜单(如确认删除、确认支付)
- 管理员操作菜单
- 需要确保用户选择一个选项的场景
- 使用
Events.Tasks且需要明确控制关闭动作和任务停止时机的场景
ESC 触发的按钮动作¶
当 can_escape: true 时,玩家按 ESC 会根据底部按钮类型触发对应按钮的动作:
| 菜单类型 | ESC 触发的动作 |
|---|---|
notice |
唯一按钮的动作 |
confirmation |
deny(取消)按钮的动作 |
multi |
已配置 exit 按钮时,触发 exit 按钮的动作 |
如果菜单依赖关闭事件或周期任务生命周期,ESC 所触发的按钮本身就是关闭路径;通常不需要在该按钮动作里额外写 close。只有你想在其它分支里主动关闭菜单时,才使用 close 或 force-close。
示例配置:
Settings:
can_escape: true
Bottom:
type: 'confirmation'
confirm:
text: '&a[ 确认 ]'
actions:
- 'tell: &a你选择了确认'
deny:
text: '&c[ 取消 ]'
actions:
- 'tell: &c你选择了取消'
- 'close'
lifetime 参数¶
lifetime - 菜单存在时间上限¶
lifetime 的单位为秒,默认值为 300(5 分钟)。该值同时决定 Paper callback 的有效期和 KaMenu 服务端的菜单关闭定时器。
达到上限后,KaMenu 会:
- 确认该玩家当前仍处于原菜单会话,避免旧定时器误关后来打开的新菜单;
- 主动关闭 Dialog;
- 停止该菜单的
Events.Tasks; - 清理 repeat 分页状态;
- 执行
Events.Close作为超时清理动作。
超时属于硬性上限,Events.Close 中的 return 不会阻止菜单关闭。小于或等于 0 的无效配置会回退到默认的 300 秒。
所有服务端 callback 始终保持一次性。reset 或打开新菜单会重新创建 callback,并重新计算 lifetime。lifetime 可用于关闭长时间停留的菜单或等待遮罩,但不能代替按钮动作中的正常关闭或刷新逻辑。
after_action 参数¶
功能说明¶
定义玩家点击按钮后,客户端在等待服务器响应期间的行为。
背景:为什么需要此参数?¶
服务器与客户端之间的网络通信存在一定的延迟:
- 正常情况:延迟仅为几十毫秒
- 网络差/服务器负载高:延迟可能达到 1 秒或更长
在此期间,如果玩家对游戏世界进行操作(如移动物品、丢弃物品等),可能导致后续菜单逻辑与实际状态不一致,引发异常行为。
after_action 参数用于声明在客户端本地执行指定操作,防止玩家在服务器响应期间进行非法操作,确保菜单逻辑的完整性。
可选值¶
| 值 | 客户端行为 | 适用场景 |
|---|---|---|
CLOSE(默认) |
直接关闭菜单界面 | 没有二级菜单或无需处理后续行为的场景 |
NONE |
不执行任何本地行为 | 需要由服务器显式关闭、刷新或打开新菜单的场景 |
WAIT_FOR_RESPONSE |
显示遮罩界面,等待服务器响应 | 需要等待服务器显式关闭、刷新或打开新菜单的场景 |
配置示例¶
详细说明¶
1. CLOSE(默认)¶
点击按钮后,客户端立即关闭菜单界面。
优点:
- 简单直接
- 用户体验流畅
缺点:
- 无法防止网络延迟期间的非法操作
适用场景:
- 没有二级菜单的简单菜单
- 无需处理后续行为的场景
示例:
2. NONE¶
点击按钮后,客户端不执行任何本地行为,所有逻辑由服务器控制。
优点:
- 灵活性最高
- 服务器完全控制菜单行为
- 适合需要根据条件决定关闭、刷新或打开其它菜单的场景
缺点:
- 需要在每个按钮动作路径中明确关闭、刷新或打开菜单
适用场景:
- 需要完全由服务器控制行为的场景
- 需要根据条件决定是否关闭的场景
- 点击后需要刷新当前菜单或打开其它菜单的场景
警告
重要提示:
当 after_action: NONE 时,客户端点击按钮后不会自动关闭菜单,但普通按钮和正文可点击文本的服务端 callback 均固定只能触发一次。若动作完成后没有关闭或重建菜单,后续点击将不会再产生服务器回调,客户端会留下无法响应的缓存界面。
使用 after_action: NONE 时,必须确保每个按钮的每条条件分支最终执行以下动作之一:
- close / force-close:关闭菜单
- reset:刷新当前菜单,重新建立按钮回调
- open / force-open:打开其它菜单
lifetime 到期时会主动关闭菜单,避免失效界面长期残留,但它只是一项兜底措施。
示例:
Settings:
after_action: NONE
Bottom:
type: 'confirmation'
confirm:
text: '&a[ 确认删除 ]'
actions:
- condition: '%player_balance% >= 1000'
allow:
- 'console: eco take %player_name% 1000'
- 'tell: &a扣款成功!'
- 'close' # 手动关闭菜单
deny:
- 'tell: &c余额不足!'
- 'reset' # 重新渲染菜单,避免留下无回调的旧界面
deny:
text: '&c[ 取消 ]'
actions:
- 'close'
3. WAIT_FOR_RESPONSE¶
点击按钮后,客户端显示遮罩界面,等待服务器响应后继续操作。
优点:
- 完全防止网络延迟期间的非法操作
- 适合重要操作
- 用户体验稳定
缺点:
- 需要确保每个按钮动作路径最终关闭、刷新或打开菜单(否则会卡在遮罩界面)
- 增加一步等待时间
适用场景:
- 有二级菜单(会自动打开新菜单)
- 涉及重要操作(交易、权限变更)
- 网络环境不稳定或 TPS 较低的服务器
- 点击后必须等待服务端完成校验、刷新或跳转的场景
警告
重要提示:
使用 WAIT_FOR_RESPONSE 时,客户端会进入等待响应状态。和 NONE 一样,按钮回调仍然是一次性的;如果动作链结束后没有 close、reset、open / force-open 等能关闭或重新渲染菜单的动作,客户端会持续停留在等待遮罩或旧菜单状态,玩家无法继续有效交互。
因此,使用 WAIT_FOR_RESPONSE 时,请确保每个按钮的每条条件分支最终都会执行以下动作之一:
- close / force-close:关闭菜单并结束等待
- reset:刷新当前菜单并重新建立按钮回调
- open / force-open:打开其它菜单并结束当前等待
示例(带二级菜单):
Settings:
after_action: WAIT_FOR_RESPONSE
Bottom:
type: 'multi'
buttons:
open_sub_menu:
text: '&a[ 打开子菜单 ]'
actions:
- 'open: shop/weapons' # 打开二级菜单,会自动关闭遮罩
exit:
text: '&c[ 退出 ]'
actions:
- 'close'
示例(无二级菜单,必须显式结束):
Settings:
after_action: WAIT_FOR_RESPONSE
Bottom:
type: 'confirmation'
confirm:
text: '&a[ 确认支付 ]'
actions:
- 'console: eco take %player_name% 1000'
- 'tell: &a支付成功!'
- 'close' # 必须:关闭菜单,移除遮罩
deny:
text: '&c[ 取消 ]'
actions:
- 'close' # 必须:关闭菜单,移除遮罩
示例(校验失败后继续交互,必须刷新):
Settings:
after_action: WAIT_FOR_RESPONSE
Bottom:
type: 'confirmation'
confirm:
text: '&a[ 确认 ]'
actions:
- condition: 'isPosInt.$(amount)'
allow:
- 'tell: &a输入有效'
- 'close'
deny:
- 'toast: type=task;msg=输入错误;icon=barrier'
- 'reset' # 必须:重新渲染菜单,移除等待状态并重建按钮回调
need_placeholder 参数¶
功能说明¶
配置菜单所需的 PlaceholderAPI 扩展列表。在打开菜单前,插件会检查所需的扩展是否已加载。如果扩展未加载:
- 管理员玩家(有 kamenu.admin 权限):会显示详细提示,包含缺失的扩展列表和点击下载按钮
- 普通玩家:会显示简化的提示信息
此功能确保菜单中的占位符变量能正常工作,避免因扩展缺失导致的显示错误。
配置格式¶
可选值¶
need_placeholder 是一个字符串列表,每个元素表示一个 PlaceholderAPI 扩展的标识符。
配置示例¶
基础示例:
Title: '&8» &6&l玩家信息 &8«'
Settings:
need_placeholder:
- 'player'
- 'vault'
Body:
message:
type: 'message'
text: |
&a玩家名称: %player_name%
&a玩家余额: %vault_eco_balance%
&a在线时间: %player_time_played%
Bottom:
type: 'notice'
confirm:
text: '&a[ 确定 ]'
actions:
- 'close'
管理员提示¶
当管理员(有 kamenu.admin 权限)尝试打开缺少依赖的菜单时,会显示类似以下信息:
每个扩展名称(如 [player])都是可点击的:
- 点击扩展:自动执行
/papi ecloud download <扩展名>命令 - 悬停显示:显示将要执行的具体下载命令
普通玩家提示¶
普通玩家会看到简化提示:
(可在语言文件中自定义)
信息
如何获取扩展标识:
1. 使用 /papi list 命令查看已安装的扩展
2. 访问 PlaceholderAPI Expansion 搜索扩展
3. 查看扩展的官方文档或源码
完整示例¶
示例 1:普通商店菜单(推荐配置)¶
Title: '&8» &6&l服务器商店 &8«'
Settings:
can_escape: true # 允许 ESC 退出
after_action: NONE # 由服务器控制
pause: false
Bottom:
type: 'multi'
buttons:
buy:
text: '&a[ 购买 ]'
actions:
- 'console: give %player_name% diamond 1'
- 'console: eco take %player_name% 100'
- 'tell: &a购买成功!'
- 'close'
exit:
text: '&c[ 退出 ]'
actions:
- 'tell: &c再见!'
- 'close'
示例 2:重要确认菜单¶
Title: '&8» &c&l确认删除 &8«'
Settings:
can_escape: false # 禁止 ESC 退出
after_action: WAIT_FOR_RESPONSE # 防止网络延迟操作
pause: false
Bottom:
type: 'confirmation'
confirm:
text: '&c[ 确认删除 ]'
actions:
- condition: '%player_name% == target_player'
allow:
- 'tell: &a已删除目标物品'
- 'close' # 必须:关闭菜单
deny:
- 'tell: &c你不是物品所有者!'
- 'close'
deny:
text: '&a[ 取消 ]'
actions:
- 'tell: &a已取消删除'
- 'close' # 必须:关闭菜单
示例 3:管理员操作菜单¶
Title: '&8» &4&l管理员工具 &8«'
Settings:
can_escape: false # 禁止 ESC 退出
after_action: NONE # 由服务器控制
pause: false
Bottom:
type: 'multi'
buttons:
ban:
text: '&c[ 封禁玩家 ]'
actions:
- 'open: admin/ban_player'
kick:
text: '&e[ 踢出玩家 ]'
actions:
- 'open: admin/kick_player'
exit:
text: '&7[ 返回 ]'
actions:
- 'open: main_menu'
示例 4:简单通知菜单¶
Title: '&8» &a&l通知 &8«'
Settings:
can_escape: true # 允许 ESC 退出
after_action: CLOSE # 直接关闭
pause: false
Body:
message:
type: 'message'
text: |
&a欢迎访问我们的服务器!
&7请遵守服务器规则,共同维护良好的游戏环境。
Bottom:
type: 'notice'
confirm:
text: '&a[ 确定 ]'
actions:
- 'tell: &a已阅读通知'
最佳实践¶
1. 默认配置推荐¶
对于大多数菜单,推荐使用以下默认配置:
使用该配置时,所有按钮动作路径都必须显式 close、reset 或打开其它菜单。
2. 重要操作配置¶
对于涉及重要操作(删除、支付、权限变更等)的菜单:
重要提示: 使用 WAIT_FOR_RESPONSE 时,确保所有按钮动作路径最终都会 close、reset 或打开其它菜单。
3. 条件关闭配置¶
当需要根据条件决定是否关闭菜单时:
Settings:
can_escape: true
after_action: NONE
Bottom:
type: 'confirmation'
confirm:
text: '&a[ 确认 ]'
actions:
- condition: 'checkCondition'
allow:
- 'tell: &a操作成功'
- 'close'
deny:
- 'tell: &c操作失败,请重试'
- 'reset' # 保持菜单可交互时必须重新渲染
4. 网络环境考虑¶
网络良好的服务器:
- 大部分场景使用
after_action: NONE - 简单菜单可以使用
after_action: CLOSE - 使用
after_action: NONE时,每个按钮路径最终必须close、reset或打开其它菜单,避免客户端保留无回调的缓存界面
网络不稳定或 TPS 较低的服务器:
- 重要操作使用
after_action: WAIT_FOR_RESPONSE - 确保每个按钮路径最终都会
close、reset或打开其它菜单
注意事项¶
-
after_action 选择
- 默认使用
NONE,灵活性最高 - 重要操作使用
WAIT_FOR_RESPONSE,确保数据一致性 NONE不会自动关闭菜单,按钮回调是一次性的;所有动作分支都必须显式close、reset或openWAIT_FOR_RESPONSE也必须显式结束或重建交互;所有动作分支都必须close、reset或open
- 默认使用
-
can_escape 使用
- 普通菜单保持
true,提供更好的用户体验 - 重要确认菜单设为
false,强制用户选择 - 使用
Events.Tasks或依赖Events.Close时,优先让 ESC 对应按钮承担关闭职责;只有需要手动关闭其它分支时才使用close/force-close
- 普通菜单保持
-
pause 参数
- 仅单机有效,多人服务器无需关注
- 通常保持默认值
false
-
向后兼容
- 旧版本配置文件不包含
Settings节点时,使用默认值 - 建议所有新配置文件都包含
Settings节点
- 旧版本配置文件不包含
相关文档¶
- 🔘 底部按钮 (Bottom) - 了解按钮动作配置
- 🤖 动作 (Actions) - 了解所有可用的动作类型
- ⚙️ 事件 (Events) - 了解事件系统
- 📊 PlaceholderAPI - 了解 PlaceholderAPI 集成