Skip to content

🧠 Inventory System — Mental Model

This page explains how to think about Inventory in RevFramework.

It is not an API reference.
It is a conceptual map that helps you decide:

  • Where does this behaviour belong?
  • Which extension point should I use?
  • What should I never touch?

If you understand this page, the API will feel obvious.


🎯 The Core Idea

Inventory is a service-controlled container system with explicit mutation boundaries and deterministic results.

Inventory is not “a list of items on a character”.

It is a service‑driven container system designed to guarantee:

  • consistent slot semantics
  • deterministic mutation results
  • clear authority boundaries
  • predictable UI updates

Everything in the system exists to enforce those guarantees.


🧱 The Single Source of Truth

SceneInventoryService

There is exactly one authority on inventory state in a scene:

SceneInventoryService

It is the default Unity host and orchestration layer.

It is responsible for:

  • container creation and tracking
  • mutation orchestration
  • authority validation
  • delta publication (via internal tracking)

Nothing else should:

  • mutate container contents
  • create containers directly
  • bypass authority checks
  • emit container change events

If something outside the service does these things, the design boundaries of the system have likely been violated.


📦 Containers (The Fundamental Unit)

An inventory container is the fundamental storage unit.

A container contains:

Slots → ItemStacks → ItemDefinitions

Key properties:

  • containers belong to an owner GameObject
  • containers are identified by ContainerId
  • containers contain slot arrays (resizable via service)
  • each slot holds zero or one stack

Containers are created lazily by the service when first required.

Consumers never construct containers directly.


🧾 Item Stacks

An ItemStack represents a quantity of an item definition.

Stacks contain:

  • item definition (ItemDefinition)
  • quantity
  • durability
  • metadata

Stacks are value-like data, not live objects.

Important rules:

  • quantity must respect ItemDefinition.maxStack
  • empty stacks are represented by ItemStack.Empty
  • equality comparisons are implementation-defined (internal utilities)

Stacks are safe for:

  • UI
  • persistence
  • serialization

🔄 The Mutation Boundary

All inventory mutations occur through:

IInventoryService

Every mutation returns:

InvOpResult

Operations include:

  • adding items
  • removing items
  • splitting stacks
  • merging stacks
  • swapping slots
  • moving between containers

Mutations are always explicit and deterministic.

No mutation silently fails.


📊 Events (State Observation)

Inventory state changes are communicated through:

OnContainerChanged

Events provide an InventoryDelta describing:

  • container owner
  • container id
  • slot-level changes

These events allow UI to update without polling.

Rule of thumb:

UI listens to events.
UI never mutates containers directly.


🔎 Read vs Mutation Surfaces

Inventory deliberately separates read access from mutation access.

Read

  • IInventoryService (read operations)
  • IReadOnlyInventoryContainer (via IInventoryService.Get)

Used by:

  • UI
  • debugging tools
  • search systems

Mutation

  • IInventoryService

Used by:

  • gameplay systems
  • equipment
  • crafting
  • pickups

This separation prevents accidental mutations.


🧰 Convenience Wrappers

These components provide usability layers on top of the service.

CharacterInventory

Provides a character-local wrapper around a container.

Useful for:

  • debugging
  • inspector display
  • local gameplay logic

However, it does not replace the service.

For multiplayer or authority-sensitive logic, prefer IInventoryService.


CharacterEquipment

Manages fixed equipment slots and integrates with inventory containers.

Responsibilities:

  • equip items from inventory
  • unequip items to inventory
  • enforce equipment filters

Equipment uses internal containers but exposes safe, result-first APIs.


ItemUseSystem

Consumes inventory items and executes their configured use effects.

Effects are resolved through:

UseEffectResolver

The system:

  • applies effects
  • consumes items
  • respects authority rules

It does not manage containers directly.


🔍 Searching & Sorting

Inventory supports:

  • container searching
  • slot sorting

These behaviours are provided through strategy interfaces:

  • IInventorySearch
  • IInventorySorter

Important:

  • search and sort operate on existing containers only
  • they do not create containers implicitly

🔐 Authority

Inventory mutations may be guarded by an authority policy.

Authority is provided by:

IInventoryAuthority

Typical setups include:

  • single-player (always true)
  • multiplayer ownership validation

Authority checks occur inside the service before mutation.

External code must never bypass them.


💾 Snapshots & Persistence

Inventory supports snapshot capture and restoration.

Snapshots store:

  • inventory containers
  • equipment containers
  • item stacks

Snapshot behaviour is controlled by:

  • InventorySnapshotOptions
  • MissingItemPolicy

Snapshots support: - save/load - missing-item handling

Snapshots are state helpers, not a full persistence system.


🔌 Extension Points

Inventory exposes safe extension seams:

  • IInventorySearch
  • IInventorySorter
  • IInventoryAuthority
  • IItemDatabase
  • IUseEffect

These allow behaviour to be customized without modifying core systems.


🚫 What Never Belongs Where

  • UI must never mutate containers
  • containers must never be created manually
  • gameplay systems must not bypass the service
  • inventory logic must not depend on presentation systems
  • external systems must not access internal container classes

Violating these rules breaks the system’s guarantees.


🧠 The One-Sentence Model

Inventory is a service-controlled container system that guarantees deterministic mutations and observable state changes.


TL;DR

  • One authoritative service
  • Containers hold slot-based stacks
  • Mutations go through IInventoryService
  • UI observes InventoryDelta events
  • Extension points enable custom behaviour without modifying core systems