Skip to content

5 Minute Innovation: The Instrument Case Inventory

Proposal: Replace the traditional flat inventory UI with a diegetic 3D instrument case the player swings off their back. Items live inside the case as physical objects in the game world, not in a menu.


The Concept

The player carries an instrument case on their back. A quick flick of the right stick swings it around to the front. The lid pops open, revealing compartments of crafting components, tools, 4" vinyl cantrip records, and consumables. Over time, players personalize the case exterior with collectible stickers -- a visible record of achievements and identity.

Why it matters: Everything in The Smithy is about the physical world of music-making. A traditional inventory screen breaks immersion. The case keeps the player inside the world.


System Architecture

graph TB
    subgraph Evennia["EVENNIA SERVER (Python)"]
        IH[InventoryHandler]
        DB[(player.db.inventory<br/>player.db.stickers)]
        IH --> DB
    end

    subgraph WS["WEBSOCKET BRIDGE"]
        direction LR
        S2C["Server → Client<br/>full_sync | slot_update<br/>slot_clear | sticker_added"]
        C2S["Client → Server<br/>inventory_move<br/>inventory_use | sticker_place"]
    end

    subgraph UE5["UE5 CLIENT (C++)"]
        WSS[SmithyWebSocketSubsystem]
        IDM[InventoryDataManager]
        ICC[InventoryCaseComponent]
        WBP[WBP_InventoryCase<br/>12-slot grid widget]
        WSS --> IDM
        IDM --> ICC
        ICC --> WBP
    end

    Evennia <-->|JSON over WebSocket| WS
    WS <-->|JSON over WebSocket| UE5

    style Evennia fill:#2d4a2d,stroke:#5a5,color:#fff
    style UE5 fill:#2d2d4a,stroke:#55a,color:#fff
    style WS fill:#4a3d2d,stroke:#a85,color:#fff

Data Flow: Adding an Item

sequenceDiagram
    participant E as Evennia Server
    participant WS as WebSocket
    participant DM as InventoryDataManager
    participant CC as CaseComponent
    participant UI as Slot Widget

    E->>WS: inventory_slot_update (JSON)
    WS->>DM: ProcessSlotUpdate()
    DM->>DM: Update Slots[index]
    DM->>CC: OnInventoryChanged broadcast
    CC->>UI: Refresh slot grid
    UI->>UI: Show icon + stack count

    Note over E,UI: ~1 frame latency from server push to visual update

Case Interaction State Machine

stateDiagram-v2
    [*] --> Closed
    Closed --> Opening: Right stick flick / button press
    Opening --> Open: Lerp complete (0.4s)
    Open --> Closing: Right stick flick / button press
    Closing --> Closed: Lerp complete (0.3s)

    Open --> Open: Click slot → use item
    Open --> Open: Drag slot → reorder

    note right of Opening: Case swings from back to front<br/>Lid rotates open (-110 deg)
    note right of Closing: Reverse animation<br/>Case returns to back

The Case Interior -- Golden Ratio Layout

The case interior follows a golden ratio spiral subdivision, giving each item type a compartment proportional to its importance. The largest section is a vinyl sleeve rack holding 4" cantrip records, spiraling inward through tools and components to the smallest consumable pockets -- mirroring how a DJ's flight case organizes by frequency of use.

    Golden Ratio Spiral Subdivision
    ================================

    +---------------------------------+-----------------------+
    |                                 |                       |
    |   CANTRIP VINYL SLEEVES (3)     |      TOOLS (3)        |
    |                                 |     +---------+       |
    |    +------+ +------+ +------+   |     | Pliers  |       |
    |    | .--. | | .--. | | .--. |   |     | File    |       |
    |    ||4"  || ||4"  || ||4"  ||   |     | Clamp   |       |
    |    || () || || () || || () ||   |     +---------+       |
    |    ||    || ||    || ||    ||   +----------+----+-------+
    |    | `--' | | `--' | | `--' |   |          |    |       |
    |    |Melody| |Rhythm| |Harm. |   | COMPNTS  |    | CONS. |
    |    |Weave | |Pulse | |Bind  |   |   (3)    |    |  (3)  |
    |    +------+ +------+ +------+   |  Fork    |    | Rosin |
    |                                 |  Wire    |    | Wax   |
    |    5 : 8 ratio                  |  Peg     |    | Dust  |
    |    (padded record dividers)     |          |    |       |
    +---------------------------------+----------+----+-------+
             phi^2                       phi^0    phi   phi^-1
                                                    ^-- smallest
                                                        compartments
                                                        spiral inward
