Attempting to read FOnlineSessionSearchResult leads to crash

I’ve been trying to get the values from the Online Session Search Result to my Row Widget (named Server Entry). However, everytime it tries to read the FServerData values, it crashes.

Code in GI where Server Data is set and passed to the menu widget:

void UMyGameInstance::OnFindServersComplete(bool Success)
{
	UE_LOG(LogTemp, Error, TEXT("Browsing Complete"));
	if (!Success || !SearchSettingsPtr.IsValid() || !JoinGameMenu)
	{
		UE_LOG(LogTemp, Error, TEXT("Browsing not successful, or Search Settings no longer valid"));
		return;
	}

	//Iterator for Index referencing purposes
	int32 Itr = 0;

	//Register each Server Entry to the Server Browser Widget
	for (FOnlineSessionSearchResult& SearchResult : SearchSettingsPtr->SearchResults)
	{
		if (SearchResult.IsValid())
		{
			FServerData ServerData;
			ServerData.Name = SearchResult.GetSessionIdStr();
			ServerData.MaxPlayers = SearchResult.Session.SessionSettings.NumPublicConnections;
			ServerData.CurrentPlayers = ServerData.MaxPlayers - SearchResult.Session.NumOpenPublicConnections;
			ServerData.Ping = SearchResult.PingInMs;
			ServerData.SearchIndex = Itr;

			UE_LOG(LogTemp, Error, TEXT("Attempting to Register Server Entry: %s - %d - %d"), *SearchResult.GetSessionIdStr(), SearchResult.PingInMs, SearchResult.Session.SessionSettings.NumPublicConnections);
			JoinGameMenu->RegisterServerEntry(ServerData);
			Itr++;
		}
	}
}

And, where the functionality is in my menu widget:

void UWULJoinSubMenu::RegisterServerEntry(FServerData& ServerData)
{
	//Create Widget for Server Entry
	UWULServerEntry* NewEntry = CreateWidget<UWULServerEntry>(this, UWULServerEntry::StaticClass());
	if (NewEntry)
	{
		//Null-Check Search Results
		if (MyGameInstance->SearchSettingsPtr.IsValid())
		{
			if (ServerData.Name.IsEmpty())
			{
				UE_LOG(LogTemp, Error, TEXT("Server not named"));
			}
			else
			{
				//Set values for 
				NewEntry->PlayerCountText->SetText(FText::FromString(FString::FromInt(ServerData.CurrentPlayers) + "/" + FString::FromInt(ServerData.MaxPlayers)));
				NewEntry->PingText->SetText(FText::FromString(FString::FromInt(ServerData.Ping)));
				NewEntry->ServerNameText->SetText(FText::FromString(ServerData.Name));
				ServerList->AddChild(NewEntry);
			}
		}
		else UE_LOG(LogTemp, Error, TEXT("Invalid Search Settings or Search Result"));
	}
}

I’ve deviated from the lecture code a bit, but I believe I’ve kept the concept the same. I know that the Search Result is valid, because in my log it writes: [2022.06.14-01.02.35:968][906]LogTemp: Error: Attempting to Register Server Entry: FE2DF01F4C7A53E2873B8586D4459702 - 118 - 10. However, once I try to call the values in the struct and pass them to the Set Text function in my widget, I get a nullptr error.

Has anyone encountered this or would be able to tell me what’s happening?

I appreciate the help!

Can you show the code where SearchSettingsPtr is declared, initialised and also where the search is initiated. Also, the code where the delegate is bound.

The method itself you have there looks about right so the only thing I can think is that it’s not declared correctly or called correctly. The code for refreshing the sessions should look something like the following:

in the header:

TSharedPtr<class FOnlineSessionSearch> SessionSearch;

and in the cpp file, the search should be like the following:

