I tried to use c++ to create sessions, and find and join them in unreal. I took a reference to this blog.
How To Use Sessions In C++ - UE4: Guidebook (gg-labs.com)
However, if I use my c++ code to create a session, it can be created, but my c++ can’t find the session.
But the c++ code can find the session created by the blueprint.
And, the blueprint Find Session code can find both C++ created session and Blueprint created session. But it could only join the blueprint created session.
Here is the log of creating session, upper is in blueprint and lower is in c++:
Here is for search and connection log info snippet. Everything are the same except this one:
The good one:
LogOnlineSession: OSS: Join session: traveling to MY IP:7777
But the bad one is:
LogOnlineSession: OSS: Join session: traveling to MY IP:0
what could cause this error? Anyone help!
Here is my code in c++:
// Fill out your copyright notice in the Description page of Project Settings.
#include "NetCode/NetworkInstance.h"
#include "CreateSessionCallbackProxy.h"
#include "Engine.h"
#include "Interfaces/OnlineSessionInterface.h"
#include "OnlineSessionSettings.h"
UNetworkInstance::UNetworkInstance()
{
OnCreateSessionCompleteDelegate = FOnCreateSessionCompleteDelegate::CreateUObject(this,&UNetworkInstance::OnSessionCreateComplete);
OnStartSessionCompleteDelegate = FOnStartSessionCompleteDelegate::CreateUObject(this,&UNetworkInstance::OnSessionStartComplete);
OnFindSessionsCompleteDelegate = FOnFindSessionsCompleteDelegate::CreateUObject(this, &UNetworkInstance::OnSessionFindComplete);
}
/*Create session settings and create a session with that setting*/
bool UNetworkInstance::HostSession(int MaxConnectionNum, bool bIsLan)
{
if(const IOnlineSubsystem* OnlineSubsystem = IOnlineSubsystem::Get())
{
/*Get the session interface so we can call "Createsession" function*/
IOnlineSessionPtr Session = OnlineSubsystem->GetSessionInterface();
if(Session.IsValid())
{
SessionSettings = MakeShareable(new FOnlineSessionSettings());
SessionSettings->bAllowInvites = true;
SessionSettings->bIsLANMatch = bIsLan;
SessionSettings->NumPublicConnections =MaxConnectionNum;
SessionSettings->NumPrivateConnections = 0;
SessionSettings->bAllowJoinInProgress = true;
SessionSettings->bAllowJoinViaPresence = true;
SessionSettings->bAllowJoinViaPresenceFriendsOnly = false;
SessionSettings->bIsDedicated = false;
SessionSettings->bUsesPresence =true;
SessionSettings->bShouldAdvertise = true;
/*Set start up level*/
SessionSettings->Set(SETTING_MAPNAME,FString("FashionNext"),EOnlineDataAdvertisementType::ViaOnlineService);
/*Bind delegate*/
OnCreateSessionCompleteDelegateHandle = Session->AddOnCreateSessionCompleteDelegate_Handle(OnCreateSessionCompleteDelegate);
const ULocalPlayer* LocalPlayer =GetFirstGamePlayer();
if(GEngine)GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Cyan, FString::Printf(TEXT("Net ID:%s!"),*LocalPlayer->GetPreferredUniqueNetId().ToString()));
/*destroy previous session first if there is one*/
Session->DestroySession(FName("FashionNext"));
return Session->CreateSession(*LocalPlayer->GetPreferredUniqueNetId(),FName("FashionNext"),*SessionSettings);
}
}
else
{
if(GEngine)GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Red, TEXT("No OnlineSubsytem found!"));
}
return false;
}
/*Once create session successfully, then try to start the session*/
void UNetworkInstance::OnSessionCreateComplete(FName SessionName, bool bIsSuccessful)
{
if(const IOnlineSubsystem* OnlineSubsystem = IOnlineSubsystem::Get())
{
IOnlineSessionPtr Session = OnlineSubsystem->GetSessionInterface();
if(Session.IsValid())
{
Session->ClearOnCreateSessionCompleteDelegate_Handle(OnCreateSessionCompleteDelegateHandle);
}
if(bIsSuccessful)
{
if(GEngine)GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Cyan, FString::Printf(TEXT("Create session successfully!")));
OnStartSessionCompleteDelegateHandle = Session->AddOnStartSessionCompleteDelegate_Handle(OnStartSessionCompleteDelegate);
Session->StartSession(FName("FashionNext"));
}else
{
if(GEngine)GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Cyan, FString::Printf(TEXT("Create session Failed!")));
}
}
}
/*Once start session successfully, open the SCAN QR level*/
void UNetworkInstance::OnSessionStartComplete(FName SessionName, bool bIsSuccessful)
{
if(const IOnlineSubsystem* OnlineSubsystem = IOnlineSubsystem::Get())
{
IOnlineSessionPtr Session = OnlineSubsystem->GetSessionInterface();
if(Session.IsValid())
{
Session->ClearOnStartSessionCompleteDelegate_Handle(OnStartSessionCompleteDelegateHandle);
}
if(bIsSuccessful)
{
if(GEngine)GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Cyan, FString::Printf(TEXT("Start :%s session successfully!"),*SessionName.ToString()));
UGameplayStatics::OpenLevel(GetWorld(),FName("ScanQR"),true,FString("?listen"));
}else
{
if(GEngine)GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Cyan, FString::Printf(TEXT("Start :%s session Failed!"),*SessionName.ToString()));
}
}
}
/*Try to find Session*/
void UNetworkInstance::FindSession(bool bIsLAN)
{
if(const IOnlineSubsystem* OnlineSubsystem = IOnlineSubsystem::Get())
{
IOnlineSessionPtr Session = OnlineSubsystem->GetSessionInterface();
if(Session.IsValid())
{
SessionSearch = MakeShareable(new FOnlineSessionSearch);
SessionSearch->bIsLanQuery = bIsLAN;
SessionSearch->MaxSearchResults = 10;
SessionSearch->PingBucketSize =50;
SessionSearch->QuerySettings.Set(SEARCH_PRESENCE,true, EOnlineComparisonOp::Equals);
}
//Using in Find Sessions
const TSharedRef<FOnlineSessionSearch> SearchSessionRef = SessionSearch.ToSharedRef();
OnFindSessionsCompleteDelegateHandle = Session->AddOnFindSessionsCompleteDelegate_Handle(OnFindSessionsCompleteDelegate);
const ULocalPlayer* LocalPlayer = GetFirstGamePlayer();
if(GEngine)GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Cyan, FString::Printf(TEXT("Net ID:%s!"),*LocalPlayer->GetPreferredUniqueNetId().ToString()));
Session->FindSessions(*LocalPlayer->GetPreferredUniqueNetId(),SearchSessionRef);
}else
{
// If something goes wrong, just call the Delegate Function directly with "false".
OnSessionFindComplete(false);
}
}
void UNetworkInstance::SimplfiedJoined()
{
if(const IOnlineSubsystem* OnlineSubsystem = IOnlineSubsystem::Get())
{
IOnlineSessionPtr Session = OnlineSubsystem->GetSessionInterface();
if(Session.IsValid())
{
SessionSearch = MakeShareable(new FOnlineSessionSearch);
SessionSearch->bIsLanQuery = false;
SessionSearch->MaxSearchResults = 10;
SessionSearch->PingBucketSize =50;
SessionSearch->QuerySettings.Set(SEARCH_PRESENCE,true, EOnlineComparisonOp::Equals);
const TSharedRef<FOnlineSessionSearch> SearchSessionRef = SessionSearch.ToSharedRef();
const ULocalPlayer* LocalPlayer = GetFirstGamePlayer();
Session->FindSessions(*LocalPlayer->GetPreferredUniqueNetId(),SearchSessionRef);
if(SessionSearch->SearchResults.Num()>0)
{
if(GEngine) GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Cyan, FString::Printf(TEXT("Yeah!")));
Session->JoinSession(*LocalPlayer->GetPreferredUniqueNetId(),FName("FashionNext"),SessionSearch->SearchResults[0]);
}
}
}
}
void UNetworkInstance::OnSessionFindComplete( bool bIsSuccessful)
{
if(const IOnlineSubsystem* OnlineSubsystem = IOnlineSubsystem::Get())
{
IOnlineSessionPtr Session = OnlineSubsystem->GetSessionInterface();
if(Session.IsValid())
{
if(GEngine) GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Cyan, FString::Printf(TEXT("Num Search Results: %d"), SessionSearch->SearchResults.Num()));
Session->ClearOnFindSessionsCompleteDelegate_Handle(OnFindSessionsCompleteDelegateHandle);
if(SessionSearch->SearchResults.Num()>0)
{
const ULocalPlayer* LocalPlayer = GetFirstGamePlayer();
for(auto& SearchResult:SessionSearch->SearchResults)
{
if(SearchResult.Session.OwningUserId != LocalPlayer->GetPreferredUniqueNetId())
{
Join(SearchResult);
break;
}
}
}
}
if(!bIsSuccessful)
{
if(GEngine) GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Red, FString::Printf(TEXT("Num Search Results: %d"), SessionSearch->SearchResults.Num()));
}
}
}
bool UNetworkInstance::Join(const FOnlineSessionSearchResult& SearchResult)
{
if(const IOnlineSubsystem* OnlineSubsystem = IOnlineSubsystem::Get())
{
IOnlineSessionPtr Session = OnlineSubsystem->GetSessionInterface();
if(Session.IsValid())
{
OnJoinSessionCompleteDelegateHandle = Session->AddOnJoinSessionCompleteDelegate_Handle(OnJoinSessionCompleteDelegate);
const ULocalPlayer* LocalPlayer = GetFirstGamePlayer();
if(GEngine) GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Red, FString::Printf(TEXT("Trying to join!")));
return Session->JoinSession(*LocalPlayer->GetPreferredUniqueNetId(),FName("FashionNext"),SearchResult);
}
}
return false;
}
void UNetworkInstance::OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result)
{
if(GEngine) GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Red, FString::Printf(TEXT("OnJoinSessionComplete %s, %d"), *SessionName.ToString(), static_cast<int32>(Result)));
IOnlineSubsystem* OnlineSub = IOnlineSubsystem::Get();
if (OnlineSub)
{
// Get SessionInterface from the OnlineSubsystem
IOnlineSessionPtr Sessions = OnlineSub->GetSessionInterface();
if (Sessions.IsValid())
{
// Clear the Delegate again
Sessions->ClearOnJoinSessionCompleteDelegate_Handle(OnJoinSessionCompleteDelegateHandle);
// Get the first local PlayerController, so we can call "ClientTravel" to get to the Server Map
// This is something the Blueprint Node "Join Session" does automatically!
APlayerController * const PlayerController = GetFirstLocalPlayerController();
// We need a FString to use ClientTravel and we can let the SessionInterface contruct such a
// String for us by giving him the SessionName and an empty String. We want to do this, because
// Every OnlineSubsystem uses different TravelURLs
FString TravelURL;
if (PlayerController && Sessions->GetResolvedConnectString(SessionName, TravelURL))
{
// Finally call the ClienTravel. If you want, you could print the TravelURL to see
// how it really looks like
PlayerController->ClientTravel(TravelURL, ETravelType::TRAVEL_Absolute);
}
}
}
}