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:
- 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
- I use a packaged game, different Steam accounts and the same search region
- 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);
}
}
}