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 17:41:05 -07:00

7.9 KiB

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.