Hello, I’m working with UE 4.27 and I’ve been trying to make the OnSessionParticipantsChangeDelegate work in order to make changes when a player enters a session. However, it isn’t being called even when the session has been created and the player has joined with no problem. Any ideas?
If it is useful, I’m using Steam and inviting the player with its overlay. First I create the session with a pc and then i send an invitation to the other. After that I accept the invitation and join the session. Here’s the code:
SessionsManager.h
#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "Interfaces/OnlineSessionInterface.h"
#include "GameFramework/PlayerState.h"
#include "Kismet/GameplayStatics.h"
#include "Online.h"
#include "SessionsManager.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMyOnCreateSessionCompleteDelegate, bool, bWasSuccessful);
DECLARE_MULTICAST_DELEGATE_ThreeParams(FMyOnRegisterPlayersCompleteDelegate, FName SessionName, const TArray< FUniqueNetIdRef >& UnregisteredPlayers, bool bWasSuccessful);
DECLARE_MULTICAST_DELEGATE_OneParam(FMyOnJoinSessionCompleteDelegate, EOnJoinSessionCompleteResult::Type Result);
DECLARE_MULTICAST_DELEGATE_OneParam(FMyOnInviteAcceptedDelegate, bool bWasSuccessful);
DECLARE_MULTICAST_DELEGATE_OneParam(FMyOnSessionParticipantJoinDelegate, const FUniqueNetId& ChangingPlayer);
UCLASS()
class SALSETESONLINELIBRARY_API USessionsManager : public UGameInstanceSubsystem
{
GENERATED_BODY()
USessionsManager();
public:
//
// Custom delegates
//
FMyOnCreateSessionCompleteDelegate MyOnCreateSessionCompleteDelegate;
FMyOnJoinSessionCompleteDelegate MyOnJoinSessionCompleteDelegate;
FMyOnRegisterPlayersCompleteDelegate MyOnRegisterPlayersCompleteDelegate;
FMyOnInviteAcceptedDelegate MyOnInviteAcceptedDelegate;
FMyOnSessionParticipantJoinDelegate MyOnSessionParticipantsJoinDelegate;
void CreateSession(int32 NumPublicConnections, FString MatchType, FString TypeOfAccess);
void JoinSession(const FOnlineSessionSearchResult& SessionResult);
UFUNCTION(BlueprintCallable) void RegisterPlayer(APlayerState* Player);
protected:
//
// System callbacks
//
void OnCreateSessionComplete(FName SessionName, bool bWasSuccessful);
void OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result);
void OnRegisterPlayersComplete(FName SessionName, const TArray< FUniqueNetIdRef >& RegisteredPlayers, bool bWasSuccessful);
void OnInviteAccepted(const bool bWasSuccessful, const int32 ControllerId, FUniqueNetIdPtr UserId, const FOnlineSessionSearchResult& InviteResult);
void OnSessionParticipantsChange(FName SessionName, const FUniqueNetId& ChangingUser, bool JoinEvent);
private:
IOnlineSessionPtr SessionInterface;
ULocalPlayer* LocalPlayer;
TSharedPtr<FOnlineSessionSettings> LastSessionSettings;
TSharedPtr<FOnlineSessionSearch> LastSessionSearch;
bool bCreateSessionOnDestroy{ false };
int32 LastNumPublicConnections;
FString LastMatchType;
FString LastTypeOfAccess;
//
// System delegates
//
FOnCreateSessionCompleteDelegate CreateSessionCompleteDelegate;
FDelegateHandle CreateSessionCompleteDelegateHandle;
FOnJoinSessionCompleteDelegate JoinSessionCompleteDelegate;
FDelegateHandle JoinSessionCompleteDelegateHandle;
FOnRegisterPlayersCompleteDelegate RegisterPlayersCompleteDelegate;
FOnSessionUserInviteAcceptedDelegate InviteAcceptedDelegate;
FDelegateHandle OnSessionUserInviteAcceptedHandle;
FOnSessionParticipantsChangeDelegate SessionParticipantsChangeDelegate;
FDelegateHandle OnSessionParticipantsChangeHandle;
};
SessionsManager.cpp
#include "SessionsManager.h"
#include "OnlineSubsystem.h"
#include "FriendsManager.h"
#include "OnlineSessionSettings.h"
USessionsManager::USessionsManager():
CreateSessionCompleteDelegate(FOnCreateSessionCompleteDelegate::CreateUObject(this, &USessionsManager::OnCreateSessionComplete)),
JoinSessionCompleteDelegate(FOnJoinSessionCompleteDelegate::CreateUObject(this, &USessionsManager::OnJoinSessionComplete)),
RegisterPlayersCompleteDelegate(FOnRegisterPlayersCompleteDelegate::CreateUObject(this, &USessionsManager::OnRegisterPlayersComplete)),
InviteAcceptedDelegate(FOnSessionUserInviteAcceptedDelegate::CreateUObject(this, &USessionsManager::OnInviteAccepted)),
SessionParticipantsChangeDelegate(FOnSessionParticipantsChangeDelegate::CreateUObject(this, &USessionsManager::OnSessionParticipantsChange))
{
IOnlineSubsystem* Subsystem = IOnlineSubsystem::Get();
if (Subsystem)
{
SessionInterface = Online::GetSessionInterface();
if(SessionInterface.IsValid())
{
OnSessionUserInviteAcceptedHandle = SessionInterface->AddOnSessionUserInviteAcceptedDelegate_Handle(InviteAcceptedDelegate);
OnSessionParticipantsChangeHandle = SessionInterface->AddOnSessionParticipantsChangeDelegate_Handle(SessionParticipantsChangeDelegate);
}
}
}
void USessionsManager::CreateSession(int32 NumPublicConnections, FString MatchType, FString TypeOfAccess)
{
if (!SessionInterface.IsValid())
return;
auto ExistingSession = SessionInterface->GetNamedSession(NAME_GameSession);
if (ExistingSession != nullptr)
{
bCreateSessionOnDestroy = true;
LastNumPublicConnections = NumPublicConnections;
LastMatchType = MatchType;
LastTypeOfAccess = TypeOfAccess;
return;
}
CreateSessionCompleteDelegateHandle = SessionInterface->AddOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegate);
LastSessionSettings = MakeShareable(new FOnlineSessionSettings());
LastSessionSettings->bIsLANMatch = IOnlineSubsystem::Get()->GetSubsystemName() == "NULL" ? true : false;
LastSessionSettings->NumPublicConnections = NumPublicConnections;
LastSessionSettings->bUsesPresence = true;
LastSessionSettings->bUseLobbiesIfAvailable = true;
LastSessionSettings->Set(FName("MatchType"), MatchType, EOnlineDataAdvertisementType::ViaOnlineServiceAndPing);
LastSessionSettings->BuildUniqueId = 1;
LastSessionSettings->bAllowInvites = true;
if(TypeOfAccess == "Public")
{
LastSessionSettings->bShouldAdvertise = true;
LastSessionSettings->bAllowJoinViaPresence = true;
}
else
{
LastSessionSettings->bShouldAdvertise = false;
if(TypeOfAccess == "FriendsOnly")
{
LastSessionSettings->bAllowJoinViaPresence = true;
LastSessionSettings->bAllowJoinViaPresenceFriendsOnly = true;
}
else // InviteOnly
{
LastSessionSettings->bAllowJoinViaPresence = false; // Si utilitzar o no la presence per la sessió.
LastSessionSettings->bAllowJoinViaPresenceFriendsOnly = false;
}
}
LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
if (!SessionInterface->CreateSession(*LocalPlayer->GetPreferredUniqueNetId(), NAME_GameSession, *LastSessionSettings))
{
SessionInterface->ClearOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegateHandle);
MyOnCreateSessionCompleteDelegate.Broadcast(false);
}
}
void USessionsManager::JoinSession(const FOnlineSessionSearchResult& SessionResult)
{
if (!SessionInterface.IsValid())
{
MyOnJoinSessionCompleteDelegate.Broadcast(EOnJoinSessionCompleteResult::UnknownError);
return;
}
JoinSessionCompleteDelegateHandle = SessionInterface->AddOnJoinSessionCompleteDelegate_Handle(JoinSessionCompleteDelegate);
LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
if (!SessionInterface->JoinSession(*LocalPlayer->GetPreferredUniqueNetId(), NAME_GameSession, SessionResult))
{ SessionInterface->ClearOnJoinSessionCompleteDelegate_Handle(JoinSessionCompleteDelegateHandle);
MyOnJoinSessionCompleteDelegate.Broadcast(EOnJoinSessionCompleteResult::UnknownError);
}
}
void USessionsManager::OnCreateSessionComplete(FName SessionName, bool bWasSuccessful)
{
if (SessionInterface)
{
SessionInterface->ClearOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegateHandle);
}
MyOnCreateSessionCompleteDelegate.Broadcast(bWasSuccessful);
}
void USessionsManager::OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result)
{
if(SessionInterface)
{
FString ConnectionInfo = FString();
SessionInterface->GetResolvedConnectString(SessionName, ConnectionInfo);
if(!ConnectionInfo.IsEmpty())
{
if(APlayerController* PC = UGameplayStatics::GetPlayerController(GetWorld(), 0))
{
PC->ClientTravel(ConnectionInfo, ETravelType::TRAVEL_Absolute);
}
}
SessionInterface->ClearOnJoinSessionCompleteDelegate_Handle(JoinSessionCompleteDelegateHandle);
}
MyOnJoinSessionCompleteDelegate.Broadcast(Result);
}
void USessionsManager::OnRegisterPlayersComplete(FName SessionName, const TArray<FUniqueNetIdRef>& RegisteredPlayers, bool bWasSuccessful)
{
if(bWasSuccessful)
{
MyOnRegisterPlayersCompleteDelegate.Broadcast(SessionName, RegisteredPlayers, bWasSuccessful);
}
}
void USessionsManager::OnInviteAccepted(const bool bWasSuccessful, const int32 ControllerId, FUniqueNetIdPtr UserId, const FOnlineSessionSearchResult& InviteResult)
{
if(bWasSuccessful && SessionInterface)
{
if (InviteResult.IsSessionInfoValid() && GetWorld())
{
JoinSession(InviteResult);
MyOnInviteAcceptedDelegate.Broadcast(bWasSuccessful);
}
}
}
void USessionsManager::OnSessionParticipantsChange(FName SessionName, const FUniqueNetId& ChangingUser, bool JoinEvent)
{
if(JoinEvent)
{
MyOnSessionParticipantsJoinDelegate.Broadcast(ChangingUser);
}
}