Skip to content

配置详解 ​

plugins/EmakiAccessory/config.yml 主配置和 pages/*.yml 饰品页的写法: 每个键做什么, 默认值是多少, 能填什么范围

plugins/EmakiAccessory/config.yml 是主配置, pages/*.yml 定义饰品页. version 是配置结构标记, 由项目资源同步流程维护, 插件按它合并新增的默认键

顶层键 ​

发货默认值 (完整内容):

yaml
version: "1.1.8"
language: "zh_CN"
release_default_data: true
drop_on_death: false
unique: true
slot_sources:
  pdc:
    enabled: false
    key: ""
  lore:
    enabled: false
    patterns:
      - "^穿戴部位[::]\\s*(.+)$"
    separator: ","
    aliases:
      "戒指": "ring"
      "项链": "necklace"
      "腰带": "belt"
      "护符": "charm"
persistence:
  autosave_seconds: 60
  drain_timeout_seconds: 10
字段类型必填默认值取值范围说明
versionstring否"1.1.8"—配置结构版本, 由内置资源同步流程维护, 用于合并新增默认键; 缺失时回退 "1.0.0"
languagestring否"zh_CN"—语言文件名, 对应 lang/<language>.yml; 空或全空白回退 zh_CN, 指向不存在的文件时用默认语言加载
release_default_databoolean否truetrue / false是否在启动时释放缺失的内置默认数据文件. 为 true 时补齐缺失的 parts.yml, pages/main.yml, pages/secondary.yml, sets/example_set.yml, 已存在的文件不覆盖; 为 false 时跳过默认数据写入 (config.yml, lang/*.yml 与 gui/accessory_gui.yml 不在此开关管辖范围)
drop_on_deathboolean否falsetrue / false死亡时是否把生效页的饰品加入掉落列表
uniqueboolean否truetrue / false是否禁止同一页内同时放置两件相同饰品
slot_sourcesobject否见"slot_sources 穿戴槽位来源"—追加的"可穿戴槽位"声明来源; 缺失时用内置默认值
durabilityobject否见"durability 饰品耐久度"—饰品耐久度功能开关与每次受伤扣点; 缺失时用内置默认值 (默认关闭)
persistenceobject否见"persistence 持久化"—自动保存与关服时写到文件的参数

drop_on_death ​

设为 true 后, 玩家死亡时生效页的饰品会追加到死亡掉落列表, 交给原版死亡流程处理, 而不是塞回背包 -- 塞回背包会让同一件饰品同时出现在掉落物和背包里

  • 其他插件已经开启 keepInventory (死亡不掉落) 时本项不生效, 饰品一律保留
  • 只清空生效页: 非生效页的饰品保留在数据里, 不会被清空也不会掉落. 生效页为空 (例如玩家没有该页权限) 时什么都不掉落
yaml
# 允许死亡时掉落生效页饰品
drop_on_death: true

unique ​

去重只在同一个页内判定: 系统只检查该玩家在该页上的现有饰品, 跨页放同款不冲突

判定优先按 EmakiItem 的物品定义 id (物品的身份串 emakiitem:<定义id>): 同一个定义的两件饰品即使等级或词条不同也算重复. EmakiItem 不可用或物品没有定义 id 时, 回退为原版材质判定 (material:<材质名小写>), 此时同材质的两件饰品会被视为重复

yaml
# 关闭去重, 允许同一页放两件同款饰品
unique: false

slot_sources 穿戴槽位来源 ​

这里给饰品"能戴在哪些槽位"追加读取来源. 物品自带的声明来自 EmakiItem 写入的 emakiitem:accessory_slots; 下面两项是在此之上由你显式开启的额外来源, 任一命中就允许穿戴, 两项都关闭 (默认) 时只有物品自带声明生效. 注意, EmakiAttribute 的 active_slot 与 EmakiSkills 的技能载荷 (物品上记录技能数据的部分) 不再参与这里的判定

字段类型必填默认值取值范围说明
slot_sources.pdc.enabledboolean否falsetrue / false是否从物品 PDC 追加槽位列表
slot_sources.pdc.keystring否""—NamespacedKey 全写, 逐字使用填写值, 不做大小写改写. 设为空或无法解析为 NamespacedKey 时该来源不会生效, 也不报错 (enabled 为 true 也读不到). 优先按字符串列表读取, 读不到时回退为单个字符串并按 separator 切分
slot_sources.lore.enabledboolean否falsetrue / false是否从 Lore 用正则追加槽位列表
slot_sources.lore.patternslist<string>否见下方默认片段—正则列表, 每条的捕获组 1 是槽位列表文本; 用 find 匹配 (子串命中即可). 匹配前会去除 MiniMessage 标签并折叠空白, 按纯文本书写. 编译失败的正则记录 accessory.invalid_slot_pattern 警告并跳过该条; 列表为空 (或全部无效) 时该来源不会生效, 也不报错
slot_sources.lore.separatorstring否","—槽位列表分隔符, 同时用于 pdc 的字符串回退分支; 空或全空白回退 ","
slot_sources.lore.aliasesmap<string,string>否见下方默认片段—Lore 槽位名到 parts.yml 部位 id 的映射. 查找时先按原文再按小写匹配; 未列出的值按规范化结果使用 (去首尾空白, 转小写, 空格换下划线). 键或值为空白的条目在加载时被丢弃

发货默认值片段:

yaml
slot_sources:
  pdc:
    enabled: false
    key: ""
  lore:
    enabled: false
    patterns:
      - "^穿戴部位[::]\\s*(.+)$"
    separator: ","
    aliases:
      "戒指": "ring"
      "项链": "necklace"
      "腰带": "belt"
      "护符": "charm"

示例: 从 Lore 读取"穿戴部位: 戒指, 项链", 并把中文槽位名映射到部位 id

yaml
slot_sources:
  lore:
    enabled: true
    patterns:
      - "^穿戴部位[::]\\s*(.+)$"
    separator: ","
    aliases:
      "戒指": "ring"
      "项链": "necklace"

pages/*.yml 饰品页 ​

一个文件定义一页. 页 id 取 page_id, 与文件名无关

yaml
page_id: "main"
display_name: "<gold>主饰品栏</gold>"
order: 1
gui_template: "accessory_gui"
permission: ""
parts:
  - "necklace"
  - "ring"
  - "belt"
  - "charm"
字段类型必填默认值取值范围说明
page_idstring是——页 id, 也是数据文件里的存储分区键; 规范化后为空时该文件被跳过
display_namestring否""—页显示名, 支持 MiniMessage, 用于切页格, 启用格与 /eacc pages; 为空时界面回退显示 page_id
orderinteger否2147483647 (Integer.MAX_VALUE)—页排序, 升序; 最小者为默认启用页, 同值时再按 page_id 升序
gui_templatestring否"accessory_gui"—该页使用的布局 id (对应 gui/<id>.yml 的 id), 允许多页共用一个布局; 找不到对应布局时该页打不开 (记录 accessory.gui_template_missing)
permissionstring否""—为空表示所有人可用; 非空时逐字使用该权限串
partslist<string>是——本页启用的部位, 取值必须是 parts.yml 里已定义的部位 id; 重复项去重, 列表为空时整页被跳过 (记录 accessory.page_without_parts)

记住三条页面规则:

  • 存储隔离: 同一个槽位实例 id 在不同页各存一件饰品, 互不覆盖
  • 只有启用页生效: 其余页的饰品保留但不产生属性, 技能与套装件数
  • 失权不清数据: 玩家失去启用页权限时数据不清除, 也不自动换页; 该页打不开, 它的饰品停止生效, 玩家用 /eacc retrieve <页> 自行取回

部位在页里会按 parts.yml 的 count 展开成槽位实例, 你还要在 gui_template 指向的布局里为它摆好格子, 否则该槽位不可用并记录警告. parts 里引用了未定义的部位时, 该部位不会出现在该配件页, 并记录 accessory.page_unknown_part

durability 饰品耐久度 ​

饰品不在原版装备槽, 所以原版耐久事件 (PlayerItemDamageEvent) 碰不到它们; 耐久扣除由 EmakiAccessory 自己在玩家受伤时处理. 该功能默认关闭

yaml
durability:
  enabled: false
  damage_per_hit: 1
字段类型必填默认值取值范围说明
durability.enabledboolean否falsetrue / false功能开关. 关闭时不扣除任何耐久, 物品上的耐久数据保持不变 (等于原版耐久永不消耗)
durability.damage_per_hitinteger否1≥ 1 (小于 1 被钳制为 1)玩家每次受到伤害时, 每个允许扣除的饰品扣除的耐久度点数

扣除范围与判断规则:

  • 只检查生效页 (enabled_page) 上的饰品, 其他页不参与;
  • 只有自带耐久上限的饰品会被扣 -- 上限取物品 max_damage 组件, 未设置时回退材质自带耐久 (与 EmakiItem 的修复系统用的是同一套判断); 上限为 0 的物品永不扣;
  • 你可以在 parts.yml 用 durability_deduction: false 关闭该部位的扣除 (默认允许);
  • 扣除监听 EntityDamageEvent (MONITOR, 忽略已取消事件), finalDamage ≤ 0 的伤害不扣;
  • 扣除量不会超过上限, 扣满即停止

扣满之后: 该饰品的属性, 技能与套装件数全部停止生效, 物品还在槽内, 界面会显示 gui.durability_broken 标识, 同时提示一次 durability.broken_notify. 你把物品取回后, 用 EmakiItem 的修复流程恢复耐久就能重新生效; 耐久损耗随自动保存写入, 不需要额外的保存命令

persistence 持久化 ​

字段类型必填默认值取值范围说明
persistence.autosave_secondsinteger否60≥ 0 (负数被钳制为 0)自动保存间隔, 单位秒. 设为 0 时关闭定时保存; 实际定时周期为 max(100, 秒数 × 20) 个游戏刻 (1 个游戏刻 = 1/20 秒), 即最密 5 秒一次
persistence.drain_timeout_secondsinteger否10≥ 1 (小值被钳制为 1)停服时等待还没写到文件的写入完成的上限, 单位秒
yaml
persistence:
  autosave_seconds: 120
  drain_timeout_seconds: 15

你关闭定时保存后, 系统只在关闭窗口, 玩家退出, /eacc admin save 与服务器关服时写到文件

drain_timeout_seconds 超时后会打印保存/失败/剩余还没写到文件的改动条数并继续关服, 不会一直等着卡住关服流程

玩家数据文件 ​

每个玩家的饰品数据存在 plugins/EmakiAccessory/data/<玩家 UUID>.yml. 当前写到文件的结构 (format_version: 2):

yaml
format_version: 2
player_name: "Steve"
enabled_page: "main"
pages:
  main:
    ring_1: "<Base64 物品字节>"
  combat:
    ring_1: "<Base64 物品字节>"
字段类型必填默认值取值范围说明
format_versioninteger是 (写出时)2当前写入值固定为 2写到文件的结构版本. 读取时不校验具体取值, 识别依据只看结构 (见下两节)
player_namestring否""—最后一次写入时的玩家名; 读取时若为空则回填在线名
enabled_pagestring否默认页 (order 最小的页)—玩家当前启用的页 id; 加载后若该页不存在, 运行时回退到默认页
pagesmap<string, map<string, string>>否{}—主结构: pages.<页 id>.<槽位实例 id> = Base64 物品字节. 同一槽位实例在不同页各存一份, 互不覆盖; 空页不写出
pages.<页 id>.<槽位实例 id>string否——ItemStack.serializeAsBytes 结果再经 Base64 编码的文本; 解码失败的一条会被丢弃并记录警告
slotsmap<string, string>否——旧档 (v1) 遗留键, 仅在迁移时读取, 不再写出

v1 → v2 自动升级 ​

旧档 (v1) 把饰品放在顶层 slots: 节, 没有 pages. 加载这类文件时, 插件会把其中物品迁移到默认启用页 (order 最小的页), 并在日志记录 Migrated accessory data ... from format 1 to 2. 判定依据是"没有 pages: 且存在顶层 slots:", 并不校验 format_version 的具体取值. 若当时没有可用的默认页 (页配置为空), 迁移不会进行, 文件保持原样

结构无法识别时拒绝覆盖 ​

碰到下面两种情况时 (文件既没有 pages: 也没有 slots:, 例如被手工改坏或来自其他结构; 或旧 slots: 档没有可迁移的默认页):

  • 文件保持原样, 不会被覆盖, 该玩家本次会话从空饰品开始, 并记录 Unrecognized accessory data structure 或无法迁移的告警;
  • 该玩家的后续保存一律跳过, 并记录 Skipped saving accessories ... because its data file structure was not recognized

所以升级或手工编辑前, 先备份 plugins/EmakiAccessory/data/ 目录: 一旦结构无法识别, 插件不会用空数据覆盖原文件