Skip to content

Gem Definitions

Gem definition files are stored in gems/*.yml. A gem definition describes how the gem item is recognized, which socket types it supports, what effects it provides, and how inlay, extraction, and upgrade costs are handled.

Top-level fields

FieldTypeRequiredDescription
idstringYesUnique gem id. Lowercased on load; the file is skipped when blank.
display_namestringNoDisplay name in MiniMessage format. Defaults to id.
lorelistNoLore of the gem item itself.
gem_typestringNoGem type, such as attack, defense, utility, or universal. Defaults to universal.
levelintegerNoBase gem level. Defaults to 1, minimum 1.
base_item_sourcestringYesConstruction base material: which item is built when the gem is granted. A single item source shorthand, not a list, and not a matching position. The gem is skipped when it cannot be parsed. The legacy item_sources key is still read as a fallback for this value.
item_sourceslistNoRecognition: allowed item sources for the gem item. Omit it and the item source is unrestricted.
matcherobjectNoRecognition: non-item-source conditions (component, PDC, lore, variable). ANDed with the sibling item_sources; the gem is never recognised only when both are omitted. See Item Matcher.
custom_model_dataintegerNoOptional custom model data.
effectslistNoEffects applied when the gem is inlaid.
socket_compatibilitylistNoSocket types that can accept this gem. Empty means any socket type.
required_gemslistNoGem ids this gem depends on.
conflicting_gemslistNoGem ids that conflict with this gem.
inlay_costobjectNoCost paid when inlaying.
extract_costobjectNoCost paid when extracting.
extract_returnobjectNoHow the gem is returned after extraction.
stagesobjectNoUpgrade stage settings. The parser reads stages first; see Upgrade stages.
upgradeobjectNoFallback alias for stages. Read only when the file has no stages key.
rerollobjectNoReroll settings; see Reroll.
actions.inlay_successlistNoAction lines run after a successful inlay.
actions.extract_successlistNoAction lines run after a successful extraction.

NOTE

Listing universal in socket_compatibility lets the gem go into any socket type.

Minimal example

yaml
id: "ruby_basic"
display_name: "<red>Ruby</red>"
gem_type: "attack"
level: 1
base_item_source: "minecraft-redstone"
item_sources:
  - "minecraft-redstone"
socket_compatibility:
  - "attack"
  - "universal"
effects:
  - type: "variables"
    variables:
      physical_attack: 5
  - type: "ea_attribute"
    ea_attributes:
      physical_attack: 5.0

Effect types

TypePayload keyDescription
variablesvariablesRuntime variables used by lore templates and formulas.
ea_attributeea_attributesEmakiAttribute PDC attributes written to equipment.
es_skilles_skillsEmakiSkills skill attachments.
name_actionname_actionsName operations applied to equipment.
lore_actionlore_actionsLore operations applied to equipment.

Values under variables and ea_attributes may be numbers or expressions and can reference %level%; keys resolved earlier in the same block are available as variables to later expressions.

Top-level form

Besides the effects list, the parser also accepts variables, ea_attributes, name_actions, and lore_actions written directly on the gem root:

yaml
variables:
  physical_attack: 8
ea_attributes:
  physical_attack: 8.0

variables and ea_attributes merge both forms, with keys from effects overriding top-level keys. For name_actions and lore_actions, a top-level value takes precedence and the matching effects entry is ignored. Skills can only be declared through es_skill inside effects.

Cost example

yaml
inlay_cost:
  currencies:
    - provider: "vault"
      currency_id: ""
      base_cost: 1000
      cost_formula: "%base_cost% * %level%"
      display_name: "<gold>Coins</gold>"
  materials:
    - item_sources:
        - "minecraft-gold_nugget"
      amount: 1

Upgrade stages

Gems support level-based upgrade stages. Each stage can override the display name and the effects.

There are two possible top-level keys: the parser takes stages first and only falls back to upgrade when that key is absent. Both have exactly the same structure and meaning; upgrade is only a legacy alias.

WARNING

When a file declares both stages and upgrade, upgrade is ignored entirely (the two are not merged). Use stages in new configuration.

Stage block fields

FieldDescription
enabledWhether upgrading is enabled. When omitted it defaults to true if at least one level parsed, otherwise false.
max_levelMaximum level. When omitted it defaults to the highest configured level, or 1 when no level parsed.
gui_templateParsed and retained, but currently has no consumer, so setting it has no effect. The upgrade view reuses gui.gem_template from the socket item definition.
levelsPer-level configuration. When this key is omitted, the numeric keys of the stage block itself are read as the level table.

Level keys must parse as integers greater than 1; 1 and below, and non-numeric keys, are skipped.

Level fields

FieldDescription
display_nameDisplay name for that level. Defaults to an empty string.
variables / ea_attributesExpression variables and PDC attributes for that level.
effectsEffect list for that level, same format as the base effects.
name_actionsName operations for that level.
lore_actionsLore operations for that level.
matricesString key/value table for that level.

DANGER

Neither the stage block nor a level block reads materials, economy, success_rate, success_rates, or failure_penalty. Writing those keys into a gem definition raises no error but has no effect at all. Upgrade materials, costs, and the success roll are decided by the matching EmakiStrengthen enhancement recipe; without a usable recipe, or when EmakiStrengthen is unavailable, the upgrade entry reports that upgrading is unavailable.

Stage example

yaml
stages:
  enabled: true
  max_level: 4
  gui_template: "upgrade/default"
  levels:
    2:
      display_name: "<red>Ruby II</red>"
      effects:
        - type: "variables"
          variables:
            physical_attack: 12
        - type: "ea_attribute"
          ea_attributes:
            physical_attack: 12.0

Omitting levels and writing levels directly under the stage block is equivalent:

yaml
stages:
  2:
    display_name: "<red>Ruby II</red>"
  3:
    display_name: "<red>Ruby III</red>"

Reroll

Reroll re-rolls a gem's affixes. It is configured in the reroll block of a gem definition; when that block is absent, reroll is disabled for the gem.

Reroll block fields

FieldDescription
enabledWhether reroll is enabled. Defaults to true when a reroll block is present.
groupAffix pool group name to use. Defaults to default. When pools has no such group, the pool named default is used instead; with no default either the pool counts as empty and reroll fails.
max_affixesUpper bound on affixes generated by a full reroll. Minimum 1, defaults to 1.
poolsAffix pools keyed by group name. Fallback alias affixes (read only when pools is absent).
full_costCost of a full reroll, same structure as inlay_cost.
value_costCost of a value reroll, same structure as inlay_cost.

Affix entry fields

FieldDescription
idAffix id. Can be omitted in map form, where the entry key is used; the entry is skipped when neither is present.
weightRoll weight. Defaults to 1; non-positive values are recorded as a diagnostic.
min / maxValue range. Aliases min_value / max_value; max falls back to min when absent.
min_stage / max_stageUsable stage range. Defaults to 1 and unbounded; entries outside the range are filtered out by the gem's current stage before rolling.
display_nameAffix display name. Defaults to id.
attribute_idMatching attribute id. Defaults to id.

Reroll modes

ModeBehaviourCost key
Full rerollRe-rolls the affixes themselves by weight. The count is the smaller of max_affixes and the existing affix count, or max_affixes when the gem has no affixes yet.full_cost
Value rerollKeeps the existing affix ids and stages and only re-rolls values inside each affix's min/max range.value_cost

Settlement rules

Reroll uses a two-step "generate candidate, then confirm" flow:

  1. Opening reads the gem in the main hand, generates a candidate, charges immediately, and opens a candidate session with a time-to-live.
  2. Confirming validates the config fingerprint and the item instance; the candidate is written to the main-hand gem only when both match.

WARNING

If the gem definition changed before confirmation (fingerprint mismatch), or the main-hand item changed, the session fails and is discarded. Every termination path other than a successful confirm refunds the charge; when the player is offline at that moment the refund becomes pending and runs once the player can be scheduled again.

yaml
reroll:
  enabled: true
  group: "default"
  max_affixes: 2
  pools:
    default:
      - id: "physical_attack"
        weight: 10
        min: 5
        max: 12
        min_stage: 1
      - id: "physical_crit_rate"
        weight: 5
        min: 1
        max: 4
  full_cost:
    currencies:
      - provider: "vault"
        currency_id: ""
        base_cost: 3000
        display_name: "<gold>Coins</gold>"
  value_cost:
    currencies:
      - provider: "vault"
        currency_id: ""
        base_cost: 800
        display_name: "<gold>Coins</gold>"

Reroll command entries and the session query API are documented in Commands and Permissions and API.

Design notes

  • Use stable item_sources for recognition instead of display names or lore matching, and keep base_item_source pointing at the item you actually hand out.
  • Keep gem_type and socket_compatibility simple and easy to understand.
  • Write real stats through ea_attribute; use lore actions only for presentation.
  • Use extract_return carefully on high-value gems.