Max results find session Steam

Good time of day.
One fact haunts me.
I am trying to write a functionality for creating/joining sessions on the Steam platform.
I wrote the code, for example, I even managed to test the connection, but:

  1. I use the application identifier in steam 480, this identifier was specially created by Steam developers to test their applications, who do not have their own identifier
  2. I use a packaged game, different Steam accounts and the same search region
  3. I understand why sometimes the game is there and sometimes it is not (a similar topic).
    As I understand it, Epic Games - further, EG wrote their interfaces for the most common playgrounds, such as Steam, Epic Games, NULL and so on. Why did they do it? Most likely for unification, so that one code can work on several sites with minimal changes. Yes, it’s cool.
    But there are some problems.
    Using the Steam application ID 480, I came across the fact that the maximum number of sessions that Steam can return to you is 50. The same is written in the official Steamworks documentation.

I would like to know how to expand this number of sessions found?
Even if I have my own Steam app ID, 50 is a drop in the bucket!
I also found an interesting thing in the documentation ISteamMatchmaking::AddRequestLobbyListResultCountFilter sets a limit on the number of lobbies returned. The lower the number, the faster it is to upload the results and lobby information to the client.
But as I understood, in order to use it, I need to use not the built-in UE4 functions, but connect the Steamworks module directly to my project.

But I still wanted to use the built-in C++ functions from EG, because they have the most guides, it seems to me.

Log file in my project:

Maybe someone has a solution to this problem?

CreateGameSession

void AMP_UE4Character::CreateGameSession()
{
	if (!OnlineSessionInterface.IsValid())
	{
		return;
	}

	auto ExistingSession = OnlineSessionInterface->GetNamedSession(NAME_GameSession);
	if (ExistingSession != nullptr)
	{
		OnlineSessionInterface->DestroySession(NAME_GameSession);
	}

	OnlineSessionInterface->AddOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegate);

	TSharedPtr<FOnlineSessionSettings> SessionSettings = MakeShareable(new FOnlineSessionSettings());
	SessionSettings->bAllowInvites = true;
	SessionSettings->bIsLANMatch = IOnlineSubsystem::Get()->GetSubsystemName() == "NULL"? true : false;
	SessionSettings->NumPublicConnections = 10;
	SessionSettings->bAllowJoinInProgress = true;
	SessionSettings->bAllowJoinViaPresence = true;
	SessionSettings->bShouldAdvertise = true;
	SessionSettings->bUsesPresence = true;
	SessionSettings->bUseLobbiesIfAvailable = true;
	SessionSettings->bIsDedicated = false;
	SessionSettings->Set(FName("MatchType"), FString("FreeForAll"), EOnlineDataAdvertisementType::ViaOnlineServiceAndPing);
	const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
	OnlineSessionInterface->CreateSession(*LocalPlayer->GetPreferredUniqueNetId(), 
										   NAME_GameSession, 
										   *SessionSettings);
	
}

OnCreateSessionComplete

void AMP_UE4Character::OnCreateSessionComplete(FName NameSession, bool bWasSuccessful)
{
	if (bWasSuccessful)
	{
		if (GEngine)
		{
			GEngine->AddOnScreenDebugMessage(
				-1,
				15.f,
				FColor::Cyan,
				FString::Printf(TEXT("Create session: %s"),*NameSession.ToString()));
		}

		UWorld* World = GetWorld();
		if (World)
		{
			World->ServerTravel(FString("/Game/Maps/Lobby?listen"));
		}
	}
	else
	{
		if (GEngine)
		{
			GEngine->AddOnScreenDebugMessage(
				-1,
				15.f,
				FColor::Red,
				FString(TEXT("Failed create session")));
		}
	}
}

JoinGameSession

void AMP_UE4Character::JoinGameSession()
{
	if (!OnlineSessionInterface.IsValid())
	{
		return;
	}

	OnlineSessionInterface->AddOnFindSessionsCompleteDelegate_Handle(FindSessionsCompleteDelegate);

	SessionSearch = MakeShareable(new FOnlineSessionSearch());
	SessionSearch->bIsLanQuery = false;
	SessionSearch->MaxSearchResults = 1000;
	SessionSearch->QuerySettings.Set(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals);
	const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
	OnlineSessionInterface->FindSessions(*LocalPlayer->GetPreferredUniqueNetId(), SessionSearch.ToSharedRef());
}

OnJoinSessionsComplete

