UCrimsonInventoryManagerComponent
The central authority component. Add it to a PlayerState, Pawn, PlayerController, or a world container actor. All mutating functions are BlueprintAuthorityOnly. The inventory list replicates via FFastArraySerializer; the layout asset replicates COND_InitialOnly; ActiveConstraints replicates as a subobject array; tag-stack constraints are COND_OwnerOnly.
Initialization & layout
// Layout (set before init; replicated COND_InitialOnly)UCrimsonInventoryLayout* GetLayout() const;void SetLayout(UCrimsonInventoryLayout* InLayout); // authority-onlyconst FCrimsonLayoutRuntimeState& GetLayoutRuntime() const;FCrimsonPlacementContext MakePlacementContext(int32 LayoutGroupId = 0) const;void RebuildLayoutRuntime();// Init: tag-stack caps + currency tablesvoid InitializeInventory(const TArray<UDataTable*>& ConstraintDataTables,const TArray<FCrimsonTagStack>& DefaultIntConstraints,const TArray<FCrimsonFloatTagStack>& DefaultFloatConstraints,const TArray<UDataTable*>& CurrencyDataTables);DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnInventoryInitialized);UPROPERTY(BlueprintAssignable) FOnInventoryInitialized OnInventoryInitialized;
Item operations (authority-only, EntryId-based)
| Method | Description |
|---|---|
CanAddItemDefinition(ItemDef, Count) | Returns false (and broadcasts failure) if adding would violate any constraint |
AddItemDefinition(ItemDef, Count, Policy, ExplicitTarget) | Adds items via the layout's FindPlacement. Policy = MergeFirst / FirstFree / LastFree / MergeOnly / ExplicitTarget |
AddItemInstance(Instance, Count, Policy, ExplicitTarget) | Adds a pre-existing instance (e.g. from inventory transfer) |
RemoveItemsByDefinition(ItemDef, Count) | Removes N items by definition; -1 removes all |
RemoveItemInstance(Instance) | Removes a specific instance entirely |
MoveItemByEntry(SourceEntryId, Target) | Moves an entry; layout decides Move/Swap/Merge. Returns FCrimsonMoveResult. |
DropItemByEntry(EntryId, Qty, Location) | Removes items and broadcasts FCrimsonInventory_Message_ItemDropped; spawns one pickup actor if the item has PickupActorClass |
DropItemsByDefinition(ItemDef, Count, Location) | Same but finds items by definition; spawns one pickup actor per consumed instance |
DropEntriesAsBag(EntryIds, Location, BagActorClass) | Server-only: packs every supplied entry's full stack into a single ACrimsonPickupActorBase bag actor. Preserves per-instance state. |
SplitStackByEntry(SourceEntryId, Amount) | Creates a new entry with the split portion via the layout |
MergeStacksByEntry(SourceEntryId, TargetEntryId) | Merges source into target up to MaxStackSize |
MergeStack(Instance) | Finds compatible stacks and merges into them |
LockEntry(EntryId, bLocked) | Lock/unlock an entry. Locked entries are skipped by sort / consume / quick-merge |
ConsumeItemsByDefinition(ItemDef, Count, OutConsumed) | Removes N items and populates OutConsumed; skips locked entries |
Read operations
| Method | Description |
|---|---|
GetAllItems() | All item instances |
FindFirstItemStackByDefinition(ItemDef) | First instance matching definition |
FindEntryByEntryId(EntryId) | Entry by stable id |
FindEntryAtTarget(Target) | Entry at a layout target |
GetSlottedEntries() | Raw entry array |
GetFilteredItems(Filter) / PartitionItemsByFilter(...) | Filter-based queries |
GetTotalItemCountByInstance / ByDefinition | Aggregate stack counts |
HasRoomFor(ItemDef, Count) | Convenience: would Count items fit? |
CalculateAddableQuantity(ItemDef, Requested, OutReason) | Max that can actually be added given current constraints |
Constraint stack
// Runtime mutation (authority-only)void AddConstraint(UCrimsonInventoryConstraint* Constraint);bool RemoveConstraint(UCrimsonInventoryConstraint* Constraint);// ReadTArray<UCrimsonInventoryConstraint*> GetActiveConstraints() const;TArray<UCrimsonInventoryConstraint*> GetConstraintsByTag(FGameplayTag Tag) const;// Tag-stack caps (replicated FastArray)int32 GetCurrentIntConstraintValue(FGameplayTag Tag) const;int32 GetMaxIntConstraintValue(FGameplayTag Tag) const;float GetCurrentFloatConstraintValue(FGameplayTag Tag) const;float GetMaxFloatConstraintValue(FGameplayTag Tag) const;void ModifyIntConstraintValue(FGameplayTag Tag, int32 Delta); // authority-onlyvoid ModifyFloatConstraintValue(FGameplayTag Tag, float Delta); // authority-only
Async sort
FCrimsonInventorySortRequest Request;Request.bMergeAfterSort = true;Request.Rules = {{ TAG_Crimson_Inventory_Sort_ByItemType, true },{ TAG_Crimson_Inventory_Sort_ByName, true }};InventoryComponent->RequestAsyncSort(Request); // locked entries are excluded
Currency API
InventoryComponent->AddCurrency(GoldRowHandle, 100);bool bOk = InventoryComponent->RemoveCurrency(GoldRowHandle, 50);int64 Amount = InventoryComponent->GetCurrencyAmount(GoldRowHandle);TArray<UCrimsonInventoryCurrency*> AllGold = InventoryComponent->FindAllCurrencyByTag(TAG_Currency_Gold);UCrimsonInventoryCurrency* Coins = InventoryComponent->FindCurrencyByName(TEXT("Gold"));InventoryComponent->DropCurrency(GoldRowHandle, 10, DropLocation);InventoryComponent->RemoveCurrencyByTag(TAG_Currency_Gold, 25);
Save / Load
FCrimsonInventorySaveData SaveData = InventoryComponent->GetSaveData();// ... serializeInventoryComponent->ApplySaveData(SaveData); // authority-only
Replication notes
- FCrimsonInventoryList uses FFastArraySerializer. Every mutation calls MarkItemDirty (per entry) or MarkArrayDirty (bulk).
- LayoutAsset is Replicated, COND_InitialOnly - set during init, immutable thereafter.
- ActiveConstraints replicates as a subobject array (AddReplicatedSubObject / RemoveReplicatedSubObject on add/remove).
- LayoutRuntime is Transient, NotReplicated. Rebuilt from entries in OnRep_InventoryList and FastArray PostReplicatedAdd/Change/Remove.
- ConstraintTags (int) and ConstraintFloatTags (float) are COND_OwnerOnly.
- Currencies are replicated subobjects.
- Constraint-change notifications use Client Reliable RPCs, re-broadcast via UCrimsonMessageSubsystem so UI can subscribe without seeing the RPC plumbing.