Adding inventory microservice
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
# 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
|
||||
|
||||
## Recommended stored shape
|
||||
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
|
||||
Reference in New Issue
Block a user