Skip to content

Item Definition (full item YAML fields)

Belongs to: Server Owner Guide · Related: Item Types · Attributes & Numbers · Action System

This is QI's most central chapter: how to describe an item with YAML. After reading it you'll be able to understand and write items of any complexity.

📦 Want a ready-made recipe to copy? See Item Example Library (~140 built-in examples). 🩺 Got an error? See Validation Error Quick Reference.


1. File Layout: Grouped by Type

Item definitions live under plugins/QinhItems/items/, and the file name is the type: items in weapon.yml default to type: weapon, items in ring.yml default to type: ring.

Within each file, every top-level key is an item ID, and its definition lives under that key:

yaml
# items/weapon.yml
demo_iron_blade:        # ← item ID
  material: iron_sword
  display_name: "<white>Iron War Blade</white>"
  # …

demo_thunder_edge:      # ← another item
  material: golden_sword
  # …

This is called the grouped layout, and it's the recommended style. QI also stays compatible with the old one-file-per-item layout (where the item carries an explicit id: field); on reload it automatically migrates to the grouped layout and deletes the old file. The logic responsible for this is TypeGroupedItemFiles.

Item ID Conventions

  • Lowercase, alphanumeric + underscores / hyphens.
  • When referencing, use the bare ID, without prefix (demo_iron_blade, not qi:demo_iron_blade).
  • Internally it passes through QinhItemIds.normalize(): it automatically strips qinhitems- / qinhitems: / qi- / qi: prefixes, lowercases, and converts non-alphanumeric characters to underscores. So lookups are case-insensitive.

2. Top-Level Field Reference Table

The table below lists all fields of QinhItemDefinition and their YAML keys. Bold = commonly used fields.

YAML keyTypeDefaultMeaning
(top-level key)StringItem ID (unique)
typeStringinferred from file name / miscItem type, see Item Types
materialStringrequiredBase material or external item-source reference
display_nameString?nullItem name, MiniMessage or legacy & color codes
item_nameString?nullFallback name (used for search / item-source indexing)
loreList<String>emptyDescription lines (one entry per line)
tierString?nullQuality (uppercase, e.g. EPIC), see Quality
providersMapemptyData providers (attributes ap, binding effects, etc.), see §4 below
variablesMap<String,String>emptyVariables, see Variables
base_valuesMap<String,Double>emptyBase values (compiled into ap), see Attributes
enchantmentsMap<String,Int>emptyEnchantments: key=level
enchant_max_total_levelInt?nullTotal enchantment level cap for this item, see Enchantment Cap
gem-socketsList<String>emptyList of gem socket type IDs, see Gem Sockets
gem-stateMapemptyCurrent inlay state of each socket
gem-lore-overrideList<String>emptyCustom gem socket lore (overrides default)
sectionsList<String>emptyReferenced Section IDs
affixesList<String>emptyReferenced affix IDs
fragmentsList<String>emptyReferenced Fragment IDs
resource_packsectionnullResource pack / custom model
optionssectionItem options (see §3 below)
actionssectionActions / triggers (see Action System)
update.versionInt1Config schema version (for migration)

There are also two fields maintained by the system that you generally don't write by hand: contentHash (content hash, for change detection) and sourceFile (source file name).


3. The options Section

options controls the item's meta flags, visuals, food component, custom NBT, and so on. All optional.