void UPuzzlePlatformsGameInstance::RefreshSessions()
{
  if ( !ensure( SessionInterface != nullptr ) ) return;
  //  find sessions
  SessionSearch = MakeShareable( new FOnlineSessionSearch() );
  if ( SessionSearch.IsValid() )
  {
    UE_LOG( LogTemp, Warning, TEXT("Find Sessions Starting") )
    SessionSearch->bIsLanQuery = true;
    SessionSearch->MaxSearchResults = 500;
    SessionSearch->QuerySettings.Set( SEARCH_PRESENCE, true, EOnlineComparisonOp::Type::Equals );
    SessionInterface->FindSessions( 0, SessionSearch.ToSharedRef() );
  }
}

The declaration in the header:

protected:
	TSharedPtr<class FOnlineSessionSearch> SearchSettingsPtr;

And the “Refresh” Sessions:

void UMyGameInstance::FindServers()
{
	if (!SessionInterface.IsValid())
	{
		UE_LOG(LogTemp, Error, TEXT("Session Interface is Invalid"));
		return;
	}

	//Clear Server List to repopulate
	JoinGameMenu->ServerList->ClearChildren();

	//Get Player ID and Search for sessions
	FUniqueNetIdRepl PlayerNetID = GetWorld()->GetFirstLocalPlayerFromController()->GetUniqueNetIdForPlatformUser();
	if (PlayerNetID.IsValid())
	{
		UE_LOG(LogTemp, Error, TEXT("Browsing for Sessions"));
		SessionInterface->FindSessions(*PlayerNetID.GetUniqueNetId(), SearchSettingsPtr.ToSharedRef());
	}
	else
	{
		UE_LOG(LogTemp, Error, TEXT("Player ID or Controller is not valid"));
	}
}

void UMyGameInstance::OnFindServersComplete(bool Success)
{
	UE_LOG(LogTemp, Error, TEXT("Browsing Complete"));
	if (!Success || !SearchSettingsPtr.IsValid() || !JoinGameMenu)
	{
		UE_LOG(LogTemp, Error, TEXT("Browsing not successful, or Search Settings no longer valid"));
		return;
	}

	//Iterator for Index referencing purposes
	int32 Itr = 0;

	//Register each Server Entry to the Server Browser Widget
	for (FOnlineSessionSearchResult& SearchResult : SearchSettingsPtr->SearchResults)
	{
		if (SearchResult.IsValid())
		{
			FServerData ServerData;
			ServerData.Name = SearchResult.GetSessionIdStr();
			ServerData.MaxPlayers = SearchResult.Session.SessionSettings.NumPublicConnections;
			ServerData.CurrentPlayers = ServerData.MaxPlayers - SearchResult.Session.NumOpenPublicConnections;
			ServerData.Ping = SearchResult.PingInMs;
			ServerData.SearchIndex = Itr;

			UE_LOG(LogTemp, Error, TEXT("Attempting to Register Server Entry: %s - %d - %d"), *SearchResult.GetSessionIdStr(), SearchResult.PingInMs, SearchResult.Session.SessionSettings.NumPublicConnections);
			JoinGameMenu->RegisterServerEntry(ServerData);
			Itr++;
		}
	}
}

The Search Settings Ptr is initialized in the Init Function:

//Init Search Settings
SearchSettingsPtr = MakeShareable(new FOnlineSessionSearch());

and Search Settings are passed through the Join Game Menu (There’s checkboxes for LAN, etc.)

void UWULJoinSubMenu::SetSearchArgs()
{
	if (GameInstance && GameInstance->SearchSettingsPtr.IsValid())
	{
		GameInstance->SearchSettingsPtr->bIsLanQuery = SearchOnLAN->IsChecked();
	}

	RefreshServerBrowser();
}

I think I got this right as well. Kinda stumped on what would cause it to become invalidated as soon as I try to pull the value from it.

Thanks!

Well, I figured it out… and feel rather silly that it took me an entire week to do so.

I was creating the Server Row widget from the C++ Static Class, rather than from the Widget inheriting it. I don’t believe any of the text fields were constructed because of that, therefore they were nullptrs when trying to set their text.

Nonetheless, I appreciate the help. Thank you.

1 Like

Yes, because the Widget is based on the C++ but the controls are in the Widget Blueprint themselves. That makes sense. Glad you got it sorted.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.