OSS Steam: unable to get SteamIds for players in a session (for P2P messaging)

I don’t know if this will ever help anyone else, but I’ll leave it here just in case:

UE assumes that you’ll be using a client-server model for player connections, and parts of their Online Subsystem are built around that assumption.

The normal way to implement OnlineSubsessionSteam requires calling ServerTravel or ClientTravel for each of the players after joining the session, and from that point the player data is synced using UE’s replication sytem. Then you can get the SteamId of players from the PlayerState, as described in the forum below:
https://forums.unrealengine.com/t/how-to-get-player-steam-id/21709/28?page=2

I did find a way to get the SteamId for players in a lobby without using UE’s replication system, described below. It requires modifications to the OnlineSubsystemSteam plugin. To do modify it, you must move (and delete) the plugin folder out of “C:\Program Files\Epic Games\UE_4.25\Engine\Plugins\Online”, and put it into your own own “\Plugins” directory

You can get the SteamId by implementing a FOnlineAsyncEventSteamLobbyChatUpdate callback. In OnlineSessionInterface.h, add:

//This goes at the top of the file, with the other definitions. The bool at the end is whether the user joined or left the lobby:
DEFINE_ONLINE_DELEGATE_THREE_PARAM(OnLobbyMemberStateChanged, uint64, uint64, bool);

//This goes inside the IOnlineSession class (lower in the file):
DECLARE_MULTICAST_DELEGATE_ThreeParams(FOnLobbyMemberStateChanged, uint64, uint64, bool);
typedef FOnLobbyMemberStateChanged::FDelegate FOnLobbyMemberStateChangedDelegate;

In OnlineAsyncTaskManagerSteam.cpp, find and update the FOnlineAsyncEventSteamLobbyChatUpdate constructor to look like this:

FOnlineAsyncEventSteamLobbyChatUpdate(FOnlineSubsystemSteam* InSubsystem, const LobbyChatUpdate_t& InResults) :
		FOnlineAsyncEvent(InSubsystem),
		CallbackResults(InResults)
	{
		//Trigger any registered callbacks
		FOnlineSessionSteamPtr SessionInt = StaticCastSharedPtr<FOnlineSessionSteam>(Subsystem->GetSessionInterface());
		if (SessionInt.IsValid())
		{
			SessionInt.Get()->TriggerOnLobbyMemberStateChangedDelegates(InResults.m_ulSteamIDLobby, InResults.m_ulSteamIDUserChanged, (InResults.m_rgfChatMemberStateChange == 0x0001)); 

//Note: From the documentation here, 0x0001 is used for entering the lobby and all other values indicate leaving: https://partner.steamgames.com/doc/api/ISteamMatchmaking#EChatMemberStateChange
		}
	}

And finally, put a callback into your code to handle the event and grab the SteamId:

//Register the callback 
SessionInterface->OnLobbyMemberStateChangedDelegates.AddUObject(this, &UMultiplayerSessionsSubsystem::OnLobbyMemberStateChanged);

void UMultiplayerSessionsSubsystem::OnLobbyMemberStateChanged(uint64 LobbyId, uint64 OtherPlayerSteamId, bool enteringLobby)
{
	//Convert the steam id to a string
	std::string idString = std::to_string(OtherPlayerSteamId);
	FString idFString = UTF8_TO_TCHAR(idString.c_str());

	//Print it to the screen
	GEngine->AddOnScreenDebugMessage(
		-1,
		15.f,
		FColor::Orange,
FString::Printf(TEXT("UMultiplayerSessionMenu::OnLobbyMemberStateChanged --- steam id: %s"), *idFString)
	);
}