Tag Stacks & Replication

A tag stack container is a replicated map of GameplayTag -> count, used everywhere a system needs cheap, networked counters keyed by tag: ammo, charges, status stacks, currencies, elemental buildup. There are two: FCrimsonTagStackContainer (int32) and FCrimsonFloatTagStackContainer (float).

Why a FastArray

Both containers derive from FFastArraySerializer, so only the items that changed replicate each net update - not the whole array. A naive replicated TArray resends everything on any change; a FastArray sends a delta. That matters when counts change often (every shot, every stack tick).

AspectHow it works
StorageA private TArray<FCrimsonTagStack> plus an accelerated TMap<FGameplayTag,int32> for O(1) reads
ReplicationNetDeltaSerialize via FastArrayDeltaSerialize - delta-only; the type traits opt in with WithNetDeltaSerializer
ReadsGetStackCount / ContainsTag hit the accelerated map; safe on any machine
WritesAddStack / RemoveStack / ClearStacks - server authority only

Dirtying is handled for you

The container's own mutators call MarkItemDirty / MarkArrayDirty internally, so as a consumer you just call AddStack/RemoveStack and mark the UPROPERTY Replicated. You only deal with dirtying directly if you write a new container type - not when you use these.

Two rules that bite
(1) Mutate only under HasAuthority() - a client write is overwritten by the next server delta (silent desync). (2) Add the property to GetLifetimeReplicatedProps with DOREPLIFETIME - forgetting it compiles fine and silently never replicates.

Blueprint access

Because the container is a USTRUCT, its mutators aren't directly Blueprint-callable - use the UCrimsonTagStackStatics function library instead. Its functions take the container by ref, so they wire straight into your component's container variable: Add Tag Stack, Remove Tag Stack, Get Tag Stack Count, and the Float equivalents (which add Set Float Tag Stack).