question

ferencnagy avatar image
ferencnagy asked

UE4 - Using RedeemMatchmakerTicket in GameModeBase.Login()

Hi, I am not really good with c++ so I need some help. (but I have good c# background)
I would need to fire the RedeemMatchmakerTicket in the Login function so that I can accept or reject the login.
The problem is that with the current implementation, this is async so I can't wait for the result and decide for the login operation.
Here is my current code.

void APlayfabGameModeBase::BeginPlay()
{
	Super::BeginPlay();


	serverAPI = IPlayFabModuleInterface::Get().GetServerAPI();
	FString cmdOptions = FCommandLine::Get();
	lobbyID = UGameplayStatics::ParseOption(cmdOptions, TEXT("game_id"));
}

void APlayfabGameModeBase::OnSuccess(const PlayFab::ServerModels::FRedeemMatchmakerTicketResult & Result) const
{	
}

void APlayfabGameModeBase::OnError(const PlayFab::FPlayFabCppError & ErrorResult) const
{
}

APlayerController * APlayfabGameModeBase::Login(UPlayer * NewPlayer, ENetRole InRemoteRole, const FString & Portal, const FString & Options, const FUniqueNetIdRepl & UniqueId, FString & ErrorMessage)
{
	FString matchmakeTicket = UGameplayStatics::ParseOption(Options, TEXT("ticket"));			
	
	PlayFab::ServerModels::FRedeemMatchmakerTicketRequest request;
	request.Ticket = matchmakeTicket;
	request.LobbyId = lobbyID;

	serverAPI->RedeemMatchmakerTicket(request,
		PlayFab::UPlayFabServerAPI::FRedeemMatchmakerTicketDelegate::CreateUObject(this, &APlayfabGameModeBase::OnSuccess),
		PlayFab::FPlayFabErrorDelegate::CreateUObject(this, &APlayfabGameModeBase::OnError)
	);

	//--HERE I SHOULD WAIT AND RETURN AND ERROR MESSAGE IF LOGIN IS INVALID---


	//call original logic and return
	APlayerController* const SpawnedPlayerController = AGameModeBase::Login(NewPlayer, InRemoteRole, Portal, Options, UniqueId, ErrorMessage);


	return SpawnedPlayerController;
}

How should I make it so that the Login function waits until the task is executed?
Any extra information about this?

Thanks!
unrealMatchmaking
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Seth Du avatar image
Seth Du answered

I am not familiar with c++. However, according to my experience on C# development(Unity Engine), PlayFab API calls encapsulated in SDK are all asynchronous, which means sometimes you have to write the codes (for example, verification related...) inside the OnSuccess callbacks.

3 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

ferencnagy avatar image ferencnagy commented ·

Yeah, there is no problem with that, but for the engine, I have to give connection approved/not as the result of the function.
After looking around, with a small engine tweak I can make it work. Only drawback is having a custom built engine, but I can live with that.

0 Likes 0 ·
brendan avatar image brendan ferencnagy commented ·

Can you post your change, for the sake of others? Also, would this change be something that would be a good addition to our SDK directly?

0 Likes 0 ·
ferencnagy avatar image ferencnagy brendan commented ·

Sure, I will post my changes later today.

It requires engine modification which is not possible with plugins as far as I know, so I don't think is is possible to implement natively in your SDK.

0 Likes 0 ·
ferencnagy avatar image
ferencnagy answered

So some hints for those who will wonder here later.
I could not find a way to do it without having to use a custom engine build because:

The connection request comes in the UWorld it calls the UGameModeBase::PreLogin(params) function.
If this function signals an error then the UWorld denies the connection and clean up otherwise, it calls a WelcomePlayer(UNetConnection * Connection), which starts the load and all other stuff for the player.

So I had to modify the UWorld.cpp and AGameModeBase.cpp in the engine.

All I changed is that I made an overloaded version of the PreLogin in the GameModeBase, where added the UNetConnection object as an extra parameter.

I call this overloaded function from the UWorld and don't continue the other steps.
In the PreLogin I start the Redeem request, and from the result delegate I call back to the UWorld to either WelcomePlayer(UNetConnectionIStored) or deny and clean up the connection.

These are the responses the original code has after the original PreLogin, I just call them later.

This is the main idea, this should be enough to start.

Extra implementation info:
*I add the PlayFabId to the login Options so that I can store it in a UMap(String to Connection) and find it after getting the result from PlayFab
*Originally my new PreLogin() returns false so that the UWorld knows if the second PreLogin() with the connection data is not implemented and calls the default one.
In my project's PlayFabGamemode I return true so that UWorld knows that it will handle welcoming or rejecting the player later, so it skips that part of the UWorld code.

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.