Skip to content

GUI 系统 ​

CoreLib 的 GUI 系统涵盖菜单模板写法, 点击处理, 以及菜单以什么方式呈现给玩家

CoreLib GUI 系统给整套插件提供菜单能力: 你只要定义好自己的 GUI 配置, 打开菜单, 记录玩家的操作状态, 拦截异常点击这些事都由 CoreLib 统一处理, 不用自己写 InventoryClickEvent 那套代码

使用 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 不会改变现有菜单行为. 填了未知取值会输出一次警告, 并按 bukkit 处理

相关配置键 ​

字段类型必填默认值取值范围说明
gui.backendstring否"bukkit"bukkit / packet / auto菜单的显示方式, 取值见上表. 填了不认识的值就按 bukkit 处理并输出警告
gui.click_interval_msinteger否100≥ 0 (0 表示不限制)同一个玩家两次点击菜单之间的最小间隔, 单位毫秒; 在这个间隔内的后续点击不会被菜单处理. 填小于 0 的值按 0 处理

默认值片段:

yaml
gui:
  backend: "bukkit"
  click_interval_ms: 100

使用示例 (启用发包菜单, 并把点击间隔放宽到 150ms):

yaml
gui:
  backend: "packet"
  click_interval_ms: 150

GUI 模板配置 ​

GUI 模板就是菜单的静态定义, 描述界面的标题, 大小, 槽位布局和按钮

顶层字段 ​

字段类型必填默认值说明
idstring是—模板的唯一标识, 模块内部靠它引用这份模板. 留空时整份模板会被判为无效
titlestring / object否GUI界面标题. 支持 MiniMessage 格式字符串或 TextConfig 对象
gui_typestring否CHEST容器类型, 取值为 Bukkit InventoryType 名称. 非法值不报错地改回 CHEST; 该类型不支持自定义行数时 rows 强制为 0
rowsinteger否3界面行数, 超出 1–6 会被限制到该区间, 对应 9–54 个槽位
slotsmap否{}槽位定义, key 为槽位名称, value 为槽位配置对象. 不写时是空的, 不会报错

槽位配置字段 ​

每个槽位用来定义一组格子的外观和行为:

字段类型必填默认值说明
keystring是—槽位名称, 模块内部靠它引用这个槽位
slotslist<integer>是—对应的格子索引列表 (0 起始, 从左到右, 从上到下)
typestring否""槽位类型标签, 如 input, output, button, decoration
itemobject否—共享物品定义, 包含 source, amount 与 components. 缺少 source 时, 可以只当成一组组件改动, 用在运行时已有的物品上
soundsmap否—点击音效配置, 按点击类型区分

统一物品结构 ​

新配置和默认资源都只写嵌套结构:

yaml
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_modifiers
  • source 接受 CoreLib 当前注册的全部 ItemSource 简写; 实际能不能用, 取决于对应的解析器有没有装上
  • 普通组件值表示 SET; $unset 删除组件, $reset 恢复该材质原型的默认组件
  • 组件 ID 必须是合法的 namespaced key; 不写命名空间时补为 minecraft:, 自己写了命名空间就按写的来. 该规则同样适用于 $unset / $reset 列表. 未知 ID 或当前版本支持但值非法属于配置错误
  • 已知但高于当前服务器版本的组件会跳过并记录警告, 不会加载高版本专用类
  • 第三方来源先克隆原物品, 保留来源身份, PDC 和未知组件, 只应用当前 Paper 可安全传递的 patch
  • 旧槽位 item: <source> 与顶层 components, display_name, lore 等仍可读取, 但仅作为兼容输入; 新旧同时出现时以嵌套 item 为准
  • 玩家真实放入的目标物, 材料和业务产物仍由会话状态决定, 不会被模板展示物品强行覆盖

旧版 GUI 物品字段自动迁移已下线 ​

注意: 共享 gui/*.{yml,yaml} 不再在加载前自动迁移旧版 configured-item 字段. CoreLib 已移除 item.migration.configureditem 包与运行时 LegacyConfiguredItemConverter, GuiTemplateLoader 也不再挂接迁移入口. 你要让 GUI 模板中的物品定义直接使用 canonical 结构: 来源写 item.source (例如 minecraft-diamond_sword), 数量写 item.amount, 名称, Lore, 模型数据与组件写 item.components

旧字段 (material, item_source / item_sources, 标量 item, display_name, item_name, lore, custom_model_data, enchantments, item_flags, hidden_components, unbreakable 等) 不会再被转换或补齐, 也不会再产生 migration-backups/configured-item-format/ 备份. 所以升级前请手工改写, 并自行备份完整配置目录

点击类型 ​

GUI 系统能识别这些点击类型:

点击类型sounds 键说明
CLICKclick通用点击 (没有匹配到具体类型时就用它)
LEFTCLICKleft_click左键点击
RIGHTCLICKright_click右键点击
SHIFT_LEFTCLICKshift_left_clickShift + 左键
SHIFT_RIGHTCLICKshift_right_clickShift + 右键
MIDDLECLICKmiddle_click中键点击
DOUBLECLICKdouble_click双击
NUMBER_KEYnumber_key数字键换位
SWAP_OFFHANDswap_offhand副手交换键 (默认 F)
DROPdrop丢弃键 (默认 Q)
CONTROL_DROPcontrol_dropCtrl + 丢弃键

sounds 映射的键要写上表 sounds 键列的小写形式 (解析时不区分大小写); 写成枚举名 (如 LEFTCLICK) 不会命中, 会被当成未知键, 输出一条警告后忽略. 音效查找分三级: 先精确匹配当前点击类型; 未命中时按兼容映射再查一次 (SHIFT_LEFTCLICK 与 DOUBLECLICK 回退到 LEFTCLICK, SHIFT_RIGHTCLICK 回退到 RIGHTCLICK); 仍未命中才回退到 CLICK. 未注册的未知 sounds 键会输出一条 issue (如 Unknown gui sound key '...' ignored.)

完整 GUI 配置示例 ​

强化界面示例 ​

yaml
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:
      left_click:
        sound: minecraft:block.anvil.use
        volume: 0.8
        pitch: 1.0

锻造界面示例 ​

yaml
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:
      left_click:
        sound: minecraft:block.anvil.use
        volume: 1.0
        pitch: 1.2

GUI 会话 ​

GUI 会话用来记录玩家当前打开的界面状态. 会话由 CoreLib 自动管理, 业务模块只要通过 GuiSessionHandler 接口处理交互逻辑

会话记录的信息包括:

  • 玩家正在操作哪一个配方或流程
  • 哪些槽位是输入槽 (允许放入物品), 哪些槽位禁止拿取
  • 点击按钮后应该调用哪个业务流程
  • 关闭界面时是否需要返还输入物品
  • 当前界面的临时状态数据

有了会话, 玩家就没法通过快速点击, Shift 点击, 拖拽或异常关闭复制物品, 或绕过流程

槽位索引参考 ​

6 行界面的槽位索引布局:

text
行 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 的建议 ​

  1. 先只改显示文本: 确认语言, 颜色, 布局是否符合预期
  2. 再改槽位位置: 移动按钮时确认不会和输入槽, 输出槽冲突
  3. 最后改交互逻辑: 例如确认按钮, 返回按钮, 分页按钮
  4. 每次修改后测试异常操作: Shift 点击, 拖拽, 双击, 关闭界面, 背包满

MiniMessage 与颜色 ​

GUI 文本建议统一使用 MiniMessage 格式 (一种用 <gold> 这类标签写颜色和样式的文本格式):

yaml
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, 方便统一风格