yaml
my_item:
  material: diamond_sword
  options:
    # —— Durability / stacking ——
    unbreakable: true            # infinite durability
    max_stack_size: 1            # max stack size (1–99)
    max_durability: 1000         # custom max durability

    # —— Display flags ——
    hide_attributes: true        # hide attribute tooltip (default true)
    hide_enchants: false         # hide enchantment tooltip
    glow: true                   # fake enchant glow (auto-applies HIDE_ENCHANTS)
    item_flags:                  # extra ItemFlag
      - "HIDE_UNBREAKABLE"
      - "HIDE_ARMOR_TRIM"

    # —— Visuals ——
    custom_model_data: 10001     # custom model data (if resource_pack.custom_model_data is set, that one takes precedence)
    color: "#FF00FF"             # leather / potion dye (hex or "R,G,B")
    skull_owner: "username"      # skull skin owner (username or UUID)
    armor_trim:                  # armor trim (1.20+)
      material: "minecraft:copper"
      pattern: "minecraft:coast"
    model_data:                  # 1.20.5+ advanced model component
      floats: [1.5, 2.0]
      flags: [true, false]
      strings: ["custom_string"]
      colors: ["#FF0000", "0,255,0"]

    # —— Potion effects (for persistent effects while worn see providers.perm_effects; here are the item's own built-in potions) ——
    potion_effects:
      - "STRENGTH:200:1:false:true:true"   # type:duration(ticks):level:ambient:particles:icon
      - "SPEED:200:0"                       # the last three can be omitted

    # —— Food component ——
    food:
      nutrition: 8               # nutrition (0–20)
      saturation: 4.5            # saturation
      can-always-eat: false      # edible even when full
      eat-seconds: 1.6           # eating duration (seconds)

    # —— Constraints / binding ——
    restrictions:                # usage restrictions
      - "level:20"               # requires level 20
      - "permission:vip.use"     # requires permission
    bind_on_acquire: true        # soulbind on pickup, see Soulbinding

    # —— Custom NBT ——
    nbt:
      "custom:key1": "value1"
      "custom:number": 42
      "custom:bool": true

restrictions Syntax

Written in the options.restrictions list; validated when equipping / using. If unmet, the item's lore is marked red and use is blocked (via canUse / QinhItemUseCheckEvent):

SyntaxMeaningWho decides
level:20Requires player level ≥ 20QI native
permission:xxxRequires permissionQI native
world:world_nameRequires being in the specified worldQI native
class:战士,法师Requires classDelegated to QinhItemUseCheckEvent (third-party implementation)
Custom xxx:yyyCustomDelegated to the event

See API Reference → canUse for details.


4. The providers Section

A Provider is an "external-system payload" attached to the item. The key is the system ID, and the value is the payload (usually keyed under value, but raw / data / payload are also supported).

yaml
my_item:
  providers:
    ap:                          # ① AttributePlus attributes
      value: '{"attack_damage":18,"crit_rate":0.12}'
    perm_effects:                # ② persistent potion effects while worn
      value: '{"strength":1,"speed":0}'
    legendinlay:                 # ③ Legendinlay gem socket metadata
      value: '{"set":"qi_blade_trio","slot":"weapon","sockets":["normal"]}'
    magicgem:                    # ④ MagicGem gem socket metadata
      value: '{...}'
  • ap — combat attributes. See Attributes & Numbers for details.
  • perm_effects — persistent potion effects while worn: {"effect_name":amplifier}, 0 = level I.
  • legendinlay / magicgem — gem socket payloads, usually auto-synced and generated by the GUI / gem-sockets, see Gem Sockets for details.

A Provider can also be written in a multi-carrier-key sub-section form; for developer details see Providers & Bridges. Allowed carrier keys: value / raw / data / payload.


5. The material Field

material determines the item's underlying ItemStack. Two ways to write it:

  • Without : or - → parsed as a vanilla Material name (e.g. diamond_sword, golden_apple).
  • With : or - → treated as an external item-source reference, taking a finished item from plugins like CraftEngine / ItemsAdder / Nexo / MMOItems wholesale as the base model (along with its own model / CMD / components).

5.1 External Item-Source Reference (CraftEngine / ItemsAdder / Nexo, etc.)

Parsing is delegated to QinhCoreLib's unified item-source system (ItemSourceManagerItemManagerAPI). Supported prefixes (aliases):

Item sourceAvailable prefixes
Vanillavanilla / minecraft / mc / v / material / type
CraftEnginecraftengine / ce / craft-engine
ItemsAdderitemsadder / ia
Nexonexo / nx
MMOItemsmmoitems / mi
NeigeItemsneigeitems / ni
MythicMobsmythicmobs / mm / mythic
MagicGemmagicgem / mg / magic-gem
CustomFishingcustomfishing / cf
QinhItems (itself)qinhitems / qi

