Skip to content

Item Definitions and Sets ​

Item files live under items/ (items/*.yml), set files under sets/ (sets/*.yml); every field in both file types is described below. With an item definition you decide how a stable item ID produces an in-game item (ItemStack); with a set definition you decide what bonuses players get when they wear several pieces at once

Watch for one exception under items/: pack.yml is not an item definition. It describes how its directory looks as an item pack in the browser and is skipped by the item loader. See Browser GUI for its fields

Item definition fields ​

Top-level fields ​

Before reading the table, keep two points in mind: "Required" asks whether the plugin falls back on its own when a key is missing; "Range" states the constraint the plugin actually enforces, with "—" meaning the plugin performs no validation

FieldTypeRequiredDefaultRangeDescriptionExample
idstringYes——Unique item ID used by other modules. A blank or missing value skips the fileexample_item
itemobjectYes——Base-item definition; only source and components are read. When absent the definition cannot build a base item and is skipped with a warningsee "item and item.components"
effectslistNo—type values in "Effects system"The only entry point for business effects: variables, EmakiAttribute attributes, EmakiSkills skills, accessory slot declarations, and name/lore operation chains all go heresee "Effects system"
equip_slotstringNoallall / hand / main_hand / off_hand / helmet / chestplate / leggings / bootsEquipment slot used by business attributes and skills; it does not intercept vanilla drag-and-drop equipping. Unsupported values fall back to all with a warningmain_hand
setobjectNo——Set membership with id and piecesee "set"
conditionobjectNo——Equipment condition block; fields in "Equipment conditions"see "Equipment conditions"
repairobjectNo——Repair configuration; fields in Item Repairsee "Repair configuration"
updateobjectNo——Auto-update configuration; fields in Item Update Strategysee below
actionsobjectNo——Trigger action configuration. Keys must be trigger names listed on the Triggers pageright_click: [...]

Retired fields and syntaxes

The syntaxes below are no longer read: writing them has no effect at all and only logs one WARN on load (with the field names and file path). Rewrite them as shown

Retired syntaxLocationRewrite as
variables, ea_attributes, es_skills, accessory_slotsrootthe matching type entry inside effects
es_skill_triggers, skill_triggersrootes_skill_triggers inside a type: "es_skill" effect
name_actions, lore_actionsroota type: "name_action" / type: "lore_action" effect
source, componentsrootmove into item.source / item.components
amountroot and item.amountdefinitions no longer carry a stack size; use /ei give <player> <id> [amount], which defaults to 1
material, display_name, item_name, lorerootcustom_name / item_name / lore components under item.components
item_source, iteminside a repair.materials entryitem_sources
skill_triggersinside a type: "es_skill" effectes_skill_triggers

Why were they retired? The effect shorthands and effects were two entry points for the same data: when both were written, the merge result differed per field (override, union, or an action running twice), so you could not tell from the configuration which one took effect. amount was retired because the stack size can be given at give time instead

Sub-fields of set and update:

FieldTypeRequiredDefaultRangeDescriptionExample
set.idstringNo""—Owning set ID, matching sets/*.yml. Empty means the item takes no part in set calculationexample_set
set.piecestringNo""—The item's piece identifier in the set; it must match a pieces key in the set definitionblade
update.enabledbooleanNofalsetrue / falseWhether item update is enabled; it only applies when true and version >= 1true
update.versionintegerNo0>= 0 (applies at >= 1)Item version; the item is rebuilt only when it exceeds the version stored in item PDC1
update.preserve_amountbooleanNotruetrue / falsePreserve stack amount during the updatetrue
update.preserve_damagebooleanNotruetrue / falsePreserve durability damage during the updatetrue
update.preserve_unknown_attribute_sourcesbooleanNotruetrue / falsePreserve attributes from unknown sources during the updatetrue
update.triggersobjectNo—see Item Update StrategyUpdate trigger switches; omitted entries default to truejoin: true

An item definition now has exactly two entry points: item (item.source + item.components) and effects; none of the legacy syntax from the list above is read any more. Definitions also no longer declare a stack size — with /ei give <player> <id> [amount] you get 1 when the amount is omitted, the browser GUI gives 1 on click and a full stack on shift-click, and other modules pass the amount they need

item and item.components ​

FieldTypeRequiredDefaultRangeDescriptionExample
item.sourcestringNo—any ItemSource registered by CoreLibBase item source (ItemSource shorthand). When missing or unbuildable the definition is rejected from the cacheminecraft-diamond_sword
item.componentsmapNo——Vanilla Data Component overrides. Keys may be namespaced component IDs or the EmakiItem shorthand keys belowsee below

EmakiItem shorthand keys for item.components (converted into the matching namespaced component):

FieldTypeRequiredDefaultRangeDescriptionExample
custom_model_datascalar/mapNo——Custom model data. A scalar is wrapped as floats: [value]; a map already carrying floats/flags/strings/colors is used as-isfloats: [1001.0]
item_modelstringNo""—Item model ID; blank means no patchminecraft:custom/example_blade
tooltip_stylestringNo""—Tooltip style ID; blank means no patchminecraft:custom/rare_tooltip
enchantmentsmapNoemptyvalues must be positive integersEnchantment ID → level; non-positive or unparsable entries are droppedminecraft:sharpness: 5
item_flagslistNoemptysee belowLegacy hide flags, mapped into minecraft:tooltip_display.hidden_components- HIDE_ATTRIBUTES
hide_tooltipbooleanNofalsetrue / falseWhether to hide everything in the tooltip (tooltip_display.hide_tooltip)true
unbreakablebooleanNofalsetrue / falseWhether to write minecraft:unbreakabletrue
enchantment_glint_overridebooleanNononetrue / falseWhether to force the enchantment glint; omitting it leaves the component untouchedtrue
max_stack_sizeintNononerange allowed by the vanilla componentMaximum stack size1
raritystringNo""vanilla rarity namesItem rarity; blank means no patchrare
damageintNononerange allowed by the vanilla componentInitial durability damage0
max_damageintNononerange allowed by the vanilla componentMaximum durability1561
enchantableintNonone—Enchantability value, written as minecraft:enchantable.value15
attribute_modifierslistNoempty—Vanilla attribute modifier list. In the shorthand form each entry takes attribute (attribute ID), amount, operation (default add_number), slot (default any), and name (default emakiitem:<item id>/<attribute>); the namespaced component form uses the standard type/id/amount/operation/slot structuresee "Shared item definition and components"
rawstringNo""—Reserved key: the source reads it, but the current version produces no component from it—

Here is the item_flags mapping to components: HIDE_ENCHANTS→enchantments, HIDE_ATTRIBUTES→attribute_modifiers, HIDE_UNBREAKABLE→unbreakable, HIDE_DESTROYS→can_break, HIDE_PLACED_ON→can_place_on, HIDE_ADDITIONAL_TOOLTIP (or HIDE_POTION_EFFECTS) →potion_contents, HIDE_DYE→dyed_color, HIDE_ARMOR_TRIM→trim; any other value is treated as a component ID verbatim

Automatic migration of legacy item definitions has been retired ​

Watch out after upgrading: items/*.{yml,yaml} definitions are no longer migrated before parsing: CoreLib has removed the item.migration.configureditem package and the runtime LegacyConfiguredItemConverter, and EmakiItem's loading entry point no longer invokes a migration runner. File-rewriting migration is retired, and the parser's compatibility reading of the root-level source / amount / components shorthand is retired as well — a base item can now only be declared under item:

  • item.source for the source, for example minecraft-diamond_sword
  • item.components for names, lore, model data, enchantments, and other components
  • The stack size is not declared in the definition; pass it to /ei give <player> <id> [amount]

Back up the configuration directory before upgrading, then rewrite legacy fields by hand: they are not rewritten, filled in, or silently honoured — writing one logs a WARN on load. No plugins/EmakiItem/migration-backups/configured-item-format/ backup is produced any more, while backups written during the migration window stay in that directory and can be cleaned up manually

effects, equip_slot, set, condition, repair, update, and actions keep their existing semantics

Effects system ​

Write all item effects in one effects list and pick the kind with a type field:

typeDescription
variablesExpression engine variables for placeholder rendering in names and lore; payload uses a variables map
ea_attributeEmakiAttribute PDC attributes written to item PDC; payload uses an ea_attributes map
es_skillEmakiSkills skill attachment, granted when equipped; payload uses the es_skills list and an optional es_skill_triggers map
accessory_slotAccessory slot declaration: writes the accessory slots this item may enter into item PDC so EmakiAccessory can decide placement; payload uses an accessory_slots list
name_actionName operation chain; payload uses a name_actions (or name_action) list
lore_actionLore operation chain; payload uses a lore_actions (or lore_action) list

Besides these six built-in type values, you can register your own type through EmakiItemApi.extensions().registerEffectType(...); an entry whose type has no registered handler is skipped silently. See API

yaml
effects:
  - type: "variables"
    variables:
      physical_attack: 12
      physical_crit_rate: 5
  - type: "ea_attribute"
    ea_attributes:
      physical_attack: 12.0
      physical_crit_rate: 5.0
  - type: "es_skill"
    es_skills:
      - "fireball"
      - "flame_dash"
    es_skill_triggers:
      fireball: "right_click"
  - type: "accessory_slot"
    accessory_slots:
      - "ring"

Add the optional es_skill_triggers map (form skill_id: trigger_id) to an es_skill effect: it writes a forced equipment trigger, so the skill is cast by the given trigger while equipped and does not occupy a player skill slot

For real attribute output, put the values in the ea_attributes payload of a type: ea_attribute effect; current configs no longer use ea_attribute_meta. variables are only text/placeholder context and do not automatically become Attribute PDC attributes

When skill IDs and skill triggers are written to item PDC, the plugin does not check whether EmakiSkills is enabled; those keys are owned by a standalone protocol module

Accessory slot declaration (accessory_slot) ​

accessory_slot answers one question only: which accessory window cells this item may occupy. It does not participate in vanilla equipment slot matching and does not change equip_slot semantics. The list accepts two granularities:

ValueMeaningExample
Accessory part idAny cell of that part accepts itring accepts both ring_1 and ring_2
Slot instance idOnly that one cell accepts itring_2 accepts the second cell only

Part ids live in EmakiAccessory's parts.yml (<partId>_<index> expands to slot instance ids). Values are normalized (trimmed, lowercased) and de-duplicated; an empty list means no declaration

The declaration lives under the item PDC key emakiitem:accessory_slots (string list). EmakiAccessory reads only that key as the only item-carried declaration source:

  • An item without the key never enters the accessory window; the plugin reports gui.not_declared
  • An item that declares the key but not the current cell is rejected, reporting gui.slot_mismatch
  • An item already in a slot that stops matching is returned to the player's inventory with a message when the accessory window closes

This replaces the old behaviour: an unspecified slot used to fall back to all, so any EmakiItem item could enter any accessory cell. Your existing items gain the new key only when an update trigger rewrites them (see item update) or when you re-issue them; the accessory slot declaration participates in the definition signature, so adding it marks the definition as needing an update

The full accessory-side rules, condition gating and durability semantics live in attribute and skill integration

Shared item definition and components ​

yaml
item:
  source: minecraft-netherite_sword
  components:
    custom_name: '<gradient:red:gold>%name%</gradient>'
    lore:
      - '<gray>Attack: %physical_attack%</gray>'
    item_model: emaki:flame_blade
    custom_model_data:
      floats: [1001.0]
    attribute_modifiers:
      - type: minecraft:attack_damage
        id: emakiitem:flame_blade/attack_damage
        amount: 12.0
        operation: add_value
        slot: mainhand
    rarity: rare
    max_stack_size: 1
    $unset:
      - repairable
    $reset:
      - enchantments

Keys under components are namespaced Minecraft data-component IDs. A missing namespace defaults to minecraft: — custom_name equals minecraft:custom_name — while explicit namespaces are preserved, and the same rule applies to $unset / $reset entries. Write JSON objects, arrays, and scalars directly as YAML maps, lists, and scalars: a normal value means SET, $unset removes a component, and $reset restores the material prototype default. Text components accept MiniMessage string shorthand. For the rare NBT value that JSON cannot represent losslessly, use the controlled {$snbt: '...'} escape hatch

Error and version behavior:

  • Unknown component IDs are configuration errors and the definition is not cached
  • Invalid values for components supported by the current server are configuration errors and the definition is not cached
  • Known components introduced after the server version are skipped with a warning while the remaining components continue
  • Third-party ItemSources retain source identity, PDC, and unknown components; only patches that the current Paper runtime can safely transfer are applied

item.source accepts every ItemSource registered by CoreLib, not only Bukkit materials. If the resolver is missing, the plugin is not installed, or the source cannot create a base item, the EmakiItem definition is rejected and never cached. The minimum supported runtime is Paper 26.1+; the maintained component catalog and runtime capabilities together determine availability

Item examples ​

Basic weapon ​

yaml
id: "beginner_blade"
item:
  source: minecraft-iron_sword
  components:
    minecraft:custom_name: "<white>Beginner Longsword</white>"
    minecraft:lore:
      - "<gray>A steady, reliable starter weapon.</gray>"
      - ""
      - "<gray>Attack: <white>+10</white></gray>"
    minecraft:unbreakable: {}
    minecraft:tooltip_display:
      hidden_components:
        - minecraft:unbreakable
effects:
  - type: "ea_attribute"
    ea_attributes:
      physical_attack: 10.0
set:
  id: "beginner_set"
  piece: "weapon"

Advanced equipment with variables ​

yaml
id: "flame_blade"
item:
  source: minecraft-netherite_sword
  components:
    minecraft:custom_name: "<gradient:red:gold>%name%</gradient>"
    minecraft:lore:
      - "<dark_gray>━━━━━━━━━━━━━━━━━━</dark_gray>"
      - "<red>⚔ Physical attack: <white>+%physical_attack%</white></red>"
      - "<yellow>✦ Crit rate: <white>+%physical_crit_rate%%</white></yellow>"
      - "<dark_gray>━━━━━━━━━━━━━━━━━━</dark_gray>"
      - "<gray>A legendary blade forged in dragon fire.</gray>"
    minecraft:item_model: "emaki:flame_blade"
    minecraft:enchantment_glint_override: true
    minecraft:rarity: "rare"
    minecraft:max_stack_size: 1
effects:
  - type: "variables"
    variables:
      name: "Flame Blade"
      physical_attack: 45
      physical_crit_rate: 12
  - type: "ea_attribute"
    ea_attributes:
      physical_attack: 45.0
      physical_crit_rate: 0.12
  - type: "es_skill"
    es_skills:
      - "flame_slash"
set:
  id: "flame_set"
  piece: "weapon"

Consumable ​

yaml
id: "health_potion_large"
item:
  source: minecraft-potion
  components:
    minecraft:custom_name: "<red>Large Health Potion</red>"
    minecraft:lore:
      - "<gray>Right-click to restore 50 health.</gray>"
      - "<dark_gray>Consumed on use.</dark_gray>"
    minecraft:max_stack_size: 16
    minecraft:custom_model_data:
      floats: [1001.0]
actions:
  right_click:
    - 'heal amount=50'
    - 'play_sound sound=minecraft:entity.generic.drink volume=1 pitch=1'
    - 'clear_item slot=mainhand source=emakiitem-health_potion_large'
    - 'send_message text="<green>Restored 50 health.</green>"'

Set definitions ​

Drop set files under sets/; subdirectories are loaded recursively. When id duplicates, only the first definition is kept and a warning is logged

FieldTypeRequiredDefaultRangeDescriptionExample
idstringYes——Unique set ID. The file is skipped when it is missing or invalid (normalizes to empty)example_set
display_namestringNothe set ID—Set display name (MiniMessage); an empty value falls back to the set ID<aqua>Example Guardian Set</aqua>
piecesmapNoempty—Set piece definitions, keyed by piece IDsee "Piece definitions"
loreobjectNosee "Lore display configuration"—Lore rendering configuration for set status displaysee "Lore display configuration"
thresholdsmapNoemptykeys must be positive integersPiece-count threshold effects; non-positive or non-section entries are skipped2: {...}

Set bonuses refresh according to config.yml > set_bonus.refresh_triggers

Piece definitions ​

yaml
pieces:
  blade:
    item: "example_item"
    slot: "main_hand"
    display: "Example Blade"
  helmet:
    item: "example_guardian_helmet"
    slot: "helmet"
    display: "Guardian Helmet"
FieldTypeRequiredDefaultRangeDescriptionExample
itemstringNothe piece key—The matching item ID from items/example_item
slotstringNothe piece keymain_hand / off_hand / helmet / chestplate / leggings / boots (the default falls back to the piece key itself)Equipment slotmain_hand
displaystringNothe piece key—Piece name shown in set loreExample Blade

You can also shorten a piece to piece_key: item_id; slot and display name then both fall back to the piece key

Lore display configuration ​

yaml
lore:
  header: "<dark_gray>—— <aqua>Set Name</aqua> <gray>(%active%/%total%)</gray> ——</dark_gray>"
  equipped_format: "<green>✔ %piece%</green>"
  missing_format: "<gray>✘ %piece%</gray>"
  active_threshold_format: "<green>%line%</green>"
  inactive_threshold_format: "<dark_gray>%line%</dark_gray>"
  separator: ""
FieldTypeRequiredDefaultRangeDescriptionExample
headerstringNo<dark_gray>—— %set_name% <gray>(%active%/%total%)</gray> ——</dark_gray>—Set lore header templatesee the snippet above
equipped_formatstringNo<green>✔ %piece%</green>—Template for an equipped piecesee the snippet above
missing_formatstringNo<gray>✘ %piece%</gray>—Template for a missing piecesee the snippet above
active_threshold_formatstringNo<green>%line%</green>—Template for an active threshold linesee the snippet above
inactive_threshold_formatstringNo<dark_gray>%line%</dark_gray>—Template for an inactive threshold linesee the snippet above
separatorstringNo""—Line separator; an empty string inserts no separator line""

Threshold effects ​

A threshold key is simply the number of pieces needed to activate it

yaml
thresholds:
  2:
    lore:
      - "[2-piece] Physical attack +5"
    effects:
      - type: "ea_attribute"
        ea_attributes:
          physical_attack: 5.0
      - type: "es_skill"
        es_skills:
          - "guardian_dash"
FieldTypeRequiredDefaultRangeDescriptionExample
lorelistNoempty—Lore lines shown while the threshold is active- "[2-piece] Physical attack +5"
effectslistNoemptytype values ea_attribute / es_skill / name_action / lore_actionThreshold effect listsee "Threshold effects"

Note that the threshold top-level shorthands (ea_attributes, es_skills, name_actions, lore_actions, plus the never-effective name_action / lore_action) and the effect payload fallbacks (attributes for ea_attribute, es_skill for es_skill) are likewise no longer read; writing them only logs one WARN on load

State calculation and invalid slots ​

Set-membership visibility is calculated separately from the active piece count. Once an item definition declares a valid set.id, the state keeps that set even when every candidate is rejected by slot validation; Lore therefore displays 0/%total% instead of collapsing into a state with no set definition

Only pieces that meet all three conditions count toward activeCount and threshold activation:

  1. it resolves uniquely to a real piece in sets/*.yml;
  2. the actual equipment slot matches the item definition's equip_slot;
  3. the actual equipment slot also matches the set piece's slot

Missing or unloadable set definitions are isolated for safety: they never enter visible state, never activate rewards, and never trigger destructive Lore writes. Runtime logging emits one warning per missing set ID; with set DEBUG enabled, it also reports [DEBUG:SET_STATE] state=missing_definition action=preserve. Paper and Folia use the same pure state-construction rule; Folia changes only the owner-thread scheduling boundary

Equipment conditions ​

You can declare equipment conditions on an item; when a player fails them, that item is disabled for the player entirely:

yaml
condition:
  type: "at_least"
  entries:
    - "%emakilevel_level_main% >= 10"
    - "%player_class% == 'warrior'"
  required_count: 2
  invalid_as_failure: true
  on_pass:
    actions:
      - 'send_message text="<green>Equipment condition met.</green>"'
  on_fail:
    message: "<red>You do not meet the equipment requirements!</red>"
    actions:
      - 'send_message text="<red>Requires a level 10+ warrior.</red>"'
FieldTypeRequiredDefaultRangeDescriptionExample
typestringNoall_ofall_of / any_of / none_of / at_least / exactlyCombination modeat_least
entrieslistNoempty—Condition expression list. The key must be entries- "%player_level% >= 10"
required_countintNo0—Number of conditions that must hold; only at_least and exactly read it, and other modes ignore it completely2
invalid_as_failurebooleanNotruetrue / falseWhether an expression that fails to parse counts as unmettrue
on_pass.actionslistNoempty—Actions executed when the condition passes- 'send_message ...'
on_fail.messagestringNo""—Message sent when the condition fails<red>You do not meet the equipment requirements!</red>
on_fail.actionslistNoempty—Actions executed when the condition fails—
on_fail.block_outputbooleanNofalsetrue / falseWhether to block the item's output propagation when the condition failsfalse

WARNING

The condition list key must be written as entries. Any other name parses into an empty condition group, which silently disables the item's condition entirely without a warning

required_count is only read when type is at_least or exactly. all_of and any_of ignore it completely; adding it does not turn any_of into an "at least N" check

Gate scope ​

When the condition is not met, none of the following takes effect:

SurfaceSources
EmakiAttribute attributesLore entries and PDC attributes are both dropped
Equipment skillsLore and PDC sources are both dropped
Set attributesThe emakiitem and emakiitem_set PDC sources
Trigger actionsThat trigger is blocked
Accessory contributionWorn in the accessory window, the same item's attributes, skills and set piece count are dropped as well (evaluated by EmakiAccessory)

What stays active outside this gate: the PDC attributes written by EmakiGem, EmakiForge and EmakiStrengthen. Those are owned by their own modules and do not expire with the host item's condition

When it is evaluated: trigger actions are evaluated before each trigger; attributes and skills are evaluated per player during every equipment collection, so a level or class change applies immediately without re-equipping. The attribute and skill gate evaluation never sends on_fail.message and never runs the on_pass / on_fail actions; those stay on the trigger path only

The attribute and skill gate is hosted by EmakiAttribute and requires EmakiAttribute to be enabled. With EmakiItem alone, the condition gates trigger actions only

The accessory side uses the silent condition query of EmakiItemApi (conditionSatisfied); the query emits no message and does not need EmakiAttribute. It runs when accessory contributions are recomputed, so a condition change reaches the accessory window only on the next recompute (equip or page swap, GUI edit, join load, reload, retrieval, durability break) — unlike the real-time equipment path. See accessory window for the unmet-condition marker

Repair configuration ​

When an item's durability runs out, you can repair it with materials or currency:

yaml
repair:
  enabled: true
  materials:
    - item_sources:
        - "minecraft-diamond"
      amount: 1
      restore: 250
  economy:
    enabled: true
    restore: "100%"
    currencies:
      - provider: "vault"
        currency_id: ""
        base_cost: 100
        cost_formula: "base_cost + missing_durability * 0.25"
        display_name: "Coins"
  on_disabled:
    - 'send_message text="<red>Your weapon broke!</red>"'
  on_repaired:
    - 'send_message text="<green>Weapon repaired!</green>"'

See Item Repair for field semantics and the full flow

Auto update ​

update decides when the item refreshes automatically:

yaml
update:
  enabled: true
  version: 1
  triggers:
    join: true
    held_change: true
    inventory_click: true
    inventory_drag: true
    pickup: true
    interact: true
    command: true

After changing an item definition, increment version to trigger an update. Get manual /ei update working first, then enable auto update step by step instead of turning on every high-frequency trigger at once. See Item Update Strategy for details