EOS OnlineService->GetLobbiesInterface()->FindLobbies() not work properly

I’m trying to use OnlineService (aka OSSv2) for an online game. A game client can create a lobby, but another game client cannot find the lobby via GetLabbiesInterface()->FindLobbyes()>.

2 game clients A and B. A and B use different Epic Accound logins:

  1. [Success] Use A to create the lobby. Lobbies can be found in the Epic Development Portal.
  2. [Success] Use A to find the lobby. FindLobbys() returned the correct lobby.
  3. [Failed] Use B to find the lobby. But got error:
2023-10-09 00:20:28.799 UnrealEditor[80654:18855762] [UE] [2023.10.08-16.20.28:799][142]LogEOSSDK: Warning: LogEOSLobby: Lobby membership count inconsistency
2023-10-09 00:20:28.799 UnrealEditor[80654:18855762] [UE] [2023.10.08-16.20.28:799][142]LogOnlineServices: Warning: [FLobbyDetailsEOS::GetLobbySnapshot] ResolveAccountIds Failed: Expected Count[1], Received Count[0], Lobby[f6ad313ebef0413380ba7c3cc232bf57]
2023-10-09 00:20:28.799 UnrealEditor[80654:18855762] [UE] [2023.10.08-16.20.28:799][142]LogOnlineServices: Warning: [FLobbyDataEOS::Create] FLobbyDetailsEOS::GetLobbySnapshot Failed: Lobby[Epic:1], Result[unknown]
2023-10-09 00:20:28.799 UnrealEditor[80654:18855762] [UE] [2023.10.08-16.20.28:799][142]LogOnlineServices: Warning: [FLobbyDataRegistryEOS::FindOrCreateFromLobbyDetails] FLobbyDataEOS::Create Failed: User[Epic:1 (EAS=[8cc24319af034b21842b27a508d15c4a] EOS=[000216e4bfc04842a690217ff9cebece])], Lobby[f6ad313ebef0413380ba7c3cc232bf57], Result[unknown]
2023-10-09 00:20:28.799 UnrealEditor[80654:18855762] [UE] [2023.10.08-16.20.28:799][142]LogOnlineServices: Warning: [FLobbySearchEOS::Create] FLobbyDataRegistryEOS::FindOrCreateFromLobbyDetails Failed: Unable to resolve search result. User[Epic:1 (EAS=[8cc24319af034b21842b27a508d15c4a] EOS=[000216e4bfc04842a690217ff9cebece])], Result[unknown]
2023-10-09 00:20:28.801 UnrealEditor[80654:18855762] [UE] [2023.10.08-16.20.28:801][142]LogOnlineServices: Warning: [FLobbiesEOSGS::JoinLobby] FLobbySearchEOS::Create Failed: User[Epic:1 (EAS=[8cc24319af034b21842b27a508d15c4a] EOS=[000216e4bfc04842a690217ff9cebece])], Result[unknown]

