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
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique gem id. Lowercased on load; the file is skipped when blank. |
display_name | string | No | Display name in MiniMessage format. Defaults to id. |
lore | list | No | Lore of the gem item itself. |
gem_type | string | No | Gem type, such as attack, defense, utility, or universal. Defaults to universal. |
level | integer | No | Base gem level. Defaults to 1, minimum 1. |
base_item_source | string | Yes | Construction 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_sources | list | No | Recognition: allowed item sources for the gem item. Omit it and the item source is unrestricted. |
matcher | object | No | Recognition: 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_data | integer | No | Optional custom model data. |
effects | list | No | Effects applied when the gem is inlaid. |
socket_compatibility | list | No | Socket types that can accept this gem. Empty means any socket type. |
required_gems | list | No | Gem ids this gem depends on. |
conflicting_gems | list | No | Gem ids that conflict with this gem. |
inlay_cost | object | No | Cost paid when inlaying. |
extract_cost | object | No | Cost paid when extracting. |
extract_return | object | No | How the gem is returned after extraction. |
stages | object | No | Upgrade stage settings. The parser reads stages first; see Upgrade stages. |
upgrade | object | No | Fallback alias for stages. Read only when the file has no stages key. |
reroll | object | No | Reroll settings; see Reroll. |
actions.inlay_success | list | No | Action lines run after a successful inlay. |
actions.extract_success | list | No | Action lines run after a successful extraction. |
NOTE
Listing universal in socket_compatibility lets the gem go into any socket type.
Minimal example
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.0Effect types
| Type | Payload key | Description |
|---|---|---|
variables | variables | Runtime variables used by lore templates and formulas. |
ea_attribute | ea_attributes | EmakiAttribute PDC attributes written to equipment. |
es_skill | es_skills | EmakiSkills skill attachments. |
name_action | name_actions | Name operations applied to equipment. |
lore_action | lore_actions | Lore 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:
variables:
physical_attack: 8
ea_attributes:
physical_attack: 8.0variables 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
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: 1Upgrade 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
| Field | Description |
|---|---|
enabled | Whether upgrading is enabled. When omitted it defaults to true if at least one level parsed, otherwise false. |
max_level | Maximum level. When omitted it defaults to the highest configured level, or 1 when no level parsed. |
gui_template | Parsed 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. |
levels | Per-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
| Field | Description |
|---|---|
display_name | Display name for that level. Defaults to an empty string. |
variables / ea_attributes | Expression variables and PDC attributes for that level. |
effects | Effect list for that level, same format as the base effects. |
name_actions | Name operations for that level. |
lore_actions | Lore operations for that level. |
matrices | String 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
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.0Omitting levels and writing levels directly under the stage block is equivalent:
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
| Field | Description |
|---|---|
enabled | Whether reroll is enabled. Defaults to true when a reroll block is present. |
group | Affix 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_affixes | Upper bound on affixes generated by a full reroll. Minimum 1, defaults to 1. |
pools | Affix pools keyed by group name. Fallback alias affixes (read only when pools is absent). |
full_cost | Cost of a full reroll, same structure as inlay_cost. |
value_cost | Cost of a value reroll, same structure as inlay_cost. |
Affix entry fields
| Field | Description |
|---|---|
id | Affix id. Can be omitted in map form, where the entry key is used; the entry is skipped when neither is present. |
weight | Roll weight. Defaults to 1; non-positive values are recorded as a diagnostic. |
min / max | Value range. Aliases min_value / max_value; max falls back to min when absent. |
min_stage / max_stage | Usable stage range. Defaults to 1 and unbounded; entries outside the range are filtered out by the gem's current stage before rolling. |
display_name | Affix display name. Defaults to id. |
attribute_id | Matching attribute id. Defaults to id. |
Reroll modes
| Mode | Behaviour | Cost key |
|---|---|---|
| Full reroll | Re-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 reroll | Keeps 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:
- Opening reads the gem in the main hand, generates a candidate, charges immediately, and opens a candidate session with a time-to-live.
- 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.
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_sourcesfor recognition instead of display names or lore matching, and keepbase_item_sourcepointing at the item you actually hand out. - Keep
gem_typeandsocket_compatibilitysimple and easy to understand. - Write real stats through
ea_attribute; use lore actions only for presentation. - Use
extract_returncarefully on high-value gems.