This repository has been archived on 2026-05-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
AgrarianGameArchive/Docs/InventoryDataModel.md
T
2026-05-17 13:43:21 -07:00

175 lines
7.6 KiB
Markdown

# 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 onto the component during load.
- 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.
## 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.