Skip to content

物品装配系统 ​

装配系统把多个模块写进同一件物品的内容, 合并成你最终看到的名称和 Lore

简单说, 装配系统就是把各模块写进物品的状态, 统一合并成最终展示. 你的装备能一路成长, 靠的就是它

为什么需要装配系统 ​

一件 RPG 装备上, 往往同时带着好几个模块写进去的内容:

  • EmakiItem 写入的基础名称, 基础 Lore, 套装, 技能
  • EmakiForge 写入的品质, 锻造材料, 额外属性
  • EmakiStrengthen 写入的星级, 强化加成, 失败标记
  • EmakiGem 写入的插槽, 宝石, 宝石等级
  • EmakiAttribute 写入或读取的属性 payload

如果每个模块都直接改最终的 Lore, 就会互相覆盖, 出现重复, 顺序混乱, 还会留下残留. 装配系统的做法是: 各模块往自己那一层 (layer) 写结构化数据, CoreLib 再统一渲染出最终展示

核心概念 ​

概念说明
namespace layer每个模块在物品上占一层数据, 这一层里装着该模块写进去的所有状态
order层的排序权重, 决定最终 Lore 里各模块的展示谁先谁后
snapshot某一层数据的快照, 用来编解码和保存
contribution这一层对最终展示的贡献, 包括 Lore 区块, 名称修饰和属性统计
renderer渲染器, 负责把所有层的贡献合并成最终的 ItemMeta

namespace layer ​

NamespaceOrder说明
forge100锻造层, 装着品质, 材料贡献和锻造配方信息
strengthen200强化层, 装着星级, 锻印, 保护状态和强化属性
gem300宝石层, 装着插槽, 宝石, 等级和宝石属性
cooking10000烹饪的展示层, 或用于特殊展示

order 数字越小越靠前, 你可以用它控制最终 Lore 里各模块谁先谁后

装配流程 ​

text
1. 业务模块完成操作 (如强化成功, 宝石镶嵌)
       ↓
2. 模块把真实状态写入 PDC (layer snapshot)
       ↓
3. 模块通过 ItemOperationLedger 执行 name_actions/lore_actions
       ↓
4. Ledger 记录操作到 PDC (emaki:item_operations), 支持后续精确回退
       ↓
5. 返回更新后的 ItemStack

需要撤销操作时 (如宝石提取, 强化降级), 走的是这样三步:

text
1. 模块调用 Ledger.revert (operationId) 或 Ledger.revertAll (sourceNamespace)
       ↓
2. Reverter 根据账本记录精确撤销对应的名称/Lore 修改
       ↓
3. 不影响其他模块的操作结果

关键服务 ​

服务说明
EmakiItemAssemblyService物品装配的入口, 接收重建请求并协调各个 layer
ItemOperationLedger统一的名称/Lore 操作账本, 支持精确回退
ItemOperationExecutor执行 name_actions/lore_actions, 并把变更记下来
ItemOperationReverter按账本记录精确回退操作
EmakiNamespaceRegistry负责 namespace 的注册和顺序管理, 记着所有已注册 layer 的 order
EmakiItemLayerCodecRegistry负责 layer 数据的编码, 解码和兼容, 处理版本迁移

Lore 操作账本 (ItemOperationLedger) ​

模块每执行一次 name_actions 或 lore_actions, Ledger 都会生成一条带 operationId 的记录, 存进物品的 PDC (物品自带的附加数据存储) (emaki:item_operations)

每条记录包含:

字段说明
operationId这次操作的唯一标识
sourceNamespace这条操作来自哪个模块 (如 gem, strengthen, forge)
timestamp操作发生的时间
nameRecords名称的修改记录 (用来回退)
loreRecordsLore 的修改记录 (用来回退)

核心 API:

方法说明
apply(itemStack, operationId, sourceNamespace, nameActions, loreActions, variables)执行操作, 并记进 PDC
revert(itemStack, operationId)精确撤销指定的这次操作
revertAll(itemStack, sourceNamespace)清空某个命名空间下的所有操作

名称修饰 (Name Contribution) ​

除了 Lore, layer 还可以给物品名称加修饰. 例如:

  • 强化层在名称前添加 +10
  • 锻造层在名称后添加品质标签 [史诗]
  • 宝石层不修改名称

名称修饰可以指定加在名称的哪个位置:

位置说明
PREFIX加在名称前面
POSTFIX加在名称后面

多个 layer 的名称修饰会按 order 排序, 再依次拼起来

NOTE

位置枚举值是 PREFIX 和 POSTFIX, 不是 SUFFIX

配置者能做什么 ​

你不会直接操作装配服务, 但你的配置会直接影响最终展示:

调整 Lore 模板 ​

每个模块的 Lore 模板就写在它自己的配置里:

yaml
# EmakiStrengthen 配置示例
lore:
  template:
    - '<gray>强化等级:<yellow>+%star%'
    - '<gray>强化加成:<green>+%bonus_attack% 攻击'

调整属性展示格式 ​

属性怎么显示, 定义在 EmakiAttribute 的 lore_formats/ 里:

yaml
# lore_formats/default_flat.yml
format: '<gray>%display_name%:<white>+%value%'

控制展示开关 ​

有些模块还能配置要不要显示某些状态:

yaml
display:
  show_quality: true
  show_material_info: false
  show_star_level: true
  show_gem_slots: true

使用模块命令刷新装备 ​

配置改完后, 已有装备的展示不会自动更新, 用模块提供的刷新命令即可:

  • 手动刷新单件装备
  • 批量刷新在线玩家装备
  • 玩家登录时自动刷新 (如果模块支持)

设计装备展示的建议 ​

  • 把"真实数值"放进 PDC / 属性 payload, 别只写 Lore. Lore 是给玩家看的, PDC 才是存数据的地方
  • Lore 里只放玩家需要看到的信息. 内部调试数据不要摆进去
  • 每个模块的 Lore 区块界限要清楚. 锻造区, 强化区, 宝石区各管各的, 不要交叉
  • 别让两个模块写同一行一样的属性. 攻击力只在一个地方展示, 玩家才不会看花眼
  • 升级旧装备前, 先在测试服抽样刷新. 确认新模板不会弄坏旧数据的展示
  • 名称修饰保持简洁. +10 烈焰剑 [史诗] 比 [+10][史诗][锻造][宝石x3] 烈焰剑 好读得多

装配触发时机 ​

下面这些操作都会触发物品重建:

操作触发模块
强化成功/失败EmakiStrengthen
锻造完成EmakiForge
宝石镶嵌/提取/升级EmakiGem
物品自动更新EmakiItem
手动刷新命令各模块
属性同步EmakiAttribute

Lore 操作里 anchor 的匹配规则 ​

用 lore_actions 里的 insert_below 或 insert_above 时要注意: anchor 留空, 和 anchor 没匹配到任何行, 结果并不一样:

操作anchor 为空anchor 未匹配到任何行
insert_below插入到 Lore 末尾插入到 Lore 末尾
insert_above插入到 Lore 开头插入到 Lore 末尾

anchor 用的是包含匹配 (contains), 命中第一行就停; insert_below 插在该行之后, insert_above 插在该行之前

Namespace ID 规范化 ​

注册 namespace 时, ID 会自动按下面的规则整理:

  • 去除首尾空格
  • 转为小写
  • 空格替换为下划线
  • 空字符串变为 unknown