Files
UnrealEngine/Engine/Plugins/Online/OnlineServicesOSSAdapter/Source/Private/Online/UserFileOSSAdapter.cpp
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

333 lines
9.6 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "Online/UserFileOSSAdapter.h"
#include "Interfaces/OnlineUserCloudInterface.h"
#include "Online/AuthOSSAdapter.h"
#include "Online/DelegateAdapter.h"
#include "Online/OnlineErrorDefinitions.h"
#include "Online/OnlineIdOSSAdapter.h"
#include "Online/OnlineServicesOSSAdapter.h"
#include "OnlineSubsystem.h"
namespace UE::Online {
void FUserFileOSSAdapter::PostInitialize()
{
Super::PostInitialize();
IOnlineSubsystem& SubsystemV1 = static_cast<FOnlineServicesOSSAdapter&>(Services).GetSubsystem();
UserCloudInterface = SubsystemV1.GetUserCloudInterface();
check(UserCloudInterface);
}
void FUserFileOSSAdapter::UpdateConfig()
{
Super::UpdateConfig();
LoadConfig(Config);
}
TOnlineAsyncOpHandle<FUserFileEnumerateFiles> FUserFileOSSAdapter::EnumerateFiles(FUserFileEnumerateFiles::Params&& InParams)
{
TOnlineAsyncOpRef<FUserFileEnumerateFiles> Op = GetOp<FUserFileEnumerateFiles>(MoveTemp(InParams));
Op->Then([this](TOnlineAsyncOp<FUserFileEnumerateFiles>& Op)
{
const FUniqueNetIdPtr LocalUserId = Services.Get<FAuthOSSAdapter>()->GetUniqueNetId(Op.GetParams().LocalAccountId);
if (!LocalUserId)
{
Op.SetError(Errors::InvalidUser());
return MakeFulfilledPromise<void>().GetFuture();
}
TPromise<void> Promise;
TFuture<void> Future = Promise.GetFuture();
MakeMulticastAdapter(this, UserCloudInterface->OnEnumerateUserFilesCompleteDelegates,
[WeakOp = Op.AsWeak(), Promise = MoveTemp(Promise), LocalUserId](bool bSuccess, const FUniqueNetId& UserId) mutable
{
const bool bThisUser = *LocalUserId == UserId;
if(bThisUser)
{
if (TOnlineAsyncOpPtr<FUserFileEnumerateFiles> Op = WeakOp.Pin())
{
if (!bSuccess)
{
Op->SetError(Errors::Unknown());
}
}
Promise.SetValue();
}
return bThisUser;
});
UserCloudInterface->EnumerateUserFiles(*LocalUserId);
return Future;
})
.Then([this](TOnlineAsyncOp<FUserFileEnumerateFiles>& Op)
{
const FUniqueNetIdPtr LocalUserId = Services.Get<FAuthOSSAdapter>()->GetUniqueNetId(Op.GetParams().LocalAccountId);
if (!LocalUserId)
{
Op.SetError(Errors::InvalidUser());
return;
}
TArray<FCloudFileHeader> FileList;
UserCloudInterface->GetUserFileList(*LocalUserId, FileList);
TArray<FString> NewEnumeratedFiles;
NewEnumeratedFiles.Reserve(FileList.Num());
for (const FCloudFileHeader& File : FileList)
{
NewEnumeratedFiles.Emplace(File.FileName);
}
EnumeratedFiles.Emplace(Op.GetParams().LocalAccountId, MoveTemp(NewEnumeratedFiles));
Op.SetResult({});
})
.Enqueue(GetSerialQueue());
return Op->GetHandle();
}
TOnlineResult<FUserFileGetEnumeratedFiles> FUserFileOSSAdapter::GetEnumeratedFiles(FUserFileGetEnumeratedFiles::Params&& Params)
{
const FUniqueNetIdPtr LocalUserId = Services.Get<FAuthOSSAdapter>()->GetUniqueNetId(Params.LocalAccountId);
if (!LocalUserId)
{
return TOnlineResult<FUserFileGetEnumeratedFiles>(Errors::InvalidUser());
}
const TArray<FString>* UserFiles = EnumeratedFiles.Find(Params.LocalAccountId);
if (!UserFiles)
{
// Call EnumerateFiles first
return TOnlineResult<FUserFileGetEnumeratedFiles>(Errors::InvalidState());
}
return TOnlineResult<FUserFileGetEnumeratedFiles>({ *UserFiles });
}
TOnlineAsyncOpHandle<FUserFileReadFile> FUserFileOSSAdapter::ReadFile(FUserFileReadFile::Params&& InParams)
{
static const TCHAR* FileContentsKey = TEXT("FileContents");
TOnlineAsyncOpRef<FUserFileReadFile> Op = GetOp<FUserFileReadFile>(MoveTemp(InParams));
const FUserFileReadFile::Params& Params = Op->GetParams();
if (Params.Filename.IsEmpty())
{
Op->SetError(Errors::InvalidParams());
return Op->GetHandle();
}
Op->Then([this](TOnlineAsyncOp<FUserFileReadFile>& Op)
{
const FUserFileReadFile::Params& Params = Op.GetParams();
const FUniqueNetIdPtr LocalUserId = Services.Get<FAuthOSSAdapter>()->GetUniqueNetId(Params.LocalAccountId);
if (!LocalUserId)
{
Op.SetError(Errors::InvalidUser());
return MakeFulfilledPromise<void>().GetFuture();
}
// First just try and read the file contents, if this succeeds we can return immediately.
TArray<uint8> FileContents;
if (UserCloudInterface->GetFileContents(*LocalUserId, Params.Filename, FileContents))
{
FUserFileContentsRef FileContentsRef = MakeShared<FUserFileContents>(MoveTemp(FileContents));
Op.SetResult({FileContentsRef});
return MakeFulfilledPromise<void>().GetFuture();
}
TPromise<void> Promise;
TFuture<void> Future = Promise.GetFuture();
MakeMulticastAdapter(this, UserCloudInterface->OnReadUserFileCompleteDelegates,
[WeakOp = Op.AsWeak(), Promise = MoveTemp(Promise), LocalUserId, Filename = Params.Filename](bool bSuccess, const FUniqueNetId& UserId, const FString& InFilename) mutable
{
const bool bThisUser = *LocalUserId == UserId;
const bool bThisFile = Filename == InFilename;
const bool bThis = bThisUser && bThisFile;
if (bThis)
{
if (TOnlineAsyncOpPtr<FUserFileReadFile> Op = WeakOp.Pin())
{
if (!bSuccess)
{
Op->SetError(Errors::Unknown());
}
}
Promise.SetValue();
}
return bThis;
});
if (!UserCloudInterface->ReadUserFile(*LocalUserId, Params.Filename))
{
Op.SetError(Errors::Unknown());
return MakeFulfilledPromise<void>().GetFuture();
}
return Future;
})
.Then([this](TOnlineAsyncOp<FUserFileReadFile>& Op)
{
const FUserFileReadFile::Params& Params = Op.GetParams();
const FUniqueNetIdPtr LocalUserId = Services.Get<FAuthOSSAdapter>()->GetUniqueNetId(Params.LocalAccountId);
if (!LocalUserId)
{
Op.SetError(Errors::InvalidUser());
return;
}
TArray<uint8> FileContents;
if (UserCloudInterface->GetFileContents(*LocalUserId, Params.Filename, FileContents))
{
FUserFileContentsRef FileContentsRef = MakeShared<FUserFileContents>(MoveTemp(FileContents));
Op.SetResult({ FileContentsRef });
}
else
{
Op.SetError(Errors::Unknown());
}
})
.Enqueue(GetSerialQueue());
return Op->GetHandle();
}
TOnlineAsyncOpHandle<FUserFileWriteFile> FUserFileOSSAdapter::WriteFile(FUserFileWriteFile::Params&& InParams)
{
TOnlineAsyncOpRef<FUserFileWriteFile> Op = GetOp<FUserFileWriteFile>(MoveTemp(InParams));
const FUserFileWriteFile::Params& Params = Op->GetParams();
if (Params.Filename.IsEmpty())
{
Op->SetError(Errors::InvalidParams());
return Op->GetHandle();
}
Op->Then([this](TOnlineAsyncOp<FUserFileWriteFile>& Op)
{
const FUserFileWriteFile::Params& Params = Op.GetParams();
const FUniqueNetIdPtr LocalUserId = Services.Get<FAuthOSSAdapter>()->GetUniqueNetId(Params.LocalAccountId);
if (!LocalUserId)
{
Op.SetError(Errors::InvalidUser());
return MakeFulfilledPromise<void>().GetFuture();
}
TPromise<void> Promise;
TFuture<void> Future = Promise.GetFuture();
MakeMulticastAdapter(this, UserCloudInterface->OnWriteUserFileCompleteDelegates,
[WeakOp = Op.AsWeak(), Promise = MoveTemp(Promise), LocalUserId, Filename = Params.Filename](bool bSuccess, const FUniqueNetId& UserId, const FString& InFilename) mutable
{
const bool bThisUser = *LocalUserId == UserId;
const bool bThisFile = Filename == InFilename;
const bool bThis = bThisUser && bThisFile;
if (bThis)
{
if (TOnlineAsyncOpPtr<FUserFileWriteFile> Op = WeakOp.Pin())
{
if (bSuccess)
{
Op->SetResult({});
}
else
{
Op->SetError(Errors::Unknown());
}
}
Promise.SetValue();
}
return bThis;
});
// WriteUserFile takes a non-const ref, not sure why.
FUserFileContents& FileContents = const_cast<FUserFileContents&>(Params.FileContents);
if (!UserCloudInterface->WriteUserFile(*LocalUserId, Params.Filename, FileContents, Config.bCompressBeforeUpload))
{
Op.SetError(Errors::Unknown());
return MakeFulfilledPromise<void>().GetFuture();
}
return Future;
})
.Enqueue(GetSerialQueue());
return Op->GetHandle();
}
TOnlineAsyncOpHandle<FUserFileDeleteFile> FUserFileOSSAdapter::DeleteFile(FUserFileDeleteFile::Params&& InParams)
{
TOnlineAsyncOpRef<FUserFileDeleteFile> Op = GetOp<FUserFileDeleteFile>(MoveTemp(InParams));
const FUserFileDeleteFile::Params& Params = Op->GetParams();
if (Params.Filename.IsEmpty())
{
Op->SetError(Errors::InvalidParams());
return Op->GetHandle();
}
Op->Then([this](TOnlineAsyncOp<FUserFileDeleteFile>& Op)
{
const FUserFileDeleteFile::Params& Params = Op.GetParams();
const FUniqueNetIdPtr LocalUserId = Services.Get<FAuthOSSAdapter>()->GetUniqueNetId(Params.LocalAccountId);
if (!LocalUserId)
{
Op.SetError(Errors::InvalidUser());
return MakeFulfilledPromise<void>().GetFuture();
}
TPromise<void> Promise;
TFuture<void> Future = Promise.GetFuture();
MakeMulticastAdapter(this, UserCloudInterface->OnDeleteUserFileCompleteDelegates,
[WeakOp = Op.AsWeak(), Promise = MoveTemp(Promise), LocalUserId, Filename = Params.Filename](bool bSuccess, const FUniqueNetId& UserId, const FString& InFilename) mutable
{
const bool bThisUser = *LocalUserId == UserId;
const bool bThisFile = Filename == InFilename;
const bool bThis = bThisUser && bThisFile;
if (bThis)
{
if (TOnlineAsyncOpPtr<FUserFileDeleteFile> Op = WeakOp.Pin())
{
if (bSuccess)
{
Op->SetResult({});
}
else
{
Op->SetError(Errors::Unknown());
}
}
Promise.SetValue();
}
return bThis;
});
const bool bShouldCloudDelete = true;
const bool bShouldLocallyDelete = true;
if (!UserCloudInterface->DeleteUserFile(*LocalUserId, Params.Filename, bShouldCloudDelete, bShouldLocallyDelete))
{
Op.SetError(Errors::Unknown());
return MakeFulfilledPromise<void>().GetFuture();
}
return Future;
})
.Enqueue(GetSerialQueue());
return Op->GetHandle();
}
/* UE::Online */ }