diff --git a/Plugins/GenericItemization/Binaries/Win64/UnrealEditor-GenericItemization.dll b/Plugins/GenericItemization/Binaries/Win64/UnrealEditor-GenericItemization.dll index df2c2cd..427fd67 100644 Binary files a/Plugins/GenericItemization/Binaries/Win64/UnrealEditor-GenericItemization.dll and b/Plugins/GenericItemization/Binaries/Win64/UnrealEditor-GenericItemization.dll differ diff --git a/Plugins/GenericItemization/Binaries/Win64/UnrealEditor-GenericItemization.pdb b/Plugins/GenericItemization/Binaries/Win64/UnrealEditor-GenericItemization.pdb index ad94939..b124ae7 100644 Binary files a/Plugins/GenericItemization/Binaries/Win64/UnrealEditor-GenericItemization.pdb and b/Plugins/GenericItemization/Binaries/Win64/UnrealEditor-GenericItemization.pdb differ diff --git a/Plugins/GenericItemization/Source/GenericItemization/Private/GenericItemizationInstanceTypes.cpp b/Plugins/GenericItemization/Source/GenericItemization/Private/GenericItemizationInstanceTypes.cpp index 6e13e3a..df665aa 100644 --- a/Plugins/GenericItemization/Source/GenericItemization/Private/GenericItemizationInstanceTypes.cpp +++ b/Plugins/GenericItemization/Source/GenericItemization/Private/GenericItemizationInstanceTypes.cpp @@ -1,6 +1,5 @@ #include "GenericItemizationInstanceTypes.h" #include "ItemManagement/ItemInventoryComponent.h" -#include "Engine/DataTable.h" /************************************************************************/ /* Affixes @@ -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 ReplicatedAffixes; + if (Ar.IsSaving()) + { + for (const TInstancedStruct& 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 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(FString()); + if (ItemDefinitionEntry) + { + ItemDefinition = ItemDefinitionEntry->ItemDefinition; + } + } +} + void FFastItemInstance::Initialize(FInstancedStruct& InItemInstance, FInstancedStruct& InUserContextData) { ItemInstance = InItemInstance; diff --git a/Plugins/GenericItemization/Source/GenericItemization/Private/GenericItemizationInstancingFunctions.cpp b/Plugins/GenericItemization/Source/GenericItemization/Private/GenericItemizationInstancingFunctions.cpp index 4b7ce09..caf92ff 100644 --- a/Plugins/GenericItemization/Source/GenericItemization/Private/GenericItemizationInstancingFunctions.cpp +++ b/Plugins/GenericItemization/Source/GenericItemization/Private/GenericItemizationInstancingFunctions.cpp @@ -33,7 +33,7 @@ bool UItemInstancingFunction::CalculateAffixLevel_Implementation(const FInstance return false; } - const TInstancedStruct& ItemDefinition = ItemInstancePtr->ItemDefinition; + const TInstancedStruct& ItemDefinition = ItemInstancePtr->GetItemDefinition(); if (!ItemDefinition.IsValid()) { return false; @@ -75,7 +75,7 @@ bool UItemInstancingFunction::SelectItemQualityType_Implementation(const FInstan return false; } - const TInstancedStruct& ItemDefinition = ItemInstancePtr->ItemDefinition; + const TInstancedStruct& ItemDefinition = ItemInstancePtr->GetItemDefinition(); if (!ItemDefinition.IsValid()) { return false; @@ -163,7 +163,7 @@ bool UItemInstancingFunction::DetermineAffixCount_Implementation(const FInstance return false; } - const TInstancedStruct& ItemDefinition = ItemInstancePtr->ItemDefinition; + const TInstancedStruct& ItemDefinition = ItemInstancePtr->GetItemDefinition(); if (!ItemDefinition.IsValid()) { return false; diff --git a/Plugins/GenericItemization/Source/GenericItemization/Private/GenericItemizationPickFunctions.cpp b/Plugins/GenericItemization/Source/GenericItemization/Private/GenericItemizationPickFunctions.cpp index 03d34fb..cdcfbce 100644 --- a/Plugins/GenericItemization/Source/GenericItemization/Private/GenericItemizationPickFunctions.cpp +++ b/Plugins/GenericItemization/Source/GenericItemization/Private/GenericItemizationPickFunctions.cpp @@ -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(FString()); if (!IsValid(ItemDropTableCollectionEntry.DataTable) @@ -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 ItemDefinitionEntries; - ItemDefinitions->GetAllRows(Context, ItemDefinitionEntries); - // Seed all of the Picks we will make a selection from. - using FItemPickEntry = FPickEntry>; + using FItemPickEntry = FPickEntry; TArray PickEntries; - PickEntries.Reserve(ItemDefinitionEntries.Num()); - - for (const FItemDefinitionEntry* ItemDefinition : ItemDefinitionEntries) + ItemDefinitions->ForeachRow(FString(), [&](const FName& RowName, const FItemDefinitionEntry& ItemDefinitionEntry) { + const FItemDefinitionEntry* ItemDefinition = &ItemDefinitionEntry; if (ItemDefinition && ItemDefinition->ItemDefinition.IsValid()) { FInstancedStruct InstancedItemDefinition = FInstancedStruct::Make(); 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) @@ -166,8 +167,7 @@ bool UItemDefinitionCollectionPickFunction::PickItem_Implementation(const FInsta GetRandomPick(RandomPick); if (RandomPick.PickType.IsSet()) { - OutItem = FInstancedStruct::Make(); - OutItem.InitializeAs(RandomPick.PickType.GetValue().GetScriptStruct(), RandomPick.PickType.GetValue().GetMemory()); + OutItemHandle = RandomPick.PickType.GetValue(); return true; } @@ -258,8 +258,8 @@ bool UAffixPickFunction::GetAffixesWithMinimumNativeRequirements(const FInstance { const FItemInstance* ItemInstancePtr = ItemInstance.GetPtr(); if (!ItemInstancePtr - || !ItemInstancePtr->ItemDefinition.IsValid() - || !IsValid(ItemInstancePtr->ItemDefinition.Get().InstancingFunction)) + || !ItemInstancePtr->GetItemDefinition().IsValid() + || !IsValid(ItemInstancePtr->GetItemDefinition().Get().InstancingFunction)) { return false; } @@ -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(Context, [&](const FName& RowName, const FAffixDefinitionEntry& AffixDefinitionEntry) + AffixPool->ForeachRow(FString(), [&](const FName& RowName, const FAffixDefinitionEntry& AffixDefinitionEntry) { const TInstancedStruct& AffixDefinitionInstance = AffixDefinitionEntry.AffixDefinition; if (AffixDefinitionInstance.IsValid()) @@ -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; } @@ -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; diff --git a/Plugins/GenericItemization/Source/GenericItemization/Private/GenericItemizationStatics.cpp b/Plugins/GenericItemization/Source/GenericItemization/Private/GenericItemizationStatics.cpp index 5818f10..6db41a9 100644 --- a/Plugins/GenericItemization/Source/GenericItemization/Private/GenericItemizationStatics.cpp +++ b/Plugins/GenericItemization/Source/GenericItemization/Private/GenericItemizationStatics.cpp @@ -28,7 +28,8 @@ TOptional> UGenericItemizationStatics::Pick PickFunctionCDO->bIncludeNoPick = bIncludeNoPick; FInstancedStruct PickedItem; - if (PickFunctionCDO->PickItem(DropTableCollectionEntry.Get().PickRequirements, ItemInstancingContext, PickedItem)) + FDataTableRowHandle PickedItemHandle; // @NOTE: PickedItemhandle is unused in this context, since we are passing on a TableType instead. + if (PickFunctionCDO->PickItem(DropTableCollectionEntry.Get().PickRequirements, ItemInstancingContext, PickedItem, PickedItemHandle)) { TInstancedStruct InstancedItem; InstancedItem.InitializeAsScriptStruct(PickedItem.GetScriptStruct(), PickedItem.GetMemory()); @@ -39,9 +40,9 @@ TOptional> UGenericItemizationStatics::Pick return Result; } -TOptional> UGenericItemizationStatics::PickItemDefinitionFromCollection(const TInstancedStruct& ItemDefinitionCollection, const FInstancedStruct& ItemInstancingContext) +TOptional UGenericItemizationStatics::PickItemDefinitionFromCollection(const TInstancedStruct& ItemDefinitionCollection, const FInstancedStruct& ItemInstancingContext) { - TOptional> Result = TOptional>(); + TOptional Result = TOptional(); if (!ItemDefinitionCollection.IsValid()) { @@ -65,21 +66,19 @@ TOptional> UGenericItemizationStatics::PickIte // Seed the PickFunction and then execute it. PickFunctionCDO->ItemDefinitions = ItemDefinitionCollection.Get().ItemDefinitions; - FInstancedStruct PickedItemDefinition; - if (PickFunctionCDO->PickItem(ItemDefinitionCollection.Get().PickRequirements, ItemInstancingContext, PickedItemDefinition)) + FDataTableRowHandle PickItemDefinitionHandle; + FInstancedStruct PickedItem; // @NOTE: PickedItem is unused in this context, since we are passing on a Handle instead. + if (PickFunctionCDO->PickItem(ItemDefinitionCollection.Get().PickRequirements, ItemInstancingContext, PickedItem, PickItemDefinitionHandle)) { - TInstancedStruct InstancedItemDefinition; - InstancedItemDefinition.InitializeAsScriptStruct(PickedItemDefinition.GetScriptStruct(), PickedItemDefinition.GetMemory()); - - Result.Emplace(InstancedItemDefinition); + Result.Emplace(PickItemDefinitionHandle); } return Result; } -TOptional> UGenericItemizationStatics::PickItemDefinitionEntry(const TInstancedStruct& ItemDefinitionEntry, const FInstancedStruct& ItemInstancingContext) +TOptional UGenericItemizationStatics::PickItemDefinitionEntry(const TInstancedStruct& ItemDefinitionEntry, const FInstancedStruct& ItemInstancingContext) { - TOptional> Result = TOptional>(); + TOptional Result = TOptional(); const FItemDefinitionEntry* ItemDefinitionEntryPtr = ItemDefinitionEntry.Get().ItemDefinitionRow.GetRow(FString()); if (!IsValid(ItemDefinitionEntry.Get().ItemDefinitionRow.DataTable) @@ -94,7 +93,7 @@ TOptional> UGenericItemizationStatics::PickIte const FItemDefinition& ItemDefinition = ItemDefinitionEntryPtr->ItemDefinition.Get(); if (ItemDefinition.bSpawnable) { - Result.Emplace(ItemDefinitionEntryPtr->ItemDefinition); + Result.Emplace(ItemDefinitionEntry.Get().ItemDefinitionRow); } } @@ -107,19 +106,19 @@ TOptional UGenericItemizationStatics::PickAffixDefinitionFo const FItemInstance* ItemInstancePtr = ItemInstance.GetPtr(); if (!ItemInstancePtr - || !ItemInstancePtr->ItemDefinition.IsValid() - || !IsValid(ItemInstancePtr->ItemDefinition.Get().InstancingFunction)) + || !ItemInstancePtr->GetItemDefinition().IsValid() + || !IsValid(ItemInstancePtr->GetItemDefinition().Get().InstancingFunction)) { return Result; } - UDataTable* const AffixPool = ItemInstancePtr->ItemDefinition.Get().AffixPool; + UDataTable* const AffixPool = ItemInstancePtr->GetItemDefinition().Get().AffixPool; if (!AffixPool || !AffixPool->GetRowStruct()->IsChildOf(FAffixDefinitionEntry::StaticStruct())) { return Result; } - const UItemInstancingFunction* const InstancingFunctionCDO = ItemInstancePtr->ItemDefinition.Get().InstancingFunction.GetDefaultObject(); + const UItemInstancingFunction* const InstancingFunctionCDO = ItemInstancePtr->GetItemDefinition().Get().InstancingFunction.GetDefaultObject(); check(InstancingFunctionCDO); if (IsValid(InstancingFunctionCDO->AffixPickFunction)) @@ -130,7 +129,6 @@ TOptional UGenericItemizationStatics::PickAffixDefinitionFo AffixPickFunctionCDO->AffixPool = AffixPool; FDataTableRowHandle PickedAffixHandle; - FInstancedStruct PickedAffix; if (AffixPickFunctionCDO->PickAffix(ItemInstance, ItemInstancingContext, PickedAffixHandle)) { Result.Emplace(PickedAffixHandle); @@ -146,13 +144,13 @@ TOptional> UGenericItemizationStatics::Generate const FItemInstance* ItemInstancePtr = ItemInstance.GetPtr(); if (!ItemInstancePtr - || !ItemInstancePtr->ItemDefinition.IsValid() - || !IsValid(ItemInstancePtr->ItemDefinition.Get().InstancingFunction)) + || !ItemInstancePtr->GetItemDefinition().IsValid() + || !IsValid(ItemInstancePtr->GetItemDefinition().Get().InstancingFunction)) { return Result; } - const UItemInstancingFunction* const InstancingFunctionCDO = ItemInstancePtr->ItemDefinition.Get().InstancingFunction.GetDefaultObject(); + const UItemInstancingFunction* const InstancingFunctionCDO = ItemInstancePtr->GetItemDefinition().Get().InstancingFunction.GetDefaultObject(); check(InstancingFunctionCDO); FInstancedStruct NewAffixInstance; @@ -171,7 +169,7 @@ TOptional> UGenericItemizationStatics::Generate return Result; } -bool PickItemDefinition_Recursive(const TInstancedStruct& InPick, const FInstancedStruct& ItemInstancingContext, FInstancedStruct& OutPick) +bool PickItemDefinition_Recursive(const TInstancedStruct& InPick, const FInstancedStruct& ItemInstancingContext, FDataTableRowHandle& OutItemDefinitionHandle) { if (!InPick.IsValid()) { @@ -185,19 +183,17 @@ bool PickItemDefinition_Recursive(const TInstancedStruct& In const TOptional> DropTableType = UGenericItemizationStatics::PickDropTableCollectionEntry(PickedItemDropTableCollection, ItemInstancingContext, false); if (DropTableType.IsSet()) { - return PickItemDefinition_Recursive(DropTableType.GetValue(), ItemInstancingContext, OutPick); + return PickItemDefinition_Recursive(DropTableType.GetValue(), ItemInstancingContext, OutItemDefinitionHandle); } } else if (InPick.GetScriptStruct()->IsChildOf(FItemDefinitionCollection::StaticStruct())) { TInstancedStruct PickedItemDefinitionCollection; PickedItemDefinitionCollection.InitializeAsScriptStruct(InPick.GetScriptStruct(), InPick.GetMemory()); - const TOptional> ItemDefinition = UGenericItemizationStatics::PickItemDefinitionFromCollection(PickedItemDefinitionCollection, ItemInstancingContext); - if (ItemDefinition.IsSet()) + const TOptional ItemDefinitionHandle = UGenericItemizationStatics::PickItemDefinitionFromCollection(PickedItemDefinitionCollection, ItemInstancingContext); + if (ItemDefinitionHandle.IsSet()) { - FInstancedStruct Item; - Item.InitializeAs(ItemDefinition.GetValue().GetScriptStruct(), ItemDefinition.GetValue().GetMemory()); - OutPick = Item; + OutItemDefinitionHandle = ItemDefinitionHandle.GetValue(); return true; } } @@ -205,12 +201,10 @@ bool PickItemDefinition_Recursive(const TInstancedStruct& In { TInstancedStruct PickedItemDefinitionRow; PickedItemDefinitionRow.InitializeAsScriptStruct(InPick.GetScriptStruct(), InPick.GetMemory()); - const TOptional> ItemDefinition = UGenericItemizationStatics::PickItemDefinitionEntry(PickedItemDefinitionRow, ItemInstancingContext); - if (ItemDefinition.IsSet()) + const TOptional ItemDefinitionHandle = UGenericItemizationStatics::PickItemDefinitionEntry(PickedItemDefinitionRow, ItemInstancingContext); + if (ItemDefinitionHandle.IsSet()) { - FInstancedStruct Item; - Item.InitializeAs(ItemDefinition.GetValue().GetScriptStruct(), ItemDefinition.GetValue().GetMemory()); - OutPick = Item; + OutItemDefinitionHandle = ItemDefinitionHandle.GetValue(); return true; } } @@ -218,7 +212,7 @@ bool PickItemDefinition_Recursive(const TInstancedStruct& In return false; } -bool UGenericItemizationStatics::PickItemDefinitionsFromDropTable(const FDataTableRowHandle& ItemDropTableCollectionEntry, const FInstancedStruct& ItemInstancingContext, TArray& OutItemDefinitions) +bool UGenericItemizationStatics::PickItemDefinitionsFromDropTable(const FDataTableRowHandle& ItemDropTableCollectionEntry, const FInstancedStruct& ItemInstancingContext, TArray& OutItemDefinitionHandles) { const FDataTableRowHandle& DropTable = ItemDropTableCollectionEntry; const FItemDropTableCollectionEntry* DropTableCollection = DropTable.GetRow(FString()); @@ -230,7 +224,7 @@ bool UGenericItemizationStatics::PickItemDefinitionsFromDropTable(const FDataTab } int32 PickCount = DropTableCollection->PickCount; - OutItemDefinitions.Empty(PickCount); + OutItemDefinitionHandles.Empty(PickCount); while (PickCount > 0) { PickCount--; @@ -242,20 +236,26 @@ bool UGenericItemizationStatics::PickItemDefinitionsFromDropTable(const FDataTab const TOptional> InitialPickResult = UGenericItemizationStatics::PickDropTableCollectionEntry(TInstancedStruct::Make(DropTableCollectionRow), ItemInstancingContext, true); if (InitialPickResult.IsSet()) // If this is false, then we either ended with NoPick being selected or something failed. { - FInstancedStruct FinalPick; - if (PickItemDefinition_Recursive(InitialPickResult.GetValue(), ItemInstancingContext, FinalPick)) + FDataTableRowHandle PickedItemDefinitionHandle; + if (PickItemDefinition_Recursive(InitialPickResult.GetValue(), ItemInstancingContext, PickedItemDefinitionHandle)) { - OutItemDefinitions.Add(FinalPick); + OutItemDefinitionHandles.Add(PickedItemDefinitionHandle); } } } - return OutItemDefinitions.Num() > 0; + return OutItemDefinitionHandles.Num() > 0; } -bool UGenericItemizationStatics::GenerateItemInstanceFromItemDefinition(const FInstancedStruct& ItemDefinition, const FInstancedStruct& ItemInstancingContext, FInstancedStruct& OutItemInstance) +bool UGenericItemizationStatics::GenerateItemInstanceFromItemDefinition(const FDataTableRowHandle& ItemDefinitionHandle, const FInstancedStruct& ItemInstancingContext, FInstancedStruct& OutItemInstance) { - if (!ItemDefinition.IsValid() || !ItemDefinition.GetScriptStruct()->IsChildOf(FItemDefinition::StaticStruct())) + if (ItemDefinitionHandle.IsNull()) + { + return false; + } + + const FItemDefinitionEntry* ItemDefinitionEntry = ItemDefinitionHandle.GetRow(FString()); + if (!ItemDefinitionEntry) { return false; } @@ -270,9 +270,7 @@ bool UGenericItemizationStatics::GenerateItemInstanceFromItemDefinition(const FI // ===================================================================================== // 1. Create the new ItemInstance from the ItemDefinition that we have. - TInstancedStruct ItemInstanceItemDefinition; - ItemInstanceItemDefinition.InitializeAsScriptStruct(ItemDefinition.GetScriptStruct(), ItemDefinition.GetMemory()); - + const TInstancedStruct& ItemInstanceItemDefinition = ItemDefinitionEntry->ItemDefinition; if (!IsValid(ItemInstanceItemDefinition.Get().InstancingFunction)) { return false; @@ -289,7 +287,7 @@ bool UGenericItemizationStatics::GenerateItemInstanceFromItemDefinition(const FI return false; } - MutableItemInstance->ItemDefinition = ItemInstanceItemDefinition; + MutableItemInstance->SetItemDefinition(ItemDefinitionHandle); MutableItemInstance->ItemSeed = FMath::Rand(); // @TODO: How do we generate the ItemSeed? Do we need some kind of global manager that handles that? MutableItemInstance->ItemStream.Initialize(MutableItemInstance->ItemSeed); MutableItemInstance->ItemLevel = FMath::Clamp(ItemInstancingContextPtr->ItemLevel, 1, InstancingFunctionCDO->GetMaximumItemLevel()); diff --git a/Plugins/GenericItemization/Source/GenericItemization/Private/ItemManagement/ItemDrop.cpp b/Plugins/GenericItemization/Source/GenericItemization/Private/ItemManagement/ItemDrop.cpp index 1058d71..c8634c7 100644 --- a/Plugins/GenericItemization/Source/GenericItemization/Private/ItemManagement/ItemDrop.cpp +++ b/Plugins/GenericItemization/Source/GenericItemization/Private/ItemManagement/ItemDrop.cpp @@ -38,9 +38,9 @@ void AItemDrop::GetItemInstanceStruct(FItemInstance& OutItemInstanceStruct) cons void AItemDrop::GetItemDefinitionStruct(FItemDefinition& OutItemDefinitionStruct) const { - if (ItemInstance.IsValid() && ItemInstance.Get().ItemDefinition.IsValid()) + if (ItemInstance.IsValid() && ItemInstance.Get().GetItemDefinition().IsValid()) { - OutItemDefinitionStruct = ItemInstance.Get().ItemDefinition.Get(); + OutItemDefinitionStruct = ItemInstance.Get().GetItemDefinition().Get(); } } diff --git a/Plugins/GenericItemization/Source/GenericItemization/Private/ItemManagement/ItemDropperComponent.cpp b/Plugins/GenericItemization/Source/GenericItemization/Private/ItemManagement/ItemDropperComponent.cpp index b9d1117..8e64413 100644 --- a/Plugins/GenericItemization/Source/GenericItemization/Private/ItemManagement/ItemDropperComponent.cpp +++ b/Plugins/GenericItemization/Source/GenericItemization/Private/ItemManagement/ItemDropperComponent.cpp @@ -52,15 +52,15 @@ bool UItemDropperComponent::DropItems_Implementation(FInstancedStruct UserContex // Grab all of the ItemDefinitions that we will be creating ItemInstances for. // These represent successfully picked Items that will be dropped from that ItemDropTable. - TArray ItemDefinitions; - if (UGenericItemizationStatics::PickItemDefinitionsFromDropTable(ItemDropTable, ItemInstancingContext, ItemDefinitions)) + TArray ItemDefinitionHandles; + if (UGenericItemizationStatics::PickItemDefinitionsFromDropTable(ItemDropTable, ItemInstancingContext, ItemDefinitionHandles)) { // Generate all of the actual ItemInstances for the ItemDefinitions we selected. TArray ItemInstances; - for (const FInstancedStruct& ItemDefinition : ItemDefinitions) + for (const FDataTableRowHandle& ItemDefinitionHandle : ItemDefinitionHandles) { FInstancedStruct ItemInstance; - if (UGenericItemizationStatics::GenerateItemInstanceFromItemDefinition(ItemDefinition, ItemInstancingContext, ItemInstance)) + if (UGenericItemizationStatics::GenerateItemInstanceFromItemDefinition(ItemDefinitionHandle, ItemInstancingContext, ItemInstance)) { ItemInstances.Add(ItemInstance); } diff --git a/Plugins/GenericItemization/Source/GenericItemization/Private/ItemManagement/ItemInventoryComponent.cpp b/Plugins/GenericItemization/Source/GenericItemization/Private/ItemManagement/ItemInventoryComponent.cpp index acbbb96..12ab0cc 100644 --- a/Plugins/GenericItemization/Source/GenericItemization/Private/ItemManagement/ItemInventoryComponent.cpp +++ b/Plugins/GenericItemization/Source/GenericItemization/Private/ItemManagement/ItemInventoryComponent.cpp @@ -246,7 +246,7 @@ bool UItemInventoryComponent::CanStackItems(UItemInventoryComponent* ItemToStack return false; } - const FItemDefinition* const ItemToStackWithItemDefinitionPtr = ItemToStackWithPtr->ItemDefinition.GetPtr(); + const FItemDefinition* const ItemToStackWithItemDefinitionPtr = ItemToStackWithPtr->GetItemDefinition().GetPtr(); if (!ItemToStackWithItemDefinitionPtr) { return false; @@ -290,7 +290,7 @@ bool UItemInventoryComponent::StackItemFromInventory(UItemInventoryComponent* It return false; } - const FItemDefinition* const ItemToStackWithItemDefinitionPtr = ItemToStackWithPtr->ItemDefinition.GetPtr(); + const FItemDefinition* const ItemToStackWithItemDefinitionPtr = ItemToStackWithPtr->GetItemDefinition().GetPtr(); if (!ItemToStackWithItemDefinitionPtr) { return false; @@ -375,7 +375,7 @@ bool UItemInventoryComponent::StackItemFromItemDrop(AItemDrop* ItemToStackFromIt return false; } - const FItemDefinition* const ItemToStackWithItemDefinitionPtr = ItemToStackWithPtr->ItemDefinition.GetPtr(); + const FItemDefinition* const ItemToStackWithItemDefinitionPtr = ItemToStackWithPtr->GetItemDefinition().GetPtr(); if (!ItemToStackWithItemDefinitionPtr) { return false; diff --git a/Plugins/GenericItemization/Source/GenericItemization/Private/ItemManagement/ItemStackSettings.cpp b/Plugins/GenericItemization/Source/GenericItemization/Private/ItemManagement/ItemStackSettings.cpp index d55b4c7..27bd27a 100644 --- a/Plugins/GenericItemization/Source/GenericItemization/Private/ItemManagement/ItemStackSettings.cpp +++ b/Plugins/GenericItemization/Source/GenericItemization/Private/ItemManagement/ItemStackSettings.cpp @@ -20,8 +20,8 @@ bool UItemStackSettings::CanStackWith_Implementation(const FInstancedStruct& Ite return false; } - const TInstancedStruct& ItemToStackFromDefinitionInstance = ItemToStackFromPtr->ItemDefinition; - const TInstancedStruct& ItemToStackWithDefinitionInstance = ItemToStackWithPtr->ItemDefinition; + const TInstancedStruct& ItemToStackFromDefinitionInstance = ItemToStackFromPtr->GetItemDefinition(); + const TInstancedStruct& ItemToStackWithDefinitionInstance = ItemToStackWithPtr->GetItemDefinition(); if (!ItemToStackFromDefinitionInstance.IsValid() || !ItemToStackWithDefinitionInstance.IsValid()) { return false; diff --git a/Plugins/GenericItemization/Source/GenericItemization/Public/GenericItemizationInstanceTypes.h b/Plugins/GenericItemization/Source/GenericItemization/Public/GenericItemizationInstanceTypes.h index 0acfb8e..254117b 100644 --- a/Plugins/GenericItemization/Source/GenericItemization/Public/GenericItemizationInstanceTypes.h +++ b/Plugins/GenericItemization/Source/GenericItemization/Public/GenericItemizationInstanceTypes.h @@ -97,10 +97,6 @@ struct FItemInstance FItemInstance(); - /* The static data that describes this Item. */ - UPROPERTY(EditAnywhere, BlueprintReadOnly) - TInstancedStruct ItemDefinition; - /* The Unique Id of the Item. */ UPROPERTY(EditAnywhere, BlueprintReadOnly) FGuid ItemId; @@ -129,8 +125,8 @@ struct FItemInstance UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (BaseStruct = "/Script/GenericItemization.AffixInstance")) TArray> Affixes; - /* The Context information around which this ItemInstance was called to be generated. */ - UPROPERTY(EditAnywhere, BlueprintReadOnly) + /* The Context information around which this ItemInstance was called to be generated, this is not replicated. */ + UPROPERTY(EditAnywhere, BlueprintReadOnly, NotReplicated) TInstancedStruct InstancingContext; /* The number of stacks of this Item. */ @@ -141,6 +137,30 @@ struct FItemInstance bool IsValid() const; + bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess); + + const TInstancedStruct& GetItemDefinition() const { return ItemDefinition; } + void SetItemDefinition(const FDataTableRowHandle& Handle); + +protected: + + /* The static data that describes this Item. */ + UPROPERTY(EditAnywhere, BlueprintReadOnly, NotReplicated, meta = (AllowPrivateAccess)) + TInstancedStruct ItemDefinition; + + /* Handle to the actual ItemDefinition, this is serialized instead of the ItemDefinition itself. */ + UPROPERTY() + FDataTableRowHandle ItemDefinitionHandle; + +}; + +template<> +struct TStructOpsTypeTraits : public TStructOpsTypeTraitsBase2 +{ + enum + { + WithNetSerializer = true, + }; }; USTRUCT() diff --git a/Plugins/GenericItemization/Source/GenericItemization/Public/GenericItemizationPickFunctions.h b/Plugins/GenericItemization/Source/GenericItemization/Public/GenericItemizationPickFunctions.h index 0297485..e910140 100644 --- a/Plugins/GenericItemization/Source/GenericItemization/Public/GenericItemizationPickFunctions.h +++ b/Plugins/GenericItemization/Source/GenericItemization/Public/GenericItemizationPickFunctions.h @@ -32,7 +32,7 @@ class UItemPickFunction : public UObject * Returns false if no Item was selected. */ UFUNCTION(BlueprintNativeEvent) - bool PickItem(const FInstancedStruct& PickRequirements, const FInstancedStruct& ItemInstancingContext, FInstancedStruct& OutItem) const; + bool PickItem(const FInstancedStruct& PickRequirements, const FInstancedStruct& ItemInstancingContext, FInstancedStruct& OutItem, FDataTableRowHandle& OutItemHandle) const; }; /** @@ -45,7 +45,7 @@ class UItemDropTableCollectionPickFunction : public UItemPickFunction public: - virtual bool PickItem_Implementation(const FInstancedStruct& PickRequirements, const FInstancedStruct& ItemInstancingContext, FInstancedStruct& OutItem) const override; + virtual bool PickItem_Implementation(const FInstancedStruct& PickRequirements, const FInstancedStruct& ItemInstancingContext, FInstancedStruct& OutItem, FDataTableRowHandle& OutItemHandle) const override; /* The Drop Table Collection Entry we will make a selection from. */ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta = (DisplayPriority = "1", RowType = "/Script/GenericItemization.ItemDropTableCollectionEntry")) @@ -72,7 +72,7 @@ class UItemDefinitionCollectionPickFunction : public UItemPickFunction public: - virtual bool PickItem_Implementation(const FInstancedStruct& PickRequirements, const FInstancedStruct& ItemInstancingContext, FInstancedStruct& OutItem) const override; + virtual bool PickItem_Implementation(const FInstancedStruct& PickRequirements, const FInstancedStruct& ItemInstancingContext, FInstancedStruct& OutItem, FDataTableRowHandle& OutItemHandle) const override; /* The Definitions of all Items we can select from. */ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta = (DisplayPriority = "1", RequiredAssetDataTags = "RowStructure=/Script/GenericItemization.ItemDefinitionEntry")) diff --git a/Plugins/GenericItemization/Source/GenericItemization/Public/GenericItemizationStatics.h b/Plugins/GenericItemization/Source/GenericItemization/Public/GenericItemizationStatics.h index 9ef9c82..456816a 100644 --- a/Plugins/GenericItemization/Source/GenericItemization/Public/GenericItemizationStatics.h +++ b/Plugins/GenericItemization/Source/GenericItemization/Public/GenericItemizationStatics.h @@ -37,7 +37,7 @@ class GENERICITEMIZATION_API UGenericItemizationStatics : public UBlueprintFunct * @param ItemDefinitionCollection The collection of ItemDefinitions we want to make a selection from. * @param ItemInstancingContext Contains information about the Context around which an ItemInstance is called to be generated. */ - static TOptional> PickItemDefinitionFromCollection(const TInstancedStruct& ItemDefinitionCollection, const FInstancedStruct& ItemInstancingContext); + static TOptional PickItemDefinitionFromCollection(const TInstancedStruct& ItemDefinitionCollection, const FInstancedStruct& ItemInstancingContext); /** * Picks the ItemDefinition from the passed in entry. @@ -47,7 +47,7 @@ class GENERICITEMIZATION_API UGenericItemizationStatics : public UBlueprintFunct * @param ItemDefinitionEntry The entry of the particular ItemDefinition we are returning. * @param ItemInstancingContext Contains information about the Context around which an ItemInstance is called to be generated. */ - static TOptional> PickItemDefinitionEntry(const TInstancedStruct& ItemDefinitionEntry, const FInstancedStruct& ItemInstancingContext); + static TOptional PickItemDefinitionEntry(const TInstancedStruct& ItemDefinitionEntry, const FInstancedStruct& ItemInstancingContext); /** * Gets a handle to a single AffixDefinition for the passed in ItemInstance that meets its requirements. @@ -75,7 +75,7 @@ class GENERICITEMIZATION_API UGenericItemizationStatics : public UBlueprintFunct * @return False if no picks were made. */ UFUNCTION(BlueprintCallable, Category = "Generic Itemization") - static bool PickItemDefinitionsFromDropTable(const FDataTableRowHandle& ItemDropTableCollectionEntry, const FInstancedStruct& ItemInstancingContext, TArray& OutItemDefinitions); + static bool PickItemDefinitionsFromDropTable(const FDataTableRowHandle& ItemDropTableCollectionEntry, const FInstancedStruct& ItemInstancingContext, TArray& OutItemDefinitionHandles); /** * Generates a new Item Instance from the passed in ItemDefinition and ItemLevel. @@ -86,7 +86,7 @@ class GENERICITEMIZATION_API UGenericItemizationStatics : public UBlueprintFunct * @return False if an ItemInstance could not be generated. */ UFUNCTION(BlueprintCallable, Category = "Generic Itemization") - static bool GenerateItemInstanceFromItemDefinition(const FInstancedStruct& ItemDefinition, const FInstancedStruct& ItemInstancingContext, FInstancedStruct& OutItemInstance); + static bool GenerateItemInstanceFromItemDefinition(const FDataTableRowHandle& ItemDefinitionHandle, const FInstancedStruct& ItemInstancingContext, FInstancedStruct& OutItemInstance); /** * Makes an exact copy of the ItemInstance except for its ItemId, ItemSeed and ItemStream, these are all regenerated.