Skip to content

材料与品质

这一页覆盖 EmakiForge 中和"材料"、"品质"相关的所有内容:品质怎么算、保底怎么触发、图纸怎么写、材料格式是什么样的,以及物品刷新服务的工作原理。

品质系统

品质等级格式

品质等级用紧凑的三段式格式定义:

"名称-权重-倍率"
类型说明示例
名称String品质的显示名称传说
权重Integer加权随机的权重值,越大越容易出2
倍率Double材料贡献的乘数,直接影响最终属性2.0

示例品质池:

yaml
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 最后兜底(随机完再检查)。

保底计数器机制

保底系统是为了解决"脸黑"问题——防止玩家连续几十次都出低品质:

yaml
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设定品质下限,随机结果太低时自动提升在随机之后应用
yaml
# 强制品质 — 比如"传说之心"这种特殊材料
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 上:

yaml
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}"

品质动作示例

不同品质等级可以触发不同的动作,比如出传说品质时全服广播:

yaml
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/ 目录下。玩家需要在锻造界面的图纸槽位放入匹配的图纸物品才能开始锻造。

yaml
# 图纸唯一标识符
id: iron_sword_blueprint

# 显示名称
displayName: "<white>铁剑图纸"

# 物品来源(用于匹配玩家放入的图纸物品)
source: "minecraft:paper"

# 标签(配方的 blueprint_requirements 通过标签匹配图纸)
tags:
  - sword
  - iron
  - melee

# 图纸提供的基础锻造容量(与配方的 forge_capacity 叠加)
forgeCapacity: 50
字段类型必填说明
idString图纸唯一标识符
displayNameString显示名称,支持 MiniMessage
sourceString物品来源 ID,系统用这个来判断玩家放入的物品是不是这张图纸
tagsList标签列表,配方通过 blueprint_requirements 匹配这些标签
forgeCapacityInteger图纸额外提供的锻造容量,和配方的 forge_capacity 叠加

材料格式

材料定义了锻造所需的输入物品及其效果。可以放在 materials/ 目录下作为独立文件,也可以直接内联写在配方里。

yaml
# 物品来源 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: "精良"
字段类型必填默认值说明
itemString物品来源 ID
amountInteger所需数量
optionalBooleanfalse是否可选。可选材料不放也能锻造,但放了会有额外效果
capacity_costInteger0占用的锻造容量。所有材料的容量消耗总和不能超过锻造容量上限
effectsList[]材料效果列表,详见配方页面的效果类型说明

ForgeItemRefreshService

物品刷新服务解决的问题是:配方改了之后,已经锻造出来的物品怎么办?

它的做法是通过签名比较来检测变化。每次锻造时,系统会根据配方版本、材料定义等信息计算一个签名,存在物品的 PDC 里。后续如果配方改了,签名就对不上了,刷新服务会自动重建物品的展示层。

触发时机

  • 玩家打开背包时
  • 玩家手持物品切换时
  • 管理员执行刷新命令时
  • 配方/材料资源重载后

刷新流程

检测物品是否包含 forge layer 数据

读取物品 PDC 中的 forge layer snapshot

用当前配方定义计算新签名

和物品上存储的旧签名比较
    ├── 签名一致 → 不需要刷新,跳过
    └── 签名不一致 → 执行刷新

    根据最新的配方和材料定义重建 structured_presentation

    更新物品的名称、Lore 和 PDC 数据

    写入新签名

签名基于什么计算

  • 配方 ID 和版本
  • 材料定义的哈希值
  • 品质等级和倍率
  • structured_presentation 模板的哈希值

所以只要你改了配方里和展示相关的任何内容,签名就会变,已有物品就会被自动刷新。

提示

刷新服务只更新展示层(名称、Lore),不会改变已经写入的属性数值。属性值在锻造时就确定了,写死在 PDC 里,不受后续配置变更影响。如果你确实需要改属性,只能让玩家重新锻造。

Released under the GPL-3.0 License