Implement Subsystem - Wallet Essentials - (Unreal Engine module)
Unwrap the subsystem
Byte Wars uses a Game Instance Subsystem called WalletEssentialsSubsystem
to wrap the AccelByte Gaming Services (AGS) Online Subsystem (OSS). This subsystem utilizes the FOnlineWalletAccelByte
provided by the AGS OSS. In this tutorial, you'll work with a starter version of the subsystem, allowing you to implement the required functions from scratch.
What's in the Starter Pack
To follow along with this tutorial, a starter subsystem class named WalletEssentialsSubsystem_Starter
has been prepared. You can find it in the Resources section. It includes the following files:
- Header file:
Source/AccelByteWars/TutorialModules/Monetization/WalletEssentials/WalletEssentialsSubsystem_Starter.h
- CPP file:
Source/AccelByteWars/TutorialModules/Monetization/WalletEssentials/WalletEssentialsSubsystem_Starter.cpp
The WalletEssentialsSubsystem_Starter
class includes several helpful components:
- Declaration and initialization of the AGS OSS
FOnlineWalletAccelByte
interface, which provides access to AGS Software Development Kit (SDK) features.
private:
FOnlineWalletAccelBytePtr WalletInterface;
void UWalletEssentialsSubsystem_Starter::Initialize(FSubsystemCollectionBase& Collection)
{
// ...
const FOnlineSubsystemAccelByte* Subsystem = static_cast<FOnlineSubsystemAccelByte*>(Online::GetSubsystem(GetWorld()));
ensure(Subsystem);
WalletInterface = Subsystem->GetWalletInterface();
ensure(WalletInterface);
// ...
}
- A helper function for retrieving the local user number from a Player Controller. This is necessary because widgets, the primary users of this subsystem, use Player Controllers to reference players, while the OSS interface requires a local user number to identify the requesting user.
private:
// ...
static int32 GetLocalUserNumFromPlayerController(const APlayerController* PlayerController);
Additionally, there is a model file Source/AccelByteWars/TutorialModules/Monetization/WalletEssentials/WalletEssentialsModel.h
that defines the delegates used to handle backend responses, along with a predefined localized text that displays when the subsystem fails to retrieve the data.
#define TEXT_BALANCE_ERROR NSLOCTEXT("AccelByteWars", "balance_error", "NaN")
DECLARE_MULTICAST_DELEGATE_TwoParams(FOnGetWalletInfoComplete, bool /*bWasSuccessful*/, const FAccelByteModelsWalletInfo& /*Response*/);
Implement query wallet info
-
Open the
WalletEssentialsSubsystem_Starter
header file and declare the following function to request the wallet information from the backend.public:
void QueryOrGetWalletInfoByCurrencyCode(
const APlayerController* OwningPlayer,
const FString& CurrencyCode,
const bool bAlwaysRequestToService = true) const; -
Declare the following delegate and handler function to process the backend response.
public:
// ...
FOnGetWalletInfoComplete OnQueryOrGetWalletInfoCompleteDelegates;private:
// ...
void OnQueryOrGetWalletInfoByCurrencyCodeComplete(
int32 LocalUserNum,
bool bWasSuccessful,
const FAccelByteModelsWalletInfo& Response,
const FString& Error) const; -
Go to the
WalletEssentialsSubsystem_Starter
CPP file and implement theQueryOrGetWalletInfoByCurrencyCode()
function. This function sends a request to retrieve the player's wallet information.void UWalletEssentialsSubsystem_Starter::QueryOrGetWalletInfoByCurrencyCode(
const APlayerController* OwningPlayer,
const FString& CurrencyCode,
const bool bAlwaysRequestToService) const
{
const int32 LocalUserNum = GetLocalUserNumFromPlayerController(OwningPlayer);
WalletInterface->GetWalletInfoByCurrencyCode(LocalUserNum, CurrencyCode, bAlwaysRequestToService);
} -
Implement the
OnQueryOrGetWalletInfoByCurrencyCodeComplete()
function, which triggers theOnQueryOrGetWalletInfoCompleteDelegates
delegate using the data from the backend response.void UWalletEssentialsSubsystem_Starter::OnQueryOrGetWalletInfoByCurrencyCodeComplete(
int32 LocalUserNum,
bool bWasSuccessful,
const FAccelByteModelsWalletInfo& Response,
const FString& Error) const
{
OnQueryOrGetWalletInfoCompleteDelegates.Broadcast(bWasSuccessful, Response);
} -
Still in the CPP file, navigate to the
Initialize()
function and replace its contents with the following code. This binds theOnQueryOrGetWalletInfoByCurrencyCodeComplete()
function to the actual response delegate in theFOnlineWalletAccelByte
interface.void UWalletEssentialsSubsystem_Starter::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
const FOnlineSubsystemAccelByte* Subsystem = static_cast<FOnlineSubsystemAccelByte*>(Online::GetSubsystem(GetWorld()));
ensure(Subsystem);
WalletInterface = Subsystem->GetWalletInterface();
ensure(WalletInterface);
WalletInterface->OnGetWalletInfoCompletedDelegates->AddUObject(this, &ThisClass::OnQueryOrGetWalletInfoByCurrencyCodeComplete);
} -
Navigate to the
Deinitialize()
function and replace its contents with the following code. This unbinds theOnQueryOrGetWalletInfoByCurrencyCodeComplete()
function.void UWalletEssentialsSubsystem_Starter::Deinitialize()
{
Super::Deinitialize();
WalletInterface->OnGetWalletInfoCompletedDelegates->RemoveAll(this);
}
Resources
- The files used in this tutorial section are available in the Byte Wars GitHub repository.