Inventory Invariants
The technical PDF presents these as strong invariants. In the current code, they are rules the integration must preserve and test, not guarantees of every low-level path.
| Intended invariant | Current enforcement or limit |
|---|---|
| Each entry has a unique valid SlotID | Normal adds generate GUIDs; AddToArray does not reject duplicates |
| ItemID resolves to a registered definition | Manager lookups check it; low-level helpers can bypass registration |
| 0 < StackSize ≤ MaxStackSize for live entries | Add helpers clamp; removal leaves zero until component removes the entry |
| MaxStackSize > 0 | AddToArray guards it; capacity calculations require valid asset data |
| Quantity conserved during transfers | External transfer assumes successful target add; general rollback absent |
| Failed operation leaves state unchanged | Over-removal and multi-step paths can mutate before failure |
| Capacity is never exceeded | Manager checks cover normal adds; direct SplitSlot has no slot-capacity check |
| Carry weight matches entries | Most component mutations recompute it; AddItemToSlot omits refresh |
| Only server mutates authoritative state | Common helpers check authority; low-level split/merge/component paths do not consistently guard it |
SlotID is stable for an entry's lifetime. Deleting and recreating a stack produces a new entry identity; it is not a persistent per-unit item GUID. Store additional instance identities separately if a weapon or unique item needs one.
Avoid direct write access to InventoryData even though it is BlueprintReadWrite/EditAnywhere in the current header. Changing replicated fields without dirty marking, capacity checks and carry-weight maintenance breaks the intended model. See Implementation Limits.