Skip to content

Commit

Permalink
ItemInstance serialization optimization.
Browse files Browse the repository at this point in the history
Modified the `FItemInstance` type to serialize an `FDataTableRowHandle` to its `FItemDefinition` instead of serializing the definition itself.
  • Loading branch information
mattyman174 committed Mar 4, 2024
1 parent c50a088 commit dacc405
Show file tree
Hide file tree
Showing 13 changed files with 178 additions and 94 deletions.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include "GenericItemizationInstanceTypes.h"
#include "ItemManagement/ItemInventoryComponent.h"
#include "Engine/DataTable.h"

/************************************************************************/
/* Affixes
Expand Down Expand Up @@ -68,6 +67,74 @@ bool FItemInstance::IsValid() const
return ItemSeed != -1;
}

bool FItemInstance::NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess)
{
Ar << ItemId;
Ar << ItemSeed;
Ar << ItemLevel;
Ar << AffixLevel;
Ar << QualityType;
Ar << StackCount;

// Ar << ItemDefinitionHandle;
Ar << ItemDefinitionHandle.DataTable;
Ar << ItemDefinitionHandle.RowName;
if (Ar.IsLoading())
{
SetItemDefinition(ItemDefinitionHandle);
}

//Ar << ItemStream;
int32 ItemStreamSeed;
if (Ar.IsSaving())
{
ItemStreamSeed = ItemStream.GetCurrentSeed();
}
Ar << ItemStreamSeed;
if (Ar.IsLoading())
{
ItemStream.Initialize(ItemStreamSeed);
}

// Ar << Affixes;
TArray<FInstancedStruct> ReplicatedAffixes;
if (Ar.IsSaving())
{
for (const TInstancedStruct<FAffixInstance>& Affix : Affixes)
{
FInstancedStruct ReplicatedAffix;
ReplicatedAffix.InitializeAs(Affix.GetScriptStruct(), Affix.GetMemory());
ReplicatedAffixes.Add(ReplicatedAffix);
}
}
SafeNetSerializeTArray_WithNetSerialize<31>(Ar, ReplicatedAffixes, Map); // @NOTE: This means we have a practical maximum of 32 Affixes per ItemInstance. Should we expose this somehow?
if (Ar.IsLoading())
{
for (const FInstancedStruct& ReplicatedAffix : ReplicatedAffixes)
{
TInstancedStruct<FAffixInstance> Affix;
Affix.InitializeAsScriptStruct(ReplicatedAffix.GetScriptStruct(), ReplicatedAffix.GetMemory());
Affixes.Add(Affix);
}
}

bOutSuccess = true;
return true;
}

void FItemInstance::SetItemDefinition(const FDataTableRowHandle& Handle)
{
ItemDefinitionHandle = Handle;
if (!ItemDefinitionHandle.IsNull())
{
const FItemDefinitionEntry* ItemDefinitionEntry = ItemDefinitionHandle.GetRow<FItemDefinitionEntry>(FString());
if (ItemDefinitionEntry)
{
ItemDefinition = ItemDefinitionEntry->ItemDefinition;
}
}
}

void FFastItemInstance::Initialize(FInstancedStruct& InItemInstance, FInstancedStruct& InUserContextData)
{
ItemInstance = InItemInstance;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ bool UItemInstancingFunction::CalculateAffixLevel_Implementation(const FInstance
return false;
}

const TInstancedStruct<FItemDefinition>& ItemDefinition = ItemInstancePtr->ItemDefinition;
const TInstancedStruct<FItemDefinition>& ItemDefinition = ItemInstancePtr->GetItemDefinition();
if (!ItemDefinition.IsValid())
{
return false;
Expand Down Expand Up @@ -75,7 +75,7 @@ bool UItemInstancingFunction::SelectItemQualityType_Implementation(const FInstan
return false;
}

const TInstancedStruct<FItemDefinition>& ItemDefinition = ItemInstancePtr->ItemDefinition;
const TInstancedStruct<FItemDefinition>& ItemDefinition = ItemInstancePtr->GetItemDefinition();
if (!ItemDefinition.IsValid())
{
return false;
Expand Down Expand Up @@ -163,7 +163,7 @@ bool UItemInstancingFunction::DetermineAffixCount_Implementation(const FInstance
return false;
}

const TInstancedStruct<FItemDefinition>& ItemDefinition = ItemInstancePtr->ItemDefinition;
const TInstancedStruct<FItemDefinition>& ItemDefinition = ItemInstancePtr->GetItemDefinition();
if (!ItemDefinition.IsValid())
{
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
/* Items
/************************************************************************/