Login Params:

	FExternalUIShowLoginUI::Params Params;
	UIService->ShowLoginUI(MoveTemp(Params)).OnComplete([this](const TOnlineResult<FExternalUIShowLoginUI>& Result)
	...

Create Params:

	FCreateLobby::Params Params;
	Params.LocalAccountId = PlayerAccountInfo->AccountId;
	Params.LocalName = FName(GetNickName());
	Params.MaxMembers = 2;
	Params.SchemaId = FName(TEXT("GameLobby"));
	Params.bPresenceEnabled = true;
	Params.JoinPolicy = ELobbyJoinPolicy::PublicAdvertised;
	Params.Attributes.Emplace(FSchemaAttributeId(TEXT("MapName")), FString(TEXT("DefaultMap2")));
	LobbiesService->CreateLobby(MoveTemp(Params)).OnComplete([this](const TOnlineResult<FCreateLobby>& Result)
	...

Find Params:

	FFindLobbies::Params Params;
	Params.LocalAccountId = PlayerAccountInfo->AccountId;
	Params.MaxResults = 10;
	LobbiesService->FindLobbies(MoveTemp(Params)).OnComplete([this](const TOnlineResult<FFindLobbies>& Result)
	...

DefaultEngine.ini:

[OnlineServices]
DefaultServices = Epic

[OnlineServices.EOS]
ProductId = ...
SandboxId = p-...
DeploymentId = ...
ClientId = ...
ClientSecret = ...

[OnlineServices.Lobbies]
+SchemaDescriptors = (Id="GameLobby", ParentId="LobbyBase")
!SchemaCategoryAttributeDescriptors = ClearArray
+SchemaCategoryAttributeDescriptors = (SchemaId="LobbyBase", CategoryId="Lobby", AttributeIds=("SchemaCompatibilityId"))
+SchemaCategoryAttributeDescriptors = (SchemaId="LobbyBase", CategoryId="LobbyMember")
+SchemaCategoryAttributeDescriptors = (SchemaId="GameLobby", CategoryId="Lobby", AttributeIds=("GameMode", "GameSessionId", "MapName", "MatchTimeout"))
+SchemaCategoryAttributeDescriptors = (SchemaId="GameLobby", CategoryId="LobbyMember", AttributeIds=("Appearance"))
+SchemaAttributeDescriptors = (Id="SchemaCompatibilityId", Type="Int64", Flags=("Public", "SchemaCompatibilityId"))
+SchemaAttributeDescriptors = (Id="GameMode", Type="String", Flags=("Public"), MaxSize=64)
+SchemaAttributeDescriptors = (Id="GameSessionId", Type="String", Flags=("Private"), MaxSize=64)
+SchemaAttributeDescriptors = (Id="MapName", Type="String", Flags=("Public"), MaxSize=64)
+SchemaAttributeDescriptors = (Id="MatchTimeout", Type="Double", Flags=("Public"))
+SchemaAttributeDescriptors = (Id="Appearance", Type="String", Flags=("Public"), MaxSize=64)

UE Version:
Version: 5.3.1-28051148+++UE5+Release-5.3
Platform: macOS 13.5.2 (x86_64)

It’s a bug in FLobbyDetailsEOS::GetLobbySnapshot().

EOS_LobbyDetails_GetMemberByIndex is used to immediately retrieve individual members registered with a lobby. Note: this information is only available if you are actively in the lobby. It is not available for search results.

These codes fixed the problem.

TFuture<TDefaultErrorResultInternal<FLobbyServiceSnapshot>> FLobbyDetailsEOS::GetLobbySnapshot() const
{
	TSharedPtr<FAuthEOSGS> AuthInterface = Prerequisites->AuthInterface.Pin();
	if (!AuthInterface)
	{
		UE_LOG(LogOnlineServices, Warning, TEXT("[FLobbyDetailsEOS::GetLobbySnapshot] Failed: Auth interface missing. Lobby[%s]"),
			UTF8_TO_TCHAR(GetInfo()->GetLobbyIdEOS()));
		return MakeFulfilledPromise<TDefaultErrorResultInternal<FLobbyServiceSnapshot>>(Errors::MissingInterface()).GetFuture();
	}

	EOS_LobbyDetails_GetMemberCountOptions GetMemberCountOptions = {};
	GetMemberCountOptions.ApiVersion = 1;
	UE_EOS_CHECK_API_MISMATCH(EOS_LOBBYDETAILS_GETMEMBERCOUNT_API_LATEST, 1);

	const uint32_t MemberCount = EOS_LobbyDetails_GetMemberCount(LobbyDetailsHandle, &GetMemberCountOptions);

	TSharedRef<TArray<EOS_ProductUserId>> MemberProductUserIds = MakeShared<TArray<EOS_ProductUserId>>();
	MemberProductUserIds->Reserve(MemberCount);

	for (uint32_t MemberIndex = 0; MemberIndex < MemberCount; ++MemberIndex)
	{
		EOS_LobbyDetails_GetMemberByIndexOptions GetMemberByIndexOptions = {};
		GetMemberByIndexOptions.ApiVersion = 1;
		UE_EOS_CHECK_API_MISMATCH(EOS_LOBBYDETAILS_GETMEMBERBYINDEX_API_LATEST, 1);
		GetMemberByIndexOptions.MemberIndex = MemberIndex;
		auto MemberId = EOS_LobbyDetails_GetMemberByIndex(LobbyDetailsHandle, &GetMemberByIndexOptions);
		if (MemberId != nullptr)
		{
			MemberProductUserIds->Emplace(MemberId);
		}
	}

	TPromise<TDefaultErrorResultInternal<FLobbyServiceSnapshot>> Promise;
	TFuture<TDefaultErrorResultInternal<FLobbyServiceSnapshot>> Future = Promise.GetFuture();

	EOS_LobbyDetails_GetLobbyOwnerOptions GetLobbyOwnerOptions = {};
	GetLobbyOwnerOptions.ApiVersion = 1;
	UE_EOS_CHECK_API_MISMATCH(EOS_LOBBYDETAILS_GETLOBBYOWNER_API_LATEST, 1);

	const EOS_ProductUserId LobbyOwner = EOS_LobbyDetails_GetLobbyOwner(LobbyDetailsHandle, &GetLobbyOwnerOptions);

	if (MemberProductUserIds->IsEmpty())
	{
		MemberProductUserIds->Emplace(LobbyOwner);
	}

	// Resolve lobby member product user ids to FAccountId before proceeding.
	AuthInterface->ResolveAccountIds(AssociatedLocalUser, *MemberProductUserIds)
	             .Next([StrongThis = AsShared(), Promise = MoveTemp(Promise), MemberProductUserIds, LobbyOwner](
		             TArray<FAccountId>&& ResolvedAccountIds) mutable
	{
		if (MemberProductUserIds->Num() != ResolvedAccountIds.Num())
		{
			UE_LOG(LogOnlineServices, Warning, TEXT("[FLobbyDetailsEOS::GetLobbySnapshot] ResolveAccountIds Failed: Expected Count[%d], Received Count[%d], Lobby[%s]"),
				MemberProductUserIds->Num(), ResolvedAccountIds.Num(), UTF8_TO_TCHAR(StrongThis->GetInfo()->GetLobbyIdEOS()));
			Promise.EmplaceValue(Errors::Unknown());
			return;
		}

		FLobbyServiceSnapshot LobbyServiceSnapshot;
		LobbyServiceSnapshot.MaxMembers = StrongThis->GetInfo()->GetMaxMembers();
		LobbyServiceSnapshot.JoinPolicy = TranslateJoinPolicy(StrongThis->GetInfo()->GetPermissionLevel());
		
		// Resolve member info.
		{
			for (int32 MemberIndex = 0; MemberIndex < MemberProductUserIds->Num(); ++MemberIndex)
			{
				const EOS_ProductUserId MemberProductUserId = (*MemberProductUserIds)[MemberIndex];
				const FAccountId ResolvedMemberAccountId = ResolvedAccountIds[MemberIndex];

				if (MemberProductUserId == LobbyOwner)
				{
					LobbyServiceSnapshot.OwnerAccountId = ResolvedMemberAccountId;
				}

				LobbyServiceSnapshot.Members.Add(ResolvedMemberAccountId);
			}
		}

		// Resolve lobby attributes
		{
			EOS_LobbyDetails_GetAttributeCountOptions GetAttributeCountOptions = {};
			GetAttributeCountOptions.ApiVersion = 1;
			UE_EOS_CHECK_API_MISMATCH(EOS_LOBBYDETAILS_GETATTRIBUTECOUNT_API_LATEST, 1);

			const uint32_t AttributeCount = EOS_LobbyDetails_GetAttributeCount(StrongThis->LobbyDetailsHandle, &GetAttributeCountOptions);
			for (uint32_t AttributeIndex = 0; AttributeIndex < AttributeCount; ++AttributeIndex)
			{
				EOS_LobbyDetails_CopyAttributeByIndexOptions CopyAttributeByIndexOptions = {};
				CopyAttributeByIndexOptions.ApiVersion = 1;
				UE_EOS_CHECK_API_MISMATCH(EOS_LOBBYDETAILS_COPYATTRIBUTEBYINDEX_API_LATEST, 1);
				CopyAttributeByIndexOptions.AttrIndex = AttributeIndex;

				EOS_Lobby_Attribute* LobbyAttribute = nullptr;
				ON_SCOPE_EXIT
				{
					EOS_Lobby_Attribute_Release(LobbyAttribute);
				};

				EOS_EResult EOSResult = EOS_LobbyDetails_CopyAttributeByIndex(StrongThis->LobbyDetailsHandle, &CopyAttributeByIndexOptions, &LobbyAttribute);
				if (EOSResult != EOS_EResult::EOS_Success)
				{
					UE_LOG(LogOnlineServices, Warning, TEXT("[FLobbyDetailsEOS::GetLobbySnapshot] EOS_LobbyDetails_CopyAttributeByIndex Failed: Lobby[%s], Result[%s]"),
						UTF8_TO_TCHAR(StrongThis->GetInfo()->GetLobbyIdEOS()), *LexToString(EOSResult));
					Promise.EmplaceValue(Errors::FromEOSResult(EOSResult));
					return;
				}

				FLobbyAttributeTranslator<ELobbyTranslationType::FromService> AttributeTranslator(*LobbyAttribute->Data);
				LobbyServiceSnapshot.SchemaServiceSnapshot.Attributes.Add(MoveTemp(AttributeTranslator.GetMutableAttributeData()));
			}
		}

		UE_LOG(LogOnlineServices, VeryVerbose, TEXT("[FLobbyDetailsEOS::GetLobbySnapshot] Succeeded: Lobby[%s]"),
			UTF8_TO_TCHAR(StrongThis->GetInfo()->GetLobbyIdEOS()));
		Promise.EmplaceValue(MoveTemp(LobbyServiceSnapshot));
	});

	return Future;
}
2 Likes

OkOk, it’s a bug :slightly_frowning_face:

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