I’m using eXi’s Session Multiplayer guide and I’m having trouble making the FindSessions function work with UMG/Blueprints. I made some SessionList and SessionsRow UMG widgets like in the Multiplayer Shootout and was going to use them along with the C++ session functions. Specifically, I was going to grab every session found in FindSessions and create a SessionRow based around it. However, I have one major problem:
It seems like I can’t use the FOnlineSessionSearchResult objects used in FindSessions in a UFunction. Every time I try to use that class as a function type or a parameter, I get this error when I compile:
1> D:/Documents/Unreal Projects/MegaRisk/Source/MegaRisk/BaseGameInstance_Network.h(130) : Unrecognized type 'FOnlineSessionSearchResult' - type must be a UCLASS, USTRUCT or UENUM
1>Error : Failed to generate code for MegaRiskEditor - error code: OtherCompilationError (5)
1> UnrealHeaderTool failed for target 'MegaRiskEditor' (platform: Win64, module info: D:\Documents\Unreal Projects\MegaRisk\Intermediate\Build\Win64\MegaRiskEditor\Development\UnrealHeaderTool.manifest).
1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\Microsoft.MakeFile.Targets(37,5): error MSB3073: The command ""E:\Programs\Epic Games\4.10\Engine\Build\BatchFiles\Build.bat" MegaRiskEditor Win64 Development "D:\Documents\Unreal Projects\MegaRisk\MegaRisk.uproject" -rocket -waitmutex" exited with code -1.
So, I was wondering if there’s any way to use C++ session functions with Blueprints. I’ve been searching through the ShooterGame demo but it looks like they use C++ UI, which is something I’m trying to avoid.
Is there anyway to use these things with Blueprints/UMG at all?
Here’s some of the code:
BaseGameInstance_Network.h
//Host Session Stuff
TSharedPtr<class FOnlineSessionSettings> SessionSettings;
void FindSessions(TSharedPtr<const FUniqueNetId> UserId, FName SessionName, bool bIsLAN, bool bIsPresence);
FOnFindSessionsCompleteDelegate OnFindSessionsCompleteDelegate;
FDelegateHandle OnFindSessionsCompleteDelegateHandle;
TSharedPtr<class FOnlineSessionSearch> SessionSearch;
void OnFindSessionsComplete(bool bWasSuccessful);
//Join Session and Delete Session stuff, all exactly as it is in the tutorial
public:
//Blueprint implementation
UFUNCTION(BlueprintCallable, Category = "Network|Test")
void StartOnlineGame(FName sessionName, bool isLan, int32 maxPlayerNum);
UFUNCTION(BlueprintCallable, Category = "Network|Test")
void FindOnlineGames(TArray<FOnlineSessionSearchResult> &results, bool isLan);
UFUNCTION(BlueprintCallable, Category = "Network|Test")
void JoinOnlineGame(FName sessionName);
UFUNCTION(BlueprintCallable, Category = "Network|Test")
void DestroySessionAndLeaveGame(FName sessionName);
BaseGameInstance_Network.cpp
//Everything but the UFunctions are same as in tut, but I'll put the HostSession and FindSession stuff here anyway
bool UBaseGameInstance_Network::HostSession(TSharedPtr<const FUniqueNetId> UserId, FName SessionName, bool bIsLAN, bool bIsPresence, int32 MaxNumPlayers) {
IOnlineSubsystem* const OnlineSub = IOnlineSubsystem::Get();
if (OnlineSub){
IOnlineSessionPtr Sessions = OnlineSub->GetSessionInterface();
if (Sessions.IsValid() && UserId.IsValid()){
SessionSettings = MakeShareable(new FOnlineSessionSettings());
SessionSettings->bIsLANMatch = bIsLAN;
SessionSettings->bUsesPresence = bIsPresence;
SessionSettings->NumPublicConnections = MaxNumPlayers;
SessionSettings->NumPrivateConnections = 0;
SessionSettings->bAllowInvites = true;
SessionSettings->bAllowJoinInProgress = true;
SessionSettings->bShouldAdvertise = true;
SessionSettings->bAllowJoinViaPresence = true;
SessionSettings->bAllowJoinViaPresenceFriendsOnly = false;
SessionSettings->Set(SETTING_MAPNAME, FString("NewMap"), EOnlineDataAdvertisementType::ViaOnlineService);
OnCreateSessionCompleteDelegateHandle = Sessions->AddOnCreateSessionCompleteDelegate_Handle(OnCreateSessionCompleteDelegate);
return Sessions->CreateSession(*UserId, SessionName, *SessionSettings);
}
}
else
{ GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Red, TEXT("No OnlineSubsytem found!")); }
return false;
}
void UBaseGameInstance_Network::OnCreateSessionComplete(FName SessionName, bool bWasSuccessful){
GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Red, FString::Printf(TEXT("OnCreateSessionComplete %s, %d"), *SessionName.ToString(), bWasSuccessful));
IOnlineSubsystem* OnlineSub = IOnlineSubsystem::Get();
if (OnlineSub){
IOnlineSessionPtr Sessions = OnlineSub->GetSessionInterface();
if (Sessions.IsValid()){
Sessions->ClearOnCreateSessionCompleteDelegate_Handle(OnCreateSessionCompleteDelegateHandle);
if (bWasSuccessful){
OnStartSessionCompleteDelegateHandle = Sessions->AddOnStartSessionCompleteDelegate_Handle(OnStartSessionCompleteDelegate);
Sessions->StartSession(SessionName);
} //4 more lines of }'s here
void UBaseGameInstance_Network::OnStartOnlineGameComplete(FName SessionName, bool bWasSuccessful)
{
GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Red, FString::Printf(TEXT("OnStartSessionComplete %s, %d"), *SessionName.ToString(), bWasSuccessful));
IOnlineSubsystem* OnlineSub = IOnlineSubsystem::Get();
if (OnlineSub){
IOnlineSessionPtr Sessions = OnlineSub->GetSessionInterface();
if (Sessions.IsValid()){
Sessions->ClearOnStartSessionCompleteDelegate_Handle(OnStartSessionCompleteDelegateHandle);
}
}
if (bWasSuccessful)
{ UGameplayStatics::OpenLevel(GetWorld(), "NewMap", true, "listen"); }
}
void UBaseGameInstance_Network::FindSessions(TSharedPtr<const FUniqueNetId> UserId, FName SessionName, bool bIsLAN, bool bIsPresence)
{
IOnlineSubsystem* OnlineSub = IOnlineSubsystem::Get();
if (OnlineSub){
IOnlineSessionPtr Sessions = OnlineSub->GetSessionInterface();
if (Sessions.IsValid() && UserId.IsValid()){
SessionSearch = MakeShareable(new FOnlineSessionSearch());
SessionSearch->bIsLanQuery = bIsLAN;
SessionSearch->MaxSearchResults = 20;
SessionSearch->PingBucketSize = 50;
if (bIsPresence)
{ SessionSearch->QuerySettings.Set(SEARCH_PRESENCE, bIsPresence, EOnlineComparisonOp::Equals); }
TSharedRef<FOnlineSessionSearch> SearchSettingsRef = SessionSearch.ToSharedRef();
OnFindSessionsCompleteDelegateHandle = Sessions->AddOnFindSessionsCompleteDelegate_Handle(OnFindSessionsCompleteDelegate);
Sessions->FindSessions(*UserId, SearchSettingsRef);
}
}
else
{ OnFindSessionsComplete(false); }
}
void UBaseGameInstance_Network::OnFindSessionsComplete(bool bWasSuccessful){
GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Red, FString::Printf(TEXT("OFindSessionsComplete bSuccess: %d"), bWasSuccessful));
IOnlineSubsystem* const OnlineSub = IOnlineSubsystem::Get();
if (OnlineSub){
IOnlineSessionPtr Sessions = OnlineSub->GetSessionInterface();
if (Sessions.IsValid()){
Sessions->ClearOnFindSessionsCompleteDelegate_Handle(OnFindSessionsCompleteDelegateHandle);
GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Red, FString::Printf(TEXT("Num Search Results: %d"), SessionSearch->SearchResults.Num()));
if (SessionSearch->SearchResults.Num() > 0){
// "SessionSearch->SearchResults" is an Array that contains all the information. You can access the Session in this and get a lot of information.
// This can be customized later on with your own classes to add more information that can be set and displayed
for (int32 SearchIdx = 0; SearchIdx < SessionSearch->SearchResults.Num(); SearchIdx++){
GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Red, FString::Printf(TEXT("Session Number: %d | Sessionname: %s "), SearchIdx + 1, *(SessionSearch->SearchResults[SearchIdx].Session.OwningUserName)));
} //Many more }'s here
//Blueprint implementation
void UBaseGameInstance_Network::StartOnlineGame(FName sessionName, bool isLan, int32 maxPlayerNum){
// Creating a local player where we can get the UserID from
ULocalPlayer* const Player = GetFirstGamePlayer();
// Call our custom HostSession function. GameSessionName is a GameInstance variable
HostSession(Player->GetPreferredUniqueNetId(), GameSessionName, isLan, true, maxPlayerNum);}
void UBaseGameInstance_Network::FindOnlineGames(TArray<FOnlineSessionSearchResult> &results, bool isLan){
ULocalPlayer* const Player = GetFirstGamePlayer();
FindSessions(Player->GetPreferredUniqueNetId(), GameSessionName, isLan, true);
results = SessionSearch->SearchResults;
}