Zeeshaun 9a7d6544ef
All checks were successful
Deploy Promiscuity Auth API / deploy (push) Successful in 46s
Deploy Promiscuity Character API / deploy (push) Successful in 46s
Deploy Promiscuity Locations API / deploy (push) Successful in 46s
k8s smoke test / test (push) Successful in 7s
Adding inventory microservice
2026-03-15 10:21:49 -05:00

4.4 KiB

InventoryApi

Purpose

Owns item-instance state.

This service should answer:

  • what item records currently belong to a character, location, or other container owner
  • where each item currently is
  • whether an item move, split, merge, equip, or consume action is valid
  • which specific item instance is being traded, auctioned, or transferred

This service should not own:

  • auth/token issuance
  • character identity creation
  • location generation
  • auction bidding logic

Ownership model

  • every inventory record has an ownerType and ownerId
  • USER can read and mutate items owned by their own characters
  • USER can read and mutate location/container items only when gameplay rules allow it
  • SUPER can read and mutate any inventory item
  • access should be resolved through the current owner, not from the item id alone

Initial design

Use one MongoDB document per inventory item record.

Practical interpretation:

  • non-stackable items: one document per item instance
  • stackable items: one document per stack

Reasons:

  • every item or stack gets a stable UUID, which is useful for auctions, trade, mail, and auditing
  • ownership transfer is explicit and cheap: update ownerType, ownerId, and slot fields
  • future item metadata like durability, rarity rolls, or provenance can live on the item document
  • auction listings can point to specific item ids instead of vague stack descriptions

Tradeoffs:

  • inventory reads are queries over many documents instead of one aggregate read
  • stack merging and slot enforcement need careful indexes and mutation logic
  • transfers should use transactions when they touch multiple item documents

Suggested endpoints

  • GET /api/inventory/by-owner/{ownerType}/{ownerId} Return all item records currently owned by that container owner.
  • POST /api/inventory/by-owner/{ownerType}/{ownerId}/grant Create a new item record or add quantity into an existing compatible stack.
  • POST /api/inventory/by-owner/{ownerType}/{ownerId}/move Move an item or stack within the same owner inventory.
  • POST /api/inventory/transfer Move quantity from one owner inventory to another.
  • POST /api/inventory/items/{itemId}/consume Consume quantity from a specific item record.
  • POST /api/inventory/items/{itemId}/equip Equip a specific item into a character equipment slot.
  • POST /api/inventory/items/{itemId}/unequip Return an equipped item to a character inventory slot.

Notes:

  • equip and unequip only make sense for character-owned items
  • transfer is the core world interaction primitive for looting, dropping, trading, chest interaction, and auction handoff
  • a future AuctionApi can reserve or re-own specific item ids without redesigning InventoryApi

Item identity

Every inventory record should have a stable UUID string such as:

  • a8d4218b-5e20-4e47-8b5f-0f0f0b9d7e10

Each record also carries an itemKey such as:

  • wood
  • stone
  • pistol
  • small_health_potion

Recommended distinction:

  • id: unique item-record identifier used for ownership changes, auctions, and references
  • itemKey: item definition identifier used to decide stackability and gameplay behavior

Each item document should include:

  • id
  • itemKey
  • quantity
  • ownerType
  • ownerId
  • slot
  • equippedSlot
  • ownerUserId when applicable
  • createdUtc
  • updatedUtc

Optional future fields:

  • durability
  • rarity
  • instanceData
  • listingId
  • reservedUntilUtc

MVP rules

  • an item record must belong to exactly one owner at a time
  • stackable items may share itemKey but should still be represented by one stack record per occupied slot
  • non-stackable items must always have quantity = 1
  • equipped items should set equippedSlot and clear slot
  • unequipped bag items should set slot and clear equippedSlot
  • slot occupancy must be unique per (ownerType, ownerId, slot)
  • all mutating endpoints should be idempotent where practical

Client shape

The Godot client should fetch all items for the currently relevant owner and group them into a bag view locally.

Good pattern:

  • login/select character
  • GET /api/inventory/by-owner/character/{characterId}
  • when opening a stash or world container: GET /api/inventory/by-owner/location/{locationId}
  • cache the returned item records locally
  • call transfer/equip/consume endpoints using specific itemId values
  • replace local state with the server response after each mutation