Skip to content

Blueprints and Materials ​

Forge uses blueprint requirements to gate recipe entry and material entries to decide cost, capacity, quality modifiers, and extra effects. A blueprint answers "may I do this", a material answers "what do I use, and how well does it turn out"

Blueprint requirements ​

yaml
blueprint_requirements:
  - item_sources:
      - "minecraft-enchanted_book"
    amount: 1
FieldTypeRequiredDefaultAllowed valuesDescription
idstringNoDerived from the item_sources shorthand, or a matcher digest when there is no sourceNon-blank string (a declared blank value reports IDENTITY_BLANK)Stable identity of the requirement; counts aggregate by it. See Accepting several forms of one blueprint
blueprint_idstringNoSame as idSame as idAlias of id; when both are present id wins
item_sourceslist<string>Noempty (unrestricted source)Item source shorthand, e.g. minecraft-enchanted_bookAllowed blueprint sources. ANDed with matcher; when both are omitted the entry never matches (BLUEPRINT_MATCH_EMPTY)
matcherobjectNoempty (no extra condition)Component / PDC / Lore conditionsGeneral item matcher. See Item Matcher
amountintegerNo1> 0 (<= 0 makes the entry fail to parse and rejects the whole recipe)Required amount
itemstringNoblankItem source shorthandCompatibility key: read as a display shorthand only when item_sources is absent; it does not participate in identity derivation

Blueprint requirements are checked before forging and nothing is consumed. They are suitable for recipe scrolls, unlock items, or profession certificates

Shipped default: the bundled recipes/example_recipe.yml uses two entries sharing one id to demonstrate two acceptable forms of one blueprint; the copyable form is in Accepting several forms of one blueprint

Accepting several forms of one blueprint ​

Write each acceptable form as its own entry sharing one id. Counts aggregate by id, so holding any one form satisfies the requirement instead of being read as two separate blueprints the player must hold at once

yaml
blueprint_requirements:
  # Narrow form first: an official knowledge book carrying the marker
  - id: blueprint_accepted
    item_sources:
      - "minecraft-knowledge_book"
    amount: 1
    matcher:
      type: component
      component: custom_model_data
      path: "floats[0]"
      operator: "=="
      value: 1.0
  # Broad form last: a plain enchanted book
  - id: blueprint_accepted
    item_sources:
      - "minecraft-enchanted_book"
    amount: 1

This replaces the older approach of packing every form into one matcher's any_of

Material list ​

yaml
materials:
  - item_sources:
      - "minecraft-iron_ingot"
    amount: 3
    capacity_cost: 5
    effects:
      - type: "variables"
        variables:
          physical_damage: 5
      - type: "ea_attribute"
        ea_attributes:
          physical_attack: 5.0
FieldTypeRequiredDefaultAllowed valuesDescription
material_idstringNoDerived from the item_sources shorthand, or a matcher digest when there is no sourceNon-blank string (a declared blank value reports IDENTITY_BLANK)Stable selection and lookup identity; may be declared independently from count_key and audit_id. See Material identity
count_keystringNoThe resolved material_idNon-blank stringQuantity aggregation and consumption identity
audit_idstringNoThe resolved material_idNon-blank string; within one recipe it may not be shared by different material_id values (reports AUDIT_ID_CONFLICT)Identity written into the forged-item PDC and used for refresh lookup
item_sourceslist<string>Noempty (unrestricted source)Item source shorthand, e.g. minecraft-iron_ingotAllowed material sources; when no identity is declared they help derive one. ANDed with matcher; when both are omitted the entry never matches (MATERIAL_MATCH_EMPTY)
matcherobjectNoempty (no extra condition)Component / PDC / Lore conditionsGeneral item matcher. See Item Matcher
amountintegerNo1Non-zero (0 makes the entry fail to parse and rejects the whole recipe)Required amount
capacity_costnumber | expressionNo0Rounded to an integer after evaluation, >= 0Forge capacity occupied by this material. Expressions and random configs are evaluated per attempt
optionalbooleanNofalsetrue / falseWhether this material is optional
effectslist<object>Noempty list—Effects contributed by this material, see Material effects
itemstringNoblankItem source shorthandCompatibility key: read as a display shorthand only when item_sources is absent; it does not participate in identity derivation

When both item_sources and matcher are omitted, the material entry never matches

WARNING

Do not write id, display_name, or description inside a materials[] entry. The material parser treats a node carrying any of those three keys as "not a material definition" and returns nothing, which makes the whole recipe fail to load (INVALID_CONFIG). The material identity key is material_id

Within one recipe, every entry sharing a material_id must use the same count_key, audit_id, amount, and optional, otherwise MATERIAL_IDENTITY_CONFLICT is reported

