Gem Processes
This page describes the complete processes and internal data models for EmakiGem's four major operations in detail.
Inlay Process
Player places equipment and gem → Clicks confirm
│
├─ 1. Validate equipment and gem
│ Check items are non-null, non-air
│
├─ 2. Match equipment template (GemItemMatcher)
│ Iterate all GemItemDefinitions, match via item_sources / slot_groups / lore_contains
│
├─ 3. Check target socket
│ Confirm the selected socket is opened and unoccupied
│
├─ 4. Check compatibility
│ Whether the gem's socket_compatibility includes the socket's type
│ Check max_same_type and max_same_id limits
│
├─ 5. Calculate success rate
│ Use inlay_success.rate_formula or default_chance
│
├─ 6. Fee timing
│ Based on failure_action:
│ - return_gem: Charge before failure (fee non-refundable)
│ - destroy_gem: Charge before failure
│ - none: Charge after success
│
├─ 7. Roll dice
│ Random number < success rate → Success
│
├─ Success path:
│ ├─ 8a. Update GemState (add socketAssignment)
│ ├─ 9a. Rebuild item (applyState)
│ └─ 10a. Consume gem item
│
└─ Failure path:
├─ failure_action = return_gem → Gem returned to player
├─ failure_action = destroy_gem → Gem destroyed
└─ failure_action = none → Gem returnedSocket Opening Process
Player places equipment and socket opener → Clicks confirm
│
├─ 1. Match socket opener (SocketOpenerService)
│ Iterate socket_openers config, match item_source
│
├─ 2. Find the first unopened compatible socket
│ Iterate the equipment template's slots, find a socket whose type is in opens_gem_types and is not yet opened
│
├─ 3. Update GemState (add openedSlotIndex)
│
├─ 4. Rebuild item (applyState)
│
├─ 5. Consume socket opener (if consume_on_success = true)
│
└─ 6. Execute success_actionsExtraction Process
Player selects the socket to extract from → Clicks confirm
│
├─ 1. Validate selected socket has a gem
│
├─ 2. Charge extraction fee (extract_cost)
│
├─ 3. Determine return mode (extract_return.mode)
│ ├─ exact: Return original gem (including level)
│ ├─ downgrade: Return downgraded gem
│ └─ degraded: Probabilistically return degraded or original gem
│
├─ 4. Update GemState (remove socketAssignment, socket remains opened)
│
├─ 5. Rebuild item (applyState)
│
└─ 6. Return gem to player's inventoryUpgrade Process
Player places gem → Confirms upgrade
│
├─ 1. Validate gem
│ Check gem definition exists and upgrade.enabled = true
│
├─ 2. Check level cap
│ Current level < max_level
│
├─ 3. Validate upgrade materials
│ Check economy.currencies and materials are satisfied
│
├─ 4. Charge fees
│ Deduct currency and consume materials
│
├─ 5. Roll dice
│ Use success_rates[next_level] or global_success_rates
│
├─ Success:
│ Generate new level gem item, replace original gem
│
└─ Failure:
Based on failure_penalty / global_failure_penalty:
├─ none: Maintain current level
├─ downgrade: Downgrade by one level
└─ destroy: Destroy the gemapplyState Internal Flow
applyState is the core rebuild flow of the gem system, called after every state change:
1. GemSnapshotBuilder builds the gem layer snapshot
├─ Iterate all socketAssignments
├─ Collect stats / attributes for each inlaid gem
├─ Build structured_presentation data
└─ Generate LayerSnapshot
2. AssemblyService.preview previews the rebuild
├─ Merge gem layer snapshot with other layers (forging, enhancement, etc.)
├─ Render name contributions (name_contributions)
└─ Render Lore sections (lore_sections)
3. GemPdcAttributeWriter writes attributes
├─ Write gem attributes to PDC (via PdcAttributeApi)
└─ Only executes when EmakiAttribute is availableGemState Data Model
Gem state data is stored in the equipment's PDC, recording all socket opening and inlay information. See the API & Integration page for detailed data structure definitions and programming interfaces.
GemItemInstance
Each inlaid gem instance contains:
| Field | Type | Description |
|---|---|---|
gemId | string | Gem definition ID |
level | int | Gem level |
token | string | Unique identification token |
PDC Serialization Format
# Audit data stored in item PDC
item_definition_id: "diamond_sword"
opened_slots: [0, 1, 2]
socket_assignments:
0:
gem_id: "ruby_attack"
level: 3
token: "ruby_attack:3:abc123"
1:
gem_id: "sapphire_defense"
level: 1
token: "sapphire_defense:1:def456"
updated_at: 1700000000000Tip
GemState is an immutable record type. Every modification creates a new instance. The withOpenedSlots() and withAssignment() methods return new GemState objects.
Note
applyState triggers a complete item rebuild flow, including all registered assembly layers (gem, forging, enhancement, etc.). This ensures cross-module state consistency, but also means every gem operation refreshes the entire item display.