// Copyright ExByte Studios. Item Interaction Ecosystem. #pragma once #include "CoreMinimal.h" #include "Net/Serialization/FastArraySerializer.h" #include "ItemInstanceData.h" #include "ReplicatedInventoryList.generated.h" class UInventoryComponent; /** * One replicated item slot (section 7.3). The item carries its own ContainerId / * SlotIndex inside FItemInstanceData, but they are mirrored here so the FastArray * delta only needs the entry, and so clients can route OnRep callbacks per slot. */ USTRUCT() struct ITEMINVENTORY_API FRepInventoryEntry : public FFastArraySerializerItem { GENERATED_BODY() UPROPERTY() FGuid ContainerId; UPROPERTY() int32 SlotIndex = INDEX_NONE; UPROPERTY() FItemInstanceData Item; FRepInventoryEntry() = default; FRepInventoryEntry(const FGuid& InContainer, int32 InSlot, const FItemInstanceData& InItem) : ContainerId(InContainer), SlotIndex(InSlot), Item(InItem) {} }; /** * FastArraySerializer carrying every item the inventory owns across all containers * (section 7.3 / 32). One list per component delta-replicates only changed entries. */ USTRUCT() struct ITEMINVENTORY_API FReplicatedInventoryList : public FFastArraySerializer { GENERATED_BODY() UPROPERTY() TArray Entries; /** Not replicated - set by the owning component so callbacks can broadcast. */ UPROPERTY(NotReplicated) TObjectPtr OwnerComponent = nullptr; bool NetDeltaSerialize(FNetDeltaSerializeInfo& DeltaParms) { return FFastArraySerializer::FastArrayDeltaSerialize(Entries, DeltaParms, *this); } //~ FFastArraySerializer client callbacks void PostReplicatedAdd(const TArrayView& AddedIndices, int32 FinalSize); void PostReplicatedChange(const TArrayView& ChangedIndices, int32 FinalSize); void PreReplicatedRemove(const TArrayView& RemovedIndices, int32 FinalSize); // --- Server-side mutation helpers (mark dirty for delta replication) --- /** Adds or replaces the entry occupying (Container, Slot). Returns the live entry. */ FRepInventoryEntry& AddOrUpdate(const FGuid& Container, int32 Slot, const FItemInstanceData& Item); /** Removes the entry with the given instance id. Returns true if one was removed. */ bool RemoveByInstanceId(const FGuid& InstanceId); /** Marks an existing entry dirty after its Item was mutated in place. */ void MarkEntryDirtyByInstanceId(const FGuid& InstanceId); FRepInventoryEntry* FindByInstanceId(const FGuid& InstanceId); const FRepInventoryEntry* FindByInstanceId(const FGuid& InstanceId) const; }; template<> struct TStructOpsTypeTraits : public TStructOpsTypeTraitsBase2 { enum { WithNetDeltaSerializer = true }; };