全局设置 (Settings)
Settings 节点用于配置菜单的全局行为参数,包括关闭方式、动作执行后的行为等。
配置项总览#
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
can_escape |
Boolean |
true |
是否允许玩家通过 ESC 键关闭菜单 |
after_action |
String |
CLOSE |
点击按钮执行动作后的客户端行为 |
lifetime |
Long |
300 |
菜单最大存在时间,单位为秒 |
need_placeholder |
List<String> |
null |
菜单所需的 PlaceholderAPI 扩展列表 |
min_click_delay |
Long |
0 |
仅 Container 菜单生效;同一会话中有效按钮点击的最小间隔,单位为毫秒 |
pass_arguments |
Section |
禁用 | 目标菜单参数传递设置,Dialog 和 Container 均支持 |
pass_arguments - 菜单参数#
pass_arguments 用于为目标菜单创建独立的参数上下文。参数不会写入 meta、数据库或共享 YAML,因此不会因为异步动作产生临时数据覆盖或读取延迟。
KaMenu 的标准配置节点名称是
Settings,完整路径为Settings.pass_arguments。
配置格式#
Settings:
pass_arguments:
enable: true
default:
- '默认值'
- '%player_name%'
- '{meta:test}'
- '{js:[hello]}'
must: 2
参数解析规则#
enable: false或未配置时,目标菜单不创建参数上下文default是按索引排列的默认参数列表- 打开目标菜单时,显式传入的参数优先
- 显式参数数量不足时,缺少的位置使用
default中同索引的值 - 默认值在目标菜单打开前解析,支持 PlaceholderAPI、KaMenu 内置变量、MetaData 和 JavaScript
must表示补充默认值后至少需要的参数数量;数量不足时阻止菜单打开must未配置或为0时不限制数量- 多出来的显式参数会保留
传参动作#
open 和 force-open 支持在菜单 ID 后继续写参数,参数可以使用空格或英文逗号分隔;参数包含空格时使用单引号、双引号或反引号包裹:
Buttons:
profile:
display:
material: PLAYER_HEAD
name: '&a打开资料'
actions:
left:
- 'open: profile/detail {meta:target} vip'
search:
display:
material: PAPER
name: '&a打开搜索'
actions:
left:
- 'open: search/result,`钻石 剑`'
目标菜单内部可以通过 {arg:0}、{arg:1} 读取参数,也可以使用 {args} 获取空格连接后的完整参数,使用 {arg_count} 获取参数数量。它们可用于标题、Body、按钮物品、条件、Events 和动作:
Title: '&8查询:{arg:0}'
Body:
info:
type: 'message'
text: '目标玩家:{arg:0},模式:{arg:1}'
Events:
Open:
- 'tell: &7正在打开 {arg:0} 的菜单'
Buttons:
confirm:
display:
material: EMERALD
name: '&a确认 {arg:0}'
actions:
left:
- 'tell: &a参数数量:{arg_count}'
- 'close'
reset 与菜单切换#
reset 会保留当前菜单已经解析完成的参数并重新渲染;使用 open 或 force-open 切换到新菜单时,新菜单会重新按照自身的 default 和 must 规则解析参数。
Container 菜单的 Settings#
箱子、漏斗、发射器、投掷器、熔炉、高炉、烟熏炉和铁砧菜单目前支持以下 Settings 配置:
Settings:
need_placeholder:
- 'player'
- 'vault'
min_click_delay: 200
need_placeholder#
need_placeholder 是 Container 和 Dialog 共用的 PlaceholderAPI 前置检查。列表中的每一项是 PlaceholderAPI 扩展标识符,例如:
%player_name%对应player%vault_eco_balance%对应vault
打开菜单时,KaMenu 会先检查 PlaceholderAPI 是否启用,以及这些扩展是否已经注册。检查失败会阻止菜单渲染,避免玩家打开显示不完整或动作判断错误的菜单。管理员会收到缺失扩展的可点击下载提示,普通玩家只会收到依赖缺失提示。
该配置不会自动扫描菜单中的所有 %...% 变量;菜单使用了 PlaceholderAPI 扩展时,应主动将扩展标识符写入列表。没有使用 PAPI 扩展的菜单无需配置 need_placeholder。
min_click_delay#
min_click_delay 用于限制同一玩家在当前 Container 菜单会话中的有效按钮点击频率,单位为毫秒,行为类似 TrMenu 的 Options.Min-Click-Delay:
Settings:
min_click_delay: 200
0或未配置:不限制点击频率,默认保持当前行为200:两次有效按钮点击之间至少间隔 200 毫秒- 只对按钮可见、且最终解析出动作的点击生效
- 空槽位、不可见按钮和没有动作的按钮不会消耗冷却
- 冷却按菜单会话记录;重新打开、
reset或切换到其他菜单后会重新计时 - 被冷却拦截的点击不会执行任何按钮动作,也不会改变物品或刷新菜单
建议将商店、领取奖励、扣除经济或点券等容易因重复点击产生重复执行的菜单设置为 150 至 300 毫秒。需要允许快速连续操作的菜单可以保持默认值 0。
Container 菜单不使用 Dialog 专属的 can_escape、after_action 和 lifetime 设置。Container 的关闭、动作完成后的跳转以及生命周期请使用按钮动作和 Events.Open / Events.Close 配置。
can_escape 参数#
功能说明#
控制菜单的关闭方式,决定玩家是否可以通过 ESC 键关闭菜单。
可选值#
| 值 | 说明 |
|---|---|
true(默认) |
玩家可通过 ESC 键关闭菜单,并触发底部按钮对应的动作 |
false |
玩家必须点击指定按钮才能关闭菜单,禁用 ESC 退出功能 |
配置示例#
Settings:
can_escape: false # 强制玩家必须点击按钮关闭菜单
使用场景#
推荐使用 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 服务端的菜单关闭定时器。
Spigot v1.7.0 同样支持 lifetime 主动关闭,并会清理 Tasks、分页状态和执行 Events.Close。纯客户端 url: / copy: 导致的提前关闭无法即时通知服务端,但仍会由 lifetime 兜底收尾。
达到上限后,KaMenu 会:
- 确认该玩家当前仍处于原菜单会话,避免旧定时器误关后来打开的新菜单;
- 主动关闭 Dialog;
- 停止该菜单的
Events.Tasks; - 清理 repeat 分页状态;
- 执行
Events.Close作为超时清理动作。
超时属于硬性上限,Events.Close 中的 return 不会阻止菜单关闭。小于或等于 0 的无效配置会回退到默认的 300 秒。
Settings:
lifetime: 300
所有服务端 callback 始终保持一次性。reset 或打开新菜单会重新创建 callback,并重新计算 lifetime。lifetime 可用于关闭长时间停留的菜单或等待遮罩,但不能代替按钮动作中的正常关闭或刷新逻辑。
after_action 参数#
功能说明#
定义玩家点击按钮后,客户端在等待服务器响应期间的行为。
背景:为什么需要此参数?#
服务器与客户端之间的网络通信存在一定的延迟:
- 正常情况:延迟仅为几十毫秒
- 网络差/服务器负载高:延迟可能达到 1 秒或更长
在此期间,如果玩家对游戏世界进行操作(如移动物品、丢弃物品等),可能导致后续菜单逻辑与实际状态不一致,引发异常行为。
after_action 参数用于声明在客户端本地执行指定操作,防止玩家在服务器响应期间进行非法操作,确保菜单逻辑的完整性。
可选值#
| 值 | 客户端行为 | 适用场景 |
|---|---|---|
CLOSE(默认) |
直接关闭菜单界面 | 没有二级菜单或无需处理后续行为的场景 |
NONE |
不执行任何本地行为 | 需要由服务器显式关闭、刷新或打开新菜单的场景 |
WAIT_FOR_RESPONSE |
显示遮罩界面,等待服务器响应 | 需要等待服务器显式关闭、刷新或打开新菜单的场景 |
配置示例#
Settings:
after_action: CLOSE # 默认值
# after_action: NONE
# after_action: WAIT_FOR_RESPONSE
详细说明#
1. CLOSE(默认)#
点击按钮后,客户端立即关闭菜单界面。
优点:
- 简单直接
- 用户体验流畅
缺点:
- 无法防止网络延迟期间的非法操作
适用场景:
- 没有二级菜单的简单菜单
- 无需处理后续行为的场景
示例:
Settings:
after_action: CLOSE
Bottom:
type: 'notice'
confirm:
text: '&a[ 关闭 ]'
actions:
- 'close'
2. NONE#
点击按钮后,客户端不执行任何本地行为,所有逻辑由服务器控制。
优点:
- 灵活性最高
- 服务器完全控制菜单行为
- 适合需要根据条件决定关闭、刷新或打开其它菜单的场景
缺点:
- 需要在每个按钮动作路径中明确关闭、刷新或打开菜单
适用场景:
- 需要完全由服务器控制行为的场景
- 需要根据条件决定是否关闭的场景
- 点击后需要刷新当前菜单或打开其它菜单的场景
示例:
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 较低的服务器
- 点击后必须等待服务端完成校验、刷新或跳转的场景
示例(带二级菜单):
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 权限):会显示详细提示,包含缺失的扩展列表和点击下载按钮
- 普通玩家:会显示简化的提示信息
此功能确保菜单中的占位符变量能正常工作,避免因扩展缺失导致的显示错误。
配置格式#
Settings:
need_placeholder:
- 'player' # Player 扩展
- 'server' # Server 扩展
- 'vault' # Vault 扩展
可选值#
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 权限)尝试打开缺少依赖的菜单时,会显示类似以下信息:
§c该菜单需要以下PlaceholderAPI扩展:§e[player],§e[server]
每个扩展名称(如 [player])都是可点击的:
- 点击扩展:自动执行
/papi ecloud download <扩展名>命令 - 悬停显示:显示将要执行的具体下载命令
普通玩家提示#
普通玩家会看到简化提示:
§c该菜单缺少必要的依赖文件,请联系管理员。
(可在语言文件中自定义)
完整示例#
示例 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. 默认配置推荐#
对于大多数菜单,推荐使用以下默认配置:
Settings:
can_escape: true
after_action: NONE
使用该配置时,所有按钮动作路径都必须显式 close、reset 或打开其它菜单。
2. 重要操作配置#
对于涉及重要操作(删除、支付、权限变更等)的菜单:
Settings:
can_escape: false
after_action: WAIT_FOR_RESPONSE
重要提示: 使用 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 集成