void AMP_UE4Character::OnJoinSessionsComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result)
{
	if (!OnlineSessionInterface.IsValid())
	{
		return;
	}

	FString Address;
	if (OnlineSessionInterface->GetResolvedConnectString(NAME_GameSession, Address))
	{
		if (GEngine)
		{
			GEngine->AddOnScreenDebugMessage(
				-1,
				15.f,
				FColor::Yellow,
				FString::Printf(TEXT("Connection string: %s"), *Address)
			);
		}
		APlayerController* PlayerController = GetGameInstance()->GetFirstLocalPlayerController();
		if (PlayerController)
		{
			PlayerController->ClientTravel(Address, ETravelType::TRAVEL_Absolute);
		}
	}
}

OnFindSessionsComplete

void AMP_UE4Character::OnFindSessionsComplete(bool bWasSuccessful)
{
	if (!OnlineSessionInterface.IsValid())
	{
		return;
	}
	if (SessionSearch->SearchResults.Num() == 0 )
	{
		if (GEngine)
		{
			GEngine->AddOnScreenDebugMessage(
				-1,
				15.f,
				FColor::Emerald,
				FString::Printf(TEXT("Session search: 0")));
		}
	}

	for (auto Result : SessionSearch->SearchResults)
	{
		FString Id = Result.GetSessionIdStr();
		FString User = Result.Session.OwningUserName;
		FString MatchType;

		Result.Session.SessionSettings.Get(FName("MatchType"), MatchType);

		if (GEngine)
		{
			GEngine->AddOnScreenDebugMessage(
				-1,
				15.f,
				FColor::Emerald,
				FString::Printf(TEXT("Id: %s, User: %s"), *Id, *User));
		}

		if (MatchType == FString("FreeForAll"))
		{
			if (GEngine)
			{
				GEngine->AddOnScreenDebugMessage(
					-1,
					15.f,
					FColor::Emerald,
					FString::Printf(TEXT("Joing Match Type: %s"), *MatchType));
			}
			OnlineSessionInterface->AddOnJoinSessionCompleteDelegate_Handle(JoinSessionCompleteDelegate);
			const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();
			OnlineSessionInterface->JoinSession(*LocalPlayer->GetPreferredUniqueNetId(), NAME_GameSession, Result);
		}
	}

}

Hi and welcome to the GameDev.TV community.

I’ve never looked into how many results I get back from this but I always thought if I set MaxSearchResults to 1000 then I could up to that amount returned.

Is it possible it returns 50 and you have to request the next 50 and so on, so you don’t get more than is necessary?

Which course are you working on via the website and lecture specifically is causing the issues so I can better understand your issue.

I started taking the udemy course and wandered into your site in search of an answer, because it seemed to me that only something is actively discussed on it.
The course is called Unreal Engine 5 c++ Multiplayer Shooter, but this is not so important, since I understood from the discussions that you were doing something very similar in your course.

All that has been found out now is that when calling the FindSession method from OnlineSessionInterface, the method of the same name is called from OnlineSessionInterfaceSteam.
At the same time, FindSession from OnlineSessionInterfaceSteam returns itself, that is, recursion (I haven’t figured out how it works yet).

The extended log shows that when searching for a session, FOnlineAsyncTaskSteamFindLobbiesForFindSessions is called : [2024.01.26-14.12.43:408][233] LogOnline: Verbose: OSS: Async task ‘FOnlineAsyncTaskSteamFindLobbiesForFindSessions bWasSuccessful: 1 NumResults: 50’ succeeded in 0.518616 seconds

But I have not found a definition of this function anywhere. More precisely, I did not find it in the OnlineSessionAsyncLobbySteam.h file

I’m still haunted by the idea that you can connect Steamworks and use the Find/CreateSessions functions from the Steam API itself. But EG couldn’t have missed an important detail in 50 sessions and not given access to change this number.

According to the logs, it always outputs a result of 50 sessions and stops there without going over 50 each time to the value set in MaxSearchResults.

I would understand if I set MaxSearchResults = 100 and he went through the sessions 2 times 50 times, but he just returns the first 50 and that’s it.

At first, the idea was to somehow write 50 to the structure and run the next iteration of the search, and then running 2 times I would get 100 sessions, but each time it would run the same search with the same set of results or with minimal differences.

Yeah, that isn’t our course - that is Stephen Ulibarri. Stephen did do a section in the C++ course but here we only support the content of the gamedev tv courses that are hosted here and created by our team. We can’t really support third party content or people’s own projects unless it is based on or directly linked to the courses here. Sorry we can’t be of more help.

I do remember something that may be of use. he has a discord server which you can get access to if you signed up to one of his courses.

It’s a shame, I was hoping I could get help.
I know almost no English and therefore I communicate through a translator.
I would like to take the courses live, but the language barrier will not allow me to do this.

1 Like

I understand but we don’t have the resources to provide support outside of courses. I wish you all the best. And good luck in finding a solution

It’s a pity, because as I understand in your course, this problem is also present (judging by the topics) and it seemed to me that I was much closer to solving this problem.

Privacy & Terms