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
FOnlineWalletAccelByteinterface, which provides access to AGS Software Development Kit (SDK) features.
private:
FOnlineWalletV2AccelBytePtr WalletInterface;
void UWalletEssentialsSubsystem_Starter::Initialize(FSubsystemCollectionBase& Collection)
{
// ...
const FOnlineSubsystemAccelByte* Subsystem = static_cast<FOnlineSubsystemAccelByte*>(Online::GetSubsystem(GetWorld()));
ensure(Subsystem);
WalletInterface = Subsystem->GetWalletV2Interface();
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 FAccelByteModelsWalletInfoResponse& /*Response*/);
Implement query wallet info
-
Open the
WalletEssentialsSubsystem_Starterheader 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 FAccelByteModelsWalletInfoResponse& Response,
const FString& Error) const; -
Go to the
WalletEssentialsSubsystem_StarterCPP 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->GetWalletInfoByCurrencyCodeV2(LocalUserNum, CurrencyCode, bAlwaysRequestToService);
} -
Implement the
OnQueryOrGetWalletInfoByCurrencyCodeComplete()function, which triggers theOnQueryOrGetWalletInfoCompleteDelegatesdelegate using the data from the backend response.void UWalletEssentialsSubsystem_Starter::OnQueryOrGetWalletInfoByCurrencyCodeComplete(
int32 LocalUserNum,
bool bWasSuccessful,
const FAccelByteModelsWalletInfoResponse& 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 theFOnlineWalletAccelByteinterface.void UWalletEssentialsSubsystem_Starter::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
const FOnlineSubsystemAccelByte* Subsystem = static_cast<FOnlineSubsystemAccelByte*>(Online::GetSubsystem(GetWorld()));
ensure(Subsystem);
WalletInterface = Subsystem->GetWalletV2Interface();
ensure(WalletInterface);
WalletInterface->OnGetWalletInfoV2CompletedDelegates->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->OnGetWalletInfoV2CompletedDelegates->RemoveAll(this);
}
Resources
- The files used in this tutorial section are available in the Byte Wars GitHub repository.