bool UItemPickFunction::PickItem_Implementation(const FInstancedStruct& PickRequirements, const FInstancedStruct& ItemInstancingContext, FInstancedStruct& OutItem) const
bool UItemPickFunction::PickItem_Implementation(const FInstancedStruct& PickRequirements, const FInstancedStruct& ItemInstancingContext, FInstancedStruct& OutItem, FDataTableRowHandle& OutItemHandle) const
{
return false;
}

bool UItemDropTableCollectionPickFunction::PickItem_Implementation(const FInstancedStruct& PickRequirements, const FInstancedStruct& ItemInstancingContext, FInstancedStruct& OutItem) const
bool UItemDropTableCollectionPickFunction::PickItem_Implementation(const FInstancedStruct& PickRequirements, const FInstancedStruct& ItemInstancingContext, FInstancedStruct& OutItem, FDataTableRowHandle& OutItemHandle) const
{
const FItemDropTableCollectionEntry* DropTableCollection = ItemDropTableCollectionEntry.GetRow<FItemDropTableCollectionEntry>(FString());
if (!IsValid(ItemDropTableCollectionEntry.DataTable)
Expand Down Expand Up @@ -102,37 +102,38 @@ bool UItemDropTableCollectionPickFunction::DoesItemDropTableCollectionSatisfyPic
return true;
}

bool UItemDefinitionCollectionPickFunction::PickItem_Implementation(const FInstancedStruct& PickRequirements, const FInstancedStruct& ItemInstancingContext, FInstancedStruct& OutItem) const
bool UItemDefinitionCollectionPickFunction::PickItem_Implementation(const FInstancedStruct& PickRequirements, const FInstancedStruct& ItemInstancingContext, FInstancedStruct& OutItem, FDataTableRowHandle& OutItemHandle) const
{
if (!IsValid(ItemDefinitions) || !ItemDefinitions->GetRowStruct()->IsChildOf(FItemDefinitionEntry::StaticStruct()))
{
return false;
}

const FString Context;
TArray<FItemDefinitionEntry*> ItemDefinitionEntries;
ItemDefinitions->GetAllRows(Context, ItemDefinitionEntries);

// Seed all of the Picks we will make a selection from.
using FItemPickEntry = FPickEntry<TInstancedStruct<FItemDefinition>>;
using FItemPickEntry = FPickEntry<FDataTableRowHandle>;
TArray<FItemPickEntry> PickEntries;
PickEntries.Reserve(ItemDefinitionEntries.Num());

for (const FItemDefinitionEntry* ItemDefinition : ItemDefinitionEntries)
ItemDefinitions->ForeachRow<FItemDefinitionEntry>(FString(), [&](const FName& RowName, const FItemDefinitionEntry& ItemDefinitionEntry)
{
const FItemDefinitionEntry* ItemDefinition = &ItemDefinitionEntry;
if (ItemDefinition && ItemDefinition->ItemDefinition.IsValid())
{
FInstancedStruct InstancedItemDefinition = FInstancedStruct::Make<FItemDefinition>();
InstancedItemDefinition.InitializeAs(ItemDefinition->ItemDefinition.GetScriptStruct(), ItemDefinition->ItemDefinition.GetMemory());
if(ItemDefinition->ItemDefinition.Get().bSpawnable && DoesItemDefinitionSatisfyPickRequirements(PickRequirements, ItemInstancingContext, InstancedItemDefinition))
if (ItemDefinition->ItemDefinition.Get().bSpawnable && DoesItemDefinitionSatisfyPickRequirements(PickRequirements, ItemInstancingContext, InstancedItemDefinition))
{
FItemPickEntry NewEntry;
NewEntry.PickChance = ItemDefinition->ItemDefinition.Get().PickChance;
NewEntry.PickType.Emplace(ItemDefinition->ItemDefinition);

// Add the Item to the list of ones we can select from.
FDataTableRowHandle Handle;
Handle.DataTable = ItemDefinitions;
Handle.RowName = RowName;
NewEntry.PickType.Emplace(Handle);

PickEntries.Add(NewEntry);
}
}
}
});

// @TODO: We need to make this generic so it can be used by any Pick type code and overridden if necessary to implement other algorithms.
auto GetRandomPick = [&PickEntries](FItemPickEntry& OutEntry)
Expand Down Expand Up @@ -166,8 +167,7 @@ bool UItemDefinitionCollectionPickFunction::PickItem_Implementation(const FInsta
GetRandomPick(RandomPick);
if (RandomPick.PickType.IsSet())
{
OutItem = FInstancedStruct::Make<FItemDefinition>();
OutItem.InitializeAs(RandomPick.PickType.GetValue().GetScriptStruct(), RandomPick.PickType.GetValue().GetMemory());
OutItemHandle = RandomPick.PickType.GetValue();
return true;
}

Expand Down Expand Up @@ -258,8 +258,8 @@ bool UAffixPickFunction::GetAffixesWithMinimumNativeRequirements(const FInstance
{
const FItemInstance* ItemInstancePtr = ItemInstance.GetPtr<FItemInstance>();
if (!ItemInstancePtr
|| !ItemInstancePtr->ItemDefinition.IsValid()
|| !IsValid(ItemInstancePtr->ItemDefinition.Get().InstancingFunction))
|| !ItemInstancePtr->GetItemDefinition().IsValid()
|| !IsValid(ItemInstancePtr->GetItemDefinition().Get().InstancingFunction))
{
return false;
}
Expand All @@ -271,8 +271,7 @@ bool UAffixPickFunction::GetAffixesWithMinimumNativeRequirements(const FInstance

// Generate the pool of all Affixes that meet our minimum requirements for selection.
OutAffixHandles.Empty();
const FString Context;
AffixPool->ForeachRow<FAffixDefinitionEntry>(Context, [&](const FName& RowName, const FAffixDefinitionEntry& AffixDefinitionEntry)
AffixPool->ForeachRow<FAffixDefinitionEntry>(FString(), [&](const FName& RowName, const FAffixDefinitionEntry& AffixDefinitionEntry)
{
const TInstancedStruct<FAffixDefinition>& AffixDefinitionInstance = AffixDefinitionEntry.AffixDefinition;
if (AffixDefinitionInstance.IsValid())
Expand All @@ -282,7 +281,7 @@ bool UAffixPickFunction::GetAffixesWithMinimumNativeRequirements(const FInstance
{
// =====================================================================================
// 1. The ItemDefinition must be of the same or lower QualityLevel for this Affix to be available.
if (AffixDefinition.OccursForQualityLevel > 0 && ItemInstancePtr->ItemDefinition.Get().QualityLevel > AffixDefinition.OccursForQualityLevel)
if (AffixDefinition.OccursForQualityLevel > 0 && ItemInstancePtr->GetItemDefinition().Get().QualityLevel > AffixDefinition.OccursForQualityLevel)
{
return;
}
Expand All @@ -297,7 +296,7 @@ bool UAffixPickFunction::GetAffixesWithMinimumNativeRequirements(const FInstance

// =====================================================================================
// 3. Make sure the ItemDefinition is of a valid ItemType to receive this Affix.
const FGameplayTag& ItemType = ItemInstancePtr->ItemDefinition.Get().ItemType;
const FGameplayTag& ItemType = ItemInstancePtr->GetItemDefinition().Get().ItemType;
if (ItemType.IsValid() && !ItemType.MatchesAny(AffixDefinition.OccursForItemTypes))
{
return;
Expand Down
Loading

0 comments on commit dacc405

Please sign in to comment.