Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Inventory

The inventory resource contains the items carried by one character. Empty slots are omitted, which makes it easy to scan the items that are actually present.

UseRoute or events
Read carried itemsGET /clients/{client}/items
Use, drop, give, or pick up an itemPOST /clients/{client}/items/...
Swap inventory slotsPOST /clients/{client}/items/swap
Sell, store, withdraw, or repair by exact namePOST /clients/{client}/items/...
Drop goldPOST /clients/{client}/gold/drop
Give goldPOST /clients/{client}/gold/give
Watch changes and submitted actionsInventory events

Reading inventory

curl "http://127.0.0.1:2626/clients/ZiLo/items"

Each occupied item includes:

  • slot, using the client’s one-based inventory slot
  • sprite and dye_color
  • An available canonical name
  • quantity and can_stack
  • durability and max_durability
Inventory {
    observation: ObservationMetadata,
    items: InventoryItem[]?,
}

InventoryItem {
    slot: u8,
    sprite: u16,
    dye_color: u8,
    name: string?,
    quantity: u32,
    can_stack: bool,
    durability: u32,
    max_durability: u32,
}

The sprite value has the client’s internal item classification flag removed. Stackable names do not include the rendered [ quantity ] suffix because quantity is already a separate field.

The client’s special gold slot is omitted. Use the top-level gold field from character status instead.

Using and moving items

Use an item by one-based slot or case-insensitive name:

curl --request POST \
  --header "Content-Type: application/json" \
  --data '{"name":"Red Potion"}' \
  "http://127.0.0.1:2626/clients/ZiLo/items/use"

Drop an item only at a zero-based map tile:

curl --request POST \
  --header "Content-Type: application/json" \
  --data '{"slot":12,"destination":{"x":3,"y":6}}' \
  "http://127.0.0.1:2626/clients/ZiLo/items/drop"

Give an item only to a visible human, monster, or NPC:

curl --request POST \
  --header "Content-Type: application/json" \
  --data '{"name":"Red Potion","quantity":2,"target":"OtherPlayer"}' \
  "http://127.0.0.1:2626/clients/ZiLo/items/give"

quantity defaults to 1. An empty slot, zero quantity, quantity larger than the current stack, or quantity other than 1 for a non-stackable item returns 400 Bad Request. The DLL checks the live slot and quantity again on the game thread before submitting the action.

Pick up the top ground item at a tile with:

curl --request POST \
  --header "Content-Type: application/json" \
  --data '{"position":{"x":3,"y":6}}' \
  "http://127.0.0.1:2626/clients/ZiLo/items/pickup"

The client protocol identifies the tile rather than a ground object ID. On a stacked tile, the server decides which visible item is picked up.

Gold uses the same distinct ground and entity routes:

curl --request POST \
  --header "Content-Type: application/json" \
  --data '{"amount":100,"destination":{"x":3,"y":6}}' \
  "http://127.0.0.1:2626/clients/ZiLo/gold/drop"

curl --request POST \
  --header "Content-Type: application/json" \
  --data '{"amount":100,"target":"OtherPlayer"}' \
  "http://127.0.0.1:2626/clients/ZiLo/gold/give"

An object target may be a visible human or named creature, matched without case sensitivity, or its numeric object ID. Name lookup checks human players first, then falls back to monsters and NPCs. The local character is not a valid transfer target.

Rearrange inventory with the same swap payload used by skills and spells:

curl --request POST \
  --header "Content-Type: application/json" \
  --data '{"source":{"name":"Red Potion"},"destination":{"slot":12}}' \
  "http://127.0.0.1:2626/clients/ZiLo/items/swap"

Each selector contains exactly one of slot or name. Names are matched without case sensitivity. A destination selected by slot may be empty; a name always resolves to an occupied slot. The two selectors must resolve to different slots.

Chant and NPC item actions

Send arbitrary nonempty ASCII text through the spell-chant channel with:

curl --request POST \
  --header "Content-Type: application/json" \
  --data '{"text":"ard cradh"}' \
  "http://127.0.0.1:2626/clients/ZiLo/chant"

The convenience routes submit the NPC phrases shown below through that same channel:

RouteRequestSubmitted chant
/items/sell{"name":"Dark Belt"}buy my Dark Belt
/items/sell-all{"name":"Dark Belt"}buy my all Dark Belt
/items/deposit{"name":"Dark Belt"}i will deposit Dark Belt
/items/withdraw{"name":"Dark Belt"}give my Dark Belt back
/items/repair{"name":"Dark Belt"}repair my Dark Belt
/items/repair-allNo bodyrepair all

Item names are case-sensitive and must be supplied verbatim. daRPC does not look them up in the current inventory or normalize their capitalization, punctuation, repeated spaces, or leading and trailing spaces. The complete formatted chant must contain at most 255 ASCII bytes.

How inventory stays current

The initial baseline reads the occupied inventory slots from client memory. Later inventory packets tell daRPC which slots may have changed.

Some game actions update more than one slot. Moving an item, swapping two items, splitting a stack, or merging stacks can arrive as several closely spaced updates. daRPC waits for a short quiet period, rereads the affected slots, and applies the complete group before REST or SSE consumers see it.

This avoids reporting a simple move as an item leaving and immediately coming back. Repeating an identical same-slot update produces no event.

Inventory events

The complete payload structures and batch rules are in Inventory and equipment events.

EventMeaning
item.addedA slot gained an item or a stack quantity increased.
item.removedA slot became empty or a stack quantity decreased.
item.changedAn existing item moved, swapped, split, merged, or changed details.
item.usedThe client submitted an item-use request.
item.droppedThe client submitted an item drop with slot, quantity, and destination.
item.givenThe client submitted an item exchange request with slot, quantity, and target ID.
item.picked_upThe client submitted a tile pickup with its chosen destination slot.
item.pickup_failedA submitted tile pickup received correlated carry-limit feedback.
gold.droppedThe client submitted a gold drop with amount and destination.
gold.givenThe client submitted a gold transfer with amount and target ID.

These names refer only to carried inventory. Ground items use item.appeared, item.disappeared, and item.moved as described in World.

Action events describe an outgoing request observed at the client’s normal packet boundary. Giving an item opens the game’s ordinary exchange flow; it does not mean the other player accepted it. Later inventory and gold state events confirm results accepted by the server.

When the system message <item>, You can't have more than <limit>. follows one unambiguous pending pickup, the daemon also emits item.pickup_failed. Its payload includes the attempted position and destination slot, item_name, limit, reason: "carry_limit", the original feedback, and submission timing. The ordinary message.system event remains in the stream. Ambiguous or expired pickup attempts do not produce the semantic failure event.

Continue an open offer, set gold, accept, or cancel through the player exchange API.

Each inventory event contains:

{
    observation,
    batch_index,
    batch_count,
    slot,
    before,
    after,
}

before is null when the slot was empty. after is null when the slot became empty. batch_index is zero-based, and all frames from one multi-slot change share the same batch_count. The daemon has already applied the whole batch to the REST inventory before it sends the first frame.

When a tool needs a simple answer rather than slot-by-slot history, it can handle any inventory event by rereading /items.

Availability

items: null means the client could not expose inventory at that time. An empty array means the inventory was read successfully and no occupied items were found.