Function bodies 468 total
Server_RequestOpenContainer_Implementation method · cpp · L696-L739 (44 LOC)Source/VaultCore/Private/Component/InventoryManagerComponent.cpp
void UInventoryManagerComponent::Server_RequestOpenContainer_Implementation(AActor* Container)
{
UInventoryValidationSubsystem* Validation = CachedValidation.Get();
if (!Validation)
{
UE_LOG(LogVaultValidation, Warning, TEXT("OpenContainer: Validation subsystem unavailable"));
return;
}
// Distance check
FGameplayTag DistResult = Validation->CheckDistance(GetOwner(), Container);
if (DistResult != VaultTags::Validation_Success)
{
UE_LOG(LogVaultValidation, Warning, TEXT("OpenContainer: Too far from container"));
return;
}
// Access policy: check read permission on the container's inventory (if present)
UInventoryManagerComponent* ContainerInv = Container->FindComponentByClass<UInventoryManagerComponent>();
if (ContainerInv)
{
FGameplayTag AccessResult = Validation->CheckAccessPolicy(
GetOwner(), ContainerInv, nullptr, EAccessOperation::Read);
if (AccessResult != VaultTags::Validation_Success)
{
UE_LOG(LogVaultValidation, Warning, TEXT("OpenContainer: Server_RequestTransformItems_Validate method · cpp · L742-L746 (5 LOC)Source/VaultCore/Private/Component/InventoryManagerComponent.cpp
bool UInventoryManagerComponent::Server_RequestTransformItems_Validate(UItemTransformationRule* Rule)
{
return ValidateRPCPreconditions() && IsValid(Rule);
}Server_RequestTransformItems_Implementation method · cpp · L747-L755 (9 LOC)Source/VaultCore/Private/Component/InventoryManagerComponent.cpp
void UInventoryManagerComponent::Server_RequestTransformItems_Implementation(UItemTransformationRule* Rule)
{
const FGameplayTag Result = Authority_TransformItems(Rule);
if (Result != VaultTags::Validation_Success)
{
UE_LOG(LogVaultValidation, Warning, TEXT("TransformItems: Failed — %s"), *Result.ToString());
}
}Server_RequestBulkMove_Validate method · cpp · L756-L760 (5 LOC)Source/VaultCore/Private/Component/InventoryManagerComponent.cpp
bool UInventoryManagerComponent::Server_RequestBulkMove_Validate(const TArray<FItemMoveIntent>& MoveIntents)
{
return ValidateRPCPreconditions() && MoveIntents.Num() > 0;
}Server_RequestBulkMove_Implementation method · cpp · L761-L796 (36 LOC)Source/VaultCore/Private/Component/InventoryManagerComponent.cpp
void UInventoryManagerComponent::Server_RequestBulkMove_Implementation(const TArray<FItemMoveIntent>& MoveIntents)
{
UInventoryValidationSubsystem* Validation = CachedValidation.Get();
if (!Validation)
{
UE_LOG(LogVaultValidation, Warning, TEXT("BulkMove: Validation subsystem unavailable"));
return;
}
APawn* OwnerPawn = Cast<APawn>(GetOwner());
APlayerController* PC = OwnerPawn ? Cast<APlayerController>(OwnerPawn->GetController()) : nullptr;
// All-or-nothing: validate every intent before executing any
for (const FItemMoveIntent& Intent : MoveIntents)
{
const FGameplayTag Result = Validation->ValidateMoveIntent(PC, this, this, Intent.SourceIndex, Intent.TargetIndex);
if (Result != VaultTags::Validation_Success)
{
UE_LOG(LogVaultValidation, Warning,
TEXT("BulkMove: Validation failed — %s (Source=%d, Target=%d). Rejecting entire batch."),
*Result.ToString(), Intent.SourceIndex, Intent.TargetIndex);
return;
}
}
// Execute all swaps
for (const FIteAuthority_TransformItems method · cpp · L799-L967 (169 LOC)Source/VaultCore/Private/Component/InventoryManagerComponent.cpp
FGameplayTag UInventoryManagerComponent::Authority_TransformItems(UItemTransformationRule* Rule)
{
if (!ensureMsgf(GetOwnerRole() == ROLE_Authority,
TEXT("Authority_TransformItems called on non-authority")))
{
return VaultTags::Validation_Error_ServerNotReady;
}
if (!IsValid(Rule) || !IsValid(Rule->OutputDef) || Rule->Inputs.Num() == 0)
{
return VaultTags::Validation_Error_ItemNotFound;
}
UInventoryValidationSubsystem* Validation = CachedValidation.Get();
// Access policy check: actor must have modify permission to transform items.
// Transformation consumes inputs and creates outputs — requires full modify rights.
if (Validation)
{
APawn* OwnerPawn = Cast<APawn>(GetOwner());
AActor* RequestingActor = OwnerPawn ? Cast<AActor>(OwnerPawn->GetController()) : GetOwner();
FGameplayTag AccessResult = Validation->CheckAccessPolicy(RequestingActor, this, nullptr, EAccessOperation::Modify);
if (AccessResult != VaultTags::Validation_Success)
{
UE_LOG(LogVaultValFindEntryByID method · cpp · L970-L974 (5 LOC)Source/VaultCore/Private/Component/InventoryManagerComponent.cpp
const FInventoryEntry* UInventoryManagerComponent::FindEntryByID(const FGuid& InstanceID) const
{
return InventoryArray.FindByInstanceID(InstanceID);
}Repobility · MCP-ready · https://repobility.com
BP_FindEntryByID method · cpp · L975-L980 (6 LOC)Source/VaultCore/Private/Component/InventoryManagerComponent.cpp
FInventoryEntry UInventoryManagerComponent::BP_FindEntryByID(FGuid InstanceID) const
{
const FInventoryEntry* Found = FindEntryByID(InstanceID);
return Found ? *Found : FInventoryEntry();
}GetCurrencyBalance method · cpp · L981-L985 (5 LOC)Source/VaultCore/Private/Component/InventoryManagerComponent.cpp
int32 UInventoryManagerComponent::GetCurrencyBalance(FGameplayTag CurrencyType) const
{
return Wallet.GetBalance(CurrencyType);
}HasCurrencyBalance method · cpp · L986-L990 (5 LOC)Source/VaultCore/Private/Component/InventoryManagerComponent.cpp
bool UInventoryManagerComponent::HasCurrencyBalance(FGameplayTag CurrencyType, int32 Amount) const
{
return Wallet.HasBalance(CurrencyType, Amount);
}IsItemBound method · cpp · L991-L996 (6 LOC)Source/VaultCore/Private/Component/InventoryManagerComponent.cpp
bool UInventoryManagerComponent::IsItemBound(FGuid InstanceID) const
{
const FInventoryEntry* Entry = FindEntryByID(InstanceID);
return Entry && Entry->IsBound();
}IsItemExpired method · cpp · L997-L1002 (6 LOC)Source/VaultCore/Private/Component/InventoryManagerComponent.cpp
bool UInventoryManagerComponent::IsItemExpired(FGuid InstanceID) const
{
const FInventoryEntry* Entry = FindEntryByID(InstanceID);
return Entry && Entry->IsExpired();
}CreateSnapshot method · cpp · L1003-L1022 (20 LOC)Source/VaultCore/Private/Component/InventoryManagerComponent.cpp
FInventorySnapshot UInventoryManagerComponent::CreateSnapshot() const
{
FInventorySnapshot Snap;
Snap.Entries = InventoryArray.Entries;
Snap.Wallet = Wallet;
Snap.LockVersion = LockVersion;
Snap.TimestampUTC = FDateTime::UtcNow();
// Compute hash if validation subsystem is available (requires a world)
if (const UWorld* World = GetWorld())
{
if (const UInventoryValidationSubsystem* Validation = World->GetSubsystem<UInventoryValidationSubsystem>())
{
Snap.InventoryHash = Validation->ComputeInventoryHash(this);
}
}
return Snap;
}NotifyItemAdded method · cpp · L1026-L1030 (5 LOC)Source/VaultCore/Private/Component/InventoryManagerComponent.cpp
void UInventoryManagerComponent::NotifyItemAdded(const FInventoryEntry& Entry)
{
OnInventoryItemAdded.Broadcast(Entry);
}NotifyItemRemoved method · cpp · L1031-L1035 (5 LOC)Source/VaultCore/Private/Component/InventoryManagerComponent.cpp
void UInventoryManagerComponent::NotifyItemRemoved(const FGuid& InstanceID)
{
OnInventoryItemRemoved.Broadcast(InstanceID);
}Repobility — the code-quality scanner for AI-generated software · https://repobility.com
NotifyItemChanged method · cpp · L1036-L1040 (5 LOC)Source/VaultCore/Private/Component/InventoryManagerComponent.cpp
void UInventoryManagerComponent::NotifyItemChanged(const FInventoryEntry& Entry)
{
OnInventoryItemChanged.Broadcast(Entry);
}TriggerAsyncSave method · cpp · L1043-L1089 (47 LOC)Source/VaultCore/Private/Component/InventoryManagerComponent.cpp
void UInventoryManagerComponent::TriggerAsyncSave()
{
if (PersistenceMode == EVaultPersistenceMode::SessionOnly)
{
// Session-only inventory — never persist to storage
return;
}
// Snapshot inventory state on the game thread — providers handle async I/O internally
UWorld* World_Local = GetWorld();
UGameInstance* GI = World_Local ? World_Local->GetGameInstance() : nullptr;
UVaultStorageManager* StorageManager = GI ? GI->GetSubsystem<UVaultStorageManager>() : nullptr;
if (StorageManager == nullptr)
{
UE_LOG(LogVaultStorage, Warning, TEXT("TriggerAsyncSave: No VaultStorageManager available for %s"),
*GetOwner()->GetName());
return;
}
TScriptInterface<IInventoryStorageProvider> Provider = StorageManager->GetActiveProvider();
if (!Provider.GetObject())
{
UE_LOG(LogVaultStorage, Warning, TEXT("TriggerAsyncSave: No active storage provider for %s"),
*GetOwner()->GetName());
return;
}
// Build payload on game thread — plain struct snapshot is safe to hand ofOnAsyncSaveComplete method · cpp · L1090-L1117 (28 LOC)Source/VaultCore/Private/Component/InventoryManagerComponent.cpp
void UInventoryManagerComponent::OnAsyncSaveComplete(bool bSuccess, const FString& ErrorMessage)
{
if (bSuccess)
{
LockVersion++;
UE_LOG(LogVaultStorage, Verbose, TEXT("AsyncSave complete: ProfileID=%s, LockVersion=%d"),
*ProfileID, LockVersion);
}
else
{
UE_LOG(LogVaultStorage, Warning, TEXT("AsyncSave failed: ProfileID=%s — %s"), *ProfileID, *ErrorMessage);
OnSessionConflictDetected.Broadcast();
}
// Record metrics for observability
UWorld* World_Local = GetWorld();
UGameInstance* GI = World_Local ? World_Local->GetGameInstance() : nullptr;
UVaultStorageManager* SM = GI ? GI->GetSubsystem<UVaultStorageManager>() : nullptr;
if (SM != nullptr)
{
TScriptInterface<IInventoryStorageProvider> Provider = SM->GetActiveProvider();
SM->RecordOperationMetrics(
Provider.GetInterface()
? Provider->GetLastOperationMetrics()
: FStorageOperationMetrics());
}
}ValidateRPCPreconditions method · cpp · L1118-L1151 (34 LOC)Source/VaultCore/Private/Component/InventoryManagerComponent.cpp
bool UInventoryManagerComponent::ValidateRPCPreconditions()
{
// Economy config gate — reject RPCs until config is loaded in cloud mode.
// We allow the RPC through (return true) but log a warning so the _Implementation
// can handle the rejection gracefully. Returning false here would disconnect the client
// in shipping builds, which is too aggressive for a transient startup condition.
if (!bEconomyConfigReady)
{
UE_LOG(LogVaultValidation, Verbose, TEXT("RPC rejected: economy config not ready"));
}
// Rate limit check — sustained abuse results in _Validate returning false,
// which triggers a client disconnect in shipping builds (intentional for cheaters)
UInventoryValidationSubsystem* Validation = CachedValidation.Get();
if (Validation)
{
const APawn* OwnerPawn = Cast<APawn>(GetOwner());
APlayerController* PC = OwnerPawn
? Cast<APlayerController>(OwnerPawn->GetController())
: nullptr;
const FGameplayTag RateLimitResult = Validation->CheckRateLimit(PC);
HasItemByDef method · cpp · L1154-L1166 (13 LOC)Source/VaultCore/Private/Component/InventoryManagerComponent.cpp
bool UInventoryManagerComponent::HasItemByDef(const UItemDefinition* ItemDef) const
{
if (!IsValid(ItemDef)) return false;
for (const FInventoryEntry& Entry : InventoryArray.Entries)
{
if (Entry.ItemDef.Get() == ItemDef)
{
return true;
}
}
return false;
}CountItemsByDef method · cpp · L1167-L1180 (14 LOC)Source/VaultCore/Private/Component/InventoryManagerComponent.cpp
int32 UInventoryManagerComponent::CountItemsByDef(const UItemDefinition* ItemDef) const
{
if (!IsValid(ItemDef)) return 0;
int32 Total = 0;
for (const FInventoryEntry& Entry : InventoryArray.Entries)
{
if (Entry.ItemDef.Get() == ItemDef)
{
Total += Entry.StackCount;
}
}
return Total;
}GetTotalWeight method · cpp · L1181-L1194 (14 LOC)Source/VaultCore/Private/Component/InventoryManagerComponent.cpp
float UInventoryManagerComponent::GetTotalWeight() const
{
float TotalWeight = 0.0f;
for (const FInventoryEntry& Entry : InventoryArray.Entries)
{
if (!IsValid(Entry.ItemDef.Get())) continue;
if (const UItemFragment_Weight* WeightFrag = Entry.ItemDef->FindFragmentByClass<UItemFragment_Weight>())
{
TotalWeight += WeightFrag->PerItemWeight * Entry.StackCount;
}
}
return TotalWeight;
}FindItemsByTag method · cpp · L1195-L1214 (20 LOC)Source/VaultCore/Private/Component/InventoryManagerComponent.cpp
TArray<FInventoryEntry> UInventoryManagerComponent::FindItemsByTag(FGameplayTagContainer FilterTags, bool bRequireAll) const
{
TArray<FInventoryEntry> Results;
if (FilterTags.IsEmpty()) return Results;
for (const FInventoryEntry& Entry : InventoryArray.Entries)
{
if (!IsValid(Entry.ItemDef.Get())) continue;
const FGameplayTagContainer& ItemTags = Entry.ItemDef->ItemTags;
const bool bMatch = bRequireAll
? ItemTags.HasAll(FilterTags)
: ItemTags.HasAny(FilterTags);
if (bMatch)
{
Results.Add(Entry);
}
}
return Results;
}Powered by Repobility — scan your code at https://repobility.com
PreviewTransformation method · cpp · L1215-L1251 (37 LOC)Source/VaultCore/Private/Component/InventoryManagerComponent.cpp
FGameplayTag UInventoryManagerComponent::PreviewTransformation(
UItemTransformationRule* Rule,
TArray<UItemDefinition*>& OutOutputDefs,
TArray<int32>& OutOutputQuantities) const
{
OutOutputDefs.Reset();
OutOutputQuantities.Reset();
if (!IsValid(Rule))
{
return VaultTags::Validation_Error_ItemNotFound;
}
// Read-only: verify all inputs are available without mutating state
for (const FTransformInput& Input : Rule->Inputs)
{
if (!IsValid(Input.RequiredItemDef.Get()))
{
return VaultTags::Validation_Error_ItemNotFound;
}
const int32 Available = CountItemsByDef(Input.RequiredItemDef);
if (Available < Input.MinQuantity)
{
return VaultTags::Validation_Error_InsufficientQuantity;
}
}
// Report predicted outputs
if (IsValid(Rule->OutputDef.Get()))
{
OutOutputDefs.Add(Rule->OutputDef);
OutOutputQuantities.Add(Rule->OutputQuantity);
}
return VaultTags::Validation_Success;
}DepositMaterial method · cpp · L23-L76 (54 LOC)Source/VaultCore/Private/Crafting/CraftingStationComponent.cpp
FGameplayTag UCraftingStationComponent::DepositMaterial(
APlayerController* Player, FGuid ItemInstanceID, int32 Quantity)
{
if (!IsValid(Player) || !ItemInstanceID.IsValid() || Quantity <= 0)
{
return VaultTags::Validation_Error_OutOfBounds;
}
UInventoryManagerComponent* Comp = Player->GetPawn()
? Player->GetPawn()->FindComponentByClass<UInventoryManagerComponent>()
: nullptr;
if (!Comp) return VaultTags::Validation_Error_NotOwner;
const FInventoryEntry* Entry = Comp->FindEntryByID(ItemInstanceID);
if (!Entry) return VaultTags::Validation_Error_ItemNotFound;
// Lock the item to prevent concurrent operations
UInventoryValidationSubsystem* Validation = GetWorld()->GetSubsystem<UInventoryValidationSubsystem>();
if (Validation)
{
if (Validation->IsInstanceLocked(ItemInstanceID))
{
return VaultTags::Validation_Error_Locked;
}
Validation->LockInstance(ItemInstanceID);
}
// Guard against missing definition — corrupt or unloaded entries should not reach crafWithdrawMaterial method · cpp · L77-L97 (21 LOC)Source/VaultCore/Private/Crafting/CraftingStationComponent.cpp
FGameplayTag UCraftingStationComponent::WithdrawMaterial(
APlayerController* Player, int32 SlotIndex)
{
if (!InputSlots.IsValidIndex(SlotIndex))
{
return VaultTags::Validation_Error_OutOfBounds;
}
const FCraftingSlot& Slot = InputSlots[SlotIndex];
// Unlock the item
UInventoryValidationSubsystem* Validation = GetWorld()->GetSubsystem<UInventoryValidationSubsystem>();
if (Validation)
{
Validation->UnlockInstance(Slot.ItemInstanceID);
}
InputSlots.RemoveAt(SlotIndex);
return VaultTags::Validation_Success;
}ExecuteCraft method · cpp · L98-L368 (271 LOC)Source/VaultCore/Private/Crafting/CraftingStationComponent.cpp
FGameplayTag UCraftingStationComponent::ExecuteCraft(
APlayerController* Player, FGameplayTag RecipeTag)
{
if (!IsValid(Player) || !RecipeTag.IsValid())
{
return VaultTags::Validation_Error_OutOfBounds;
}
// Get the economy config via VaultStorageManager — the single source of truth for economy data
UWorld* World_Local = GetWorld();
UGameInstance* GI = World_Local ? World_Local->GetGameInstance() : nullptr;
UVaultStorageManager* StorageManager = GI ? GI->GetSubsystem<UVaultStorageManager>() : nullptr;
if (!StorageManager)
{
UE_LOG(LogVault, Warning, TEXT("ExecuteCraft: VaultStorageManager unavailable."));
return VaultTags::Validation_Error_ServerNotReady;
}
// Gate on economy config readiness — server must have loaded config before accepting crafts
if (!StorageManager->IsEconomyConfigReady())
{
UE_LOG(LogVault, Warning,
TEXT("ExecuteCraft: Economy config not ready. Recipe=%s"), *RecipeTag.ToString());
return VaultTags::Validation_Error_ServerNotReady;
}
CollectOutput method · cpp · L369-L434 (66 LOC)Source/VaultCore/Private/Crafting/CraftingStationComponent.cpp
FGameplayTag UCraftingStationComponent::CollectOutput(
APlayerController* Player, int32 OutputSlotIndex)
{
if (!OutputSlots.IsValidIndex(OutputSlotIndex))
{
return VaultTags::Validation_Error_OutOfBounds;
}
const FCraftingSlot& Slot = OutputSlots[OutputSlotIndex];
UInventoryManagerComponent* Comp = Player->GetPawn()
? Player->GetPawn()->FindComponentByClass<UInventoryManagerComponent>()
: nullptr;
if (!Comp) return VaultTags::Validation_Error_NotOwner;
if (IsValid(Slot.ItemDef.Get()))
{
// Check slot capacity before adding — if full, overflow to mail
UInventoryValidationSubsystem* Validation = GetWorld()
? GetWorld()->GetSubsystem<UInventoryValidationSubsystem>()
: nullptr;
const bool bInventoryFull = Validation
&& Validation->CheckSlotCapacity(Comp) != VaultTags::Validation_Success;
if (bInventoryFull)
{
// Overflow: route crafted item to mail for async pickup
UMailSubsystem* MailSub = GetWorld()
? GetWorld()->GetSubsystem<UMailSubsystReturnAllMaterials method · cpp · L435-L456 (22 LOC)Source/VaultCore/Private/Crafting/CraftingStationComponent.cpp
void UCraftingStationComponent::ReturnAllMaterials()
{
// Disconnect safety: unlock all deposited items
UInventoryValidationSubsystem* Validation = GetWorld()
? GetWorld()->GetSubsystem<UInventoryValidationSubsystem>()
: nullptr;
for (const FCraftingSlot& Slot : InputSlots)
{
if (Validation)
{
Validation->UnlockInstance(Slot.ItemInstanceID);
}
// Items are still in the player's inventory (they were locked, not removed)
// Unlocking returns them to usable state
}
InputSlots.Reset();
UE_LOG(LogVault, Log, TEXT("Crafting: All materials returned to owners (disconnect safety)."));
}EnsureCraftingTimer method · cpp · L459-L468 (10 LOC)Source/VaultCore/Private/Crafting/CraftingStationComponent.cpp
void UCraftingStationComponent::EnsureCraftingTimer()
{
if (!CraftingTickTimerHandle.IsValid() && GetWorld())
{
GetWorld()->GetTimerManager().SetTimer(
CraftingTickTimerHandle, this, &UCraftingStationComponent::TickCraftingJobs,
1.0f, true);
}
}TickCraftingJobs method · cpp · L469-L513 (45 LOC)Source/VaultCore/Private/Crafting/CraftingStationComponent.cpp
void UCraftingStationComponent::TickCraftingJobs()
{
const FDateTime Now = FDateTime::UtcNow();
bool bAnyCompleted = false;
for (FCraftingJob& Job : ActiveJobs)
{
if (Job.bComplete) continue;
const double ElapsedSeconds = (Now - Job.StartedAtUTC).GetTotalSeconds();
if (ElapsedSeconds >= Job.DurationSeconds)
{
Job.bComplete = true;
bAnyCompleted = true;
// Move pending outputs to OutputSlots
for (const FCraftingSlot& PendingSlot : Job.PendingOutputs)
{
OutputSlots.Add(PendingSlot);
}
UE_LOG(LogVault, Log, TEXT("Crafting job completed: %s (Recipe=%s)"),
*Job.JobID.ToString(), *Job.RecipeTag.ToString());
// Broadcast for each output
for (const FCraftingSlot& PendingSlot : Job.PendingOutputs)
{
OnCraftingComplete.Broadcast(PendingSlot.ItemDef, PendingSlot.Quantity);
}
}
}
// Remove completed jobs
if (bAnyCompleted)
{
ActiveJobs.RemoveAll([](const FCraftingJob& Job) { return Job.bComplete; });
}
// Stop timer if no mSource: Repobility analyzer · https://repobility.com
CancelCraftingJob method · cpp · L514-L533 (20 LOC)Source/VaultCore/Private/Crafting/CraftingStationComponent.cpp
FGameplayTag UCraftingStationComponent::CancelCraftingJob(FGuid JobID, APlayerController* Player)
{
const int32 Index = ActiveJobs.IndexOfByPredicate([&JobID](const FCraftingJob& Job)
{
return Job.JobID == JobID;
});
if (Index == INDEX_NONE)
{
return VaultTags::Validation_Error_ItemNotFound;
}
// Remove the job — inputs were already consumed so they cannot be returned.
// This is intentional: canceling a timed craft forfeits the materials.
ActiveJobs.RemoveAt(Index);
UE_LOG(LogVault, Log, TEXT("Crafting job cancelled: %s"), *JobID.ToString());
return VaultTags::Validation_Success;
}SalvageItem method · cpp · L536-L609 (74 LOC)Source/VaultCore/Private/Crafting/CraftingStationComponent.cpp
FGameplayTag UCraftingStationComponent::SalvageItem(APlayerController* Player, FGuid ItemInstanceID)
{
if (!IsValid(Player) || !ItemInstanceID.IsValid())
{
return VaultTags::Validation_Error_OutOfBounds;
}
UInventoryManagerComponent* Comp = Player->GetPawn()
? Player->GetPawn()->FindComponentByClass<UInventoryManagerComponent>()
: nullptr;
if (!Comp) return VaultTags::Validation_Error_NotOwner;
const FInventoryEntry* Entry = Comp->FindEntryByID(ItemInstanceID);
if (!Entry || !IsValid(Entry->ItemDef.Get())) return VaultTags::Validation_Error_ItemNotFound;
// Look up salvage recipe from economy config
UWorld* World_Local = GetWorld();
UGameInstance* GI = World_Local ? World_Local->GetGameInstance() : nullptr;
UVaultStorageManager* StorageManager = GI ? GI->GetSubsystem<UVaultStorageManager>() : nullptr;
if (!StorageManager || !StorageManager->IsEconomyConfigReady())
{
return VaultTags::Validation_Error_ServerNotReady;
}
const FVaultEconomyConfig& EconConfig = CanCraft method · cpp · L612-L659 (48 LOC)Source/VaultCore/Private/Crafting/CraftingStationComponent.cpp
bool UCraftingStationComponent::CanCraft(FGameplayTag RecipeTag, TArray<FGameplayTag>& OutMissingInputs) const
{
OutMissingInputs.Reset();
// Look up recipe from economy config
UWorld* World_Local = GetWorld();
if (!World_Local) return false;
UGameInstance* GI = World_Local->GetGameInstance();
UVaultStorageManager* SM = GI ? GI->GetSubsystem<UVaultStorageManager>() : nullptr;
if (!SM || !SM->IsEconomyConfigReady()) return false;
const FVaultEconomyConfig& Config = SM->GetEconomyConfig();
const FCraftingRecipe* Recipe = Config.CraftingRecipes.Find(RecipeTag);
if (!Recipe)
{
OutMissingInputs.Add(RecipeTag);
return false;
}
// Check each ingredient against deposited materials
bool bAllPresent = true;
for (const FCraftingIngredient& Ingredient : Recipe->Ingredients)
{
int32 AvailableQty = 0;
for (const FCraftingSlot& Slot : InputSlots)
{
if (Slot.ItemDef.Get() == Ingredient.ItemDef.Get())
{
AvailableQty += Slot.Quantity;
}
}
if (AvailableQtGetPreloadDependencies method · cpp · L4-L17 (14 LOC)Source/VaultCore/Private/Data/Fragments/ItemFragment_Visuals.cpp
void UItemFragment_Visuals::GetPreloadDependencies(TArray<UObject*>& OutDeps)
{
Super::GetPreloadDependencies(OutDeps);
// Register soft references so Asset Manager knows to load them
if (!InventoryIcon.IsNull())
{
if (UObject* IconObj = InventoryIcon.Get())
{
OutDeps.Add(IconObj);
}
}
}GetFragmentDescription method · cpp · L20-L23 (4 LOC)Source/VaultCore/Private/Data/Fragments/ItemFragment_Visuals.cpp
FText UItemFragment_Visuals::GetFragmentDescription() const
{
return DisplayName.IsEmpty() ? FText::FromString(TEXT("Visuals")) : DisplayName;
}IsValid method · cpp · L14-L19 (6 LOC)Source/VaultCore/Private/Data/InventoryEntry.cpp
bool FInventoryEntry::IsValid() const
{
// Valid if we have a tag (replicated/serialized path) OR a resolved definition (legacy/server path)
return (ItemDefTag.IsValid() || ::IsValid(ItemDef)) && InstanceID.IsValid();
}IsBound method · cpp · L20-L24 (5 LOC)Source/VaultCore/Private/Data/InventoryEntry.cpp
bool FInventoryEntry::IsBound() const
{
return !BoundToOwnerID.IsEmpty();
}IsExpired method · cpp · L25-L29 (5 LOC)Source/VaultCore/Private/Data/InventoryEntry.cpp
bool FInventoryEntry::IsExpired() const
{
return HasExpiry() && FDateTime::UtcNow() > ExpiresAtUTC;
}Repobility · MCP-ready · https://repobility.com
HasExpiry method · cpp · L30-L35 (6 LOC)Source/VaultCore/Private/Data/InventoryEntry.cpp
bool FInventoryEntry::HasExpiry() const
{
// FDateTime(0) == no expiry
return ExpiresAtUTC.GetTicks() > 0;
}GetBalance method · cpp · L38-L43 (6 LOC)Source/VaultCore/Private/Data/InventoryEntry.cpp
int32 FWalletContainer::GetBalance(FGameplayTag CurrencyTag) const
{
const int32* Found = Balances.Find(CurrencyTag);
return Found ? *Found : 0;
}HasBalance method · cpp · L44-L48 (5 LOC)Source/VaultCore/Private/Data/InventoryEntry.cpp
bool FWalletContainer::HasBalance(FGameplayTag CurrencyTag, int32 Amount) const
{
return GetBalance(CurrencyTag) >= Amount;
}AddCurrency method · cpp · L49-L58 (10 LOC)Source/VaultCore/Private/Data/InventoryEntry.cpp
void FWalletContainer::AddCurrency(FGameplayTag CurrencyTag, int32 Amount)
{
if (!ensureMsgf(Amount >= 0, TEXT("AddCurrency: negative amount %d rejected"), Amount))
{
return; // Graceful rejection — never crash the server on player-controlled data
}
int32& Balance = Balances.FindOrAdd(CurrencyTag, 0);
Balance += Amount;
}DeductCurrency method · cpp · L59-L73 (15 LOC)Source/VaultCore/Private/Data/InventoryEntry.cpp
bool FWalletContainer::DeductCurrency(FGameplayTag CurrencyTag, int32 Amount)
{
if (!ensureMsgf(Amount >= 0, TEXT("DeductCurrency: negative amount %d rejected"), Amount))
{
return false; // Graceful rejection
}
int32* Balance = Balances.Find(CurrencyTag);
if (!Balance || *Balance < Amount)
{
return false;
}
*Balance -= Amount;
return true;
}GetPrimaryAssetId method · cpp · L4-L8 (5 LOC)Source/VaultCore/Private/Data/ItemDefinition.cpp
FPrimaryAssetId UItemDefinition::GetPrimaryAssetId() const
{
return FPrimaryAssetId(TEXT("ItemDefinition"), GetFName());
}BP_FindFragmentByClass method · cpp · L9-L26 (18 LOC)Source/VaultCore/Private/Data/ItemDefinition.cpp
const UItemFragment* UItemDefinition::BP_FindFragmentByClass(TSubclassOf<UItemFragment> FragmentClass) const
{
if (!FragmentClass)
{
return nullptr;
}
for (const TObjectPtr<UItemFragment>& Fragment : Fragments)
{
if (IsValid(Fragment) && Fragment->IsA(FragmentClass))
{
return Fragment;
}
}
return nullptr;
}Initialize method · cpp · L18-L46 (29 LOC)Source/VaultCore/Private/Data/ItemDefinitionRegistry.cpp
void UItemDefinitionRegistry::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
UE_LOG(LogVaultRegistry, Display, TEXT("ItemDefinitionRegistry initializing..."));
// 1. Register hand-crafted .uasset definitions via Asset Manager
PopulateFromAssetManager();
// 2. Register DataTable-driven definitions from settings
const UVaultSettings* Settings = UVaultSettings::Get();
if (Settings && !Settings->ItemDefinitionsDataTable.IsNull())
{
UDataTable* DataTable = Settings->ItemDefinitionsDataTable.LoadSynchronous();
if (DataTable)
{
PopulateFromDataTable(DataTable);
}
else
{
UE_LOG(LogVaultRegistry, Warning,
TEXT("ItemDefinitionsDataTable configured but failed to load."));
}
}
// 3. Lock the registry
FinalizeRegistry();
}Repobility — the code-quality scanner for AI-generated software · https://repobility.com
Deinitialize method · cpp · L47-L54 (8 LOC)Source/VaultCore/Private/Data/ItemDefinitionRegistry.cpp
void UItemDefinitionRegistry::Deinitialize()
{
UE_LOG(LogVaultRegistry, Display, TEXT("ItemDefinitionRegistry shutting down. %d definitions registered."),
DefinitionMap.Num());
Super::Deinitialize();
}ResolveDefinition method · cpp · L57-L68 (12 LOC)Source/VaultCore/Private/Data/ItemDefinitionRegistry.cpp
const UItemDefinition* UItemDefinitionRegistry::ResolveDefinition(FGameplayTag ItemDefTag) const
{
if (!ItemDefTag.IsValid())
{
return nullptr;
}
FReadScopeLock ReadLock(RegistryLock);
const TObjectPtr<UItemDefinition>* Found = DefinitionMap.Find(ItemDefTag);
return Found ? Found->Get() : nullptr;
}GetAllDefinitions method · cpp · L69-L84 (16 LOC)Source/VaultCore/Private/Data/ItemDefinitionRegistry.cpp
TArray<UItemDefinition*> UItemDefinitionRegistry::GetAllDefinitions() const
{
FReadScopeLock ReadLock(RegistryLock);
TArray<UItemDefinition*> Result;
Result.Reserve(DefinitionMap.Num());
for (const auto& Pair : DefinitionMap)
{
if (IsValid(Pair.Value))
{
Result.Add(Pair.Value.Get());
}
}
return Result;
}