Shipped default: the materials: list in recipes/example_recipe.yml demonstrates required materials, optional materials, capacity_bonus, matcher-only materials, and a material combining item_sources with a component condition

Capacity and optional materials ​

forge_capacity limits the total material capacity cost. The sum of every material's capacity_cost may not exceed it

yaml
forge_capacity: 35

Guidance:

  • Keep base recipes small so players are not overwhelmed by choices
  • Advanced recipes may allow more optional material space so players can chase higher quality
  • Show optional material limits clearly in the GUI, otherwise players cannot tell why quality changed

Material matching notes ​

  • Use stable item_sources shorthand ("provider-item_id")
  • For valuable materials pin material_id so players cannot substitute counterfeit items with a different identity
  • If a material comes from another module, confirm that module loads before Forge

Material identity ​

Each material has three independently configurable identities: material_id drives selection and lookup, count_key drives quantity aggregation and consumption, and audit_id is written into the forged-item PDC and used for audit/refresh lookup. Missing values are filled in this order:

  1. material_id takes the explicit material_id, then the item_sources shorthand, then a matcher digest. count_key / audit_id do not participate in deriving material_id
  2. count_key defaults to the resolved material_id
  3. audit_id defaults to the resolved material_id

Matcher-only materials should declare material_id explicitly

A material declaring only matcher (no item_sources) falls back to a matcher digest for its identity, which drifts with the matcher content. A later matcher edit can make an already-forged item report the material as missing during refresh

Give such materials an explicit material_id; add count_key and audit_id separately when selection, consumption aggregation, and audit refresh must diverge. When reading legacy audit records, Forge falls back through audit_id → material_id → count_key → legacy material_item / source; a non-canonical record that resolves successfully is marked for refresh rewrite, and a record that resolves to nothing keeps the original item with a warning instead of overwriting it with incomplete data

General item matcher ​

Both blueprint_requirements[] and materials[] combine two sibling fields with AND: item_sources carries only allowed item sources, matcher carries only component / PDC / Lore conditions. Full syntax (the complete type set, operators, path, and nesting) is in Item Matcher

WARNING

A matcher must not contain item source conditions. type: item_source / item_sources / source / sources are rejected with a warning, and that matcher never matches

yaml
materials:
  # Narrow condition first: only iron ingots carrying Sharpness
  - material_id: enchanted_iron_ingot
    item_sources:
      - "minecraft-iron_ingot"
    matcher:
      type: component
      component: enchantments
      path: sharpness
      operator: '>='
      value: 3
    amount: 1
    capacity_cost: 10
    effects:
      - type: "variables"
        variables:
          physical_damage: 15
  # Broad condition last: plain iron ingots
  - item_sources:
      - "minecraft-iron_ingot"
    amount: 3
    capacity_cost: 5

The two materials above share the same item source, so the narrower entry must declare material_id explicitly; otherwise both derive the same identity key and their counts merge

DANGER

Materials are first-match in declaration order, so a broad condition declared earlier shadows a narrower one declared later

Forge scans materials top to bottom for each submitted item and stops at the first match. If the plain iron ingot entry above came first, enchanted iron ingots would match it too and the narrower entry would never be reached

The rule is simple: narrow conditions first, broad conditions last. blueprint_requirements uses the same first-match logic and the same ordering requirement

Material effects ​

Materials can carry effects that shape the result item after a successful forge. Effects live in a material's effects list

Effect types ​

Every effect needs at least type. The effect data keeps every key except type, but only the keys below are read

FieldTypeRequiredDefaultAllowed valuesDescription
effects[].typestringYes—variables / ea_attribute / es_skill / name_action / lore_action / quality_modify / capacity_bonusEffect type. When blank the effect fails to parse and the whole recipe is rejected
effects[].variablesobjectNoemptymap<variable name, number | expression>Variable table of a variables effect; contributes text/template values and never writes Attribute PDC
effects[].ea_attributesobjectNoemptymap<attribute id, number | expression>Attribute table of an ea_attribute effect, written into the structured PDC layer (requires EmakiAttribute)
effects[].es_skillslist<string>Noempty listSkill idsSkills attached by an es_skill effect; duplicates are removed (requires EmakiSkills)
effects[].name_actionslist<object>Noempty listCoreLib name operationsName operation chain executed by a name_action effect
effects[].lore_actionslist<object>Noempty listCoreLib lore operationsLore operation chain executed by a lore_action effect
effects[].modestringNo—force / minimumMode of a quality_modify effect; when missing or blank the effect is ignored entirely
effects[].tierstringNo—A tier name present in the quality poolTarget tier of a quality_modify effect; when missing or blank the effect is ignored entirely
effects[].valuenumber | expressionNo0Any numberCapacity bonus of a capacity_bonus effect. Evaluated per attempt, rounded to an integer; a negative total becomes 0

