简体中文
配置详解
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| 字段 | 类型 | 必填 | 默认值 | 取值范围 | 说明 |
|---|---|---|---|---|---|
version | string | 否 | "1.1.8" | — | 配置结构版本, 由内置资源同步流程维护, 用于合并新增默认键; 缺失时回退 "1.0.0" |
language | string | 否 | "zh_CN" | — | 语言文件名, 对应 lang/<language>.yml; 空或全空白回退 zh_CN, 指向不存在的文件时用默认语言加载 |
release_default_data | boolean | 否 | true | true / 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_death | boolean | 否 | false | true / false | 死亡时是否把生效页的饰品加入掉落列表 |
unique | boolean | 否 | true | true / false | 是否禁止同一页内同时放置两件相同饰品 |
slot_sources | object | 否 | 见"slot_sources 穿戴槽位来源" | — | 追加的"可穿戴槽位"声明来源; 缺失时用内置默认值 |
durability | object | 否 | 见"durability 饰品耐久度" | — | 饰品耐久度功能开关与每次受伤扣点; 缺失时用内置默认值 (默认关闭) |
persistence | object | 否 | 见"persistence 持久化" | — | 自动保存与关服时写到文件的参数 |
drop_on_death
设为 true 后, 玩家死亡时生效页的饰品会追加到死亡掉落列表, 交给原版死亡流程处理, 而不是塞回背包 -- 塞回背包会让同一件饰品同时出现在掉落物和背包里
- 其他插件已经开启
keepInventory(死亡不掉落) 时本项不生效, 饰品一律保留 - 只清空生效页: 非生效页的饰品保留在数据里, 不会被清空也不会掉落. 生效页为空 (例如玩家没有该页权限) 时什么都不掉落
yaml
# 允许死亡时掉落生效页饰品
drop_on_death: trueunique
去重只在同一个页内判定: 系统只检查该玩家在该页上的现有饰品, 跨页放同款不冲突
判定优先按 EmakiItem 的物品定义 id (物品的身份串 emakiitem:<定义id>): 同一个定义的两件饰品即使等级或词条不同也算重复. EmakiItem 不可用或物品没有定义 id 时, 回退为原版材质判定 (material:<材质名小写>), 此时同材质的两件饰品会被视为重复
yaml
# 关闭去重, 允许同一页放两件同款饰品
unique: falseslot_sources 穿戴槽位来源
这里给饰品"能戴在哪些槽位"追加读取来源. 物品自带的声明来自 EmakiItem 写入的 emakiitem:accessory_slots; 下面两项是在此之上由你显式开启的额外来源, 任一命中就允许穿戴, 两项都关闭 (默认) 时只有物品自带声明生效. 注意, EmakiAttribute 的 active_slot 与 EmakiSkills 的技能载荷 (物品上记录技能数据的部分) 不再参与这里的判定
| 字段 | 类型 | 必填 | 默认值 | 取值范围 | 说明 |
|---|---|---|---|---|---|
slot_sources.pdc.enabled | boolean | 否 | false | true / false | 是否从物品 PDC 追加槽位列表 |
slot_sources.pdc.key | string | 否 | "" | — | NamespacedKey 全写, 逐字使用填写值, 不做大小写改写. 设为空或无法解析为 NamespacedKey 时该来源不会生效, 也不报错 (enabled 为 true 也读不到). 优先按字符串列表读取, 读不到时回退为单个字符串并按 separator 切分 |
slot_sources.lore.enabled | boolean | 否 | false | true / false | 是否从 Lore 用正则追加槽位列表 |
slot_sources.lore.patterns | list<string> | 否 | 见下方默认片段 | — | 正则列表, 每条的捕获组 1 是槽位列表文本; 用 find 匹配 (子串命中即可). 匹配前会去除 MiniMessage 标签并折叠空白, 按纯文本书写. 编译失败的正则记录 accessory.invalid_slot_pattern 警告并跳过该条; 列表为空 (或全部无效) 时该来源不会生效, 也不报错 |
slot_sources.lore.separator | string | 否 | "," | — | 槽位列表分隔符, 同时用于 pdc 的字符串回退分支; 空或全空白回退 "," |
slot_sources.lore.aliases | map<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_id | string | 是 | — | — | 页 id, 也是数据文件里的存储分区键; 规范化后为空时该文件被跳过 |
display_name | string | 否 | "" | — | 页显示名, 支持 MiniMessage, 用于切页格, 启用格与 /eacc pages; 为空时界面回退显示 page_id |
order | integer | 否 | 2147483647 (Integer.MAX_VALUE) | — | 页排序, 升序; 最小者为默认启用页, 同值时再按 page_id 升序 |
gui_template | string | 否 | "accessory_gui" | — | 该页使用的布局 id (对应 gui/<id>.yml 的 id), 允许多页共用一个布局; 找不到对应布局时该页打不开 (记录 accessory.gui_template_missing) |
permission | string | 否 | "" | — | 为空表示所有人可用; 非空时逐字使用该权限串 |
parts | list<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.enabled | boolean | 否 | false | true / false | 功能开关. 关闭时不扣除任何耐久, 物品上的耐久数据保持不变 (等于原版耐久永不消耗) |
durability.damage_per_hit | integer | 否 | 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_seconds | integer | 否 | 60 | ≥ 0 (负数被钳制为 0) | 自动保存间隔, 单位秒. 设为 0 时关闭定时保存; 实际定时周期为 max(100, 秒数 × 20) 个游戏刻 (1 个游戏刻 = 1/20 秒), 即最密 5 秒一次 |
persistence.drain_timeout_seconds | integer | 否 | 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_version | integer | 是 (写出时) | 2 | 当前写入值固定为 2 | 写到文件的结构版本. 读取时不校验具体取值, 识别依据只看结构 (见下两节) |
player_name | string | 否 | "" | — | 最后一次写入时的玩家名; 读取时若为空则回填在线名 |
enabled_page | string | 否 | 默认页 (order 最小的页) | — | 玩家当前启用的页 id; 加载后若该页不存在, 运行时回退到默认页 |
pages | map<string, map<string, string>> | 否 | {} | — | 主结构: pages.<页 id>.<槽位实例 id> = Base64 物品字节. 同一槽位实例在不同页各存一份, 互不覆盖; 空页不写出 |
pages.<页 id>.<槽位实例 id> | string | 否 | — | — | ItemStack.serializeAsBytes 结果再经 Base64 编码的文本; 解码失败的一条会被丢弃并记录警告 |
slots | map<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/ 目录: 一旦结构无法识别, 插件不会用空数据覆盖原文件