Skip to content

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 returned

Socket 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_actions

Extraction 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 inventory

Upgrade 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 gem

applyState 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 available

GemState 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:

FieldTypeDescription
gemIdstringGem definition ID
levelintGem level
tokenstringUnique identification token

PDC Serialization Format

yaml
# 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: 1700000000000

Tip

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.

Released under the GPL-3.0 License