question

Martin avatar image
Martin asked

Unable to get serialized network descriptor from playfab PartyManager

Hi

I'm having some issues creating parties at the moment. This is my code:

Party::PartyNetwork *NewNetwork;
PartyError err = PartyManager::GetSingleton().ConnectToNetwork(&networkDescriptor, nullptr, &NewNetwork);
if (PARTY_FAILED(err))
{
	PartyString errorMessage;
	return PartyManager::GetErrorMessage(err, &errorMessage);
}
uint32_t NetworkCount = 0;
Party::PartyNetworkArray Networks;
err = PartyManager::GetSingleton().GetNetworks(&NetworkCount, &Networks);
if (PARTY_FAILED(err))
{
	PartyString errorMessage;
	return PartyManager::GetErrorMessage(err, &errorMessage);
}

err = Networks[0]->AuthenticateLocalUser(CurrentLocalUser, TCHAR_TO_UTF8(*InviteId), nullptr);
if (PARTY_FAILED(err))
{
	PartyString errorMessage;
	return PartyManager::GetErrorMessage(err, &errorMessage);
}

err = Networks[0]->GetNetworkDescriptor(&NewNetworkDescriptor);
if (PARTY_FAILED(err))
{
	PartyString errorMessage;
	return PartyManager::GetErrorMessage(err, &errorMessage);
}
err = PartyManager::GetSingleton().SerializeNetworkDescriptor(&NewNetworkDescriptor, SerializedNetworkDesctor);
if (PARTY_FAILED(err))
{
	PartyString errorMessage;
	return PartyManager::GetErrorMessage(err, &errorMessage);
}

return SerializedNetworkDesctor;

From this, I am trying to connect to a network and share the serialized network descriptor. However when I try to run this code, I get all the way through to the SerializeNetworkDescriptor() call and then I get the error:

the network descriptor is a placeholder that cannot be used on this device at this time

Is there something I'm doing wrong here? It seems as if I'm able to connect to the party network fine, but I'm just not able to serialize the network descriptor for others to join.

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

scott.munro@microsoft.com avatar image
scott.munro@microsoft.com answered

Hi @Martin

It sounds like we reached a resolution outside of this thread, so I wanted to come back and make sure that resolution was posted here for other's benefit.

The core issue turned out to be that the titlePlayerEntityToken being passed into PartyManager::CreateLocalUser was corrupted. Unfortunately there is a bug in PlayFab Party's client SDK that was surfacing this problem as an "unknown error". The dev team has been made aware of this bug. Thanks for your patience and assistance in finding this.

1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Martin avatar image Martin commented ·

Thanks Scott.

Turns out the TCHAR_TO_UTF8 macro in UE4 has issues when it goes above 128 chars, this causes the memory to be freed immediately after use. Think its working better now :)

1 Like 1 ·
Seth Du avatar image
Seth Du answered

May I ask are you implementing the preview feature PlayFab Party? If so, please create a support ticket so that the corresponding team will help handle your question.

2 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

toddsa avatar image toddsa commented ·

I don't see a call to PartyManager::GetSingleton().CreateNewNetwork(), is that occurring someplace else?

The call to PartyManager::SerializeNetworkDescriptor() typically occurs after connecting to the network and from the result of the state change PartyStateChangeType::CreateNewNetworkCompleted

,

I don't see the call to PartyManager::GetSingleton().CreateNewNetwork(), did that occur someplace else?

Typically you would call PartyManager::SerializeNetworkDescriptor() using the result of the state change PartyStateChangeType::CreateNewNetworkCompleted after the network has been created.What platform are you, Have you looked at the Party Chat sample?
0 Likes 0 ·
Martin avatar image Martin toddsa commented ·

Hi
Sorry yes the call to CreateNewNetwork is elsewhere and that seems successful.
After investigation, It seems like We receive the NetworkDestroyed state change. with the error message:

"the network operation cannot complete because creating the network failed"

This is my code for creating the network:
    PartyNetworkConfiguration cfg = {};


    cfg.maxDeviceCount = 3;
    cfg.maxDevicesPerUserCount = 1;
    cfg.maxEndpointsPerDeviceCount = 1;
    cfg.maxUserCount = 3;
    cfg.maxUsersPerDeviceCount = 1;


	PartyInvitationConfiguration InviteConfig;
	InviteConfig.entityIdCount = 0;
	InviteConfig.revocability = Party::PartyInvitationRevocability::Anyone;
	InviteConfig.identifier = TCHAR_TO_UTF8 (*InviteId);


    PartyNetworkDescriptor networkDescriptor = {};


    err = PartyManager::GetSingleton().CreateNewNetwork(CurrentLocalUser, &cfg, 0, nullptr, &invitationConfiguration, nullptr, &networkDescriptor, nullptr);


    if (PARTY_FAILED(err))
    {
		PartyString errorMessage;
		return PartyManager::GetErrorMessage(err, &errorMessage);
    }