Shipped default: recipes/example_recipe.yml covers six of the seven effect types (all but quality_modify) and can be copied directly

NOTE

The final effect value is configured value × material amount × quality multiplier. This applies to both variables and ea_attribute, but their semantics differ: variables only feeds the text/template context, while real attribute output must be written in ea_attributes

variables effect ​

Injects variable values into the forge result. They are scaled by the quality multiplier and can be used in lore_actions and name_actions templates

yaml
effects:
  - type: "variables"
    variables:
      fire_damage: 10
      fire_resistance: 5

ea_attribute effect ​

Writes a structured PDC attribute layer through the EmakiAttribute authoritative API (requires EmakiAttribute). The attribute value is configured value × material amount × quality multiplier. Without EmakiAttribute this effect takes a no-op path: forging still completes but no attribute is written. Current configs no longer use ea_attribute_meta

yaml
effects:
  - type: "ea_attribute"
    ea_attributes:
      physical_attack: 15.0
      physical_defense: 5.0

es_skill effect ​

Attaches skill ids to the result item (requires EmakiSkills). Use the es_skills list form; the old single es_skill field is no longer the recommended shape

yaml
effects:
  - type: "es_skill"
    es_skills:
      - "fire_slash"
      - "flame_shield"

name_action effect ​

Runs name operations on the result item, supporting every action type of the CoreLib name operation system

yaml
effects:
  - type: "name_action"
    name_actions:
      - action: "prepend_prefix"
        value: "<red>Flame </red>"
      - action: "append_suffix"
        value: " <gray>[Forged]</gray>"

lore_action effect ​

Runs lore operations on the result item, supporting every action type of the CoreLib lore operation system

yaml
effects:
  - type: "lore_action"
    lore_actions:
      - action: "insert_below"
        anchor: "Forged attributes:"
        content:
          - "<gray>Physical damage: <red>+%physical_damage%</red></gray>"
          - "<gray>Max health: <green>+%max_health%</green></gray>"

quality_modify effect ​

Modifies the quality result. Two modes are supported:

ModeDescription
forceForces the tier to the specified quality, ignoring the roll
minimumSets a quality floor; a lower roll is raised to that tier
yaml
effects:
  - type: "quality_modify"
    mode: "force"
    tier: "Epic"

IMPORTANT

The recommended field name is tier; the old quality key is no longer the documented form. force mode also skips the pity counter logic entirely

capacity_bonus effect ​

A material carrying this effect behaves as if its own capacity_cost were 0 and contributes extra capacity to the recipe

yaml
effects:
  - type: "capacity_bonus"
    value: 20

IMPORTANT

The recommended field name is value; the old amount, bonus, and capacity keys are no longer the documented form

Template variables ​

Available in name_actions value fields and lore_actions content fields:

VariableDescription
%quality%Quality tier name. Injected only when a quality tier resolved
%quality_name%Quality display name, same value as %quality%
%quality_multiplier%Quality multiplier, formatted as 0.##
%multiplier%Short alias of the quality multiplier
%<name>%Any value injected through variables effects, already scaled by material amount and quality multiplier

Full example ​

yaml
id: "example_recipe"
display_name: "<gold>Flame Sword Forging Recipe</gold>"
forge_capacity: 35

blueprint_requirements:
  - item_sources:
      - "minecraft-enchanted_book"
    amount: 1

materials:
  - item_sources:
      - "minecraft-iron_ingot"
    amount: 3
    capacity_cost: 5
    effects:
      - type: "variables"
        variables:
          physical_damage: 5
          max_health: 2
      - type: "ea_attribute"
        ea_attributes:
          physical_attack: 5.0
          max_health: 2.0
      - type: "lore_action"
        lore_actions:
          - action: "insert_below"
            anchor: "Forged attributes:"
            content:
              - "<gray>Physical damage: <red>+%physical_damage%</red></gray>"
              - "<gray>Max health: <green>+%max_health%</green></gray>"

  - item_sources:
      - "minecraft-blaze_powder"
    amount: 1
    capacity_cost: 10
    effects:
      - type: "variables"
        variables:
          fire_damage: 10
          critical_chance: 5
      - type: "ea_attribute"
        ea_attributes:
          fire_damage: 10.0
          physical_crit_rate: 5.0
      - type: "es_skill"
        es_skills:
          - "flame_strike"
      - type: "name_action"
        name_actions:
          - action: "prepend_prefix"
            value: "<red>Flame </red>"
      - type: "lore_action"
        lore_actions:
          - action: "insert_below"
            anchor: "Forged attributes:"
            content:
              - "<red>Fire damage: +%fire_damage%</red>"