Online subsystem Null - find session problem

Hello, i have a problem with FOnlineSessionNull.
I can’t find session in Null system. Creating - working good. Find - wrong.
It’s broken in my project, and in empty project also!

So what i do:

  • Create empty project - Third person template
  • Create simple menu, with buttons: create, find, join
  • Add to build.cs “Sockets”, “Networking”, “OnlineSubsystem”, “OnlineSubsystemUtils”, “OnlineSubsystemNull”
  • Add to DefaultEngine.ini - [OnlineSubsystem] DefaultPlatformService=Null
  • Create new level, for menu, add in begin play menu UI script, for sessions

In game i run:

  • 2 clients, with standalone each other
  • Or package project and run 2 separated exe files

In any variant i cant saw created session.

Settings Code for create session:

lastSettings = MakeShareable(new FOnlineSessionSettings());
lastSettings->bIsLANMatch = true;
lastSettings->NumPublicConnections = numConnections;
lastSettings->bAllowJoinInProgress = true;
lastSettings->bAllowJoinViaPresence = true;
lastSettings->bShouldAdvertise = true;
lastSettings->bUsesPresence = true;
lastSettings->Set(FName("MatchType"), MatchType, EOnlineDataAdvertisementType::ViaOnlineServiceAndPing);
lastSettings->BuildUniqueId = 1;

Settings Code for find session:

lastSearch = MakeShareable(new FOnlineSessionSearch());
lastSearch->MaxSearchResults = MaxSearchResults;
lastSearch->bIsLanQuery = true;
lastSearch->QuerySettings.Set(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals);

I don’t know what to do…

Full code of sessions class:
Header:

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "Interfaces/OnlineSessionInterface.h"
#include "Interfaces/OnlineIdentityInterface.h"
#include "SessionsSystem.generated.h"

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnSessionCreated, bool, bWasSuccessful);
DECLARE_MULTICAST_DELEGATE_TwoParams(FOnSessionFinded, const TArray<FOnlineSessionSearchResult>& SessionResults, bool bWasSuccessful);
DECLARE_MULTICAST_DELEGATE_OneParam(FOnJoinedToSession, EOnJoinSessionCompleteResult::Type Result);

UCLASS()
class USessionsSystem : public UGameInstanceSubsystem
{
	GENERATED_BODY()

public:
	virtual void Initialize(FSubsystemCollectionBase& Collection) override;
	virtual void Deinitialize() override;

	bool IsLocalOnly();
	void CreateSession(int32 numConnections, const FString& MatchType, bool local = false);
	void FindSessions(int32 MaxSearchResults, bool local = false);
	void JoinSession(const FOnlineSessionSearchResult& SessionResult);

public: // Delegats for subs
	FOnSessionCreated OnSessionCreated;
	FOnSessionFinded OnSessionFinded;
	FOnJoinedToSession OnJoinedToSession;

protected: // Handle OSS events functions
	void OnCreateSessionComplete(FName SessionName, bool success);
	void OnFindSessionsComplete(bool success);
	void OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result);

private:
	IOnlineSessionPtr session;
	IOnlineIdentityPtr identity;

	TSharedPtr<FOnlineSessionSettings> lastSettings;
	TSharedPtr<FOnlineSessionSearch> lastSearch;

	bool reCreateSession = false;
	int32 lastConnectionsNum;
	FString lastMatchType;

private: // Handle OSS events
	FOnCreateSessionCompleteDelegate DSessionCreated;
	FDelegateHandle HDSessionCreated;
	FOnFindSessionsCompleteDelegate DSessionFinded;
	FDelegateHandle HDSessionFinded;
	FOnJoinSessionCompleteDelegate DJoinedToSession;
	FDelegateHandle HDJoinedToSession;
};

cpp:

// Fill out your copyright notice in the Description page of Project Settings.


#include "SessionsSystem.h"
#include "Net/OnlineEngineInterface.h"
#include "OnlineSessionSettings.h"
#include "Online/OnlineSessionNames.h"
#include "GameFramework/PlayerState.h"
#include "OnlineSubsystem.h"



void USessionsSystem::Initialize(FSubsystemCollectionBase& Collection) {
	// any enabled Online system, include "local" system
	if (auto Subsystem = IOnlineSubsystem::Get()) {
		session = Subsystem->GetSessionInterface();
		identity = Subsystem->GetIdentityInterface();
	}
	DSessionCreated = FOnCreateSessionCompleteDelegate::CreateUObject(this, &USessionsSystem::OnCreateSessionComplete);
	DSessionFinded = FOnFindSessionsCompleteDelegate::CreateUObject(this, &USessionsSystem::OnFindSessionsComplete);
	DJoinedToSession = FOnJoinSessionCompleteDelegate::CreateUObject(this, &USessionsSystem::OnJoinSessionComplete);
	DSessionDestroyed = FOnDestroySessionCompleteDelegate::CreateUObject(this, &USessionsSystem::OnDestroySessionComplete);
	DLoginned = FOnLoginCompleteDelegate::CreateUObject(this, &USessionsSystem::OnLoginFinished);
	DLogouted = FOnLogoutCompleteDelegate::CreateUObject(this, &USessionsSystem::OnLogoutFinished);

	USubsystem::Initialize(Collection);
}

