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

265 lines
7.8 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "Online/LeaderboardsOSSAdapter.h"
#include "Online/AuthOSSAdapter.h"
#include "Online/DelegateAdapter.h"
#include "Online/ErrorsOSSAdapter.h"
#include "Online/OnlineServicesOSSAdapter.h"
#include "Online/OnlineIdOSSAdapter.h"
#include "Online/OnlineErrorDefinitions.h"
#include "OnlineSubsystem.h"
#include "Interfaces/OnlineIdentityInterface.h"
namespace UE::Online {
void FLeaderboardsOSSAdapter::PostInitialize()
{
Super::PostInitialize();
Auth = Services.Get<FAuthOSSAdapter>();
LeaderboardsInterface = static_cast<FOnlineServicesOSSAdapter&>(Services).GetSubsystem().GetLeaderboardsInterface();
check(LeaderboardsInterface);
}
TOnlineAsyncOpHandle<FReadEntriesForUsers> FLeaderboardsOSSAdapter::ReadEntriesForUsers(FReadEntriesForUsers::Params&& Params)
{
TOnlineAsyncOpRef<FReadEntriesForUsers> Op = GetOp<FReadEntriesForUsers>(MoveTemp(Params));
Op->Then([this](TOnlineAsyncOp<FReadEntriesForUsers>& Op)
{
const FUniqueNetIdPtr LocalUniqueNetId = Auth->GetUniqueNetId(Op.GetParams().LocalAccountId);
if (!LocalUniqueNetId)
{
Op.SetError(Errors::InvalidUser());
return MakeFulfilledPromise<void>().GetFuture();
}
if (Op.GetParams().AccountIds.IsEmpty() || Op.GetParams().BoardName.IsEmpty())
{
Op.SetError(Errors::InvalidParams());
return MakeFulfilledPromise<void>().GetFuture();
}
TArray<FUniqueNetIdRef> NetIds;
for (const FAccountId& AccountId : Op.GetParams().AccountIds)
{
const FUniqueNetIdPtr UniqueNetId = Auth->GetUniqueNetId(AccountId);
if (!UniqueNetId)
{
UE_LOG(LogOnlineServices, Warning, TEXT("Failed to get unique net id for user %s"), *ToLogString(AccountId));
Op.SetError(Errors::InvalidUser());
return MakeFulfilledPromise<void>().GetFuture();
}
NetIds.Add(UniqueNetId.ToSharedRef());
}
if (TOptional<FOnlineError> OnlineError = PrepareLeaderboardReadObject(Op.GetParams().BoardName))
{
Op.SetError(MoveTemp(OnlineError.GetValue()));
return MakeFulfilledPromise<void>().GetFuture();
}
TPromise<void> Promise;
TFuture<void> Future = Promise.GetFuture();
MakeMulticastAdapter(this, LeaderboardsInterface->OnLeaderboardReadCompleteDelegates,
[this, WeakOp = Op.AsWeak(), Promise = MoveTemp(Promise)](bool bSuccess) mutable
{
if (TOnlineAsyncOpPtr<FReadEntriesForUsers> Op = WeakOp.Pin())
{
if (!bSuccess)
{
ReadObject.Reset();
Op->SetError(Errors::Unknown());
}
else
{
FReadEntriesForUsers::Result Result;
ReadLeaderboardsResultFromV1ToV2(Op->GetParams().BoardName, Result.Entries);
Op->SetResult(MoveTemp(Result));
}
}
Promise.SetValue();
});
FOnlineLeaderboardReadRef ReadObjectRef = ReadObject.ToSharedRef();
if (!LeaderboardsInterface->ReadLeaderboards(NetIds, ReadObjectRef))
{
Op.SetError(Errors::Unknown());
return MakeFulfilledPromise<void>().GetFuture();
}
return Future;
})
.Enqueue(GetSerialQueue());
return Op->GetHandle();
}
TOnlineAsyncOpHandle<FReadEntriesAroundRank> FLeaderboardsOSSAdapter::ReadEntriesAroundRank(FReadEntriesAroundRank::Params&& Params)
{
TOnlineAsyncOpRef<FReadEntriesAroundRank> Op = GetOp<FReadEntriesAroundRank>(MoveTemp(Params));
Op->Then([this](TOnlineAsyncOp<FReadEntriesAroundRank>& Op)
{
const FUniqueNetIdPtr LocalUserId = Auth->GetUniqueNetId(Op.GetParams().LocalAccountId);
if (!LocalUserId)
{
Op.SetError(Errors::InvalidUser());
return MakeFulfilledPromise<void>().GetFuture();
}
if (Op.GetParams().Limit == 0 || Op.GetParams().BoardName.IsEmpty())
{
Op.SetError(Errors::InvalidParams());
return MakeFulfilledPromise<void>().GetFuture();
}
if (TOptional<FOnlineError> OnlineError = PrepareLeaderboardReadObject(Op.GetParams().BoardName))
{
Op.SetError(MoveTemp(OnlineError.GetValue()));
return MakeFulfilledPromise<void>().GetFuture();
}
TPromise<void> Promise;
TFuture<void> Future = Promise.GetFuture();
MakeMulticastAdapter(this, LeaderboardsInterface->OnLeaderboardReadCompleteDelegates,
[this, WeakOp = Op.AsWeak(), Promise = MoveTemp(Promise)](bool bSuccess) mutable
{
if (TOnlineAsyncOpPtr<FReadEntriesAroundRank> Op = WeakOp.Pin())
{
if (!bSuccess)
{
ReadObject.Reset();
Op->SetError(Errors::Unknown());
}
else
{
FReadEntriesAroundRank::Result Result;
ReadLeaderboardsResultFromV1ToV2(Op->GetParams().BoardName, Result.Entries);
Op->SetResult(MoveTemp(Result));
}
}
Promise.SetValue();
});
FOnlineLeaderboardReadRef ReadObjectRef = ReadObject.ToSharedRef();
if (!LeaderboardsInterface->ReadLeaderboardsAroundRank(Op.GetParams().Rank, Op.GetParams().Limit, ReadObjectRef))
{
Op.SetError(Errors::Unknown());
return MakeFulfilledPromise<void>().GetFuture();
}
return Future;
})
.Enqueue(GetSerialQueue());
return Op->GetHandle();
}
TOnlineAsyncOpHandle<FReadEntriesAroundUser> FLeaderboardsOSSAdapter::ReadEntriesAroundUser(FReadEntriesAroundUser::Params&& Params)
{
TOnlineAsyncOpRef<FReadEntriesAroundUser> Op = GetOp<FReadEntriesAroundUser>(MoveTemp(Params));
Op->Then([this](TOnlineAsyncOp<FReadEntriesAroundUser>& Op)
{
const FUniqueNetIdPtr LocalUserId = Auth->GetUniqueNetId(Op.GetParams().LocalAccountId);
if (!LocalUserId)
{
Op.SetError(Errors::InvalidUser());
return MakeFulfilledPromise<void>().GetFuture();
}
const FUniqueNetIdPtr TargetUniqueNetId = Auth->GetUniqueNetId(Op.GetParams().AccountId);
if (!TargetUniqueNetId)
{
Op.SetError(Errors::InvalidUser());
return MakeFulfilledPromise<void>().GetFuture();
}
if (Op.GetParams().Limit == 0 || Op.GetParams().BoardName.IsEmpty())
{
Op.SetError(Errors::InvalidParams());
return MakeFulfilledPromise<void>().GetFuture();
}
if (TOptional<FOnlineError> OnlineError = PrepareLeaderboardReadObject(Op.GetParams().BoardName))
{
Op.SetError(MoveTemp(OnlineError.GetValue()));
return MakeFulfilledPromise<void>().GetFuture();
}
TPromise<void> Promise;
TFuture<void> Future = Promise.GetFuture();
MakeMulticastAdapter(this, LeaderboardsInterface->OnLeaderboardReadCompleteDelegates,
[this, WeakOp = Op.AsWeak(), Promise = MoveTemp(Promise)](bool bSuccess) mutable
{
if (TOnlineAsyncOpPtr<FReadEntriesAroundUser> Op = WeakOp.Pin())
{
if (!bSuccess)
{
ReadObject.Reset();
Op->SetError(Errors::Unknown());
}
else
{
FReadEntriesAroundUser::Result Result;
ReadLeaderboardsResultFromV1ToV2(Op->GetParams().BoardName, Result.Entries);
Op->SetResult(MoveTemp(Result));
}
}
Promise.SetValue();
});
FOnlineLeaderboardReadRef ReadObjectRef = ReadObject.ToSharedRef();
if (!LeaderboardsInterface->ReadLeaderboardsAroundUser(TargetUniqueNetId.ToSharedRef(), Op.GetParams().Limit, ReadObjectRef))
{
Op.SetError(Errors::Unknown());
return MakeFulfilledPromise<void>().GetFuture();
}
return Future;
})
.Enqueue(GetSerialQueue());
return Op->GetHandle();
}
TOptional<FOnlineError> FLeaderboardsOSSAdapter::PrepareLeaderboardReadObject(const FString& BoardName)
{
TOptional<FOnlineError> OnlineError;
if (ReadObject)
{
OnlineError = Errors::AlreadyPending();
}
else
{
ReadObject = MakeShareable(new FOnlineLeaderboardRead());
ReadObject->SortedColumn = BoardName;
ReadObject->LeaderboardName = BoardName;
}
return OnlineError;
}
void FLeaderboardsOSSAdapter::ReadLeaderboardsResultFromV1ToV2(const FString& BoardName, TArray<FLeaderboardEntry>& OutEntries)
{
for (const FOnlineStatsRow& OnlineStatsRow : ReadObject->Rows)
{
const FVariantData* VariantData = OnlineStatsRow.Columns.Find(*BoardName);
FLeaderboardEntry& LeaderboardEntry = OutEntries.Emplace_GetRef();
LeaderboardEntry.AccountId = Auth->GetAccountId(OnlineStatsRow.PlayerId.ToSharedRef());
LeaderboardEntry.Rank = OnlineStatsRow.Rank;
VariantData->GetValue(LeaderboardEntry.Score);
}
ReadObject.Reset();
}
/* UE::Online */ }