Adding inventory microservice
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
# InventoryApi document shapes
|
||||
|
||||
This service stores one MongoDB document per inventory item record.
|
||||
|
||||
Inbound JSON documents
|
||||
- GrantInventoryItemRequest (`POST /api/inventory/by-owner/{ownerType}/{ownerId}/grant`)
|
||||
```json
|
||||
{
|
||||
"itemKey": "string",
|
||||
"quantity": 1,
|
||||
"preferredSlot": 0
|
||||
}
|
||||
```
|
||||
`preferredSlot` is optional. If omitted, the service finds a valid destination slot.
|
||||
|
||||
- MoveInventoryItemRequest (`POST /api/inventory/by-owner/{ownerType}/{ownerId}/move`)
|
||||
```json
|
||||
{
|
||||
"itemId": "uuid-string",
|
||||
"toSlot": 1,
|
||||
"quantity": 1
|
||||
}
|
||||
```
|
||||
`quantity` is optional. If omitted, move the full stack.
|
||||
|
||||
- TransferInventoryItemRequest (`POST /api/inventory/transfer`)
|
||||
```json
|
||||
{
|
||||
"itemId": "uuid-string",
|
||||
"fromOwnerType": "character",
|
||||
"fromOwnerId": "string",
|
||||
"toOwnerType": "location",
|
||||
"toOwnerId": "string",
|
||||
"toSlot": 0,
|
||||
"quantity": 1
|
||||
}
|
||||
```
|
||||
`toSlot` and `quantity` are optional. If omitted, the service finds a valid destination and transfers the full stack.
|
||||
|
||||
- ConsumeInventoryItemRequest (`POST /api/inventory/items/{itemId}/consume`)
|
||||
```json
|
||||
{
|
||||
"quantity": 1
|
||||
}
|
||||
```
|
||||
|
||||
- EquipInventoryItemRequest (`POST /api/inventory/items/{itemId}/equip`)
|
||||
```json
|
||||
{
|
||||
"ownerId": "string",
|
||||
"equipmentSlot": "weapon"
|
||||
}
|
||||
```
|
||||
Only valid for items currently owned by a character inventory.
|
||||
|
||||
- UnequipInventoryItemRequest (`POST /api/inventory/items/{itemId}/unequip`)
|
||||
```json
|
||||
{
|
||||
"ownerId": "string",
|
||||
"preferredSlot": 0
|
||||
}
|
||||
```
|
||||
Only valid for items currently equipped by a character.
|
||||
|
||||
Stored documents (MongoDB)
|
||||
- InventoryItem
|
||||
```json
|
||||
{
|
||||
"id": "string (UUID)",
|
||||
"itemKey": "wood",
|
||||
"quantity": 12,
|
||||
"ownerType": "character",
|
||||
"ownerId": "string (ObjectId or stable external id)",
|
||||
"ownerUserId": "string (ObjectId from auth token, null for public world owners)",
|
||||
"slot": 0,
|
||||
"equippedSlot": null,
|
||||
"createdUtc": "string (ISO-8601 datetime)",
|
||||
"updatedUtc": "string (ISO-8601 datetime)"
|
||||
}
|
||||
```
|
||||
|
||||
Equipped character item example:
|
||||
```json
|
||||
{
|
||||
"id": "string (UUID)",
|
||||
"itemKey": "pistol",
|
||||
"quantity": 1,
|
||||
"ownerType": "character",
|
||||
"ownerId": "string (Character ObjectId)",
|
||||
"ownerUserId": "string (ObjectId from auth token)",
|
||||
"slot": null,
|
||||
"equippedSlot": "weapon",
|
||||
"createdUtc": "string (ISO-8601 datetime)",
|
||||
"updatedUtc": "string (ISO-8601 datetime)"
|
||||
}
|
||||
```
|
||||
|
||||
Location stack example:
|
||||
```json
|
||||
{
|
||||
"id": "string (UUID)",
|
||||
"itemKey": "wood",
|
||||
"quantity": 12,
|
||||
"ownerType": "location",
|
||||
"ownerId": "string (Location ObjectId)",
|
||||
"ownerUserId": null,
|
||||
"slot": 3,
|
||||
"equippedSlot": null,
|
||||
"createdUtc": "string (ISO-8601 datetime)",
|
||||
"updatedUtc": "string (ISO-8601 datetime)"
|
||||
}
|
||||
```
|
||||
|
||||
Outbound JSON documents
|
||||
- InventoryItemResponse
|
||||
```json
|
||||
{
|
||||
"id": "string (UUID)",
|
||||
"itemKey": "wood",
|
||||
"quantity": 12,
|
||||
"ownerType": "character",
|
||||
"ownerId": "string",
|
||||
"slot": 0,
|
||||
"equippedSlot": null,
|
||||
"updatedUtc": "string (ISO-8601 datetime)"
|
||||
}
|
||||
```
|
||||
|
||||
- InventoryOwnerResponse (`GET /api/inventory/by-owner/{ownerType}/{ownerId}`)
|
||||
```json
|
||||
{
|
||||
"ownerType": "character",
|
||||
"ownerId": "string",
|
||||
"items": [
|
||||
{
|
||||
"id": "string (UUID)",
|
||||
"itemKey": "wood",
|
||||
"quantity": 12,
|
||||
"ownerType": "character",
|
||||
"ownerId": "string",
|
||||
"slot": 0,
|
||||
"equippedSlot": null,
|
||||
"updatedUtc": "string (ISO-8601 datetime)"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
- TransferInventoryResponse (`POST /api/inventory/transfer`)
|
||||
```json
|
||||
{
|
||||
"movedItemId": "string (UUID)",
|
||||
"fromOwnerType": "character",
|
||||
"fromOwnerId": "string",
|
||||
"toOwnerType": "location",
|
||||
"toOwnerId": "string",
|
||||
"fromItems": [],
|
||||
"toItems": []
|
||||
}
|
||||
```
|
||||
|
||||
Validation rules
|
||||
- `ownerType` must be a supported container type
|
||||
- `ownerId` must map to an existing owning entity where applicable
|
||||
- non-`SUPER` callers may only access owned character items unless explicit gameplay rules allow a world container read/write
|
||||
- `quantity` must be greater than `0`
|
||||
- non-stackable items must have `quantity = 1`
|
||||
- equipped items must have `slot = null`
|
||||
- unequipped bag items must have `equippedSlot = null`
|
||||
- an item must not have both `slot` and `equippedSlot` populated
|
||||
- slot occupancy must be unique for `(ownerType, ownerId, slot)` where `slot != null`
|
||||
- equipment occupancy must be unique for `(ownerType, ownerId, equippedSlot)` where `equippedSlot != null`
|
||||
|
||||
Recommended indexes
|
||||
- unique on `id`
|
||||
- index on `(ownerType, ownerId)`
|
||||
- unique on `(ownerType, ownerId, slot)` for bag slots
|
||||
- unique on `(ownerType, ownerId, equippedSlot)` for equipped slots
|
||||
- index on `itemKey`
|
||||
|
||||
Behavior rules
|
||||
- moving a full non-stackable item should update its owner and slot in place
|
||||
- moving part of a stack should split the stack and create a new item record with a new UUID for the moved quantity
|
||||
- moving into a compatible stack should merge quantities and delete or reduce the source record
|
||||
- cross-owner transfer should be transactional when it mutates multiple records
|
||||
- auctions should reference `itemId` values directly instead of copying item state into the auction document
|
||||
Reference in New Issue
Block a user