Implement Lobby with Unreal Engine SDK
Introduction
This topic is specific to the AccelByte Gaming Services (AGS) Shared Cloud tier.
AccelByte Gaming Services (AGS) Lobby provides a continuous connection between your game and its players by using WebSockets. This article will show you how to implement Lobby into your Unreal Engine game using the AGS Game SDK for the AGS Shared Cloud tier.
Prerequisites
To complete the steps in this article, you need to:
Implement AGS Authentication into your game, ensuring it works properly.
Set up your own Lobby Configurations in the AGS Admin Portal.
Quick Reference
References
#include "OnlineIdentityInterfaceAccelByte.h"
Lobby connect notification events
IdentityInterface->AddAccelByteOnConnectLobbyCompleteDelegate_Handle(USER_LOCAL_NUM
, FAccelByteOnConnectLobbyCompleteDelegate::CreateLambda([](int32 LocalUserNum, bool bWasSuccessful, const FUniqueNetId& UserId, const FOnlineErrorAccelByte& Error)
{
// Lobby connection attempt finished. Check bWasSuccessful for result.
}));
IdentityInterface->AddAccelByteOnLobbyConnectionClosedDelegate_Handle(USER_LOCAL_NUM
, FAccelByteOnLobbyConnectionClosedDelegate::CreateLambda([](int32 LocalUserNum, const FUniqueNetId& UserId, int32 StatusCode, const FString& Reason, bool bWasClean)
{
// Lobby connection closed
}));
IdentityInterface->AddAccelByteOnLobbyReconnectingDelegate_Handle(USER_LOCAL_NUM
, FAccelByteOnLobbyReconnectingDelegate::CreateLambda([](int32 LocalUserNum, const FUniqueNetId& UserId, int32 StatusCode, const FString& Reason, bool bWasClean)
{
// Lobby is reconnecting
}));
IdentityInterface->AddAccelByteOnLobbyReconnectedDelegate_Handle(0
, FAccelByteOnLobbyReconnectedDelegate::CreateLambda([]()
{
// Lobby Reconnected
}));
Lobby connect
IdentityInterface->AddAccelByteOnConnectLobbyCompleteDelegate_Handle(USER_LOCAL_NUM
, FAccelByteOnConnectLobbyCompleteDelegate::CreateLambda([](int32 LocalUserNum, bool bWasSuccessful, const FUniqueNetId& UserId, const FOnlineErrorAccelByte& Error)
{
// Lobby connection attempt finished. Check bWasSuccessful for result.
}));
IdentityInterface->ConnectAccelByteLobby(USER_LOCAL_NUM);
Lobby disconnect
IdentityInterface->AddAccelByteOnLobbyConnectionClosedDelegate_Handle(USER_LOCAL_NUM
, FAccelByteOnLobbyConnectionClosedDelegate::CreateLambda([](int32 LocalUserNum, const FUniqueNetId& UserId, int32 StatusCode, const FString& Reason, bool bWasClean)
{
// Lobby connection closed
}));
IdentityInterface->GetApiClient(USER_LOCAL_NUM)->Lobby.Disconnect();
Check if Lobby is connected
IdentityInterface->GetApiClient(USER_LOCAL_NUM)->Lobby.IsConnected();
AGS Online Subsystem Configurations for Lobby
Below are the available configurations that can be enabled in your project's DefaultEngine.ini
file.
Section | Configuration Key | Value Type | Details |
---|---|---|---|
[OnlineSubsystemAccelByte] | bAutoLobbyConnectAfterLoginSuccess | boolean | Set to true to automatically connect to Lobby after user has logged in to AGS |
[Core.Log] | LogAccelByteLobby | LogVerbosity | Set to VeryVerbose for debugging |
[Core.Log] | LogWebSockets | LogVerbosity | Set to VeryVerbose for debugging |
Quick start
In this section, you will learn how to use AGS Lobby for the AGS Shared Cloud tier.
Create a user widget C++ class called
AccelByteLobby
to specify the flow between functions when creating a Lobby menu.Add the AccelByte header to ensure the functions work correctly for AGS Lobby:
. . .
#include "OnlineIdentityInterfaceAccelByte.h"
. . .Create a new function called
SetLobbyNotificationDelegate()
to notify the player when the Lobby connection is updated. Once completed, put all the lobby-related delegates inside it. These delegates include:Delegates Response AddAccelByteOnConnectLobbyCompleteDelegate_Handle
Lobby connect attemp completed AddAccelByteOnLobbyConnectionClosedDelegate_Handle
Lobby disconnected AddAccelByteOnLobbyReconnectingDelegate_Handle
Lobby reconnecting noteAlthough you make reference to AGS Lobby, it is not yet connected. For now, you will just add debug logs to notify you of any updates after calling the references.
After you have added the delegates, the function should look like this:
- .cpp
- .h
void UAccelByteLobby::SetLobbyNotificationDelegate()
{
IdentityInterface->AddAccelByteOnConnectLobbyCompleteDelegate_Handle(USER_LOCAL_NUM
, FAccelByteOnConnectLobbyCompleteDelegate::CreateLambda([](int32 LocalUserNum, bool bWasSuccessful, const FUniqueNetId& UserId, const FOnlineErrorAccelByte& Error)
{
if (bWasSuccessful)
{
UE_LOG(LogTemp, Log, TEXT("Successfully Connected to Lobby"));
}
else
{
UE_LOG(LogTemp, Error, TEXT("Failed Connect to Lobby. Code: %s, Reason: %s"), *Error.ErrorCode, *Error.ErrorMessage.ToString());
}
}));
IdentityInterface->AddAccelByteOnLobbyConnectionClosedDelegate_Handle(USER_LOCAL_NUM
, FAccelByteOnLobbyConnectionClosedDelegate::CreateLambda([](int32 LocalUserNum, const FUniqueNetId& UserId, int32 StatusCode, const FString& Reason, bool bWasClean)
{
UE_LOG(LogTemp, Error, TEXT("Lobby disconnected. Code: %d, Message: %s"), StatusCode, *Reason);
}));
IdentityInterface->AddAccelByteOnLobbyReconnectingDelegate_Handle(USER_LOCAL_NUM
, FAccelByteOnLobbyReconnectingDelegate::CreateLambda([](int32 LocalUserNum, const FUniqueNetId& UserId, int32 StatusCode, const FString& Reason, bool bWasClean)
{
UE_LOG(LogTemp, Error, TEXT("Lobby is reconnecting"));
}));
IdentityInterface->AddAccelByteOnLobbyReconnectedDelegate_Handle(0
, FAccelByteOnLobbyReconnectedDelegate::CreateLambda([]()
{
UE_LOG(LogTemp, Error, TEXT("Lobby reconnected"));
}));
}/**
* @brief Set Lobby services notification delegates.
*/
void SetLobbyNotificationDelegate();Create a new function called
ConnectToLobby()
. This will be triggered after login is successful and will open a WebSocket that sets delegates to receive responses after requesting a connection to Lobby by callingSetLobbyNotificationDelegate()
.- .cpp
- .h
void UAccelByteLobby::ConnectToLobby()
{
SetLobbyNotificationDelegate();
IdentityInterface->ConnectAccelByteLobby(USER_LOCAL_NUM);
}/**
* @brief Connect to AGS Lobby.
*/
UFUNCTION()
void ConnectToLobby();Test your code and ensure there are no errors.
After successfully connecting to AGS Lobby, you can move to AccelByteAuth.cpp and add a call to the
IdentityInterface->ConnectAccelByteLobby()
function on the success delegate fromLoginWithUsername()
. You can findLoginWithUsername()
insideOnLoginButtonClicked()
.Test the function by triggering
OnLoginButtonClicked()
.void UAccelByteAuth::OnLoginButtonClicked()
{
...
FVoidHandler::CreateWeakLambda(this, []()
{
UE_LOG(LogTemp, Log, TEXT("Login success"));
IdentityInterface->ConnectAccelByteLobby(USER_LOCAL_NUM);
if (IdentityInterface->GetApiClient(USER_LOCAL_NUM)->Lobby.IsConnected())
{
UE_LOG(LogTemp, Log, TEXT("Lobby is connected!"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("Lobby is not connected!"));
}
}),
...
}If you have configured your code correctly, you will see the message Lobby is connected! after logging in.
noteIf Lobby is not connected successfully, check your game project configuration and make sure the user is logged in. As long as Lobby is connected, you can use all the features available in AGS Lobby.
OPTIONAL: By default, if you quit your application, you are automatically disconnected from Lobby. To manually disconnect without closing the application, use the
OnLogoutButtonClicked()
function inAccelByteAuth.cpp
.void UAccelByteAuth::OnLogoutButtonClicked()
{
...
IdentityInterface->GetApiClient(USER_LOCAL_NUM)->Lobby.Disconnect()
...
}
Congratulations! You have successfully connected to Lobby.
Continue with this article for a step-by-step guide for UI and code implementation. Otherwise, proceed to AGS Friends implementation for AGS Shared Cloud tier.
Step-by-step guide
Follow these step-by-step instructions to implement AGS Lobby for AGS Shared Cloud tier.
Implement the user interface
The following steps are optional, as AGS Lobby can run without any widgets implemented.
In this section, you will implement the heads-up display (HUD) to get the Lobby class reference. This means you need to create a Lobby Menu widget, but for now, you can leave it empty.
Create an empty widget blueprint class called
WB_LobbyMenu
.Assign
AccelByteLobby
as the parent class of theWB_LobbyMenu
.
Implement the code
In this section, you will change between the Login and Lobby widgets using a HUD.
TutorialMenuHUD
Create a HUD Blueprint class called
BP_TutorialHUD
.Create a HUD C++ class called
TutorialMenuHUD
and add the class as a parent class forBP_TutorialHUD
.Open the
TutorialMenuHUD
class and add the following headers at the top of the class:- .cpp
- .h
...
#include "AccelByte/Authentication/AccelByteAuth.h"
#include "OnlineIdentityInterfaceAccelByte.h"...
class UAccelByteAuth;
class UAccelByteLobby;
...Add the
BeginPlay()
function to check and set all of your class pointers.- .cpp
- .h
void ATutorialMenuHUD::BeginPlay()
{
Super::BeginPlay();
APlayerController* PlayerController = GetOwningPlayerController();
check(LoginMenuClass != nullptr);
check(LobbyMenuClass != nullptr);
LoginMenu = CreateWidget<UAccelByteAuth>(PlayerController, LoginMenuClass.Get());
LobbyMenu = CreateWidget<UAccelByteLobby>(PlayerController, LobbyMenuClass.Get());
}virtual void BeginPlay() override;
/**
* @brief Login menu widget class
*/
UPROPERTY(EditDefaultsOnly)
TSubclassOf<UAccelByteAuth> LoginMenuClass;
/**
* @brief Lobby menu widget class
*/
UPROPERTY(EditDefaultsOnly)
TSubclassOf<UAccelByteLobby> LobbyMenuClass;
/**
* @brief Login menu widget pointer
*/
UPROPERTY()
UAccelByteAuth* LoginMenu;
/**
* @brief Lobby Menu widget pointer
*/
UPROPERTY()
UAccelByteLobby* LobbyMenu;Add the Login and Lobby's C++ class in the
BP_TutorialHUD
under the pointer variables you declared in theBeginPlay()
function.noteYou will need to repeat Step 5 in order to add additional UI-related user widgets for in-game stores, inventories, leaderboards, etc.
Add
const
functions that will act as getters for the widgets.- .h
/**
* @brief Getter for Login Menu widget
*/
UAccelByteAuth* GetLoginMenu() const {return LoginMenu; }
/**
* @brief Getter for Lobby Menu widget
*/
UAccelByteLobby* GetLobbyMenu() const {return LobbyMenu; }Add some functions that will be called to change to the desired menu page. Since you only have the Login and Lobby widgets, create two new functions to open these widgets:
- .cpp
- .h
void ATutorialMenuHUD::OpenLoginMenu()
{
LoginMenu->AddToViewport();
}
void ATutorialMenuHUD::OpenLobbyMenu()
{
LobbyMenu->SetVisibility(ESlateVisibility::Visible);
}/**
* @brief Shows the Login Menu on screen
*/
void OpenLoginMenu();
/**
* @brief Shows the Lobby Menu, which adds the Party Menu in Sb_Party and destroys Main Menu
*/
UFUNCTION()
void OpenLobbyMenu();Add another function that will be used to destroy the widgets when you close the page.
- .cpp
- .h
void ATutorialMenuHUD::CloseLobbyMenu()
{
LobbyMenu->SetVisibility(ESlateVisibility::Collapsed);
}/**
* @brief Destroys the Lobby Menu widget and shows the Main Menu
*/
UFUNCTION()
void CloseLobbyMenu();Inside the
BeginPlay()
function, check the current session'suserId
. If it is empty, call theOpenLoginMenu()
function.- .cpp
void ATutorialMenuHUD::BeginPlay()
{
...
if (IdentityInterface->GetApiClient(USER_LOCAL_NUM)->CredentialsRef->GetUserId().IsEmpty())
{
OpenLoginMenu();
}
}
Lobby-related widget implementation update
Open the
AccelByteAuth
class and header file and add theTutorialMenuHUD
class.- .cpp
- .h
...
#include "TutorialProject/TutorialMenuHUD.h"...
class ATutorialMenuHUD;
...In
AccelByteAuth.cpp
, define theTutorialMenuHUD
's pointer in theNativeConstruct()
function.- .cpp
- .h
void UAccelByteAuth::NativeConstruct()
{
...
TutorialMenuHUD = Cast<ATutorialMenuHUD>(GetWorld()->GetFirstPlayerController()->GetHUD());
...
}/**
* @brief Instantiate all casting to the main menu HUD
*/
ATutorialMenuHUD* TutorialMenuHUD;Inside the
LoginSuccess()
function, call theConnectToLobby()
function with the Lobby getter.- .cpp
void UAccelByteAuth::LoginSuccess()
{
...
if(GetOwningPlayer() && GetOwningPlayer()->GetHUD())
{
TutorialMenuHUD->GetLobbyMenu()->ConnectToLobby();
this->RemoveFromParent();
}
}Add the Lobby Disconnect function inside the
OnLogoutButtonClicked()
function inAccelByteAuth.cpp
.- .cpp
void UAccelByteAuth::OnLogoutButtonClicked()
{
...
if (IdentityInterface->GetApiClient(USER_LOCAL_NUM)->Lobby.IsConnected())
{
IdentityInterface->GetApiClient(USER_LOCAL_NUM)->Lobby.Disconnect()
}
}
Congratulations! You have now fully implemented AGS Lobby, which is the gateway to all other services in AGS.
You are ready to move on to implementing AGS Friends for AGS Shared Cloud.
Full Code for reference
AccelByteLobby.h
// Copyright (c) 2024 AccelByte Inc. All Rights Reserved.
// This is licensed software from AccelByte Inc, for limitations
// and restrictions contact your company contract manager.
#pragma once
#include "CoreMinimal.h"
#include "AccelByteLobby.generated.h"
/**
* Component for Join to AccelByte Gaming Services (AGS) Lobby.
* This code covers AGS including :
*
* - Join Lobby
* - Leave Lobby
*/
UCLASS()
class TUTORIALPROJECT_API UAccelByteLobby : public UUserWidget
{
GENERATED_BODY()
#pragma region Utilities
public:
/**
* @brief Connect to AccelByte lobby.
*/
UFUNCTION()
void ConnectToLobby();
/**
* @brief Set Lobby services notification delegates.
*/
void SetLobbyNotificationDelegate();
#pragma endregion
};
AccelByteLobby.cpp
// Copyright (c) 2024 AccelByte Inc. All Rights Reserved.
// This is licensed software from AccelByte Inc, for limitations
// and restrictions contact your company contract manager.
#include "OnlineIdentityInterfaceAccelByte.h"
#pragma region Utilities
void UAccelByteLobby::ConnectToLobby()
{
SetLobbyNotificationDelegate();
IdentityInterface->ConnectAccelByteLobby(USER_LOCAL_NUM);;
}
void UAccelByteLobby::SetLobbyNotificationDelegate()
{
IdentityInterface->AddAccelByteOnConnectLobbyCompleteDelegate_Handle(USER_LOCAL_NUM
, FAccelByteOnConnectLobbyCompleteDelegate::CreateLambda([](int32 LocalUserNum, bool bWasSuccessful, const FUniqueNetId& UserId, const FOnlineErrorAccelByte& Error)
{
if (bWasSuccessful)
{
UE_LOG(LogTemp, Log, TEXT("Successfully connected to Lobby."));
}
else
{
UE_LOG(LogTemp, Error, TEXT("Failed to connect to Lobby. Code: %s, Reason: %s"), *Error.ErrorCode, *Error.ErrorMessage.ToString());
}
}));
IdentityInterface->AddAccelByteOnLobbyConnectionClosedDelegate_Handle(USER_LOCAL_NUM
, FAccelByteOnLobbyConnectionClosedDelegate::CreateLambda([](int32 LocalUserNum, const FUniqueNetId& UserId, int32 StatusCode, const FString& Reason, bool bWasClean)
{
UE_LOG(LogTemp, Error, TEXT("Lobby disconnected. Code: %d, Message: %s"), StatusCode, *Reason);
}));
IdentityInterface->AddAccelByteOnLobbyReconnectingDelegate_Handle(USER_LOCAL_NUM
, FAccelByteOnLobbyReconnectingDelegate::CreateLambda([](int32 LocalUserNum, const FUniqueNetId& UserId, int32 StatusCode, const FString& Reason, bool bWasClean)
{
UE_LOG(LogTemp, Error, TEXT("Lobby is reconnecting..."));
}));
IdentityInterface->AddAccelByteOnLobbyReconnectedDelegate_Handle(0
, FAccelByteOnLobbyReconnectedDelegate::CreateLambda([]()
{
UE_LOG(LogTemp, Error, TEXT("Lobby reconnected"));
}));
}
#pragma endregion
TutorialMenuHUD.h
// Copyright (c) 2024 AccelByte Inc. All Rights Reserved.
// This is licensed software from AccelByte Inc, for limitations
// and restrictions contact your company contract manager.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/HUD.h"
#include "TutorialMenuHUD.generated.h"
class UAccelByteAuth;
class UAccelByteLobby;
/**
* Menu Widget Controller. All Widget functionality control here.
*/
UCLASS()
class TUTORIALPROJECT_API ATutorialMenuHUD : public AHUD
{
GENERATED_BODY()
protected:
virtual void BeginPlay() override;
public:
/**
* @brief Shows the Login Menu on screen
*/
void OpenLoginMenu();
/**
* @brief Shows the Lobby Menu, which adds the Party Menu in Sb_Party and destroys Main Menu
*/
UFUNCTION()
void OpenLobbyMenu();
/**
* @brief Destroys the Lobby Menu widget and shows the Main Menu
*/
UFUNCTION()
void CloseLobbyMenu();
protected:
/**
* @brief Login Menu widget class
*/
UPROPERTY(EditDefaultsOnly)
TSubclassOf<UAccelByteAuth> LoginMenuClass;
/**
* @brief Lobby Menu widget class
*/
UPROPERTY(EditDefaultsOnly)
TSubclassOf<UAccelByteLobby> LobbyMenuClass;
public:
/**
* @brief Getter for Login Menu widget
*/
UAccelByteAuth* GetLoginMenu() const {return LoginMenu; }
/**
* @brief Getter for Lobby Menu widget
*/
UAccelByteLobby* GetLobbyMenu() const {return LobbyMenu; }
private:
/**
* @brief Login Menu widget pointer
*/
UPROPERTY()
UAccelByteAuth* LoginMenu;
/**
* @brief Lobby Menu widget pointer
*/
UPROPERTY()
UAccelByteLobby* LobbyMenu;
};
TutorialMenuHUD.cpp
// Copyright (c) 2024 AccelByte Inc. All Rights Reserved.
// This is licensed software from AccelByte Inc, for limitations
// and restrictions contact your company contract manager.
#include "TutorialMenuHUD.h"
#include "AccelByte/Authentication/AccelByteAuth.h"
#include "OnlineIdentityInterfaceAccelByte.h"
void ATutorialMenuHUD::BeginPlay()
{
Super::BeginPlay();
APlayerController* PlayerController = GetOwningPlayerController();
check(LoginMenuClass != nullptr);
check(LobbyMenuClass != nullptr);
LoginMenu = CreateWidget<UAccelByteAuth>(PlayerController, LoginMenuClass.Get());
LobbyMenu = CreateWidget<UAccelByteLobby>(PlayerController, LobbyMenuClass.Get());
if (IdentityInterface->GetApiClient(USER_LOCAL_NUM)->CredentialsRef->GetUserId().IsEmpty())
{
OpenLoginMenu();
}
}
void ATutorialMenuHUD::OpenLoginMenu()
{
LoginMenu->AddToViewport();
}
void ATutorialMenuHUD::OpenLobbyMenu()
{
LobbyMenu->SetVisibility(ESlateVisibility::Visible);
}
void ATutorialMenuHUD::CloseLobbyMenu()
{
LobbyMenu->SetVisibility(ESlateVisibility::Collapsed);
}
AccelByteAuth.h
// Copyright (c) 2024 AccelByte Inc. All Rights Reserved.
// This is licensed software from AccelByte Inc, for limitations
// and restrictions contact your company contract manager.
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "AccelByteAuth.generated.h"
class UVerticalBox;
class UEditableTextBox;
class UButton;
class ATutorialMenuHUD;
class UTextBlock;
/**
* Component for logging in a user with the AGS backend, as well as methods for grabbing information relating to that user.
* This code covers AGS features including:
*
* - Login with username
*/
UCLASS()
class TUTORIALPROJECT_API UAccelByteAuth : public UUserWidget
{
GENERATED_BODY()
protected:
virtual void NativeConstruct() override;
/**
* @brief Editable Text Box for Usernames inside the MainMenu Widget.
*/
UPROPERTY(meta = (BindWidget))
UEditableTextBox* Etb_Username;
/**
* @brief Editable Text Box for Passwords inside the MainMenu Widget.
*/
UPROPERTY(meta = (BindWidget))
UEditableTextBox* Etb_Password;
/**
* @brief Take Button Login inside MainMenu Widget.
*/
UPROPERTY(meta = (BindWidget))
UButton* Btn_Login;
/**
* @brief Text Block to display Login Status
*/
UPROPERTY(meta = (BindWidget))
UTextBlock* T_LoginStatus;
/**
* @brief Instantiate all casting to the main menu HUD
*/
UPROPERTY()
ATutorialMenuHUD* TutorialMenuHUD;
/**
* @brief Delegate on login complete
*/
FDelegateHandle OnLoginCompleteDelegateHandle;
/**
* @brief Delegate on logout complete
*/
FDelegateHandle OnLogoutCompleteDelegateHandle;
public:
/**
* @brief Log in an account using the AGS Game SDK. This is executed automatically on component construction unless
* otherwise configured.
*/
UFUNCTION()
void OnLoginButtonClicked();
/**
* @brief Logout a session using the AGS Game SDK. This is executed automatically on component construction unless
* otherwise configured.
*/
UFUNCTION()
void OnLogoutButtonClicked();
private:
/**
* @brief Function behavior when login is successful. This function, which is called from inside AccelByte Login OnSuccess,
* delegates inside lambda. How the login behavior works inside this function can be changed.
*/
void LoginSuccess();
/**
* @brief Function behavior when login fails. This function, which is called from inside AccelByte Login OnFailed,
* delegates inside lambda. How the login behavior works inside this function can be changed.
*
* @param ErrorMessage error message HTTP request. e.g., Unauthorized.
* @param ErrorMessage error message HTTP request. e.g., Unauthorized.
* @param ErrorJson error message for OAuth
* @param ErrorMessage error message HTTP request. e.g., Unauthorized.
* @param ErrorJson error message for OAuth
*/
void LoginFailed(const FString& ErrorMessage);
/**
* @brief Function behavior when logout is successful. This function, which is called from inside AccelByte Logout OnSuccess,
* delegates inside lambda. How the login behavior works inside this function can be changed.
*/
void LogoutSuccess();
/**
* @brief Function behavior when logout fails. This function, which is called from inside AccelByte Logout OnFailed,
* delegates inside lambda. How the login behavior works inside this function can be changed.
*/
void LogoutFailed();
};
AccelByteAuth.cpp
// Copyright (c) 2024 AccelByte Inc. All Rights Reserved.
// This is licensed software from AccelByte Inc, for limitations
// and restrictions contact your company contract manager.
#include "AccelByteAuth.h"
#include "OnlineIdentityInterfaceAccelByte.h"
#include "OnlineSubsystemUtils.h"
#include "Components/Button.h"
#include "Components/EditableTextBox.h"
#include "Components/TextBlock.h"
#define USER_LOCAL_NUM 0
void UAccelByteAuth::NativeConstruct()
{
Super::NativeConstruct();
UE_LOG(LogTemp, Log, TEXT("Log in with username"));
T_LoginStatus->SetText(FText::FromString("Please log in"));
Btn_Login->OnClicked.AddUniqueDynamic(this, &UAccelByteAuth::OnLoginButtonClicked);
}
void UAccelByteAuth::OnLoginButtonClicked()
{
T_LoginStatus->SetText(FText::FromString("Logging in..."));
const IOnlineSubsystem* Subsystem = Online::GetSubsystem(GetWorld());
ensure(Subsystem != nullptr);
const FOnlineIdentityAccelBytePtr IdentityInterface = StaticCastSharedPtr<FOnlineIdentityAccelByte>(Subsystem->GetIdentityInterface());
ensure(IdentityInterface.IsValid());
OnLoginCompleteDelegateHandle = IdentityInterface->AddOnLoginCompleteDelegate_Handle(USER_LOCAL_NUM, FOnLoginCompleteDelegate::CreateLambda([this, IdentityInterface]
(int32 LocalUserNum, bool bWasSuccessful, const FUniqueNetId& UserId, const FString& Error)
{
IdentityInterface->ClearOnLoginCompleteDelegate_Handle(USER_LOCAL_NUM, OnLoginCompleteDelegateHandle);
if (bWasSuccessful)
{
LoginSuccess();
}
else
{
LoginFailed(Error);
}
}));
const FString& Username = Etb_Username->GetText().ToString();
const FString& Password = Etb_Password->GetText().ToString();
const FOnlineAccountCredentialsAccelByte OnlineAccountCredentialsAccelByte
{EAccelByteLoginType::AccelByte, Username, Password};
IdentityInterface->Login(USER_LOCAL_NUM, OnlineAccountCredentialsAccelByte);
}
void UAccelByteAuth::OnLogoutButtonClicked()
{
const IOnlineSubsystem* Subsystem = Online::GetSubsystem(GetWorld());
ensure(Subsystem != nullptr);
const FOnlineIdentityAccelBytePtr IdentityInterface = StaticCastSharedPtr<FOnlineIdentityAccelByte>(Subsystem->GetIdentityInterface());
ensure(IdentityInterface.IsValid());
OnLogoutCompleteDelegateHandle = IdentityInterface->AddOnLogoutCompleteDelegate_Handle(USER_LOCAL_NUM, FOnLogoutCompleteDelegate::CreateLambda([this, IdentityInterface](int32 LocalUserNum, bool bWasSuccessful)
{
IdentityInterface->ClearOnLogoutCompleteDelegate_Handle(USER_LOCAL_NUM, OnLogoutCompleteDelegateHandle);
if (bWasSuccessful)
{
LogoutSuccess();
}
else
{
LogoutFailed();
}
}));
IdentityInterface->Logout(USER_LOCAL_NUM);
if (IdentityInterface->GetApiClient(USER_LOCAL_NUM)->Lobby.IsConnected())
{
IdentityInterface->GetApiClient(USER_LOCAL_NUM)->Lobby.Disconnect()
}
}
void UAccelByteAuth::LoginSuccess()
{
UE_LOG(LogTemp, Log, TEXT("Login success"));
T_LoginStatus->SetText(FText::FromString("Login successful"));
}
void UAccelByteAuth::LoginFailed(const FString& ErrorMessage)
{
UE_LOG(LogTemp, Error, TEXT("Login failed : %s"), *ErrorMessage);
T_LoginStatus->SetText(FText::FromString(FString::Printf(TEXT("Login failed : %s"), *ErrorMessage)));
}
void UAccelByteAuth::LogoutSuccess()
{
UE_LOG(LogTemp, Log, TEXT("Logout success"));
}
void UAccelByteAuth::LogoutFailed()
{
UE_LOG(LogTemp, Error, TEXT("Logout failed"));
}