材料与品质
这一页覆盖 EmakiForge 中和"材料"、"品质"相关的所有内容:品质怎么算、保底怎么触发、图纸怎么写、材料格式是什么样的,以及物品刷新服务的工作原理。
品质系统
品质等级格式
品质等级用紧凑的三段式格式定义:
"名称-权重-倍率"| 段 | 类型 | 说明 | 示例 |
|---|---|---|---|
| 名称 | String | 品质的显示名称 | 传说 |
| 权重 | Integer | 加权随机的权重值,越大越容易出 | 2 |
| 倍率 | Double | 材料贡献的乘数,直接影响最终属性 | 2.0 |
示例品质池:
tiers:
- "粗糙-40-0.6" # 40% 权重,0.6 倍率
- "普通-30-1.0" # 30% 权重,1.0 倍率
- "精良-20-1.3" # 20% 权重,1.3 倍率
- "史诗-8-1.6" # 8% 权重,1.6 倍率
- "传说-2-2.0" # 2% 权重,2.0 倍率权重不需要加起来等于 100,系统会自动归一化。上面的例子中总权重是 100 只是为了方便理解。
品质计算流程
品质的最终确定要经过好几步,每一步都可能改变结果:
1. 确定品质池
├── 配方声明了 custom_pool? → 用配方自己的品质池
└── 没声明? → 用 config.yml 中的全局 tiers
2. 检查材料品质修正
├── 有 force 修正? → 直接锁定品质,跳到步骤 6
└── 有 minimum 修正? → 先记下来,后面用
3. 检查保底计数器
├── 计数器 ≥ guarantee.count? → 强制使用 guarantee.tier,重置计数器
└── 没到? → 继续
4. 执行加权随机
└── 从品质池中按权重随机抽一个
5. 应用 minimum 修正
├── 随机结果比 minimum 低? → 提升到 minimum
└── 随机结果 ≥ minimum? → 保持不变
6. 更新保底计数器
├── 最终品质 ≥ guarantee.tier? → 计数器归零
└── 最终品质 < guarantee.tier? → 计数器 +1这个流程的设计思路是:force 优先级最高(直接跳过随机),保底次之(到了阈值就触发),minimum 最后兜底(随机完再检查)。
保底计数器机制
保底系统是为了解决"脸黑"问题——防止玩家连续几十次都出低品质:
guarantee:
enabled: true
count: 50 # 连续 50 次没出目标品质
tier: "史诗" # 第 51 次强制给史诗具体逻辑:
- 每次锻造完成后,如果最终品质低于
guarantee.tier,计数器 +1 - 如果最终品质达到或超过
guarantee.tier,计数器归零 - 计数器到了
count阈值,下次锻造直接给guarantee.tier品质 - 计数器是按玩家独立计算的,存在玩家数据文件里
提示
保底计数器只看最终品质是否达标,不管这个品质是随机出的还是被 minimum 提上去的。所以如果你的 minimum 设得比 guarantee.tier 高,保底实际上永远不会触发。
材料品质修正
材料可以通过 quality_modify 效果干预品质结果:
| modifier_type | 效果 | 优先级 |
|---|---|---|
force | 直接锁定品质,跳过随机 | 最高 — 直接覆盖一切 |
minimum | 设定品质下限,随机结果太低时自动提升 | 在随机之后应用 |
# 强制品质 — 比如"传说之心"这种特殊材料
effects:
- type: quality_modify
modifier_type: force
tier: "传说"
# 最低品质 — 高级材料保底不出太差的
effects:
- type: quality_modify
modifier_type: minimum
tier: "精良"注意
如果多个材料同时声明了 force 修正,以最后一个生效的为准(取决于材料的处理顺序)。建议每次锻造最多只放一个 force 修正材料,避免结果不可预期。
品质 structured_presentation 示例
品质等级可以通过 item_meta.structured_presentation 展示在物品名称和 Lore 上:
quality:
item_meta:
structured_presentation:
name_contributions:
quality_prefix:
order: 0
format: "{quality} "
lore_sections:
quality_info:
order: 0
lines:
- "<gray>品质:<white>{quality}"
- "<gray>倍率:<white>×{multiplier}"品质动作示例
不同品质等级可以触发不同的动作,比如出传说品质时全服广播:
quality:
actions:
传说:
- "broadcast message=<gold>✦ {player} <yellow>锻造出了 <gold>传说 <yellow>品质的 {item}!"
- "playsound sound=ui.toast.challenge_complete volume=1.0 pitch=1.0"
- "firework location=player colors=GOLD,YELLOW"
史诗:
- "playsound sound=entity.player.levelup volume=1.0 pitch=1.2"
- "sendmessage message=<light_purple>锻造出了史诗品质!"图纸格式
图纸定义了锻造的基础模板,存放在 blueprints/ 目录下。玩家需要在锻造界面的图纸槽位放入匹配的图纸物品才能开始锻造。
# 图纸唯一标识符
id: iron_sword_blueprint
# 显示名称
displayName: "<white>铁剑图纸"
# 物品来源(用于匹配玩家放入的图纸物品)
source: "minecraft:paper"
# 标签(配方的 blueprint_requirements 通过标签匹配图纸)
tags:
- sword
- iron
- melee
# 图纸提供的基础锻造容量(与配方的 forge_capacity 叠加)
forgeCapacity: 50| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | String | 是 | 图纸唯一标识符 |
displayName | String | 是 | 显示名称,支持 MiniMessage |
source | String | 是 | 物品来源 ID,系统用这个来判断玩家放入的物品是不是这张图纸 |
tags | List | 否 | 标签列表,配方通过 blueprint_requirements 匹配这些标签 |
forgeCapacity | Integer | 否 | 图纸额外提供的锻造容量,和配方的 forge_capacity 叠加 |
材料格式
材料定义了锻造所需的输入物品及其效果。可以放在 materials/ 目录下作为独立文件,也可以直接内联写在配方里。
# 物品来源 ID
item: "minecraft:iron_ingot"
# 所需数量
amount: 5
# 是否为可选材料
optional: false
# 容量消耗(占用多少锻造容量)
capacity_cost: 10
# 材料效果列表
effects:
- type: stat_contribution
stat: physical_damage
amount: 12.0
- type: attribute
attributes:
physical_attack: 10.0
physical_crit_rate: 5.0
- type: skill
skills:
- "fireball"
- type: quality_modify
modifier_type: minimum
tier: "精良"| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
item | String | 是 | — | 物品来源 ID |
amount | Integer | 是 | — | 所需数量 |
optional | Boolean | 否 | false | 是否可选。可选材料不放也能锻造,但放了会有额外效果 |
capacity_cost | Integer | 否 | 0 | 占用的锻造容量。所有材料的容量消耗总和不能超过锻造容量上限 |
effects | List | 否 | [] | 材料效果列表,详见配方页面的效果类型说明 |
ForgeItemRefreshService
物品刷新服务解决的问题是:配方改了之后,已经锻造出来的物品怎么办?
它的做法是通过签名比较来检测变化。每次锻造时,系统会根据配方版本、材料定义等信息计算一个签名,存在物品的 PDC 里。后续如果配方改了,签名就对不上了,刷新服务会自动重建物品的展示层。
触发时机
- 玩家打开背包时
- 玩家手持物品切换时
- 管理员执行刷新命令时
- 配方/材料资源重载后
刷新流程
检测物品是否包含 forge layer 数据
↓
读取物品 PDC 中的 forge layer snapshot
↓
用当前配方定义计算新签名
↓
和物品上存储的旧签名比较
├── 签名一致 → 不需要刷新,跳过
└── 签名不一致 → 执行刷新
↓
根据最新的配方和材料定义重建 structured_presentation
↓
更新物品的名称、Lore 和 PDC 数据
↓
写入新签名签名基于什么计算
- 配方 ID 和版本
- 材料定义的哈希值
- 品质等级和倍率
- structured_presentation 模板的哈希值
所以只要你改了配方里和展示相关的任何内容,签名就会变,已有物品就会被自动刷新。
提示
刷新服务只更新展示层(名称、Lore),不会改变已经写入的属性数值。属性值在锻造时就确定了,写死在 PDC 里,不受后续配置变更影响。如果你确实需要改属性,只能让玩家重新锻造。