-
Notifications
You must be signed in to change notification settings - Fork 0
feat: Inventory Management & Equipment System (spec #27) #28
Description
Feature Spec: Inventory Management & Equipment System
| Field | Value |
|---|---|
| Feature | Inventory Management & Equipment System |
| Issue | #TBD |
| Status | Draft |
| Author | The Doctor |
| Date | 2026-04-10 |
Overview
What it does
Introduces a character inventory system backed by the Item Catalog (spec #6). Characters can carry items, equip gear into defined slots, and transfer items under DM control. The /inventory Discord command shows a player’s current loadout.
Why it's needed
Inventory management is essential for loot progression, combat equipment, and player agency. This spec connects items to characters and enables the AI Action System to award items.
Out of scope
- Crafting or item upgrades
- Encumbrance penalties beyond weight tracking
- Merchant economy or trading (future spec)
Architecture Notes (The Doctor)
Projects / layers touched
-
DungeonMaster.Core— inventory entities + services -
DungeonMaster.Infrastructure— EF Core mappings + migrations -
DungeonMaster.Api— inventory endpoints -
DungeonMaster.Bot—/inventorycommand -
DungeonMaster.Shared— inventory DTOs
New interfaces in DungeonMaster.Core
IInventoryService— add/remove/equip/transfer items
Integration points with existing systems
- Spec feat: Item Catalog — custom items, spells, weapons, and armor #6 (Item Catalog): Item definitions and stats
- Spec feat: Character Sheet Setup — players create and manage their character sheets #9 (Character Sheet): inventory tied to PlayerCharacter
- Spec Spec #15: AI Action System #15 (AI Action System):
AwardItemActioninvokesIInventoryService
Domain Model
Entities
CharacterInventory
PlayerCharacterId(Guid FK, unique)Items(ICollection)
InventoryItem
CharacterInventoryId(Guid FK)ItemId(Guid FK)Quantity(int)EquippedSlot(EquipmentSlot? nullable)
Enums
EquipmentSlot
MainHandOffHandArmorAccessoryOneAccessoryTwo
Records
public sealed record InventorySnapshot(
Guid PlayerCharacterId,
IReadOnlyList<InventoryItemDto> Items,
int TotalWeight);Service Interfaces (CQRS)
public interface IInventoryService
{
Task<InventorySnapshot> GetInventoryAsync(Guid playerCharacterId, CancellationToken ct = default);
Task AddItemAsync(Guid playerCharacterId, Guid itemId, int quantity, CancellationToken ct = default);
Task RemoveItemAsync(Guid playerCharacterId, Guid itemId, int quantity, CancellationToken ct = default);
Task EquipItemAsync(Guid playerCharacterId, Guid itemId, EquipmentSlot slot, CancellationToken ct = default);
Task UnequipItemAsync(Guid playerCharacterId, Guid itemId, CancellationToken ct = default);
Task TransferItemAsync(Guid fromCharacterId, Guid toCharacterId, Guid itemId, int quantity, CancellationToken ct = default);
}API Contract (Rory)
Endpoints
GET /api/characters/{id}/inventoryPOST /api/characters/{id}/inventory/items— add item (DM-only)DELETE /api/characters/{id}/inventory/items/{itemId}— remove item (DM-only)POST /api/characters/{id}/inventory/equip— equip item (player/DM)POST /api/characters/{id}/inventory/unequip— unequip itemPOST /api/characters/{id}/inventory/transfer— DM transfer between characters
Discord Commands (Rory — Bot Layer)
/inventory— shows character inventory summary
Test Scenarios (Danny) ⚠️ COMPLETE BEFORE IMPLEMENTATION
Happy path
-
Given a character inventory exists
When the DM adds an item
Then the item appears in inventory with correct quantity -
Given a character equips a weapon
When EquipItemAsync runs
Then the item is marked with slotMainHand
Edge cases
-
Given an item is already equipped
When it is equipped again
Then the request is rejected with a validation error -
Given a transfer exceeds quantity
When TransferItemAsync runs
Then the request fails with400 Bad Request
Error / failure cases
-
Given an invalid item ID
When AddItemAsync runs
Then the API returns404 Not Found -
Given a non-DM user attempts to add items
When POST/inventory/itemsis called
Then the API returns403 Forbidden
Acceptance Criteria
Functional
- Inventory is stored per character with items and quantities
- Equipment slots enforce one item per slot
- Transfers move items between characters
-
/inventorycommand shows current loadout - AwardItemAction integrates with
IInventoryService
Non-functional
- Inventory queries respond within 200 ms
- No hardcoded item names; items resolved via Item Catalog
- All Discord IDs stored as
bigint
Dependencies
- Spec feat: Item Catalog — custom items, spells, weapons, and armor #6: Item Catalog
- Spec feat: Character Sheet Setup — players create and manage their character sheets #9: Character Sheet Setup
- Spec Spec #15: AI Action System #15: AI Action System
Agent Work Breakdown
| Agent | Task | Depends On |
|---|---|---|
| The Doctor | Approve spec | — |
| Danny | Write failing tests from Test Scenarios | Spec approved |
| Rory | Implement inventory entities + services | Danny's tests |
| Rory | Add API endpoints + Bot /inventory |
Core entities |
| Danny | Confirm all tests pass | All implementation |
Definition of Done
- Test Scenarios section completed and approved by The Doctor before implementation
- All failing tests written by Danny before implementation (TDD)
- All tests written and passing (xUnit + bot command tests)
- Code reviewed and approved by The Doctor
- EF Core migration created for inventory tables
- GitHub issue closed and linked to merged PR