Skip to main content

Listing and reading files from Player Data Storage

You can store and retrieve per-user data in Player Data Storage using the User Cloud interface. You can't retrieve data of other players though; you can only access data of the locally signed in user.

Listing files stored in Player Data Storage

To interact with Player Data Storage, first get the user cloud interface:

#include "OnlineSubsystem.h"
#include "OnlineSubsystemUtils.h"

// ...
IOnlineSubsystem* Subsystem = Online::GetSubsystem(this->GetWorld());
IOnlineUserCloudPtr UserCloud = Subsystem->GetUserCloudInterface();

Register the event handler so you know when the enumeration has completed. EnumerateUserFilesDelegateHandle is declared as an FDelegateHandle.

this->EnumerateUserFilesDelegateHandle =
UserCloud->AddOnEnumerateUserFilesCompleteDelegate_Handle(FOnEnumerateUserFilesComplete::FDelegate::CreateUObject(
this,
&UMyClass::HandleEnumerateUserFilesComplete));

Then call EnumerateUserFiles using the player ID of the local user.

UserCloud->EnumerateUserFiles(*LocalUserId);

When your callback fires, you'll want to handle any errors (check bWasSuccessful), and then deregister the event handler:

void UMyClass::HandleEnumerateUserFilesComplete(
bool bWasSuccessful,
FUniqueNetId UserId)
{
// Deregister the event handler.
IOnlineSubsystem *Subsystem = Online::GetSubsystem(this->GetWorld());
IOnlineUserCloudPtr UserCloud = Subsystem->GetUserCloudInterface();
UserCloud->ClearOnEnumerateUserFilesCompleteDelegate_Handle(this->EnumerateUserFilesDelegateHandle);
this->EnumerateUserFilesDelegateHandle.Reset();

if (!bWasSuccessful)
{
// Enumeration didn't succeed, return error.
}
else
{
// Enumeration was successful, do something.
}
}

After enumeration succeeds, you can get a list of the user's files by calling GetUserFileList:

TArray<FCloudFileHeader> Files;
UserCloud->GetUserFileList(*LocalUserId, Files);
TArray<FString> FileNames;
FileNames.Reserve(Files.Num() - 1);
for (const auto& It : Files)
{
FileNames.Add(It.FileName);
}

Reading a file from Player Data Storage

When reading files from Player Data Storage, they might need to be transparently downloaded first, so reading files is an asynchronous operation.

First, register the event handler for when the file read is complete. ReadUserFileDelegateHandle is declared as an FDelegateHandle.

this->ReadUserFileDelegateHandle = 
UserCloud->AddOnReadUserFileCompleteDelegate_Handle(FOnReadUserFileComplete::FDelegate::CreateUObject(
this,
&UMyClass::ReadUserFileDelegateHandle));

Then call ReadUserFile using the local player's ID and the file's name.

if (!UserCloud->ReadUserFile(*UserId, FileName))
{
// Couldn't read user file, return error.
}

When your callback fires, you'll want to handle any errors (check bWasSuccessful), and then deregister the event handler:

void UMyClass::ReadUserFileDelegateHandle(
bool bWasSuccessful,
const FUniqueNetId &UserId,
const FString &FileName)
{
// Deregister the event handler.
IOnlineSubsystem *Subsystem = Online::GetSubsystem(this->GetWorld());
IOnlineUserCloudPtr UserCloud = Subsystem->GetUserCloudInterface();
UserCloud->ClearOnReadUserFileCompleteDelegate_Handle(this->ReadUserFileDelegateHandle);
this->ReadUserFileDelegateHandle.Reset();

if (!bWasSuccessful)
{
// Failed to read user file, return error.
}
else
{
TArray<uint8> FileContents;
if (!UserCloud->GetFileContents(UserId, FileName, FileContents))
{
// Failed to read user file, return error.
}
else
{
// The file data is in FileContents. If you wanted to read the file contents
// as a save game, you could so like this:
USaveGame *Data = UGameplayStatics::LoadGameFromMemory(FileContents);
}
}
}