For some reason no games are listed for my test partner. No idea why. Might be different region. Anyway, I figured “Why not simply implement joining the game directly?”
I still don’t quite understand why it works the way it does. The options are named quite confusingly. For instance inviting works just fine even though I set bAllowInvite to false. But anyway.
For anyone who’s interested, here is what you need to add to make joining directly (via Shift+Tab in-game and then right clicking the player you want to join/invite):
Creating the session:
FOnlineSessionSettings Settings;
Settings.bIsLANMatch = false;
Settings.NumPublicConnections = 2;
Settings.bShouldAdvertise = true;
Settings.bUsesPresence = true;
Settings.bUseLobbiesIfAvailable = true;
Settings.bAllowInvites = false;
Settings.bAllowJoinViaPresence = true;
Settings.bAllowJoinInProgress = true;
SessionInterface->CreateSession(0, SessionName, Settings);
Declaring the join/invite callbacks in the game instance header:
virtual void OnSessionInviteReceived(const FUniqueNetId& UserId, const FUniqueNetId& FromId, const FString& AppId, const FOnlineSessionSearchResult& OnlineSessionSearchResult);
virtual void OnSessionUserInviteAccepted(bool bWasSuccessful, int ControllerId, TSharedPtr<const FUniqueNetId, ESPMode::Fast> UserId, const FOnlineSessionSearchResult& OnlineSessionSearchResult);
Implementing the methods in the game instance cpp:
void UPuzzlePlatformsGameInstance::OnSessionInviteReceived(
const FUniqueNetId& UserId,
const FUniqueNetId& FromId,
const FString& AppId,
const FOnlineSessionSearchResult& OnlineSessionSearchResult
)
{
UEngine* Engine = GetEngine();
if (!ensureMsgf(Engine != nullptr, TEXT("Engine was NULL"))) return;
if (!ensureMsgf(SessionInterface.IsValid(), TEXT("SessionInterface not ready"))) return;
Engine->AddOnScreenDebugMessage(-1, 30, FColor::Yellow, FString::Printf(TEXT("Session invite received: '%s'"), *AppId));
if (SessionInterface->JoinSession(0, NewSessionName, OnlineSessionSearchResult))
{
Engine->AddOnScreenDebugMessage(-1, 30, FColor::Blue, FString::Printf(TEXT("Joining session...")));
}
else
{
Engine->AddOnScreenDebugMessage(-1, 30, FColor::Red, FString::Printf(TEXT("Could not join session")));
}
}
void UPuzzlePlatformsGameInstance::OnSessionUserInviteAccepted(
bool bWasSuccessful,
int ControllerId,
TSharedPtr<const FUniqueNetId, ESPMode::Fast> UserId,
const FOnlineSessionSearchResult& OnlineSessionSearchResult
)
{
UEngine* Engine = GetEngine();
if (!ensureMsgf(Engine != nullptr, TEXT("Engine was NULL"))) return;
if (!ensureMsgf(SessionInterface.IsValid(), TEXT("SessionInterface not ready"))) return;
if (bWasSuccessful)
{
Engine->AddOnScreenDebugMessage(-1, 30, FColor::Blue, FString::Printf(TEXT("Session invite accepted successfully")));
}
else
{
Engine->AddOnScreenDebugMessage(-1, 30, FColor::Red, FString::Printf(TEXT("Session invite not accepted")));
}
if (SessionInterface->JoinSession(0, NewSessionName, OnlineSessionSearchResult))
{
Engine->AddOnScreenDebugMessage(-1, 30, FColor::Blue, FString::Printf(TEXT("Joining session...")));
}
else
{
Engine->AddOnScreenDebugMessage(-1, 30, FColor::Red, FString::Printf(TEXT("Could not join session")));
}
}
And of course adding the delegates in Init():
SessionInterface->OnSessionInviteReceivedDelegates.AddUObject(this, &UPuzzlePlatformsGameInstance::OnSessionInviteReceived);
SessionInterface->OnSessionUserInviteAcceptedDelegates.AddUObject(this, &UPuzzlePlatformsGameInstance::OnSessionUserInviteAccepted);
Works for me!