Why does Steam session info always report incorrect player count (zero)

Hi,

Has anyone come across an issue with the Steam OSS (using server browsing) that the session always reports that NumOpenPublicConnections is always equal to NumPublicConnections.

That is, it appears that there are no players in the session.

Our code works fine with the NULL OSS and reports the correct number of players.

Documentation on both Steamworks and the OSS is somewhat thin on the ground and so I’m currently stumbling around in the dark trying to fix this. We’re only temporarily using the Steam server browsing, but it does make it more difficult to find a server that has players in it.

Any suggestions gratefully received.

Regards,

Greg

We have the same issue. Found any solution? Could it be that we don’t have a unique APP-id?

Can you check out logs, it seems if theres something wrong with communicating with Steam it should return errors there

Joining, displaying and fetching information from the sessions found works beautifully. It’s only the player count which does not register. The logs only return the servers found, and no errors are thrown.

We’re have the same issue and I’ve been pulling my hair out with this. So far, it seems like Steam does not update the player count for some reason:

OnlineSessionAsyncServerSteam.cpp
void FOnlineAsyncTaskSteamFindServerBase::ParseSearchResult(class gameserveritem_t* ServerDetails)

ServerDetails->m_nPlayers always return 0, which is updated inside the Steam API so it’s out of reach.

Anyone could explain why is that? Maybe an authentication/registration issue?

Thank you

They had a bug before where they incorrectly registered players for session upon joining it, but they said they fixed it. Perhaps it’s something related?

No news on this?

Are you guys testing it in the editor i.e. using stand alone? I had this issue but when I packaged using the “Development” configuration it was correct.

Even in packaged product.

Have the same issue, I have this when Steam is online and I’m hosting a LAN match, please can someone help?

I’ve been getting this since like 4.6. NumPublicConnections works but NumOpenPublicConnections always returns 0 because m_nPlayers always returns 0 here

https://github.com/EpicGames/UnrealEngine/blob/f794321ffcad597c6232bc706304c0c9b4e154b2/Engine/Plugins/Online/OnlineSubsystemSteam/Source/Private/OnlineSessionAsyncServerSteam.cpp#L962

I am using app id 480, so not sure if that could cause it.

EDIT: I am no longer using app id 480 and I still get the same issues.

It took me quite some time to figure this one out so I will share what I know in here.

When searching for a dedicated server, getting player count of 0 is expected behavior for OnlineSubsystemSteam since the it never go through the Steam User Authentication process when joining a dedicated server.

Player count for a Presence Session search will always works since SteamMatchmaking()->JoinLobby(LobbyId) gets called upon player join a Presence Session to let steam backend knows that player is in that session. the corresponding step is missing while player join a Dedicated Session.

It would make more sense to do the authentication in the stage of “JoinSession” like what a Presence Session do, But unlike join a steam lobby, authentication on dedicated server require sending data from client to server to complete, Which is not easy to do since a stateful connection between client and server haven’t been established yet and Session-less connection messages are not easily accessible.

It looks strange to me that OnlineSubsystemSteam didn’t handle this process since it is required for some useful server matchmaking functionalities provided by steam to be functional (i.e. backend side query filters like “noplayers”, “notfull” and VAC).

The work around I use is doing authentication in PlayerController after connection have been established and I can use RPC calls to send data needed for authentication.

In MyPlayerController.h define a struct for authentication token:

//A struct holds necessary infos sent from client to complete authentication
USTRUCT()
struct FSteamAuthenticationToken
{
	GENERATED_BODY()

public:
	bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess)
	{
		//Ar.ByteOrderSerialize(rgchToken, 1024);
		Ar << rgchTokenString;
		Ar << unTokenLen;
		Ar << steamid;

		bOutSuccess = true;
		return true;
	}
public:

	FString rgchTokenString;
	uint32 unTokenLen = 0;
	uint64 steamid;
};

template<>
struct TStructOpsTypeTraits<FSteamAuthenticationToken> : public TStructOpsTypeTraitsBase2<FSteamAuthenticationToken>
{
	enum
	{
		WithNetSerializer = true
	};
};

Define RPC functions, our AuthTicket and Steamcallback:

UFUNCTION(Client, Reliable)
void ClientRequestSteamAuth();

UFUNCTION(Server, Reliable, WithValidation)
void ServerBeginSteamAuth(FSteamAuthenticationToken AuthToken);

//A AuthTickect client should keep track of, used when client log off 
HAuthTicket m_hAuthTicket;

//Get called on server when authentication complete with result.
STEAM_GAMESERVER_CALLBACK_MANUAL(ANetworkPlayerController, OnAuthTicketResponse, ValidateAuthTicketResponse_t, OnAuthTicketResponseCallback);

MyPlayerController.cpp:

void ANetworkPlayerController::ClientRequestSteamAuth_Implementation()
{
	if (SteamUser())
	{
		uint8 rgchToken[1024];
		uint32 unTokenLen = 0;
		m_hAuthTicket = SteamUser()->GetAuthSessionTicket(rgchToken, sizeof(rgchToken), &unTokenLen);

		FSteamAuthenticationToken SteamAuthToken;

		SteamAuthToken.rgchTokenString = BytesToString(rgchToken, 1024);
		SteamAuthToken.unTokenLen = unTokenLen;
		SteamAuthToken.steamid = SteamUser()->GetSteamID().ConvertToUint64();

		if (m_hAuthTicket != k_HAuthTicketInvalid)
		{
			ServerBeginSteamAuth(SteamAuthToken);
		}
            else
            {
                   //TODO: Client disconnect self from server since authentication failed.
            }

	}
}

bool ANetworkPlayerController::ServerBeginSteamAuth_Validate(FSteamAuthenticationToken AuthToken)
{
	return true;
}

void ANetworkPlayerController::ServerBeginSteamAuth_Implementation(FSteamAuthenticationToken AuthToken)
{
	uint8 rgchToken[1024];
	StringToBytes(AuthToken.rgchTokenString, rgchToken, 1024);
        
	OnAuthTicketResponseCallback.Register(this, &ANetworkPlayerController::OnAuthTicketResponse);

	if (k_EBeginAuthSessionResultOK != SteamGameServer()->BeginAuthSession(rgchToken, AuthToken.unTokenLen, AuthToken.steamid))
	{
		//TODO: Server disconnect client since authentication failed.
	        
		SteamGameServer()->EndAuthSession(AuthToken.steamid);
	}
}

void ANetworkPlayerController::OnAuthTicketResponse(ValidateAuthTicketResponse_t* CallbackData)
{
	uint64 PlayerSteamId = *((uint64*)PlayerState->UniqueId.GetUniqueNetId()->GetBytes());

	if (CallbackData->m_SteamID == PlayerSteamId)
	{
		OnAuthTicketResponseCallback.Unregister();

		if (CallbackData->m_eAuthSessionResponse > EAuthSessionResponse::k_EAuthSessionResponseOK)
		{
		      //TODO: Server disconnect client since authentication failed.
		}
	}
}

Also notice SteamUser()->CancelAuthTicket(m_hAuthTicket); should be called upon client actively logoff or lost connection to server, which I did not include in code above.

For others searching, steam player count is zero, steam player info not showing players. Steam BUpdateUser fails.
I had this very issue with dedicated servers and players joining without a lobby. This fix worked! Thank you so much.