Syntax (ItemReferenceParser):

yaml
material: ce:my_custom_sword       # colon form
material: ce-my_custom_sword       # hyphen form (the prefix must come before the first -)
material: nexo:ruby_blade
material: ia:iron_katana
material: mi-SWORD-Legendary        # MMOItems special case: mi-<type>-<ID>
material: ni-blade::{"品质":"传说"} # trailing ::{json} passes params to the backend

Key points:

  • The colon : and the hyphen - are equivalent: ce:xce-x. In the hyphen form, everything before the first - is the prefix, and everything after is the item ID.
  • When referencing an external source, you usually don't need to also configure resource_pack.custom_model_data—the external item already comes with its own model. For the CMD / resource-pack route, see Resource Packs & Custom Models.
  • If the backend plugin isn't installed / the item ID doesn't exist → parsing fails → the item becomes unhealthy. Use /qi diagnose to see the specific reason (SOURCE_NOT_FOUND = the prefix isn't registered, i.e. the plugin isn't installed; ITEM_NOT_FOUND = that plugin doesn't have this item).
  • The editor also supports these references when you change the material; the input hint reads e.g.: iron_sword / craftengine:xxx.

These prefixes are provided uniformly by QinhCoreLib and are shared across the whole ecosystem (QI / QinhSkills, etc.). For the full explanation, see Cross-Module Integration → QI ↔ CoreLib.

A failed material resolution causes the item to become unhealthy, which is reported in /qi status / /qi diagnose.


6. Full Annotated Example

A real, complex item that combines all of the above (a weapon, in the Thunder Edge style):

yaml
demo_thunder_edge:
  type: weapon
  material: golden_sword
  display_name: "<yellow>Thunder Edge</yellow>"
  item_name: "Thunder Edge"
  tier: EPIC
  lore:
    - ""
    - "<gray>Left-click to swing and summon thunder</gray>"
    - "<dark_gray>Cooldown 3 seconds</dark_gray>"
  providers:
    ap:
      value: '{"attack_damage":22,"crit_rate":0.12}'
  variables:
    star: "3"
  enchantments:
    sharpness: 3
    knockback: 1
  gem-sockets:
    - 绿色
    - qi_weapon
  sections:
    - quality_prefix_pool
  affixes:
    - legendary_weapon_affix
  options:
    unbreakable: true
    glow: true
    bind_on_acquire: false
    restrictions:
      - "level:20"
  resource_pack:
    custom_model_data: 12345
  actions:
    triggers:
      left_click:
        trigger:
          atom: left_click
        cooldown: 3s
        consume:
          - "item:minecraft-redstone:1"
        refs:
          - handler: qi:title
            payload: "<yellow>⚡ Thunder ⚡</yellow>||<gray>The roar echoes</gray>||3||30||10"
          - handler: qi:sound
            payload: "minecraft:entity.lightning_bolt.thunder;1;1.2"
  update:
    version: 1

🖼️ [Image placeholder] A screenshot of the Thunder Edge above in its in-game tooltip (hover), annotating which lore segment corresponds to which field · suggested assets/item-anatomy.png


7. Item Health Check

On every /qi reload, QI runs healthIssues() validation on each item. Common errors:

Error causeHow to fix
id / type / material / sourceFile is emptyFill in the required fields
display_name and lore both missingProvide at least one
max_stack_size <= 0Change to 1–99
Unknown typetype must exist in item_types.yml
Unknown materialmaterial must use a valid vanilla material name or an external-source reference

Unhealthy items are still loaded, but they're listed in /qi status / /qi diagnose / /qi problems.


8. Reload & Save

  • After editing YAML → /qi reload recompiles and hot-refreshes online players' items.
  • Saving from the GUI editor → EditorSaveGuard first runs PolicyEngine validation, then writes back to sourceFile, and hot-reloads the action table.

For the validation rules (errors you may hit when saving), see Resource Packs and the developer-oriented constraint-system explanation.


Next Steps