void USessionsSystem::Deinitialize() {
	if (session) {
		session->ClearOnCreateSessionCompleteDelegate_Handle(HDSessionCreated);
		session->ClearOnFindSessionsCompleteDelegate_Handle(HDSessionFinded);
		session->ClearOnJoinSessionCompleteDelegate_Handle(HDJoinedToSession);
		DestroySession();
	}
	if (identity) {
		if (auto playerController = GetWorld()->GetFirstPlayerController()) {
			if (ULocalPlayer* Player = Cast<ULocalPlayer>(playerController->Player)) {
				identity->ClearOnLoginCompleteDelegate_Handle(Player->GetControllerId(), HDLoginned);
				Logout();
				identity->ClearOnLogoutCompleteDelegate_Handle(Player->GetControllerId(), HDLogouted);
			}
		}
	}
	USubsystem::Deinitialize();
}

bool USessionsSystem::IsLocalOnly() {
	return IOnlineSubsystem::Get()->GetSubsystemName() == "NULL";
}

void USessionsSystem::CreateSession(int32 numConnections, const FString& MatchType, bool local) {
	if (session) {
		if (auto ExistingSession = session->GetNamedSession(NAME_GameSession)) {
			reCreateSession = true;
			lastConnectionsNum = numConnections;
			lastMatchType = MatchType;
			DestroySession();
			return;
		}

		HDSessionCreated = session->AddOnCreateSessionCompleteDelegate_Handle(DSessionCreated);

		lastSettings = MakeShareable(new FOnlineSessionSettings());
		lastSettings->bIsLANMatch = local ? true : IsLocalOnly();
		lastSettings->NumPublicConnections = numConnections;
		lastSettings->bAllowJoinInProgress = true;
		lastSettings->bAllowJoinViaPresence = true;
		lastSettings->bShouldAdvertise = true;
		lastSettings->bUsesPresence = true;
		lastSettings->Set(FName("MatchType"), MatchType, EOnlineDataAdvertisementType::ViaOnlineServiceAndPing);
		lastSettings->BuildUniqueId = 1;

		const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
		auto id = LocalPlayer->GetPreferredUniqueNetId();
		if (!session->CreateSession(*id, NAME_GameSession, *lastSettings)) {
			session->ClearOnCreateSessionCompleteDelegate_Handle(HDSessionCreated);
		}
	}
}

void USessionsSystem::FindSessions(int32 MaxSearchResults, bool local) {
	if (session) {
		HDSessionFinded = session->AddOnFindSessionsCompleteDelegate_Handle(DSessionFinded);

		lastSearch = MakeShareable(new FOnlineSessionSearch());
		lastSearch->MaxSearchResults = MaxSearchResults;
		lastSearch->bIsLanQuery = local ? true : IsLocalOnly();
		lastSearch->QuerySettings.Set(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals);

		const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
		if (!session->FindSessions(*LocalPlayer->GetPreferredUniqueNetId(), lastSearch.ToSharedRef())) {
			session->ClearOnFindSessionsCompleteDelegate_Handle(HDSessionFinded);
		}
	}
}

void USessionsSystem::JoinSession(const FOnlineSessionSearchResult& SessionResult) {
	if (session) {
		HDJoinedToSession = session->AddOnJoinSessionCompleteDelegate_Handle(DJoinedToSession);
		const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
		if (!session->JoinSession(*LocalPlayer->GetPreferredUniqueNetId(), NAME_GameSession, SessionResult)) {
			session->ClearOnJoinSessionCompleteDelegate_Handle(HDJoinedToSession);
		}
	}
}

void USessionsSystem::OnCreateSessionComplete(FName SessionName, bool success) {
	if (session) {
		session->ClearOnCreateSessionCompleteDelegate_Handle(HDSessionCreated);
	}
	OnSessionCreated.Broadcast(success);
}

void USessionsSystem::OnFindSessionsComplete(bool success) {
	if (session) {
		session->ClearOnFindSessionsCompleteDelegate_Handle(HDSessionFinded);
	}
	OnSessionFinded.Broadcast(lastSearch->SearchResults, success);
}

void USessionsSystem::OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result) {
	if (session) {
		session->ClearOnJoinSessionCompleteDelegate_Handle(HDJoinedToSession);
	}
	OnJoinedToSession.Broadcast(Result);
}