The only difference from the sample is that we get the invite id and local user from elsewhere, but I have checked that these are valid.

0 Likes 0 ·
toddsa avatar image
toddsa answered

The call to PartyManager::GetSingleton().SerializeNetworkDescriptor() looks out of place. It should most likely be PartyManager::GetSingleton().DeserializeNetworkDescriptor().

The first client should create and connect to a network and then "Deserialize" the descriptor and send it to the other clients. The other clients will "Serialize" the descriptor and connect to the network.

If you are keeping the debugger attached to a client then it most likely will get disconnected from a time out.

1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Martin avatar image Martin commented ·

This doesn't seem right. The call to SerializeNetworkDescriptor() takes a PartyNetworkDescriptor structure, and converts it to a char* string. Where as the DeserializeNetworkDescriptor() will do the reverse.


In this case, we're getting the PartyNetworkDescriptor structure from the call to GetNetworkDescriptor() and want to send it to a remote user as a string, so I'm assuming that the call to SerializeNetworkDescriptor() would be the one to use. If not, I'm not sure how we would get the string, or how to send it over a network.

Also, the error happens no matter if we have debugger attached or not

0 Likes 0 ·
scott.munro@microsoft.com avatar image
scott.munro@microsoft.com answered

Hi Martin!

First off, I agree with you that calling SerializeNetworkDescriptor (rather than Deserialize) is the appropriate thing to do. You are on track there :)

Now to really dig into your question...

Looking at your post I see a couple of things that seem off/interest me.

1. You mention a number of APIs succeeding despite your SerializeNetworkDescriptor call failing. I think there may be a misunderstanding or lack-of-clarification on what success you are talking about here. When you say CreateNewNetwork and ConnectToNetwork are "succeeding" do you mean that CreateNewNetwork returns a success PartyError? If that's the case it's important to keep in mind that significant portions of the PlayFab Party API are asynchronous. The synchronous success code that you received from calling CreateNewNetwork or ConnectToNetwork is pretty much just parameter validation that you haven't enqueued a bogus request. I suggest to truly understand how successful these operations are you look at the relevant completion state changes (CreateNewNetworkCompletedStateChange and ConnectToNetworkCompletedStateChange) they will be generated when the operations asynchronously complete by calling StartProcessingStateChanges. Be sure to inspect the result and errorDetail fields on those state change objects. The result field will let you know what class of failure (or success) you completed with and the errorDetail will give you some diagnostic info that can be translated into a developer-readable string via PartyManager::GetErrorMessage

2. How are you calling ConnectToNetwork in relation to CreateNewNetwork? From context I gather you are calling CreateNewNetwork then immediately calling ConnectToNetwork with the resulting networkdescriptor and then trying to serialize that network descriptor to transmit to other clients. Is this correct? If so, then while it is true you can use the network descriptor from CreateNewNetwork immediately in a call to ConnectToNetwork, that network descriptor cannot yet be used in the call to SerializeNetworkDescriptor. The reason again is the asynchronous nature of the API. As referenced by the error message you get from SerializeNetworkDescriptor, CreateNewNetwork's initial network descriptor result is just a placeholder which allows you to queue network connections. If you want to serialize that network descriptor you must wait until the CreateNewNetwork operation completes successfully as indicated by a CreateNewNetworkCompletedStateChange with a success result. That state change will have the fully formed network descriptor that you can then serialize and pass to other clients

3. This one's a bit beside the point but I noticed a bit of an anti-pattern in your ConnectToNetwork code.

What you posted was:

Party::PartyNetwork *NewNetwork;
PartyError err = PartyManager::GetSingleton().ConnectToNetwork(?tworkDescriptor, nullptr, &NewNetwork);
if (PARTY_FAILED(err))
{
PartyString errorMessage;
return PartyManager::GetErrorMessage(err, &errorMessage);
}
uint32_t NetworkCount = 0;
Party::PartyNetworkArray Networks;
err = PartyManager::GetSingleton().GetNetworks(&NetworkCount, &Networks);
if (PARTY_FAILED(err))
{
PartyString errorMessage;
return PartyManager::GetErrorMessage(err, &errorMessage);
}


err = Networks[0]->AuthenticateLocalUser(CurrentLocalUser, TCHAR_TO_UTF8(*InviteId), nullptr);

and what stands out to me is that you connect to a network which gives you back a PartyNetwork object but then don't use that object to call AuthenticateLocalUser. Instead you query for the full list of network objects via GetNetworks and then arbitrarily use the first one. I would recommend simplifying this by removing the GetNetworks part of that code

