# Agrarian Inventory Data Model

This document defines the baseline inventory model for the 0.1.E MVP. The
current implementation is intentionally small, but it needs a stable contract so
pickup, drop, splitting, use, equipment, persistence, and UI work all build on
the same assumptions.

## Goals

- Keep the server authoritative for every inventory mutation.
- Use stable item IDs so save files, recipes, drops, vendors, and future network
  services do not depend on display text or asset names.
- Keep stacks compact enough for replication and save data.
- Support realistic constraints through slot count and weight before adding
  more advanced volume, spoilage, durability, ownership, and container rules.
- Keep resource, food, tool, structure, medicine, and currency items inside one
  shared model unless a later system proves it needs a separate path.

## Core Records

### Item Definition

`FAgrarianItemDefinition` is the canonical design-time description of an item.
It is authored through `UAgrarianItemDefinitionAsset`.

Required MVP fields:

- `ItemId`: stable `FName` used by inventory, crafting, persistence, drops, and
  debug commands.
- `DisplayName`: player-facing label.
- `Description`: player-facing description.
- `ItemType`: broad item category.
- `UnitWeight`: per-unit carry weight used by movement and capacity systems.
- `MaxStackSize`: maximum units expected in one stack.

Future fields should be added to the item definition when they describe all
instances of an item type, such as durability profile, spoilage category,
nutrition profile, tool class, equipment slot, fuel value, material family, or
trade category.

### Item Stack

`FAgrarianItemStack` is the runtime and save-game representation of carried
items.

Required MVP fields:

- `ItemId`: stable reference to the item definition.
- `DisplayName`: cached player-facing label for early UI/debug display.
- `Quantity`: number of units in the stack.
- `UnitWeight`: cached per-unit weight so movement and debug views can work
  without synchronously loading item assets.

Stacks are valid only when `ItemId != NAME_None` and `Quantity > 0`.

Future instance-specific fields, such as durability remaining, condition,
temperature, spoilage age, ownership, quality, or custom metadata, should live
on the stack only when individual instances of the same item can differ. If an
item can have per-instance metadata, stack merge rules must require matching
metadata before combining stacks.

## Inventory Component

`UAgrarianInventoryComponent` owns a replicated `TArray<FAgrarianItemStack>`.
The player character owns the MVP inventory component.

Current baseline:

- `Items`: replicated stack list.
- `MaxSlots`: maximum occupied stack slots.
- `OnInventoryChanged`: event for HUD/UI refresh.
- `HasItem`: quantity check by `ItemId`.
- `GetItemCount`: aggregate quantity across matching stacks.
- `GetTotalWeight`: sum of `Quantity * UnitWeight`.
- `AddItem`: server-only mutation.
- `RemoveItem`: server-only mutation.
- `ServerAddItem` and `ServerRemoveItem`: RPC wrappers for authorized requests.

The component currently merges stacks by `ItemId`. Later stack splitting and
metadata work must refine this into a `CanMergeStacks` rule that considers
`MaxStackSize` and any per-instance fields.

## Authority And Replication

Inventory is server authoritative.

- Clients may request inventory actions through server RPCs.
- The server validates item IDs, quantities, ownership, distance, and action
  rules before mutating inventory.
- The replicated `Items` array is the client read model for the MVP.
- `OnRep_Items` triggers `OnInventoryChanged` for UI and debug refresh.
- Direct client-side inventory edits are not part of the supported model.

## Persistence

Save data stores the same `FAgrarianItemStack` array used by the runtime
component. This keeps the MVP save format simple and lets save/load restore the
player's inventory without a translation layer.

Save/load responsibilities:

- Save the player inventory from `UAgrarianInventoryComponent::Items`.
- Restore the stack array through
  `UAgrarianInventoryComponent::RestoreSavedItems` during load so HUD/UI
  listeners receive `OnInventoryChanged`.
- Recompute derived values such as total weight after load from stack data.
- Avoid saving UI-only selection state as part of the inventory model.

## MVP Operations

The 0.1.E inventory work should implement these operations on top of the model:

- Pickup: world item validates range, authority, stack data, and available
  inventory space before adding.
- Drop: server removes a stack quantity and spawns a world item or bundle near
  the player.
- Stack splitting: server moves a requested quantity into a new stack when slots
  are available.
- Item use: server validates the item type and applies item-specific effects.
- Equipment: only add dedicated slots once an item type needs equipped state.
- Carry capacity: continue using total weight first, with later volume or pack
  systems layered on top.
- UI: read the replicated stack list and send requests back through server RPCs.
  The MVP HUD now includes a compact inventory panel that shows occupied slots,
  total carried weight, and the first visible item stacks.

## Carry Capacity Placeholder

The 0.1.E MVP carry-capacity placeholder is implemented as a weight-first
movement penalty, not a hard inventory lock. Each `FAgrarianItemStack` stores
`UnitWeight`; `UAgrarianInventoryComponent::GetTotalWeight` sums
`Quantity * UnitWeight`; and `AAgrarianGameCharacter` reads that total through
`GetCurrentCarryWeight`.

The default comfort and heavy thresholds are `25.0` and `60.0` item-weight
units. `StrengthMultiplier` scales those thresholds so stronger characters can
carry more before penalties. Movement remains full speed at or below the
effective comfort threshold, trends down toward `65%` between comfort and heavy
loads, and uses a `45%` carry multiplier at or above the heavy threshold. The
debug HUD shows current carried weight so designers can tune item weights during
play tests.

This intentionally leaves volume, containers, backpacks, injuries, fatigue,
awkward-object handling, and hard over-encumbrance rules for later systems.
Those systems should build on the existing total-weight hook instead of adding a
parallel inventory burden model.

The 0.1.G `simple_container` recipe is intentionally only a craftable inventory
item. It uses wood, fiber, and hide so the survival loop can produce a storage
foundation now, while actual placed-container inventory, permissions, volume,
and persistence remain later system work.

## Equipment Slot Decision

Dedicated equipment slots are deferred for the 0.1.E MVP. Current MVP tools,
including `basic_tool`, do not yet drive a separate equipped-state rule; they
can stay in inventory and be checked by item ID when a gather, craft, or build
action needs a tool requirement. Adding slots before a system reads them would
create replicated state, UI work, and save/load obligations without changing
gameplay.

Equipment slots should be added when at least one implemented system needs
state such as active hand item, worn clothing, armor, backpack, held weapon,
tool durability while equipped, animation stance, or first-person/third-person
mesh attachment. When that happens, equipment should be server authoritative,
replicated, persisted, and implemented as a small slot map that references
inventory stack IDs or moves stack instances between inventory and equipment.

## Design Rules

- `ItemId` is the stable key. Display names can change.
- Inventory mutations happen on the server.
- Stacks should not exceed the item definition's `MaxStackSize` once stack
  splitting and pickup are implemented.
- Weight lives on item definitions and is cached onto stacks for runtime and
  save simplicity.
- New item categories should extend `EAgrarianItemType` only when gameplay needs
  distinct rules.
- Future world-scale storage, containers, vehicles, livestock packs, and markets
  should reuse the same item definition and stack records unless they need
  location-specific metadata.
