← back to drstreit__Unreal-01-VaultInventory

Function bodies 468 total

All specs Real LLM only Function bodies
ExecuteMigrationPipeline method · cpp · L21-L64 (44 LOC)
Source/VaultCore/Private/Migration/VaultMigrationUtility.cpp
bool UVaultMigrationUtility::ExecuteMigrationPipeline(
	const FString& RawPayload,
	int32 LoadedVersion,
	FString& OutPayload)
{
	const UVaultSettings* Settings = UVaultSettings::Get();
	if (!Settings)
	{
		UE_LOG(LogVault, Error, TEXT("Migration: UVaultSettings not available"));
		OutPayload = RawPayload;
		return false;
	}

	const int32 TargetVersion = Settings->CurrentGameSchemaVersion;

	if (LoadedVersion >= TargetVersion)
	{
		// Already current — no migration needed
		OutPayload = RawPayload;
		return true;
	}

	UE_LOG(LogVault, Display, TEXT("Migration: Upgrading payload from V%d to V%d"),
		LoadedVersion, TargetVersion);

	FString WorkingPayload = RawPayload;

	// Apply migrations sequentially: V1→V2→V3→...
	for (int32 Version = LoadedVersion; Version < TargetVersion; ++Version)
	{
		if (!ApplyMigration(Version, WorkingPayload))
		{
			UE_LOG(LogVault, Error, TEXT("Migration: Failed at V%d→V%d"), Version, Version + 1);
			OutPayload = RawPayload; // Return original on failure 
NeedsMigration method · cpp · L80-L85 (6 LOC)
Source/VaultCore/Private/Migration/VaultMigrationUtility.cpp
bool UVaultMigrationUtility::NeedsMigration(int32 LoadedVersion) const
{
	const UVaultSettings* Settings = UVaultSettings::Get();
	return Settings && LoadedVersion < Settings->CurrentGameSchemaVersion;
}
ApplyMigration method · cpp · L86-L111 (26 LOC)
Source/VaultCore/Private/Migration/VaultMigrationUtility.cpp
bool UVaultMigrationUtility::ApplyMigration(int32 FromVersion, FString& InOutPayload)
{
	const TFunction<FString(const FString&)>* MigrationFunc = MigrationRegistry.Find(FromVersion);

	if (!MigrationFunc || !(*MigrationFunc))
	{
		UE_LOG(LogVault, Warning,
			TEXT("Migration: No migration registered for V%d→V%d — passing through unchanged"),
			FromVersion, FromVersion + 1);
		// No registered migration = identity transform (data format compatible)
		return true;
	}

	const FString Result = (*MigrationFunc)(InOutPayload);

	if (Result.IsEmpty())
	{
		UE_LOG(LogVault, Error,
			TEXT("Migration: V%d→V%d returned empty payload"), FromVersion, FromVersion + 1);
		return false;
	}

	InOutPayload = Result;
	return true;
}
TriggerPostMigrationSave method · cpp · L112-L140 (29 LOC)
Source/VaultCore/Private/Migration/VaultMigrationUtility.cpp
void UVaultMigrationUtility::TriggerPostMigrationSave(
	const FString& ProfileID, const FString& MigratedPayload, UObject* WorldContextObject)
{
	if (!IsValid(WorldContextObject)) return;

	UWorld* World = WorldContextObject->GetWorld();
	if (!World) return;

	UGameInstance* GI = World->GetGameInstance();
	UVaultStorageManager* SM = GI ? GI->GetSubsystem<UVaultStorageManager>() : nullptr;
	if (SM == nullptr) return;

	TScriptInterface<IInventoryStorageProvider> Provider = SM->GetActiveProvider();
	if (!Provider.GetObject()) return;

	const UVaultSettings* Settings = UVaultSettings::Get();

	FVaultStoragePayload Payload;
	Payload.ProfileID = ProfileID;
	Payload.SchemaVersion = Settings ? Settings->CurrentGameSchemaVersion : 1;
	Payload.LockVersion = 0;
	Payload.InventoryJSON = MigratedPayload;

	FOnStorageSaveComplete OnComplete;
	Provider->AsyncSave(Payload, OnComplete);

	UE_LOG(LogVault, Display, TEXT("Migration: Triggered post-migration save for ProfileID=%s"), *ProfileID);
}
BP_RegisterMigration method · cpp · L141-L157 (17 LOC)
Source/VaultCore/Private/Migration/VaultMigrationUtility.cpp
void UVaultMigrationUtility::BP_RegisterMigration(
	int32 FromVersion, FBlueprintMigrationDelegate MigrationDelegate)
{
	if (!MigrationDelegate.IsBound())
	{
		UE_LOG(LogVault, Warning,
			TEXT("BP_RegisterMigration: Delegate not bound for V%d — registration skipped."),
			FromVersion);
		return;
	}

	RegisterMigration(FromVersion, [MigrationDelegate](const FString& RawPayload) -> FString
	{
		return MigrationDelegate.Execute(RawPayload);
	});
}
PreReplicatedRemove method · cpp · L12-L25 (14 LOC)
Source/VaultCore/Private/Network/InventoryArray.cpp
void FInventoryArray::PreReplicatedRemove(const TArrayView<int32> RemovedIndices, int32 FinalSize)
{
	if (UInventoryManagerComponent* Comp = OwningComponent.Get())
	{
		for (int32 Index : RemovedIndices)
		{
			if (Entries.IsValidIndex(Index))
			{
				Comp->NotifyItemRemoved(Entries[Index].InstanceID);
			}
		}
	}
}
PostReplicatedAdd method · cpp · L26-L66 (41 LOC)
Source/VaultCore/Private/Network/InventoryArray.cpp
void FInventoryArray::PostReplicatedAdd(const TArrayView<int32> AddedIndices, int32 FinalSize)
{
	// Resolve ItemDefTag → ItemDef for newly replicated entries (client-side)
	// ItemDef is NotReplicated — clients resolve from their local registry
	UItemDefinitionRegistry* Registry = nullptr;
	if (UInventoryManagerComponent* Comp = OwningComponent.Get())
	{
		if (UWorld* World = Comp->GetWorld())
		{
			if (UGameInstance* GI = World->GetGameInstance())
			{
				Registry = GI->GetSubsystem<UItemDefinitionRegistry>();
			}
		}

		for (int32 Index : AddedIndices)
		{
			if (Entries.IsValidIndex(Index))
			{
				FInventoryEntry& Entry = Entries[Index];

				// Client-side tag resolution: ItemDef is NotReplicated, resolve from tag
				if (!IsValid(Entry.ItemDef.Get()) && Entry.ItemDefTag.IsValid() && Registry)
				{
					Entry.ItemDef = const_cast<UItemDefinition*>(
						Registry->ResolveDefinition(Entry.ItemDefTag));

					if (!IsValid(Entry.ItemDef.Get()))
					{
						UE_LOG(LogVaultNetw
Repobility — same analyzer, your code, free for public repos · /scan/
PostReplicatedChange method · cpp · L67-L98 (32 LOC)
Source/VaultCore/Private/Network/InventoryArray.cpp
void FInventoryArray::PostReplicatedChange(const TArrayView<int32> ChangedIndices, int32 FinalSize)
{
	if (UInventoryManagerComponent* Comp = OwningComponent.Get())
	{
		// Resolve ItemDef if it's null (can happen after tag-based replication)
		UItemDefinitionRegistry* Registry = nullptr;
		if (UWorld* World = Comp->GetWorld())
		{
			if (UGameInstance* GI = World->GetGameInstance())
			{
				Registry = GI->GetSubsystem<UItemDefinitionRegistry>();
			}
		}

		for (int32 Index : ChangedIndices)
		{
			if (Entries.IsValidIndex(Index))
			{
				FInventoryEntry& Entry = Entries[Index];

				if (!IsValid(Entry.ItemDef.Get()) && Entry.ItemDefTag.IsValid() && Registry)
				{
					Entry.ItemDef = const_cast<UItemDefinition*>(
						Registry->ResolveDefinition(Entry.ItemDefTag));
				}

				Comp->NotifyItemChanged(Entry);
			}
		}
	}
}
AddEntry method · cpp · L101-L110 (10 LOC)
Source/VaultCore/Private/Network/InventoryArray.cpp
int32 FInventoryArray::AddEntry(FInventoryEntry&& NewEntry)
{
	int32 NewIndex = Entries.Add(MoveTemp(NewEntry));
	// Structural change — must dirty the entire array so replication picks up the new entry
	MarkArrayDirty();
	UE_LOG(LogVaultNetwork, Verbose, TEXT("AddEntry: Index=%d, InstanceID=%s"),
		NewIndex, *Entries[NewIndex].InstanceID.ToString());
	return NewIndex;
}
RemoveEntry method · cpp · L111-L127 (17 LOC)
Source/VaultCore/Private/Network/InventoryArray.cpp
void FInventoryArray::RemoveEntry(int32 Index)
{
	if (!Entries.IsValidIndex(Index))
	{
		UE_LOG(LogVaultNetwork, Warning, TEXT("RemoveEntry: Invalid index %d (Entries.Num=%d)"),
			Index, Entries.Num());
		return;
	}

	UE_LOG(LogVaultNetwork, Verbose, TEXT("RemoveEntry: Index=%d, InstanceID=%s"),
		Index, *Entries[Index].InstanceID.ToString());

	// RemoveAtSwap is O(1) and Iris-friendly — does not trigger full-array re-replication
	Entries.RemoveAtSwap(Index);
	MarkArrayDirty();
}
FindByInstanceID method · cpp · L128-L135 (8 LOC)
Source/VaultCore/Private/Network/InventoryArray.cpp
FInventoryEntry* FInventoryArray::FindByInstanceID(const FGuid& InstanceID)
{
	return Entries.FindByPredicate([&InstanceID](const FInventoryEntry& Entry)
	{
		return Entry.InstanceID == InstanceID;
	});
}
FindByInstanceID method · cpp · L136-L143 (8 LOC)
Source/VaultCore/Private/Network/InventoryArray.cpp
const FInventoryEntry* FInventoryArray::FindByInstanceID(const FGuid& InstanceID) const
{
	return Entries.FindByPredicate([&InstanceID](const FInventoryEntry& Entry)
	{
		return Entry.InstanceID == InstanceID;
	});
}
FindIndexByInstanceID method · cpp · L144-L151 (8 LOC)
Source/VaultCore/Private/Network/InventoryArray.cpp
int32 FInventoryArray::FindIndexByInstanceID(const FGuid& InstanceID) const
{
	return Entries.IndexOfByPredicate([&InstanceID](const FInventoryEntry& Entry)
	{
		return Entry.InstanceID == InstanceID;
	});
}
PostInitProperties method · cpp · L13-L45 (33 LOC)
Source/VaultCore/Private/Settings/VaultSettings.cpp
void UVaultSettings::PostInitProperties()
{
	Super::PostInitProperties();

	// Auto-load secrets from environment variables.
	// Transient fields start empty — env vars populate them at startup.
	// Command-line args take precedence over env vars.
	auto LoadSecret = [](FString& OutValue, const TCHAR* EnvVarName, const TCHAR* FieldName)
	{
		if (!OutValue.IsEmpty()) return; // Already set (e.g., editor manual input)

		FString Value = FPlatformMisc::GetEnvironmentVariable(EnvVarName);
		if (!Value.IsEmpty())
		{
			OutValue = Value;
			UE_LOG(LogVaultSettings, Display, TEXT("Loaded %s from env var %s"), FieldName, EnvVarName);
		}
	};

	LoadSecret(SupabaseSecretKey, TEXT("VAULT_SUPABASE_KEY"), TEXT("SupabaseSecretKey"));
	LoadSecret(AWSApiGatewayKey, TEXT("VAULT_AWS_API_KEY"), TEXT("AWSApiGatewayKey"));
	LoadSecret(RemoteEconomyConfigAuthToken, TEXT("VAULT_ECONOMY_TOKEN"), TEXT("RemoteEconomyConfigAuthToken"));
	LoadSecret(EconomyConfigSigningKey, TEXT("VAULT_ECONOMY_SIGNING_KEY"), TEX
Get method · cpp · L46-L50 (5 LOC)
Source/VaultCore/Private/Settings/VaultSettings.cpp
const UVaultSettings* UVaultSettings::Get()
{
	return GetDefault<UVaultSettings>();
}
Repobility analyzer · published findings · https://repobility.com
AsyncLoad method · cpp · L5-L33 (29 LOC)
Source/VaultCore/Private/Storage/NullStorageProvider.cpp
void UNullStorageProvider::AsyncLoad(const FString& ProfileID, FOnStorageLoadComplete OnComplete)
{
	const double Start = FPlatformTime::Seconds();

	FVaultStoragePayload Payload;
	bool bSuccess = true;

	if (const FVaultStoragePayload* Found = InMemoryStore.Find(ProfileID))
	{
		Payload = *Found;
	}
	else
	{
		// Empty load — valid, just means new player
		Payload.ProfileID = ProfileID;
	}

	LastMetrics.LatencyMs = (FPlatformTime::Seconds() - Start) * 1000.0;
	LastMetrics.PayloadSizeBytes = Payload.InventoryJSON.Len() + Payload.WalletJSON.Len();
	LastMetrics.bSuccess = bSuccess;
	LastMetrics.ErrorMessage.Empty();
	LastMetrics.HttpStatusCode = 0;

	UE_LOG(LogVaultStorage, Verbose, TEXT("NullProvider::AsyncLoad: ProfileID=%s, Found=%s"),
		*ProfileID, InMemoryStore.Contains(ProfileID) ? TEXT("true") : TEXT("false"));

	OnComplete.ExecuteIfBound(bSuccess, Payload);
}
AsyncSave method · cpp · L34-L70 (37 LOC)
Source/VaultCore/Private/Storage/NullStorageProvider.cpp
void UNullStorageProvider::AsyncSave(const FVaultStoragePayload& Payload, FOnStorageSaveComplete OnComplete)
{
	const double Start = FPlatformTime::Seconds();

	bool bSuccess = true;
	FString ErrorMessage;

	// OCC check: if we have an existing record, verify LockVersion
	if (const FVaultStoragePayload* Existing = InMemoryStore.Find(Payload.ProfileID))
	{
		if (Payload.LockVersion != Existing->LockVersion)
		{
			bSuccess = false;
			ErrorMessage = FString::Printf(
				TEXT("OCC conflict: expected LockVersion=%d, got=%d"),
				Existing->LockVersion, Payload.LockVersion);
			UE_LOG(LogVaultStorage, Warning, TEXT("NullProvider::AsyncSave: %s"), *ErrorMessage);
		}
	}

	if (bSuccess)
	{
		FVaultStoragePayload SavedPayload = Payload;
		SavedPayload.LockVersion++; // Increment on successful save
		SavedPayload.LastSyncedUTC = FDateTime::UtcNow().ToIso8601();
		InMemoryStore.Add(Payload.ProfileID, SavedPayload);
	}

	LastMetrics.LatencyMs = (FPlatformTime::Seconds() - Start) * 1000.0;
	Last
AsyncDelete method · cpp · L71-L79 (9 LOC)
Source/VaultCore/Private/Storage/NullStorageProvider.cpp
void UNullStorageProvider::AsyncDelete(const FString& ProfileID, FOnStorageSaveComplete OnComplete)
{
	InMemoryStore.Remove(ProfileID);

	UE_LOG(LogVaultStorage, Verbose, TEXT("NullProvider::AsyncDelete: ProfileID=%s"), *ProfileID);

	OnComplete.ExecuteIfBound(true, TEXT(""));
}
GetLastOperationMetrics method · cpp · L80-L84 (5 LOC)
Source/VaultCore/Private/Storage/NullStorageProvider.cpp
FStorageOperationMetrics UNullStorageProvider::GetLastOperationMetrics() const
{
	return LastMetrics;
}
SerializeInventory function · cpp · L16-L87 (72 LOC)
Source/VaultCore/Private/Storage/VaultSerializationHelpers.cpp
FString SerializeInventory(const FInventoryArray& Inventory, const FWalletContainer& Wallet)
{
	// Use UE's JSON object converter for USTRUCT serialization.
	// This handles UPROPERTY reflection automatically.
	// For production, this should use FObjectAndNameAsStringProxyArchive
	// to convert hard object refs to string names.

	TSharedRef<FJsonObject> Root = MakeShareable(new FJsonObject());

	// Serialize entries as JSON array
	TArray<TSharedPtr<FJsonValue>> EntriesArray;
	for (const FInventoryEntry& Entry : Inventory.Entries)
	{
		TSharedPtr<FJsonObject> EntryObj = MakeShareable(new FJsonObject());
		EntryObj->SetStringField(TEXT("InstanceID"), Entry.InstanceID.ToString());
		EntryObj->SetNumberField(TEXT("StackCount"), Entry.StackCount);
		EntryObj->SetStringField(TEXT("BindingPolicy"), Entry.BindingPolicy.ToString());
		EntryObj->SetStringField(TEXT("BoundToOwnerID"), Entry.BoundToOwnerID);

		if (Entry.HasExpiry())
		{
			EntryObj->SetStringField(TEXT("ExpiresAtUTC"), Entry.Exp
DeserializeInventory function · cpp · L88-L240 (153 LOC)
Source/VaultCore/Private/Storage/VaultSerializationHelpers.cpp
bool DeserializeInventory(const FString& JSON, FInventoryArray& OutInventory, FWalletContainer& OutWallet,
	const UItemDefinitionRegistry* Registry)
{
	if (JSON.IsEmpty())
	{
		// Empty payload = new player, valid
		return true;
	}

	TSharedPtr<FJsonObject> Root;
	TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JSON);

	if (!FJsonSerializer::Deserialize(Reader, Root) || !Root.IsValid())
	{
		UE_LOG(LogVaultStorage, Error, TEXT("DeserializeInventory: Failed to parse JSON"));
		return false;
	}

	// Deserialize entries
	OutInventory.Entries.Reset();
	const TArray<TSharedPtr<FJsonValue>>* EntriesArray = nullptr;
	if (Root->TryGetArrayField(TEXT("Entries"), EntriesArray))
	{
		for (const TSharedPtr<FJsonValue>& EntryVal : *EntriesArray)
		{
			const TSharedPtr<FJsonObject>* EntryObj = nullptr;
			if (!EntryVal->TryGetObject(EntryObj) || !EntryObj) continue;

			FInventoryEntry Entry;

			FString InstanceIDStr;
			if ((*EntryObj)->TryGetStringField(TEXT("InstanceID"), Insta
Initialize method · cpp · L13-L44 (32 LOC)
Source/VaultCore/Private/Storage/VaultStorageManager.cpp
void UVaultStorageManager::Initialize(FSubsystemCollectionBase& Collection)
{
	Super::Initialize(Collection);

	// Default to NullStorageProvider until a concrete provider registers
	UNullStorageProvider* NullProvider = NewObject<UNullStorageProvider>(this);
	ActiveProvider.SetObject(NullProvider);
	ActiveProvider.SetInterface(Cast<IInventoryStorageProvider>(NullProvider));

	LatencyHistory.Reserve(MetricsWindowSize);
	SuccessHistory.Reserve(MetricsWindowSize);

	// If Local_DataTable economy config is selected and no server module overrides,
	// set up the local provider directly (no HTTP needed)
	const UVaultSettings* Settings = UVaultSettings::Get();
	if (Settings && Settings->EconomyConfigProvider == EVaultEconomyConfigProvider::Local_DataTable)
	{
		ULocalEconomyConfigProvider* LocalProvider = NewObject<ULocalEconomyConfigProvider>(this);
		EconomyConfigProviderObject = LocalProvider;

		FOnEconomyConfigLoaded OnConfigLoaded;
		OnConfigLoaded.BindUObject(this, &UVaultStorageManag
RegisterStorageProvider method · cpp · L47-L60 (14 LOC)
Source/VaultCore/Private/Storage/VaultStorageManager.cpp
void UVaultStorageManager::RegisterStorageProvider(TScriptInterface<IInventoryStorageProvider> Provider)
{
	if (!Provider.GetObject())
	{
		UE_LOG(LogVaultStorage, Warning, TEXT("RegisterStorageProvider: null provider, keeping NullStorageProvider"));
		return;
	}

	ActiveProvider = Provider;

	UE_LOG(LogVaultStorage, Display, TEXT("VaultStorageManager: Registered storage provider %s"),
		*Provider.GetObject()->GetClass()->GetName());
}
Repobility · severity-and-effort ranking · https://repobility.com
RegisterEconomyConfigProvider method · cpp · L61-L82 (22 LOC)
Source/VaultCore/Private/Storage/VaultStorageManager.cpp
void UVaultStorageManager::RegisterEconomyConfigProvider(UObject* ProviderObj)
{
	if (!IsValid(ProviderObj))
	{
		UE_LOG(LogVaultEconomy, Warning, TEXT("RegisterEconomyConfigProvider: null provider"));
		return;
	}

	EconomyConfigProviderObject = ProviderObj;

	IVaultEconomyConfigProvider* Provider = Cast<IVaultEconomyConfigProvider>(ProviderObj);
	if (Provider)
	{
		FOnEconomyConfigLoaded OnConfigLoaded;
		OnConfigLoaded.BindUObject(this, &UVaultStorageManager::OnEconomyConfigLoaded);
		Provider->AsyncFetchConfig(OnConfigLoaded);

		UE_LOG(LogVaultEconomy, Display, TEXT("VaultStorageManager: Registered economy config provider %s"),
			*ProviderObj->GetClass()->GetName());
	}
}
GetActiveProvider method · cpp · L85-L89 (5 LOC)
Source/VaultCore/Private/Storage/VaultStorageManager.cpp
TScriptInterface<IInventoryStorageProvider> UVaultStorageManager::GetActiveProvider() const
{
	return ActiveProvider;
}
GetEconomyConfigProvider method · cpp · L90-L98 (9 LOC)
Source/VaultCore/Private/Storage/VaultStorageManager.cpp
IVaultEconomyConfigProvider* UVaultStorageManager::GetEconomyConfigProvider() const
{
	if (!IsValid(EconomyConfigProviderObject))
	{
		return nullptr;
	}
	return Cast<IVaultEconomyConfigProvider>(EconomyConfigProviderObject);
}
GetEconomyConfig method · cpp · L99-L108 (10 LOC)
Source/VaultCore/Private/Storage/VaultStorageManager.cpp
const FVaultEconomyConfig& UVaultStorageManager::GetEconomyConfig() const
{
	IVaultEconomyConfigProvider* Provider = GetEconomyConfigProvider();
	if (Provider && bEconomyConfigReady)
	{
		return Provider->GetCachedConfig();
	}
	return EmptyConfig;
}
OnEconomyConfigLoaded method · cpp · L109-L131 (23 LOC)
Source/VaultCore/Private/Storage/VaultStorageManager.cpp
void UVaultStorageManager::OnEconomyConfigLoaded(bool bSuccess)
{
	bEconomyConfigReady = bSuccess;

	if (bSuccess)
	{
		IVaultEconomyConfigProvider* Provider = GetEconomyConfigProvider();
		if (Provider)
		{
			const FVaultEconomyConfig& Config = Provider->GetCachedConfig();
			UE_LOG(LogVaultEconomy, Display,
				TEXT("VaultStorageManager: Economy config ready (Version=%d, LootTables=%d, Recipes=%d, Params=%d)"),
				Config.ConfigVersion, Config.LootTables.Num(),
				Config.CraftingRecipes.Num(), Config.BalanceParameters.Num());
		}
	}
	else
	{
		UE_LOG(LogVaultEconomy, Error,
			TEXT("VaultStorageManager: Economy config failed to load. bEconomyConfigReady remains false."));
	}
}
RecordOperationMetrics method · cpp · L134-L153 (20 LOC)
Source/VaultCore/Private/Storage/VaultStorageManager.cpp
void UVaultStorageManager::RecordOperationMetrics(const FStorageOperationMetrics& Metrics)
{
	TotalOperations++;

	if (LatencyHistory.Num() >= MetricsWindowSize)
	{
		LatencyHistory.RemoveAt(0);
		SuccessHistory.RemoveAt(0);
	}

	LatencyHistory.Add(Metrics.LatencyMs);
	SuccessHistory.Add(Metrics.bSuccess);

	if (!Metrics.bSuccess)
	{
		UE_LOG(LogVaultStorage, Warning, TEXT("Storage operation failed: %s (Latency=%.1fms)"),
			*Metrics.ErrorMessage, Metrics.LatencyMs);
	}
}
GetLatencyP95 method · cpp · L154-L164 (11 LOC)
Source/VaultCore/Private/Storage/VaultStorageManager.cpp
float UVaultStorageManager::GetLatencyP95() const
{
	if (LatencyHistory.Num() == 0) return 0.0f;

	TArray<float> Sorted = LatencyHistory;
	Sorted.Sort();

	const int32 P95Index = FMath::FloorToInt(Sorted.Num() * 0.95f);
	return Sorted.IsValidIndex(P95Index) ? Sorted[P95Index] : Sorted.Last();
}
GetFailureRate method · cpp · L165-L177 (13 LOC)
Source/VaultCore/Private/Storage/VaultStorageManager.cpp
float UVaultStorageManager::GetFailureRate() const
{
	if (SuccessHistory.Num() == 0) return 0.0f;

	int32 Failures = 0;
	for (bool bSuccess : SuccessHistory)
	{
		if (!bSuccess) Failures++;
	}

	return (static_cast<float>(Failures) / SuccessHistory.Num()) * 100.0f;
}
Open data scored by Repobility · https://repobility.com
CheckStorageHealth method · cpp · L180-L196 (17 LOC)
Source/VaultCore/Private/Storage/VaultStorageManager.cpp
void UVaultStorageManager::CheckStorageHealth(bool& bOutHealthy, float& OutLatencyMs, FGameplayTag& OutErrorTag) const
{
	bOutHealthy = false;
	OutLatencyMs = 0.0f;
	OutErrorTag = FGameplayTag();

	if (!ActiveProvider.GetObject())
	{
		OutErrorTag = VaultTags::Validation_Error_ServerNotReady;
		return;
	}

	// Provider exists — report as healthy with current P95 latency
	bOutHealthy = true;
	OutLatencyMs = GetLatencyP95();
}
GetMetricsSnapshot method · cpp · L197-L204 (8 LOC)
Source/VaultCore/Private/Storage/VaultStorageManager.cpp
bool UVaultStorageManager::GetMetricsSnapshot(int32& OutTotalOps, float& OutFailureRate, float& OutLatencyP95) const
{
	OutTotalOps = TotalOperations;
	OutFailureRate = GetFailureRate();
	OutLatencyP95 = GetLatencyP95();
	return true;
}
CreateBasicDef function · cpp · L49-L52 (4 LOC)
Source/VaultCore/Private/Tests/VaultScenarioTests.cpp
	UItemDefinition* CreateBasicDef()
	{
		return NewObject<UItemDefinition>();
	}
CreateStackableDef function · cpp · L55-L63 (9 LOC)
Source/VaultCore/Private/Tests/VaultScenarioTests.cpp
	UItemDefinition* CreateStackableDef(int32 MaxStack = 20)
	{
		UItemDefinition* Def = NewObject<UItemDefinition>();
		UItemFragment_Stackable* Frag = NewObject<UItemFragment_Stackable>(Def);
		Frag->MaxStackSize = MaxStack;
		Frag->bAllowPartialStacks = true;
		Def->Fragments.Add(Frag);
		return Def;
	}
CreateWeightedDef function · cpp · L66-L73 (8 LOC)
Source/VaultCore/Private/Tests/VaultScenarioTests.cpp
	UItemDefinition* CreateWeightedDef(float Weight = 2.5f)
	{
		UItemDefinition* Def = NewObject<UItemDefinition>();
		UItemFragment_Weight* Frag = NewObject<UItemFragment_Weight>(Def);
		Frag->PerItemWeight = Weight;
		Def->Fragments.Add(Frag);
		return Def;
	}
CreateStackableWeightedDef function · cpp · L76-L87 (12 LOC)
Source/VaultCore/Private/Tests/VaultScenarioTests.cpp
	UItemDefinition* CreateStackableWeightedDef(int32 MaxStack = 20, float Weight = 1.0f)
	{
		UItemDefinition* Def = NewObject<UItemDefinition>();
		UItemFragment_Stackable* SFrag = NewObject<UItemFragment_Stackable>(Def);
		SFrag->MaxStackSize = MaxStack;
		SFrag->bAllowPartialStacks = true;
		Def->Fragments.Add(SFrag);
		UItemFragment_Weight* WFrag = NewObject<UItemFragment_Weight>(Def);
		WFrag->PerItemWeight = Weight;
		Def->Fragments.Add(WFrag);
		return Def;
	}
CreateBindableDef function · cpp · L90-L95 (6 LOC)
Source/VaultCore/Private/Tests/VaultScenarioTests.cpp
	UItemDefinition* CreateBindableDef(FGameplayTag BindingPolicy)
	{
		UItemDefinition* Def = NewObject<UItemDefinition>();
		Def->DefaultBindingPolicy = BindingPolicy;
		return Def;
	}
TestRemoveItem function · cpp · L122-L128 (7 LOC)
Source/VaultCore/Private/Tests/VaultScenarioTests.cpp
	bool TestRemoveItem(UInventoryManagerComponent* Comp, const FGuid& InstanceID)
	{
		const int32 Idx = Comp->InventoryArray.FindIndexByInstanceID(InstanceID);
		if (Idx == INDEX_NONE) return false;
		Comp->InventoryArray.RemoveEntry(Idx);
		return true;
	}
Repobility — same analyzer, your code, free for public repos · /scan/
PopulateInventory function · cpp · L131-L142 (12 LOC)
Source/VaultCore/Private/Tests/VaultScenarioTests.cpp
	TArray<FGuid> PopulateInventory(UInventoryManagerComponent* Comp, int32 Count, UItemDefinition* Def = nullptr)
	{
		TArray<FGuid> IDs;
		IDs.Reserve(Count);
		for (int32 i = 0; i < Count; ++i)
		{
			UItemDefinition* ItemDef = Def ? Def : CreateBasicDef();
			FGuid ID = TestAddItem(Comp, ItemDef);
			IDs.Add(ID);
		}
		return IDs;
	}
TotalItemQuantity function · cpp · L145-L153 (9 LOC)
Source/VaultCore/Private/Tests/VaultScenarioTests.cpp
	int32 TotalItemQuantity(const UInventoryManagerComponent* Comp)
	{
		int32 Total = 0;
		for (const FInventoryEntry& Entry : Comp->GetEntries())
		{
			Total += Entry.StackCount;
		}
		return Total;
	}
RunTest method · cpp · L167-L233 (67 LOC)
Source/VaultCore/Private/Tests/VaultScenarioTests.cpp
bool FScenario_S1_MassLogin::RunTest(const FString& Parameters)
{
	// Simulate 50 players each saving 100 items, then loading them back
	UNullStorageProvider* Provider = NewObject<UNullStorageProvider>();
	constexpr int32 PlayerCount = 50;
	constexpr int32 ItemsPerPlayer = 100;

	// Phase 1: Save 50 inventories
	for (int32 P = 0; P < PlayerCount; ++P)
	{
		UInventoryManagerComponent* Comp = NewObject<UInventoryManagerComponent>();
		Comp->ProfileID = FString::Printf(TEXT("Player_%03d"), P);

		UItemDefinition* Def = CreateStackableDef(99);
		for (int32 I = 0; I < ItemsPerPlayer; ++I)
		{
			TestAddItem(Comp, Def);
		}

		// Serialize and save
		FString InvJSON;
		InvJSON = VaultSerialization::SerializeInventory(Comp->InventoryArray, Comp->Wallet);

		FVaultStoragePayload Payload;
		Payload.ProfileID = Comp->ProfileID;
		Payload.SchemaVersion = 1;
		Payload.LockVersion = 0;
		Payload.InventoryJSON = InvJSON;
		Payload.WalletJSON = TEXT("");

		bool bSaved = false;
		FOnStorageSaveCompl
RunTest method · cpp · L237-L284 (48 LOC)
Source/VaultCore/Private/Tests/VaultScenarioTests.cpp
bool FScenario_S1_SaveOnMutation::RunTest(const FString& Parameters)
{
	// Verify that Authority_AddItem triggers a save (via serialization roundtrip)
	UNullStorageProvider* Provider = NewObject<UNullStorageProvider>();
	UInventoryManagerComponent* Comp = NewObject<UInventoryManagerComponent>();
	Comp->ProfileID = TEXT("SaveMutationPlayer");

	UItemDefinition* Def = CreateBasicDef();

	// Add item
	FGuid ID = TestAddItem(Comp, Def);
	TestTrue(TEXT("Item added"), ID.IsValid());
	TestEqual(TEXT("Component has 1 entry"), Comp->GetEntryCount(), 1);

	// Serialize state after mutation
	FString InvJSON;
	InvJSON = VaultSerialization::SerializeInventory(Comp->InventoryArray, Comp->Wallet);
	TestFalse(TEXT("InventoryJSON not empty after add"), InvJSON.IsEmpty());

	// Save and reload — verify state persists
	FVaultStoragePayload Payload;
	Payload.ProfileID = TEXT("SaveMutationPlayer");
	Payload.SchemaVersion = 1;
	Payload.LockVersion = 0;
	Payload.InventoryJSON = InvJSON;
	Payload.WalletJSON 
RunTest method · cpp · L288-L353 (66 LOC)
Source/VaultCore/Private/Tests/VaultScenarioTests.cpp
bool FScenario_S1_OCCConflict::RunTest(const FString& Parameters)
{
	// Two sessions load same profile, both try to save — second must fail
	UNullStorageProvider* Provider = NewObject<UNullStorageProvider>();

	// Initial save
	FVaultStoragePayload InitPayload;
	InitPayload.ProfileID = TEXT("OCCPlayer");
	InitPayload.SchemaVersion = 1;
	InitPayload.LockVersion = 0;
	InitPayload.InventoryJSON = TEXT("{}");
	InitPayload.WalletJSON = TEXT("{}");

	bool bOk = false;
	FOnStorageSaveComplete CB;
	CB.BindLambda([&bOk](bool b, const FString&) { bOk = b; });
	Provider->AsyncSave(InitPayload, CB);
	TestTrue(TEXT("Initial save ok"), bOk);

	// Session A loads (gets LockVersion=1)
	int32 SessionAVersion = -1;
	FOnStorageLoadComplete LoadA;
	LoadA.BindLambda([&SessionAVersion](bool, const FVaultStoragePayload& P) { SessionAVersion = P.LockVersion; });
	Provider->AsyncLoad(TEXT("OCCPlayer"), LoadA);
	TestEqual(TEXT("Session A LockVersion=1"), SessionAVersion, 1);

	// Session B loads (also gets Loc
RunTest method · cpp · L357-L408 (52 LOC)
Source/VaultCore/Private/Tests/VaultScenarioTests.cpp
bool FScenario_S1_BatchSave::RunTest(const FString& Parameters)
{
	// 50 players save simultaneously, then verify all load back
	UNullStorageProvider* Provider = NewObject<UNullStorageProvider>();
	constexpr int32 PlayerCount = 50;

	// Save all
	for (int32 P = 0; P < PlayerCount; ++P)
	{
		UInventoryManagerComponent* Comp = NewObject<UInventoryManagerComponent>();
		Comp->ProfileID = FString::Printf(TEXT("Batch_%03d"), P);
		PopulateInventory(Comp, 10);
		Comp->Wallet.AddCurrency(GoldTag(), (P + 1) * 100);

		FString InvJSON;
		InvJSON = VaultSerialization::SerializeInventory(Comp->InventoryArray, Comp->Wallet);

		FVaultStoragePayload Payload;
		Payload.ProfileID = Comp->ProfileID;
		Payload.SchemaVersion = 1;
		Payload.LockVersion = 0;
		Payload.InventoryJSON = InvJSON;
		Payload.WalletJSON = TEXT("");

		bool bOk = false;
		FOnStorageSaveComplete CB;
		CB.BindLambda([&bOk](bool b, const FString&) { bOk = b; });
		Provider->AsyncSave(Payload, CB);
		TestTrue(FString::Printf(TEXT("B
RunTest method · cpp · L412-L435 (24 LOC)
Source/VaultCore/Private/Tests/VaultScenarioTests.cpp
bool FScenario_S1_StorageMetrics::RunTest(const FString& Parameters)
{
	// Verify storage operation metrics are populated after operations
	UNullStorageProvider* Provider = NewObject<UNullStorageProvider>();

	FVaultStoragePayload Payload;
	Payload.ProfileID = TEXT("MetricsPlayer");
	Payload.SchemaVersion = 1;
	Payload.LockVersion = 0;
	Payload.InventoryJSON = TEXT("{\"test\":1}");
	Payload.WalletJSON = TEXT("{}");

	FOnStorageSaveComplete CB;
	CB.BindLambda([](bool, const FString&) {});
	Provider->AsyncSave(Payload, CB);

	// Check metrics after save
	FStorageOperationMetrics Metrics = Provider->GetLastOperationMetrics();
	TestTrue(TEXT("Metrics success"), Metrics.bSuccess);
	TestTrue(TEXT("Metrics latency >= 0"), Metrics.LatencyMs >= 0.0f);

	return true;
}
RunTest method · cpp · L443-L466 (24 LOC)
Source/VaultCore/Private/Tests/VaultScenarioTests.cpp
bool FScenario_S2_RapidAddBurst::RunTest(const FString& Parameters)
{
	UInventoryManagerComponent* Comp = NewObject<UInventoryManagerComponent>();
	constexpr int32 BurstCount = 100;

	UItemDefinition* Def = CreateBasicDef();
	TSet<FGuid> UniqueIDs;

	const double Start = FPlatformTime::Seconds();
	for (int32 i = 0; i < BurstCount; ++i)
	{
		FGuid ID = TestAddItem(Comp, Def);
		TestTrue(FString::Printf(TEXT("Item %d has valid ID"), i), ID.IsValid());
		UniqueIDs.Add(ID);
	}
	const double Elapsed = (FPlatformTime::Seconds() - Start) * 1000.0;

	TestEqual(TEXT("100 entries in inventory"), Comp->GetEntryCount(), BurstCount);
	TestEqual(TEXT("100 unique IDs"), UniqueIDs.Num(), BurstCount);
	UE_LOG(LogTemp, Display, TEXT("Scenario S2: 100 item adds in %.2f ms"), Elapsed);

	return true;
}
Repobility analyzer · published findings · https://repobility.com
RunTest method · cpp · L470-L501 (32 LOC)
Source/VaultCore/Private/Tests/VaultScenarioTests.cpp
bool FScenario_S2_RapidRemoveBurst::RunTest(const FString& Parameters)
{
	UInventoryManagerComponent* Comp = NewObject<UInventoryManagerComponent>();
	TArray<FGuid> IDs = PopulateInventory(Comp, 100);
	TestEqual(TEXT("Starting with 100 items"), Comp->GetEntryCount(), 100);

	// Remove first 50
	for (int32 i = 0; i < 50; ++i)
	{
		bool bRemoved = TestRemoveItem(Comp, IDs[i]);
		TestTrue(FString::Printf(TEXT("Remove %d succeeded"), i), bRemoved);
	}

	TestEqual(TEXT("50 items remain"), Comp->GetEntryCount(), 50);

	// Verify removed items are gone
	for (int32 i = 0; i < 50; ++i)
	{
		const FInventoryEntry* Found = Comp->FindEntryByID(IDs[i]);
		TestNull(FString::Printf(TEXT("Removed item %d not found"), i), Found);
	}

	// Verify remaining items exist
	for (int32 i = 50; i < 100; ++i)
	{
		const FInventoryEntry* Found = Comp->FindEntryByID(IDs[i]);
		TestNotNull(FString::Printf(TEXT("Remaining item %d found"), i), Found);
	}

	return true;
}
RunTest method · cpp · L505-L528 (24 LOC)
Source/VaultCore/Private/Tests/VaultScenarioTests.cpp
bool FScenario_S2_StackMerge::RunTest(const FString& Parameters)
{
	// Test stacking mechanics: add items and verify total quantity is conserved.
	// TestAddItem creates separate entries (merging is Authority_AddItem behavior
	// that requires actor context). We verify the data structures support stacking.
	UInventoryManagerComponent* Comp = NewObject<UInventoryManagerComponent>();
	UItemDefinition* Def = CreateStackableDef(20);

	// Add 20 stacks of 5
	for (int32 i = 0; i < 20; ++i)
	{
		TestAddItem(Comp, Def, 5);
	}

	// Total quantity should be 100
	int32 TotalQty = TotalItemQuantity(Comp);
	TestEqual(TEXT("Total quantity is 100"), TotalQty, 100);

	// 20 separate entries (no merging without Authority context)
	TestEqual(TEXT("20 entries created"), Comp->GetEntryCount(), 20);

	return true;
}
RunTest method · cpp · L532-L550 (19 LOC)
Source/VaultCore/Private/Tests/VaultScenarioTests.cpp
bool FScenario_S2_InventoryFullRejection::RunTest(const FString& Parameters)
{
	UInventoryManagerComponent* Comp = NewObject<UInventoryManagerComponent>();
	UInventoryValidationSubsystem* V = NewObject<UInventoryValidationSubsystem>();

	// Fill to default capacity (40 slots)
	const UVaultSettings* Settings = UVaultSettings::Get();
	const int32 MaxSlots = Settings ? Settings->DefaultMaxInventorySlots : 40;
	PopulateInventory(Comp, MaxSlots);
	TestEqual(TEXT("At max capacity"), Comp->GetEntryCount(), MaxSlots);

	// Validate that capacity check fails
	FGameplayTag Result = V->CheckSlotCapacity(Comp);
	TestEqual(TEXT("SlotCapacity returns InventoryFull"),
		Result, FGameplayTag(VaultTags::Validation_Error_InventoryFull));

	return true;
}
‹ prevpage 5 / 10next ›