Skip to content

Socket Item Definitions and GUI Templates

Socket item definition files are stored in items/*.yml. They define which equipment can have gem sockets, what socket types are available, which sockets are initially open, and which GUI templates should be used.

Socket item fields

FieldDescription
idUnique socket item definition id.
item_sourcesAllowed item sources for the equipment. Combined with slot_groups and matcher using AND. Empty or absent means unrestricted.
matcherNon-item-source conditions (component, PDC, lore, variable) deciding which equipment uses this socket definition. See below.
slot_groupsGroup list matched against the item material name; values are lowercased on load and blank entries dropped. Combined with item_sources and matcher using AND. Empty or absent means unrestricted. See Group names.
matchDeprecated and no longer read. See Migrating from match.
slotsSocket slot list.
default_open_slotsSlot indexes that are open by default.
allowed_gem_typesGem type whitelist for this equipment.
max_same_typeMaximum gems of the same type. Unlimited when not configured.
max_same_idMaximum gems with the same gem id.
guiGUI template references.
obtain.name_actionsName operations applied when the gem layer is first written.
obtain.lore_actionsLore operations applied when the gem layer is first written.
obtain.actionsAction lines run when the gem layer is first written.

Matching rules (item_sources + matcher + slot_groups)

Equipment matching is decided by three top-level fields, combined with AND:

FieldDescription
item_sourcesAllowed item sources; matching any one entry passes. Empty means unrestricted.
matcherNon-item-source conditions only: component, PDC, lore, variable. Item source conditions belong in item_sources and are rejected at load time if written inside a matcher. Syntax is in Item Matcher.
slot_groupsGroup list matched against the item material name; matching any one entry passes. Empty means unrestricted.

Group names

slot_groups tests the item's material name (such as diamond_sword), not the equipment slot the player wears it in. The recognised group names are:

Group nameMatches when
weapon, swordMaterial name ends with _sword or _axe.
armor, helmet, chestplate, leggings, bootsMaterial name ends with one of _helmet, _chestplate, _leggings, _boots.
offhand, shieldMaterial name ends with shield, or contains totem.
toolMaterial name ends with one of _pickaxe, _axe, _shovel, _hoe.
Any other valueFalls back to a substring test: matches when the material name contains the value.

WARNING

helmet, chestplate, leggings, and boots are exactly equivalent to armor: each matches all four armour pieces and does not narrow the match to that one piece. To restrict to a specific piece, list it in the top-level item_sources, or rely on the substring fallback (for example write just _helmet).

Likewise _axe belongs to both weapon and tool, so axes match either group.

DANGER

When all three are empty (the file declares none of item_sources, matcher, and slot_groups), this socket definition matches every item. Forgetting to convert a legacy match block leaves exactly this state.

Migrating from match

The old match block (with item_sources, slot_groups, and lore_contains) is no longer read. Where each field goes:

Old fieldCurrent form
match.item_sourcesPromoted to a top-level item_sources
match.slot_groupsPromoted to a top-level slot_groups
match.lore_containsA type: component child inside matcher with component: lore and operator: contains, one per text fragment

/gem convert-legacy performs the conversion:

CommandBehaviour
/gem convert-legacyDry run; prints the diff it would produce without touching files.
/gem convert-legacy confirmRewrites items/*.yml and leaves a .bak backup per file.

--apply is equivalent to confirm. The command requires emakigem.admin.

WARNING

If a file contains both match and an existing matcher (or top-level slot_groups), the conversion reports a conflict and skips that file. Merge them manually first.

Run the dry run first anyway to review the diff. match.item_sources is promoted straight to the top-level item_sources field and never written inside matcher, so converted files need no manual fix-up.

Weapon socket item example

yaml
id: "weapon_socket_item"
slot_groups:
  - "weapon"
item_sources:
  - "minecraft-diamond_sword"
slots:
  - index: 0
    type: "attack"
    display_name: "<red>Attack Socket</red>"
  - index: 1
    type: "universal"
    display_name: "<white>Universal Socket</white>"
  - index: 2
    type: "defense"
    display_name: "<blue>Defense Socket</blue>"
default_open_slots:
  - 0
allowed_gem_types:
  - "attack"
  - "defense"
  - "utility"
  - "universal"
max_same_type: 0
max_same_id: 1
gui:
  gem_template: "gem/default"
  open_template: "open/default"
obtain:
  name_actions:
    - action: "prepend_prefix"
      value: "<gold>✦</gold> "
  lore_actions:
    - action: "append"
      content:
        - "<gray>Sockets: <dark_gray>(%opened_slots%/%total_slots%)</dark_gray></gray>"
  actions:
    - 'send_message text="<gray>Socketable item detected: <yellow>%item_definition_id%</yellow></gray>"'

obtain applies when the item is first recognized and the gem layer is written. Its lore_actions can use template variables such as %opened_slots%, %total_slots%, and %item_definition_id%.

GUI directories

DirectoryPurpose
gui/gem/Inlay, extraction, upgrade, and reroll GUI templates.
gui/open/Socket opening GUI templates.

GUI blocks and placeholders

In gui/gem/*.yml and gui/open/*.yml, each block under slots declares which renderer owns it through type. Blocks with a type are filled in dynamically, and the custom_name and lore written in the block are only templates resolved through placeholders at render time. Blocks without a type (frames and fillers, for example) are purely static decoration and take no placeholder substitution.

Type constants

typeViewPurpose
target_itemInlay / OpenTarget equipment display slot.
socket_infoInlay / OpenSocket overview information.
socket_slotInlay / OpenA single socket cell; when several slots are declared they map to socket indexes in order.
preview_displayInlay / OpenPreview of the pending operation.
confirmInlay / OpenConfirm button.
socket_summaryInlayAggregated socket statistics.
opener_itemOpenSocket opener input slot.
mode_inlayInlaySwitch to inlay mode.
mode_extractInlaySwitch to extract mode.
mode_upgradeInlaySwitch to upgrade mode.
mode_reroll_fullInlaySwitch to full reroll mode.
mode_reroll_valueInlaySwitch to value reroll mode.

A type value not listed here is owned by no renderer, and the block degrades to a static item.

Placeholder groups

Each type supplies one pair of placeholders: a title for custom_name and a line collection for lore.

typeTitle placeholderLines placeholder
target_item%target_title%%target_lines%
socket_info%info_title%%info_lines%
socket_summary%summary_title%%summary_lines%
socket_slot%slot_title%%slot_lines%
preview_display%preview_title%%preview_lines%
confirm%confirm_title%%confirm_lines%
opener_item%opener_title%%opener_lines%
All mode_*%mode_title%%mode_lines%

Every mode_* block shares the same placeholder pair; the renderer picks the wording from that block's type, so all five mode blocks can use an identical template.

How line placeholders expand

Line placeholders (%*_lines%) behave differently from plain placeholders inside lore:

FormResult
A line containing only %x_lines%Expands into one line per collection element.
Empty collectionExpands to zero lines; the line disappears.
Mixed inline form (such as Stats: %x_lines%)Does not expand; stays a single line and keeps the prefix.
Placeholder not suppliedKept literally, showing %key% to the player.

custom_name only performs scalar substitution and never expands into multiple lines.

Besides the title and line placeholders, some blocks supply extra scalar placeholders (such as %slot% for socket cells, and %item%, %opened%, %total%, %locked% for socket info) that can be referenced directly in line text.

WARNING

After a plugin upgrade, GUI files that already exist under plugins/EmakiGem/gui/ are left untouched: default GUI resources are static files, released only when the target path is missing, and are never overwritten or merged with the bundled version (only config.yml and lang/*.yml use versioned merging). Existing configuration therefore does not pick up newly added type values or placeholders. To adopt them, add the matching blocks by hand, or back up and delete the GUI file so the plugin releases the default version again.

Use different socket definitions for weapons, armor, and accessories so gems cannot be inserted into unintended equipment.