[MD] ### KaProxy 跨服目标选择器 - 新增 `{cross}` 标记。在动作末尾的目标选择器 `{player: 选择器}` 后追加 `{cross}`,即可通过 KaProxy 把动作转发到其他后端执行。 - 新增 KaMenu `kaproxy.enabled` 配置项。启用后自动注册 `kaproxy:main` 插件消息通道;关闭或卸载时自动注销。 - KaProxy 新增 `modules.kamenu` 模块及 `servers` 配置。列表控制可接收跨服动作的后端;设为 `all` 或 `*` 时转发到所有后端,始终排除来源服。 - 目标后端收到动作后在本地求值选择器,因此 PAPI 变量和 KaMenu 内置条件在各服均可正常使用。 - 跨服执行采用后端白名单保护,仅支持 `tell`、`actionbar`、`title`、`sound`、`hovertext`、`money`、`points`、`data`、`gdata`、`tmpdata`、`meta`、`set-data`、`set-gdata`、`set-meta`。非白名单动作会被拒绝并记录警告。 - `/kaproxy status` 现在显示 Kamenu 模块状态。 ### 文档 - 新增 KaProxy Kamenu 模块中英文文档,并补充 KaMenu 中英文动作文档与菜单编写 Skill 的跨服选择器说明。 ### 容器类多页菜单与运行时动态槽位 - **多页菜单**:KaMenu 容器类菜单现在支持原生多页布局。`Layout` 接受页数组(如 `[['A...'], ['B...']]`),`page: n` / `page: next` / `page: prev` / `page: +n` / `page: -n` 动作在会话内安全切页,不触发菜单 Open/Close,并保留参数、任务和图标状态。迁移器将 TrMenu 多页 `Layout` 与 `Default-Layout` 无损转换为 `Layout` 页数组与 `Settings.default_page`。 - **运行时动态槽位**:按钮可声明 `slot` 表达式(支持 PAPI 变量与 KaMenu 变量),在每次打开、刷新或翻页时按玩家状态解析为槽位,不再依赖静态 `Layout` 字符。例如 `slot: '%player_empty_slots%'` 让按钮随玩家空槽数量移动。 - **多副本槽位**:`slot: [8, 9, 10]`(扁平列表)表示同一按钮同时渲染在多个槽位。 - **运动帧动画**:`slot: [[8], [9], [10]]`(列表的列表)表示逐帧循环,每次刷新把按钮移动到下一帧位置,实现 TrMenu 风格的运动槽位效果。 - 点击位置优先查运行时动态槽位映射,再回退到静态布局。动态槽位与静态布局槽位冲突时跳过该动态按钮,旧槽位物品在帧切换时被自动清理。 - **运行时标题覆盖(`set-title` 动作)**:新增 `set-title: <标题>` 动作,可在点击或任务中动态覆盖当前容器会话的库存窗口标题,优先级高于配置 `Title`。覆盖值会一直生效直到会话结束,后续 `refresh: title` / `refresh: *` 与周期 `Title-Update` 都以该覆盖值刷新,因此可结合 PAPI 变量做出随状态变化的标题。该动作与 `title:`(向玩家发送淡入淡出大标题特效、不影响库存标题)相互区分。 ### 修复 - 修复 Paper 原生 Dialog 的 `Inputs` 中 `type: checkbox` 无论勾选状态如何都返回 `false` 的问题。回调现在按组件声明类型读取响应,checkbox 使用布尔值读取,不再被数值读取的默认 `0` 覆盖。 - 修复 Paper 平台上聊天可点击文本(`hovertext:` 发送、`<text=...;actions=...>`)的自定义回调在执行 `Events.Click` 动作时丢失 `contextId` 的问题。`contextId` 现已沿解析链路(`parseClickableText` → 回调 → `executeActionList`)透传,与 Spigot 路径一致,使点击回调能正确关联原菜单的参数会话与任务上下文(此前 Paper 该路径的 `contextId` 为空)。 [/MD]
[MD] ### 临时数据 tmpdata - 新增 `tmpdata:` 动作,支持带到期时间的玩家级键值对,到期后自动清空,适合冷却、限时加成、限时称号等场景。 - 数据持久化到 SQLite/MySQL,玩家下线或服务器重启后仍按原到期时间计算,不会提前失效。 - 支持 `set`、`add`、`take`、`addtime`、`taketime`、`refresh`、`delete` 七种操作类型。 - `ttl` 参数支持纯数字(按秒)与 `1d2h30m15s` 组合(d/h/m/s,不区分大小写)两种写法,`ttl=0` 可作立即作废。 ### 时间与数值边界 - `addtime` 只延长到期时间,`taketime` 提前到期;`taketime` 后剩余时间小于等于 0 时立即删除该键(扣时间溢出处理)。 - `refresh` 把到期时间重置为 now + `ttl`,不保留剩余时间。 - `add` / `take` 命中有效键时只改动数值,提供 `ttl` 时同时续期;键不存在或已过期时必须有 `ttl` 才能按新键写入。 - `addtime` / `taketime` / `refresh` 作用于不存在或已过期的键时安全跳过并输出警告,不会复活旧键。 - 到期时间戳运算使用饱和加法,极端数值不会导致 Long 溢出。 ### 读取与剩余时间展示 - 新增 `{tmpdata:键名}`(存储值)、`{tmpdata_time:键名}`(剩余秒数,纯整数,已过期返回 `0`)、`{tmpdata_time_format:键名}`(可读文本如 `1天 2时 30分 15秒`)三个内置变量,可在普通文本与条件表达式中使用。 - 新增 PAPI 占位符 `%kamenu_tmpdata_键名%`、`%kamenu_tmpdata_time_键名%`(纯数字秒数,方便其他插件直接数值判断)、`%kamenu_tmpdata_timeformat_键名%`(用户可读文本)。 - 新增 JavaScript 便捷函数 `tmpdata(key, targetPlayer)`,脚本内也可用 `kvar("tmpdata_time:key")`、`kvar("tmpdata_time_format:key")` 读取剩余时间。 - 到期值读取时立即返回空,数据库中的过期行由周期任务(`config.yml` 的 `tmpdata-purge-interval`,默认 60 秒)在异步线程物理清理。 [/MD]
[MD] ### Container 自由槽位 - 新增顶层 `Free-Slots`,可在箱子、漏斗、发射器和投掷器菜单中定义一个或多个具名真实物品槽位。 - 支持左/右键放入和取出、同类物品合并、异种交换、Shift 转移及受控拖拽;数字键、副手、双击、丢弃和创造克隆等高风险操作默认拒绝。 - 新增 `place` / `take` 开关和条件,以及 `place`、`take`、`deny_place`、`deny_take` 事务事件;拒绝操作时物品保持在原位置。 - 新增 `{free:<id>.*}`、`{free:incoming.*}`、`{free:stored.*}` 和 `{free:result.*}` 物品属性变量,支持数量、材质、名称、Lore、附魔、模型、外部物品来源等状态。 - 新增 `[FREE:<id>]` 完整 ItemStack 预览,可保留药水、书本、PDC 及 Bukkit 可访问的其他物品元数据。 ### 原子消费与返还 - 新增 `free-slot` 动作,支持单槽消费、多材料原子消费、主动返还一个或全部自由槽,以及刷新引用自由槽的按钮。 - 多材料不足、ID 无效、会话失效或背包容量不足时不执行部分修改,并中断当前动作链,避免材料不足仍发放奖励。 - 自由槽变化后自动刷新全部 Container 按钮,`variants` 可立即根据材料状态切换外观和动作。 ### 持久化托管与安全恢复 - 新增自由槽持久化托管账本和 `PREPARED`、`HELD`、`RETURN_PENDING` 等状态,SQLite 与 MySQL 写入按会话串行执行。 - 正常关闭、菜单跳转、重载和玩家退出时返还真实物品;背包不足时保留待返还记录并在玩家下次登录时重试。 - 释放示例菜单触发菜单重载前会先安全关闭活动 Container 会话,避免旧代际窗口遗留自由槽物品。 - 插件停用时保留托管记录并等待已开始的 SQL 操作,避免 Folia 玩家调度与数据库连接池关闭时序导致物品丢失。 - 修复新版 Paper 不再提供 SnakeYAML 私有 `Base64Coder` 时,自由槽首次放入物品抛出 `NoClassDefFoundError` 的问题;旧版换行 Base64 数据仍可读取。 - 优化自由槽放入、取出、交换、Shift 和拖拽的客户端同步,在玩家事件线程直接提交已校验的最终状态,避免取消原版事务后出现回滚再渲染的双重动画。 - 自由槽 SQL 托管失败时会关闭当前窗口并进入统一返还流程,避免已提交到 UI 的真实物品滞留在无可靠账本的会话中。 - Paper、Folia 与 Spigot 统一使用服务端当前槽位和玩家光标重放已取消的左右键事务,不再依赖不同核心的 `InventoryAction` 或事件光标快照,避免普通放入和取出时丢失物品。 ### 兼容性与文本图标 - 修复 Spigot Dialog 可点击文本在 `text` 或 `hover` 中包含 ItemsAdder、Oraxen、CraftEngine 字形标签时,被内部 `>` 提前截断并退化为纯文本的问题。 - 扩展 `&item:[...]` 二维图标语法,可自动解析原版材质以及 ItemsAdder、Oraxen、CraftEngine 自定义物品纹理,并支持通过根目录 `item_sprites.yml` 覆盖复杂模型的图标。 - Sprite 图标仅在 Minecraft `1.21.9+` 启用;运行于 `1.21.8` 及以下服务器时会安全隐藏标记,且不调用第三方物品 API 或读取其资源包。 ### TrMenu 迁移修复 - 修复 `action` / `actions` 被宽泛匹配为 `actionbar` 的问题;标准 YAML 锚点包装的 `actions` 列表会先展开,再逐项转换内部动作。 - 迁移器现在处理 YAML 解析后的锚点内容,不再把 `*锚点名` 当作动作文本;源锚点名称可能由输出序列化器展开或重新命名。 [/MD]
[MD] ### 容器类菜单文档重构 - 重构中英文容器类菜单文档,为 `Type`、`Title`、`Settings`、`Layout`、`Buttons`、`Properties`、刷新机制和 `Events` 增加字段一览表、逐项说明和实际案例。 - 新增从文件创建、布局设计、按钮定义到重载打开的容器类菜单新手教程,并补充常见解析错误和动态 `variants` 示例。 - 完善容器类菜单文档导航、顶层配置流程、跨版本边界和 Dialog 与容器类菜单的结构差异说明。 - 将原 TrMenu 迁移页面重构为统一迁移总览,新增 DeluxeMenus 快速迁移教程、不兼容内容列表及迁移报告和 `TRM_*` 错误代码解析。 - 补充容器类菜单 `Title` 的字符串列表轮播模式,说明 `Title-Update` 每次推进一项,以及手动刷新只重新解析当前项的区别。 ### 条件列表解析加固 - 支持在 Dialog 消息文本、Body 物品 Lore、按钮悬浮文字和容器物品 Lore 中按 YAML 顺序混写静态字符串与条件分支。 - 条件分支可在原位置插入一行或多行内容;完全由条件 Map 组成的旧配置仍保持首个非空候选语义。 - 新增行尾 `{condition: 条件}` 快捷条件,可用于上述字符串列表和所有字符串动作;条件不成立时跳过整行或整条动作。 - 统一单行动作修饰符为 `{chance: 数值}`、`{wait: tick}` 和 `{condition: 条件}`,不再使用别名、尖括号或等号格式。 - TrMenu 迁移器可将源 Lore 的行尾条件和动作概率/延迟转换为 KaMenu 标准修饰符。 ### 迁移日志输出 - `/km migrate dm` 和 `/km migrate trmenu` 的逐文件结果、完整诊断与冲突明细改为写入 `plugins/KaMenu/logs/migration/` 下的独立日志文件。 - 聊天框仅保留迁移、入口合并、运行时重载摘要和日志路径;日志写入失败时完整报告会回退到服务器控制台。 ### 菜单引用与 TrMenu node 迁移 - 新增菜单级 `References`,支持 `{ref:path}` 公共引用、`{config:path}` 当前配置引用,以及 Dialog 组件和容器按钮中的 `{self:id}` / `{self:path}` 自身引用。 - 新增 `{ref:[path;arg0;arg1]}` 参数模板与 `{refarg:n}` 占位符;支持嵌套引用、大小写不敏感路径、简单列表换行展开,并检测缺失路径、结构引用、循环和超过 16 层的递归。 - `{ref:*}`、`{config:*}` 和 `{self:*}` 可安全用于条件表达式;修复 `{self:path}`,现会返回当前组件或按钮的完整配置路径。 - TrMenu 迁移器现可将静态 `{node:*}` / `{nodes:*}` / `{n:*}` 转换为 KaMenu 引用,只按需复制实际使用的节点到 `References.trmenu`。 - 支持 TrMenu node 模板参数和图标上下文 `@iconId@`,动态路径或不可嵌入的结构会生成明确的 `TRM_NODE_*` 诊断,不会猜测转换。 [/MD]
[MD] ### Container 按钮状态变体 - 新增 `Buttons.<id>.variants`,允许同一个物理槽位根据权限、冷却、物品、数据或其他条件显示不同的完整按钮状态。 - 每个变体独立配置完整的 `display` 和 `actions`,避免为同一槽位的名称、Lore、材质和点击动作重复编写条件。 - 支持 `priority` 优先级:数值越小越优先;相同优先级保持 YAML 声明顺序。 - 当所有变体都未指定 `priority` 时,严格按照 YAML 从上到下选择第一个满足条件的变体。 - 渲染和点击时都会重新判断当前变体,避免权限或冷却变化后执行已经过期的动作。 - 保留旧版按钮格式兼容;同一个按钮不能混用 `variants` 与顶层 `display` / `actions`。 - 增加变体配置错误诊断,包括缺少 `display.material`、无效 `priority` 和混用旧格式等情况。 ### DeluxeMenus 迁移增强 - DeluxeMenus 中同一 `slot` 的多个候选物品现在会自动迁移为 KaMenu 的 `variants`。 - 迁移器按 DM 的 `priority` 升序处理,相同优先级保持源文件顺序。 - DM 未显式配置 `priority` 时,迁移器会写入 DM 的默认有效值,避免迁移后候选顺序发生变化。 - `requirements_menu.yml` 已用于实际 Paper1.16.5 测试服验证,3 个菜单成功生成,运行时菜单重载成功。 - 移除插件资源内的静态 `dm_migrated` 迁移样例,迁移结果仅在运行时输出到 `plugins/KaMenu/menus/dm_migrated`,避免将第三方菜单快照打包进插件。 ### TrMenu 迁移系统 - 新增 `/km migrate trmenu`(别名 `trm`),将 TrMenu stable-v3 经典库存菜单编译为 KaMenu V2 Container 标准 YAML;默认读取 `plugins/TrMenu/menus`,输出到 `plugins/KaMenu/menus/trmenu_migrated`。 - 迁移器不依赖 TrMenu、Kether 或 TabooLib,也不会在迁移期间执行源菜单的 JavaScript、指令和动作。 - 支持版本化正则键、单页常用容器布局、显式槽位、反引号多字符按钮 ID、嵌套图标变体、常见物品字段和跨文件菜单跳转。 - 支持常用 Kether 条件、消息/指令/音效/经济/点券/数据等动作、组合动作、延迟与概率,以及 `Events.Open`、`Events.Close` 和自动任务。 - 可静态审计的纯返回值 `Functions` 会转换为菜单 JavaScript;TrMenu 私有对象、任意 Kether 流程和动态私有物品表达式会被拒绝或明确报告。 - 普通 `Bindings.Commands` 会合并到 `custom_commands.yml`;默认保留同名指令和已有目标文件,使用 `overwrite` 才会替换。 - 可兼容的 `Bindings.Items` 会合并到独立的 `item_bindings.yml`,支持 material、lore、name、data 和 model-data,并保留 TrMenu 默认的 2000ms 绑定冷却;不安全的 trait 会跳过并输出诊断。 - 新增 TrMenu 固定 `utils` 映射:在线玩家和装备槽位条件转换为 KaMenu 原生条件,`utils.getEquipment` 转换为 `[HEAD:玩家]` 等标准物品来源;简单参数形式的 `hasMoney` 和 `hasItem` 复用现有条件。 - 新增 `set-args` 与 `del-args` 标准动作,并迁移 TrMenu 同名动作;`set-args` 替换当前菜单参数后刷新 Container 或 Dialog,`del-args` 仅清理当前参数。 - 新增结构化 WARNING/ERROR 诊断、原子写入和 KaMenu Container 二次解析校验;不支持的条件不会被静默删除后继续执行受保护动作。 - 增加中英文 TrMenu 迁移文档,并使用 stable-v3 内置样例进行批量兼容审计。 [/MD]
[MD] ### V2 容器菜单 - 新增基于 Bukkit 虚拟库存的 Container 菜单运行时,默认不依赖 ProtocolLib、PacketEvents 或 NMS 发包层。 - 支持 `CHEST`、`HOPPER`、`DISPENSER`、`DROPPER`、`FURNACE`、`BLAST_FURNACE`、`SMOKER` 和 `ANVIL` 容器类型。 - 新增 `Type`、`Layout`、`Buttons`、`Properties`、`Update`、`Title-Update` 和按钮级 `update` 配置。 - Container 菜单复用 KaMenu 的变量、PlaceholderAPI、条件、JavaScript、actions 包、生命周期事件和动作队列。 - 增加熔炉火焰/加工箭头百分比刷新,以及 `Events.Progress` 边沿触发事件。 - 增加铁砧输入、重命名结果和 `$(input)` 上下文支持。 - 所有容器交互、拖拽和快捷键库存操作均按只读菜单处理,防止展示物品进入玩家库存。 ### DeluxeMenus 迁移 - 新增 `/km migrate dm`,默认读取 `plugins/DeluxeMenus/gui_menus`,也支持手动指定源文件和目录。 - 支持 DM 菜单布局、槽位、物品显示、条件、点击动作、分页和 `open_command` 迁移。 - `open_command` 会写入 KaMenu V2 标准菜单和 `custom_commands.yml`。 - 支持 `overwrite` 覆盖目标菜单和冲突的自定义指令;默认保留现有配置并报告冲突。 ### 自定义指令独立化 - 自定义指令从 `config.yml` 独立到插件根目录的 `custom_commands.yml`。 - 新增独立文件管理器,负责默认文件释放、配置读取、保存、旧配置迁移和备份。 - `/km reload config` 和 `/km reload all` 会同步重载 `config.yml`、`custom_commands.yml` 和在线玩家的命令补全。 - 旧版 `config.yml > custom-commands` 会在启动时自动迁移,并生成 `custom_commands_legacy_backup_<时间戳>.yml`。 - 配置版本升级为 v6。 ### 兼容性边界 - 保留 Paper、Folia 和 Spigot 的现有 Dialog 支持、平台适配和生命周期清理。 - Container 菜单当前使用 Bukkit 公共虚拟库存方案,不提供后台熔炉模拟,也不包含基于 NMS 的假窗口实现。 - 公共运行时编译基线降至 Bukkit/Spigot 1.16.5,并将公共运行时字节码目标降至 Java 16;仅在现代核心上加载的 Dialog 适配器仍单独使用 Java 21。 - 构建环境仍使用 Java 21;Paper/Folia 1.21.7+ 服务端本身继续要求 Java 21。 - Paper/Folia 1.21.7+ 和 Spigot 1.21.6+ 才启用原生 Dialog;较低核心自动降级为无 Dialog 模式,Container、actions、变量、JavaScript、存储和自定义指令仍可用。 - 仅将 Libby 随插件 JAR 提供;Kotlin 会在无 Kotlin 依赖的 `onLoad` 引导段优先热加载,随后再挂载 Adventure/MiniMessage 及其他运行依赖。 - 旧版 Paper 内置的 Adventure 不满足新版 MiniMessage 时会自动回退到 Legacy 文本,避免依赖冲突导致插件无法启用;`sprite`、`head` 等现代标签仅在兼容的现代核心上生效。 - bStats 运行库通过 Libby 下载并重定位到 KaMenu 私有命名空间,避免触发 bStats 的未重定位检查,也不增加插件 JAR 体积。 [/MD]
[MD] ### 菜单依赖检查顺序修复 - `Settings.need_placeholder` 现在会在 `Events.Open` 之前检查。 - 缺少必需的 PlaceholderAPI 扩展时,菜单不会再提前执行 Open 事件中的数据写入、扣款、物品或指令动作。 - Paper、Spigot 和 Floodgate 表单入口使用一致的检查顺序;强制重开路径仍保留依赖检查作为安全兜底。 ### Paper Dialog 解析统一 - Paper Dialog 改为使用与 Spigot、Floodgate 相同的共享菜单编译器,不再由平台入口单独解析 YAML。 - `Title`、`Settings`、`Body`、`Inputs`、`Bottom`、条件、变量、repeat、分页、输入清理和按钮定义先编译为统一模型,再由 Paper 原生渲染器显示。 - 修复 `Body.item.material` 未识别 `stock:<保存物品名>` 的问题;现在会读取 KaMenu 保存物品库中的完整 ItemStack,并按 `amount` 配置覆盖数量。 - Paper 按钮继续使用原生一次性 callback,并保留 actions、输入捕获、客户端 URL/复制动作、`Settings.lifetime`、菜单任务和生命周期行为。 - 非法 Dialog 参数仍会阻止菜单打开并保留底层异常,便于定位错误配置,现有菜单格式无需修改。 [/MD]
[MD] ### Geyser/Floodgate 基岩版按钮图标 - `Bottom` 普通按钮和 `repeat.item` 动态按钮新增可选的 `icon` 配置。 - 支持 `url` 网络图片和 `path` 基岩版资源包路径,URL 也可直接使用字符串简写。 - `repeat.item.icon` 支持 `{item.xxx}`、PlaceholderAPI 和 KaMenu 内置变量,可为每个动态项目生成不同图片。 - Floodgate 玩家打开无输入组件且至少含一个有效图标的菜单时,KaMenu 会发送带图标的基岩版 `SimpleForm`。 - Java 玩家、没有图标的菜单及带 `Inputs` 的菜单保持原有 Java Dialog/Geyser 转换路径,不改变现有行为。 [/MD]
[MD] ### Folia 关服修复 - 修复 Folia 核心关闭服务器时调用 Bukkit 全局任务取消接口导致的 `UnsupportedOperationException`。 - 关闭插件时改为使用 KaMenu 自身的调度任务清理逻辑,避免触发 Folia 不支持的全局调度器操作。 ### repeat 动态按钮矩阵补齐 - `type: repeat` 会按当前页实际渲染的动态按钮数量和 `columns` 自动补齐矩阵。 - 当按钮数量无法被 `columns` 整除时,追加空白按钮,使动态按钮区域保持完整对齐。 - 空白按钮没有显示文本,不执行 `item.actions` 或其他业务动作,点击后仅执行 `reset`。 - 如果 `item.width` 已配置,空白按钮会复用该宽度,保持整个动态按钮矩阵对齐。 - 上一页、下一页等普通分页按钮不计入动态按钮补齐数量,仍会在补位按钮后按配置顺序追加。 - Paper 与 Spigot 的 Dialog 渲染路径均保持一致。 [/MD]