graph LR
    subgraph CASE["INSTRUMENT CASE INTERIOR -- Golden Spiral"]
        direction LR

        subgraph PHI2["CANTRIP VINYLS -- 4in Record Sleeves<br/>(largest: 5 units)"]
            direction TB
            S6["Melody Weave<br/>4in vinyl"]
            S7["Rhythm Pulse<br/>4in vinyl"]
            S8["Harmonic Bind<br/>4in vinyl"]
        end

        subgraph REMAIN[" "]
            direction TB

            subgraph PHI1["TOOLS<br/>(3 units)"]
                direction LR
                S3["Pliers"]
                S4["File"]
                S5["Clamp"]
            end

            subgraph INNER[" "]
                direction LR

                subgraph PHI0["COMPONENTS<br/>(2 units)"]
                    direction TB
                    S0["Tuning Fork"]
                    S1["Wire Spool"]
                    S2["Bridge Peg"]
                end

                subgraph PHIM1["CONSUMABLES<br/>(1 unit)"]
                    direction TB
                    S9["Rosin Cake"]
                    S10["Seal Wax"]
                    S11["Fae Dust"]
                end
            end
        end
    end

    style PHI2 fill:#2d2d4a,stroke:#77a,color:#fff
    style PHI1 fill:#2d4a3d,stroke:#5a7,color:#fff
    style PHI0 fill:#4a3d2d,stroke:#a85,color:#fff
    style PHIM1 fill:#4a2d3d,stroke:#a57,color:#fff

Golden ratio proportions (Fibonacci): Compartment areas follow 5 : 3 : 2 : 1 -- each section roughly phi (1.618) times the next smaller one, spiraling inward from the record sleeves to the consumable nooks.

Compartment Slots Ratio Design Intent
Cantrips (4" vinyl sleeves) 3 5 Largest -- learned musical spells stored as miniature records in padded dividers
Tools 3 3 Mid-size -- reusable workshop equipment, held in elastic loops
Components 3 2 Smaller -- crafting materials in lined compartments
Consumables 3 1 Smallest -- single-use items tucked in corner pockets

Greybox Milestones

gantt
    title Greybox Prototype Milestones
    dateFormat X
    axisFormat %s

    section Backend
    M1 Data Layer (Evennia)        :m1, 0, 1
    M2 WebSocket Bridge            :m2, after m1, 1

    section Frontend
    M3 Static Case + Slots         :m3, after m2, 1
    M4 Click Interaction           :m4, after m3, 1
    M5 Open/Close Animation        :m5, after m4, 1
    M6 Gesture Input (Stick Flick) :m6, after m5, 1
    M7 Sticker System              :m7, after m5, 1
Milestone Acceptance Criteria
M1 Data Layer Manipulate inventory via Evennia commands, data persists
M2 WebSocket Bridge UE5 connects, receives full sync, logs parsed data
M3 Static Case Inventory UI visible in world, shows synced data
M4 Interaction Point at slots, click them, server receives requests
M5 Animation Button press swings case to front and opens lid
M6 Gesture Input Right stick flick toggles case open/close
M7 Stickers Add sticker via Evennia, decal appears on case in UE5

Sticker System

Players accumulate stickers over time -- achievement markers, band logos, fae symbols. Stickers are DecalComponents positioned on the case mesh surface, synced through the same WebSocket channel.

graph LR
    A[Player earns sticker<br/>via Evennia event] --> B[StickerData stored<br/>in player.db]
    B --> C[sticker_added pushed<br/>via WebSocket]
    C --> D[CaseComponent spawns<br/>DecalComponent]
    D --> E[Decal positioned on<br/>case exterior mesh]

    style A fill:#4a3d2d,stroke:#a85,color:#fff
    style E fill:#2d2d4a,stroke:#55a,color:#fff

Each sticker carries: position (x,y normalized 0-1), rotation, scale, and an asset reference. The case becomes a personal artifact that tells the player's story.


Tech Stack Summary

Layer Technology Role
Backend Evennia (Python 3.11) Inventory state, persistence, game logic
Protocol WebSocket + JSON 7 message types (4 server-push, 3 client-request)
Frontend UE5.6 C++ Case mesh, widget, animation, input
Input Enhanced Input System Right stick gesture detection + button fallback
UI UMG + Common UI Gamepad-navigable slot grid on WidgetComponent

Discussion Points

  1. Slot count: Is 12 right, or do we need room to grow?
  2. Gesture input: Right stick flick vs. dedicated button -- should the flick be the primary or secondary method?
  3. Sticker placement: Should players choose where stickers go, or auto-place?
  4. Item drag-and-drop: Include in greybox or defer?
  5. Case art priority: When do we replace greybox geometry with the real instrument case model?