GUI 系统
CoreLib GUI 系统提供菜单模板、打开请求、会话管理和交互控制基础设施。业务模块不需要从零处理 InventoryClickEvent,而是定义自己的 GUI 配置,再交由 CoreLib 统一管理。
使用 GUI 系统的模块
| 模块 | 用途 |
|---|---|
| EmakiForge | 锻造界面、配方书。 |
| EmakiStrengthen | 强化界面、材料槽、保护材料槽。 |
| EmakiGem | 镶嵌、提取、开孔、升级界面。 |
| EmakiSkills | 技能界面、触发器选择界面。 |
| EmakiCooking | 蒸锅、烤炉、榨汁机、发酵桶 GUI。 |
| EmakiAttribute | 属性点加点界面。 |
| EmakiItem | 物品修复界面。 |
| EmakiLevel | 等级面板、排行榜界面。 |
| EmakiStorage | 分页仓库界面。 |
菜单渲染后端
plugins/EmakiCoreLib/config.yml 的 gui.backend 决定 Emaki 系列所有菜单如何呈现给玩家:
| 值 | 说明 |
|---|---|
bukkit | 默认值。打开真实服务端容器,无需任何前置插件。 |
packet | 由 CoreLib 内置的发包虚拟菜单,刷新不同行数时复用同一窗口、光标不会被重置;需要额外安装 PacketEvents。未安装时自动回退为 bukkit。 |
auto | 安装了 PacketEvents 就用 packet,否则用 bukkit。 |
默认保持 bukkit,升级 CoreLib 不会改变现有菜单行为。
GUI 模板配置
GUI 模板是菜单的静态定义,描述界面的标题、大小、槽位布局和按钮。
顶层字段
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
id | string | 是 | — | 模板唯一标识,模块内部引用时使用。 |
title | string / object | 是 | — | 界面标题。支持 MiniMessage 格式字符串或 TextConfig 对象。 |
rows | integer | 是 | — | 界面行数,取值范围 1–6,对应 9–54 个槽位。 |
slots | map | 是 | — | 槽位定义,key 为槽位名称,value 为槽位配置对象。 |
槽位配置字段
每个槽位定义了一组格子的外观和行为:
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
key | string | 是 | — | 槽位名称,用于业务代码引用。 |
slots | list<integer> | 是 | — | 对应的格子索引列表(0 起始,从左到右、从上到下)。 |
type | string | 否 | "" | 槽位类型标签,如 input、output、button、decoration。 |
item | object | 否 | — | 共享物品定义,包含 source、amount 与 components。缺少 source 时可作为运行时物品的纯组件 patch。 |
sounds | map | 否 | — | 点击音效配置,按点击类型区分。 |
统一物品结构
新配置和默认资源只写嵌套结构:
item:
source: minecraft-anvil
amount: 1
components:
custom_name: '<green>确认</green>'
lore:
- '<gray>点击执行</gray>'
item_model: emaki:confirm
enchantment_glint_override: true
$unset:
- repairable
$reset:
- attribute_modifierssource接受 CoreLib 当前注册的全部 ItemSource 简写;实际可用性取决于对应 resolver 是否已安装。- 普通组件值表示
SET;$unset删除组件,$reset恢复该材质原型的默认组件。 - 组件 ID 必须是合法的 namespaced key;省略命名空间时默认补为
minecraft:,显式命名空间保持不变。该规则同样适用于$unset/$reset列表。未知 ID 或当前版本支持但值非法属于配置错误。 - 已知但高于当前服务器版本的组件会跳过并记录警告,不会加载高版本专用类。
- 第三方来源先克隆原物品,保留来源身份、PDC 和未知组件,只应用当前 Paper 可安全传递的 patch。
- 旧槽位
item: <source>与顶层components、display_name、lore等仍可读取,但仅作为兼容输入;新旧同时出现时以嵌套item为准。 - 玩家真实放入的目标物、材料和业务产物仍由会话状态决定,不会被模板展示物品强行覆盖。
旧版 GUI 物品字段自动迁移
从 CoreLib 4.5.11 起,共享 gui/*.{yml,yaml} 会在 YamlDocument 正式加载和 GuiTemplateParser 解析之前执行一次纯结构迁移。迁移会遍历整份 YAML 中的候选 configured-item 节点,因此除常见 slots 外,也能处理 pages/buttons、virtual_items 等模块自定义容器中的旧物品定义。
迁移规则与运行时 LegacyConfiguredItemConverter 保持一致:
material、item_source/item_sources、标量item等旧来源字段迁移到item.source;amount迁移到item.amount。display_name、item_name、lore、custom_model_data、enchantments、item_flags、hidden_components、unbreakable等旧展示字段迁移到item.components。- 已存在的现代
item.source、item.amount和组件值优先,混合格式中的旧值不会覆盖现代值。 - 如果候选节点包含
components.raw或item.components.raw,整个节点会安全跳过,避免改写无法无损理解的原始组件负载。 - 槽位布局、声音、动作、分页规则和其它非目标业务字段保持不变;迁移完成后再次运行不会产生额外修改。
每批实际修改都会先把原文件原文备份到对应插件数据目录的 migration-backups/configured-item-format/<时间戳>/,并保留相对于 gui/ 源目录的路径。迁移结果先写入同目录临时文件并重新解析校验,校验通过后才替换原文件;写入、校验或替换失败时,原文件保持不变或从本批备份恢复,GUI 加载不会继续使用未经验证的迁移结果。BoostedYAML 的注释模型会尽可能保留未改业务节点的注释,但仍建议正式服升级前备份完整配置目录。
该兼容层不读取 config.yml、语言文件或插件描述符中的版本号,也不按版本门禁执行;它只根据旧字段是否存在决定是否迁移。实现集中在 CoreLib item.migration.configureditem 包,GUI 侧只由 GuiTemplateLoader 作为生产桥接入口,因此结束兼容期后可整体删除,不会把旧格式逻辑留在通用 YamlFiles / YamlDirectoryLoader 或 canonical parser 中。
点击类型
GUI 系统识别以下点击类型:
| 类型 | 说明 |
|---|---|
CLICK | 通用点击(作为 fallback,当没有匹配到具体类型时使用)。 |
LEFTCLICK | 左键点击。 |
RIGHTCLICK | 右键点击。 |
音效查找优先级:先查 LEFTCLICK / RIGHTCLICK,未找到时回退到 CLICK。
完整 GUI 配置示例
强化界面示例
id: strengthen_gui
title: '<dark_gray>装备强化'
rows: 6
slots:
background:
slots: [0,1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,50,51,52,53]
type: decoration
item:
source: minecraft-black_stained_glass_pane
components:
minecraft:custom_name: ' '
minecraft:tooltip_display:
hide_tooltip: true
target:
slots: [13]
type: input
item:
source: minecraft-air
components:
minecraft:custom_name: '<gray>放入目标装备'
minecraft:lore:
- '<dark_gray>将需要强化的装备放在这里'
confirm:
slots: [49]
type: button
item:
source: minecraft-anvil
components:
minecraft:custom_name: '<green>开始强化'
minecraft:lore:
- '<gray>放入装备和材料后点击'
- ''
- '<yellow>左键点击开始强化'
minecraft:enchantments:
minecraft:unbreaking: 1
minecraft:tooltip_display:
hidden_components:
- minecraft:enchantments
sounds:
LEFTCLICK:
sound: minecraft:block.anvil.use
volume: 0.8
pitch: 1.0锻造界面示例
id: forge_gui
title: '<dark_gray>锻造台'
rows: 6
slots:
background:
slots: [0,1,2,3,4,5,6,7,8,9,17,18,26,27,35,36,44,45,46,47,48,49,50,51,52,53]
type: decoration
item:
source: minecraft-gray_stained_glass_pane
components:
minecraft:custom_name: ' '
blueprint_slot:
slots: [10]
type: input
item:
components:
minecraft:custom_name: '<aqua>图纸槽'
minecraft:lore:
- '<gray>放入锻造图纸'
material_slots:
slots: [11,12,13,14,15,16,19,20,21,22,23,24,25]
type: input
item:
components:
minecraft:custom_name: '<yellow>材料槽'
minecraft:lore:
- '<gray>放入锻造材料'
target_slot:
slots: [28]
type: input
item:
components:
minecraft:custom_name: '<gold>目标装备'
minecraft:lore:
- '<gray>放入需要锻造的装备'
result_preview:
slots: [34]
type: output
item:
components:
minecraft:custom_name: '<green>预览结果'
confirm:
slots: [43]
type: button
item:
source: minecraft-smithing_table
components:
minecraft:custom_name: '<green>确认锻造'
sounds:
LEFTCLICK:
sound: minecraft:block.anvil.use
volume: 1.0
pitch: 1.2GUI 会话
GUI 会话用于记录玩家当前打开的界面状态。会话由 CoreLib 自动管理,业务模块通过 GuiSessionHandler 接口处理交互逻辑。
会话记录的信息包括:
- 玩家正在操作哪一个配方或流程。
- 哪些槽位是输入槽(允许放入物品),哪些槽位禁止拿取。
- 点击按钮后应该调用哪个业务流程。
- 关闭界面时是否需要返还输入物品。
- 当前界面的临时状态数据。
会话的核心作用是防止玩家通过快速点击、Shift 点击、拖拽或异常关闭复制物品或绕过流程。
槽位索引参考
6 行界面的槽位索引布局:
行 1: 0 1 2 3 4 5 6 7 8
行 2: 9 10 11 12 13 14 15 16 17
行 3: 18 19 20 21 22 23 24 25 26
行 4: 27 28 29 30 31 32 33 34 35
行 5: 36 37 38 39 40 41 42 43 44
行 6: 45 46 47 48 49 50 51 52 53常用位置:
- 中心位置(6 行):
22(第 3 行中间)或31(第 4 行中间) - 底部中间:
49 - 四角:
0、8、45、53
修改 GUI 的建议
- 先只改显示文本:确认语言、颜色、布局是否符合预期。
- 再改槽位位置:移动按钮时确认不会和输入槽、输出槽冲突。
- 最后改交互逻辑:例如确认按钮、返回按钮、分页按钮。
- 每次修改后测试异常操作:Shift 点击、拖拽、双击、关闭界面、背包满。
MiniMessage 与颜色
GUI 文本建议统一使用 MiniMessage 格式:
item:
source: minecraft-smithing_table
components:
minecraft:custom_name: '<gold>传说锻造台'
minecraft:lore:
- '<gray>放入图纸、材料和目标装备。'
- '<yellow>点击开始锻造。'
- ''
- '<dark_gray>消耗:<white>500 金币'常用 MiniMessage 标签:
| 标签 | 效果 |
|---|---|
<red> | 红色文本 |
<green> | 绿色文本 |
<gold> | 金色文本 |
<gray> | 灰色文本 |
<dark_gray> | 深灰色文本 |
<yellow> | 黄色文本 |
<aqua> | 青色文本 |
<bold> | 粗体 |
<italic> | 斜体 |
<strikethrough> | 删除线 |
<gradient:gold:yellow> | 渐变色 |
如果某个模块仍兼容传统颜色符(&a、§b),也建议逐步迁移到 MiniMessage,方便统一风格。