CrimsonInventory
Layout-agnostic inventory system. Topology (flat slots, 2D grid, weight-ordered list, bag-of-bags, ...) is selected by assigning a UCrimsonInventoryLayout data asset. Caps and rules live in a runtime-mutable UCrimsonInventoryConstraint array on the component. Items are described by UCrimsonInventoryItemDefinition assets composed of UCrimsonInventoryItemFragment extensions; live items are UCrimsonInventoryItemInstance replicated subobjects of UCrimsonInventoryManagerComponent.
Also included: per-component currency, async pickup nodes with partial-success handling, ACrimsonContainerActorBase for world chests with four ownership scopes (Shared / PerPlayer / PerParty / PerDungeonInstance), UCrimsonContainerSubsystem for purely-virtual stashes (banks/account vaults), and a crafting station base class. UI <-> server routing is centralized in UCrimsonInventoryRoutingComponent on the PlayerController - projects no longer write Server_ RPCs for inventory operations.
Design decisions
Layout = topology only. Layouts never store caps or rules. A flat layout with weight, a grid layout with typed cells, a weight layout with per-type item count caps - all of these are configurations of the same component, composed from the constraint stack at runtime.
Constraints are first-class and runtime-mutable. Add a constraint when the player equips a bag, remove it when unequipping. Bumping the slot cap by +10 and weight cap by +50 when picking up a Backpack item is a two-line operation: ModifyIntConstraintValue(Slots, +10) and ModifyFloatConstraintValue(Weight, +50). Both replicate automatically.
Stable EntryId. Every entry has a server-assigned int64 EntryId that stays stable across FastArray reorders. UI binding, RPCs, and layout caches all key off EntryId, not slot index.
No CrimsonSaveSystem dependency. Save data is exposed as plain structs: FCrimsonInventorySaveData (layout asset, items, runtime constraints, tag-stack caps, currencies) and FCrimsonContainerSaveData. Wire these into whatever save system the game project uses.
No CrimsonInteraction or CrimsonEquipment dependency. World containers and crafting stations implement ICrimsonInteractableTarget from CrimsonCommon. Equipment integration uses ICrimsonAbilitySystemOwner from CrimsonCommon.
Plugin dependencies
| Type | Name |
|---|---|
| Crimson plugin | CrimsonCommon |
| Engine modules | Core, CoreUObject, Engine, GameplayTags, GameplayAbilities, NetCore, CrimsonCommon, DeveloperSettings, UMG, IrisCore (private) |
Key types
| Category | Type | Role |
|---|---|---|
| Core | UCrimsonInventoryManagerComponent | Actor component: layout, constraint stack, items, currencies. All mutations authority-only. |
| Core | UCrimsonInventoryItemDefinition | Immutable data asset describing an item type |
| Core | UCrimsonInventoryItemInstance | Replicated live item; int/float tag stacks + state fragments |
| Core | FCrimsonInventoryEntry | One slot: instance + stack + EntryId + slot/grid/rotation/group + locked |
| Layout | UCrimsonInventoryLayout | Abstract DataAsset base. Topology only - no caps. |
| Layout | UCrimsonInventoryLayout_FlatSlot | Indexed slot list (MMO/RPG) |
| Layout | UCrimsonInventoryLayout_Grid | 2D Tetris with optional rotation (Diablo/Tarkov/PoE) |
| Layout | UCrimsonInventoryLayout_Weight | Append-only list with float-tag weight cap (Skyrim/Fallout) |
| Layout | FCrimsonItemFootprint | {Dimensions, Weight, SlotCost, bAllowRotation} consumed by layouts |
| Constraints | UCrimsonInventoryConstraint | Abstract base: CanAcceptItem, CanAcceptAt, CalculateMaxAllowedQuantity, OnItemAdded, OnItemRemoved, SaveState/LoadState |
| Constraints | UCrimsonInventoryConstraint_Slot | Slot-count cap; reads Slots tag stack |
| Constraints | UCrimsonInventoryConstraint_IntTag | Tag-keyed integer cap |
| Constraints | UCrimsonInventoryConstraint_FloatTag | Tag-keyed float cap (weight); reads Footprint Weight |
| Constraints | UCrimsonInventoryConstraint_TypeFilter | Allow/block items by ItemType tags |
| Constraints | UCrimsonInventoryConstraint_GridCellRule | Per-cell allow/block for grid layouts (gem sockets, potion belt) |
| Constraints | UCrimsonInventoryConstraint_StackLimit | Aggregate cap across all matching items |
| Constraints | UCrimsonInventoryConstraint_CustomRule | Blueprint extension base for arbitrary rules |
| Fragments | UCrimsonInventoryItemFragment_Footprint | Geometric footprint read by layouts |
| Fragments | UCrimsonInventoryItemFragment_Data | Stackable / unique / max stack size |
| Fragments | UCrimsonInventoryItemFragment_Visuals | Icon, slot widget, pickup actor class |
| Fragments | UCrimsonInventoryItemFragment_GrantCurrency | On pickup, convert directly to currency |
| Fragments | UCrimsonInventoryItemFragment_Constraint | Per-item attached constraints (in addition to component stack) |
| Fragments | UCrimsonInventoryStateFragment | Base for per-instance mutable state (Durability, Lifetime) |
| Containers | ACrimsonContainerActorBase | Replicating world chest wrapping a manager component; ICrimsonInteractableTarget |
| Containers | UCrimsonContainerSubsystem | Game-instance subsystem for purely-virtual stashes (banks) |
| Containers | ICrimsonPickupable | Interface for actors holding FCrimsonInventoryPickup |
| Containers | ACrimsonPickupActorBase | Base for dropped-item world actors |
| Crafting | ACrimsonCraftingStationBase | Interactable world actor that coordinates ingredient consumption |
| Crafting | UCrimsonCraftingRecipe / UCrimsonCraftingRecipeBook | Recipe data |
| Currency | UCrimsonInventoryCurrency / UCrimsonBasicCurrency | Replicated currency handlers |
| Async | UCrimsonInventoryAsync_AttemptAddItem / _AttemptPickup | BP async nodes with partial-success paths |
| Routing | UCrimsonInventoryRoutingComponent | Attach to PlayerController. Owns Server_ RPCs for move/split/drop/lock/transfer/open. Virtual access control, per-player containers, party / dungeon-instance scope resolvers. |