Party::PartyNetwork *NewNetwork;

PartyError err = PartyManager::GetSingleton().ConnectToNetwork(networkDescriptor, nullptr, &NewNetwork);

if (PARTY_FAILED(err))

{

PartyString errorMessage;

return PartyManager::GetErrorMessage(err, &errorMessage);

}

uint32_t NetworkCount = 0;

Party::PartyNetworkArray Networks;

err = PartyManager::GetSingleton().GetNetworks(&NetworkCount, &Networks);

if (PARTY_FAILED(err))

{

PartyString errorMessage;

return PartyManager::GetErrorMessage(err, &errorMessage);

}

err = Networks[0]->AuthenticateLocalUser(CurrentLocalUser, TCHAR_TO_UTF8(*InviteId), nullptr);

Let me know if that clarifies things!

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Martin avatar image
Martin answered

Thanks for the answer Scott.


I've managed to simplify things down a bit from my original problem, the problem seems to be when creating the network. The main issue is that the network is responding with a failure in creating the network in the first place. Currently, I'm not calling the connect code at all, I'm just trying to create the network.

After a call to CreateNewNetwork, as specified in the original code, I now call this code very tick:

	uint32_t PartyStateChangeCount;
	PartyStateChangeArray StateChangeArray;
	PartyError err = PartyManager::GetSingleton().StartProcessingStateChanges(&PartyStateChangeCount, &StateChangeArray);
	if (PARTY_FAILED(err))
	{
		PartyString errorMessage;
		PartyError Error = PartyManager::GetErrorMessage(err, &errorMessage);
		UE_LOG(LogTemp, Warning, TEXT("Error Unable to get state chage: %s"), UTF8_TO_TCHAR(errorMessage));
		return;
	}
	if (PartyStateChangeCount > 0)
	{
		for (uint32_t ChangeCount = 0; ChangeCount < PartyStateChangeCount; ChangeCount++)
		{
			UE_LOG(LogTemp, Warning, TEXT("state chage: %s"), *StateChangeToString(StateChangeArray[ChangeCount]));
			switch (StateChangeArray[ChangeCount]->stateChangeType)
			{
			case PartyStateChangeType::CreateNewNetworkCompleted:
			{
				PartyCreateNewNetworkCompletedStateChange* NetworkCreatedState = (PartyCreateNewNetworkCompletedStateChange*)StateChangeArray[ChangeCount];
				PartyString errorMessage;
				PartyError Error = PartyManager::GetErrorMessage(NetworkCreatedState->errorDetail, &errorMessage);
				UE_LOG(LogTemp, Warning, TEXT("Netowrk Created: result %d  message: %s"), (int)NetworkCreatedState->result, UTF8_TO_TCHAR(errorMessage));
				break;
			}
			}
		}
	}
	PartyManager::GetSingleton().FinishProcessingStateChanges(PartyStateChangeCount, StateChangeArray);

When this executes, I get the following output:

[2020.02.06-11.27.31:821][374]LogTemp: Warning: Found 1 State changes
[2020.02.06-11.27.31:822][374]LogTemp: Warning: state chage: RegionChanged
[2020.02.06-11.27.32:030][387]LogTemp: Warning: Found 1 State changes
[2020.02.06-11.27.32:030][387]LogTemp: Warning: state chage: CreateNewNetworkCompleted
[2020.02.06-11.27.37:143][387]LogTemp: Warning: Netowrk Created: result 1  message: encountered unknown error

So the main problem at the moment seems to be this "unknown error" when creating the party. Do you have any idea what might be causing this?

Thanks

2 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

scott.munro@microsoft.com avatar image scott.munro@microsoft.com commented ·

Apologies for the delay @Martin! My notification settings weren't correct so I had no idea you responded 6 days ago :(

The next avenue I would check would be what the state change result and error detail on the RegionsChanged state change is. It might indicate something interesting.

is the code you posted for how you create your networks still accurate/up-to-date? I notice a weird discrepancy where your invitation configuration is named `InviteConfig` but when you pass the configuration into the CreateNewNetwork call you pass in something different called `invitationConfiguration`. If it's out of date, I'd appreciate an update!

0 Likes 0 ·
Martin avatar image Martin scott.munro@microsoft.com commented ·

Hi Scott
Thanks for looking at this, It looks like the region change has happened successfully. I get a 0 result with a message of "operation succeeded"

The code is up to date, I can confirm we are using the correct InviteConfig variable, and still getting the same error. This appears to be a copy/paste error for the original code, sorry. Let me know if theres anything else you need

0 Likes 0 ·

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.