English
Socket Openers
Socket openers unlock reserved gem sockets on equipment. They separate "sockets defined by the equipment template" from "sockets currently usable by the player", which is useful for long-term progression, event materials, paid materials, or dungeon drops
Workflow
- Equipment defines available and reserved sockets in
items/*.yml - The player opens the socket opening GUI
- The player inserts the target equipment and an opener item
- The module checks whether the equipment matches a socket item definition
- The module finds a locked socket whose type is allowed by the opener
- On success, the opener may be consumed and the opened socket is written to the gem layer
- EmakiGem rebuilds the equipment presentation
Global configuration
Socket openers are configured under socket_openers in config.yml:
yaml
socket_openers:
attack_drill:
enabled: true
item_sources:
- "minecraft-blaze_rod"
opens_gem_types:
- "attack"
consume_on_success: true
actions:
success:
- 'send_message text="<green>Opened an attack gem socket!</green>"'
- "play_sound sound=block.anvil.use volume=1.0 pitch=1.1"
failure:
- 'send_message text="<red>This equipment has no reserved attack socket.</red>"'
- "play_sound sound=entity.villager.no volume=1.0 pitch=0.8"Fields
| Field | Type | Required | Default | Range | Description |
|---|---|---|---|---|---|
socket_openers.<id> | object | No | empty (no openers) | the key is the opener id (lowercased) | One opener entry; the entry is skipped when the key is blank |
enabled | boolean | No | true | true / false | Whether this opener is enabled. A disabled opener's item is not treated as opener material |
custom_model_data | integer | No | unset | any integer | Restricts the opener item to a specific CustomModelData; not checked when omitted |
display_name | string | No | opener id | MiniMessage text | Opener display name |
lore | list | No | empty list | MiniMessage text | Opener lore |
opens_gem_types | list | No | empty (no type restriction) | socket types; containing any also means unrestricted | Socket types this opener can unlock |
consume_on_success | boolean | No | true | true / false | Whether the opener is consumed after success |
item_sources | list | No | empty (unrestricted) | item source shorthand | Allowed opener item sources. ANDed with the sibling matcher |
matcher | object | No | empty | see Item Matcher | Non-item-source conditions only (component, PDC, lore). The opener never matches when both item_sources and matcher are omitted |
actions.success | list | No | empty | CoreLib action lines | Actions executed after successful opening |
actions.failure | list | No | empty | CoreLib action lines | Actions executed when opening fails |
Narrowing an opener with a matcher
How to write it: item_sources and matcher are sibling fields and both must hold. Put the item type in item_sources and only data conditions in matcher. For example, only a renamed blaze rod counts as the attack opener:
yaml
socket_openers:
attack_drill:
enabled: true
item_sources:
- minecraft-blaze_rod
matcher:
type: component
component: custom_name
operator: contains
value: Attack Drill
opens_gem_types:
- "attack"Full syntax (type list, operators, path) is in Item Matcher
Default openers
| Opener | Default enabled | Default item | Types | Use case |
|---|---|---|---|---|
attack_drill | true | minecraft-blaze_rod | attack | Weapon or damage equipment progression |
defense_drill | true | minecraft-prismarine_shard | defense | Armor or defensive accessory progression |
universal_drill | true | minecraft-echo_shard | any | Rare universal opener |
legendary_drill | false | minecraft-blaze_rod + matcher (name contains "legendary") | attack, defense | Demonstrates "item source + component condition together"; disabled by default, enable it after confirming the match scope |
Relationship with socket item definitions
Openers do not create arbitrary sockets. Declare the reserved sockets in the socket item definition first:
yaml
slots:
- index: 0
type: "attack"
display_name: "<red>Attack Socket</red>"
- index: 1
type: "attack"
display_name: "<red>Attack Socket II</red>"
- index: 2
type: "universal"
display_name: "<white>Universal Socket</white>"
default_open_slots:
- 0Take this example:
attack_drillcan open socket1universal_drillcan open socket1or2- If all matching sockets are already open, opening fails and
actions.failureruns
Troubleshooting
- Opener is not recognized: confirm that at least one of
item_sourcesandmatcheris declared, and that both conditions hold for the held item - No socket can be opened: check that
slotshas entries not listed indefault_open_slots, and that the type matches - Opener is not consumed: check that
consume_on_successistrue, then check permission bypass settings - Display does not update: check whether the gem layer rebuilds the item and reopen the GUI if needed