> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Usando o PlayFab Party com o MPSD

> Combine a rede de voz e de dados do PlayFab Party com o XBOX Multiplayer Session Directory (MPSD) para o gerenciamento de sessões e convites entre redes.

Os cenários multijogador do XBOX dependem do uso do serviço Multiplayer Session Directory (MPSD) e de documentos do MPSD. Os documentos do MPSD funcionam como a lista de participantes da sua sessão de jogo atual e impulsionam experiências multijogador como matchmaking, convites da plataforma, listas de jogadores recentes e ingresso em andamento.

Neste documento, descreveremos como você pode incorporar o PlayFab Party a fluxos multijogador comuns que exigem o MPSD.

Este documento não fornece uma discussão aprofundada sobre o MPSD e todos os seus recursos. Para obter mais informações, consulte a [documentação do MPSD](/pt-BR/services/xbox-services/multiplayer/mpsd/live-mpsd-overview).

## Matchmaking

Veja a seguir um fluxo simplificado de como usar o matchmaking e o MPSD junto com o PlayFab Party:

1. Os jogadores criarão sessões do MPSD e se reunirão nelas; essas sessões representam os grupos que desejam jogar juntos nas sessões de matchmaking. Os jogadores se reunirão nessas sessões usando os recursos de convite e ingresso do XBOX.

2. Esses grupos de jogadores enviarão tíquetes ao serviço de matchmaking, que reunirá grupos de jogadores compatíveis em uma sessão de matchmaking. Essa sessão de matchmaking será, por sua vez, representada por um novo documento de sessão no qual os jogadores ingressarão. Os jogadores também devem escutar as alterações nesse documento de sessão.

3. Depois que a sessão de matchmaking for finalizada e a lista de participantes estiver bloqueada, o título deverá eleger um dos membros da sessão de matchmaking para configurar a rede do PlayFab Party. Uma estratégia simples para selecionar o criador da rede do Party é usar o primeiro membro do documento de sessão do MPSD de matchmaking.

4. O membro selecionado criará a rede com um `PartyInvitation` inicial que restringe o acesso à rede apenas aos membros da sessão de matchmaking. Depois que a criação da rede for concluída com êxito, o membro selecionado deverá publicar o descritor de rede resultante e o convite do Party no documento de sessão como uma propriedade de sessão para que os outros membros a usem.

   ```cpp theme={null}
   void
   OnMatchmakingSessionFinalized(
       uint32_t usersInSessionCount,
       const uint64_t* usersInSession
       )
   {
       PartyInvitationConfiguration initialInvite{};
       initialInvite.identifier = nullptr; // let Party select the invitation identifier for simplicity
       initialInvite.revocability = PartyInvitationRevocability::Anyone; // must be revocable by anyone

       // the updated invite should contain all users in the matchmaking session
       std::vector<PartyString> entityIdsInSession;
       for (uint32_t i = 0; i < usersInSessionCount; ++i)
       {
           uint64_t xboxUserId = usersInSession[i];
           // Call title-defined xuid->entityid mapping helper
           PartyString xboxUserEntityId = GetEntityIdFromXboxUserId(xboxUserId);
           if (xboxUserEntityId != nullptr)
           {
               entityIdsInSession.push_back(xboxUserEntityId);
           }
           else
           {
               DEBUGLOG("User %llu did not have a matching entity ID.", xboxUserId);
           }
       }
       initialInvite.entityIdCount = entityIdsInSession.size();
       initialInvite.entityIds = entityIdsInSession.data();

       // This is an asynchronous call. It will be completed when StartProcessingStateChanges generates a
       // PartyCreateNewNetworkCompletedStateChange struct
       PartyError error = PartyManager::GetSingleton().CreateNewNetwork(
           m_localPartyUser,
           &networkConfiguration,
           0,
           nullptr,
           &initialInvite,
           nullptr,
           nullptr,
           nullptr);
       if (FAILED(error))
       {
           DEBUGLOG("PartyManager::CreateNetwork failed! 0x%08x\n", error);
           return;
       }
   }

   void
   HandleCreateNewNetworkCompleted(
       const PartyCreateNewNetworkCompletedStateChange& createNewNetworkCompletedStateChange
       )
   {
       if (createNewNetworkCompletedStateChange.result == PartyStateChangeResult::Succeeded)
       {
           // The network was created successfully! Post the networks descriptor and invitation

           char serializedDescriptor[c_maxSerializedNetworkDescriptorStringLength + 1];
           PartyError error = PartyManager::SerializeNetworkDescriptor(
               &createNewNetworkCompletedStateChange.networkDescriptor,
               serializedDescriptor);
           if (PARTY_FAILED(error))
           {
               DEBUGLOG("PartyManager::SerializeNetworkDescriptor failed: 0x%08x\n", error);
               return;
           }

           UpdateSessionProperty(
               "PartyNetworkDescriptor", // arbitrary property name
               serializedDescriptor);

           UpdateSessionProperty(
               "PartyInitialInvitation", // arbitrary property name
               createNewNetworkCompletedStateChange.appliedInitialInvitationIdentifier);
       }
       else
       {
           // The network was not created successfully.
           // Please refer to CreateNewNetwork reference documentation for retry guidance
       }
   }
   ```

5. Quando cada membro vir o documento de sessão atualizado, poderá usar o descritor de rede e o convite para se conectar à rede e ingressar nela.

   ```cpp theme={null}
   void
   OnNetworkInformationPostedToSessionDocument(
       PartyString serializedNetworkDescriptor,
       PartyString invitationId
       )
   {
       PartyNetworkDescriptor networkDescriptor;
       PartyError error = PartyManager::DeserializeNetworkDescriptor(serializedNetworkDescriptor, &networkDescriptor);
       if (PARTY_FAILED(error))
       {
           DEBUGLOG("PartyManager::DeserializeNetworkDescriptor failed: 0x%08x\n", error);
           return;
       }

       // attempt to connect to the network
       PartyNetwork* network;
       error = PartyManager::GetSingleton().ConnectToNetwork(
           &networkDescriptor,
           nullptr,
           &network);
       if (PARTY_FAILED(error))
       {
           DEBUGLOG("PartyManager::ConnectToNetwork failed: 0x%08x\n", error);
           return;
       }

       // immediately queue an authentication on the network we've attempted to connect to.
       error = network->AuthenticateLocalUser(
           m_localUser,
           invitationId,
           nullptr);
       if (PARTY_FAILED(error))
       {
           DEBUGLOG("PartyNetwork::AuthenticateLocalUser failed: 0x%08x\n", error);
           return;
       }
   }
   ```

<Note>
  Aqui apresentamos um fluxo para incorporar o matchmaking e o MPSD com o PlayFab Party. As ideias principais desse fluxo podem ser estendidas a outros fluxos do MPSD de seu interesse, mas apresentar todos os fluxos possíveis está fora do escopo desta documentação. Para obter mais informações, consulte a [documentação completa do MPSD](https://learn.microsoft.com/en-us/gaming/gdk/_content/gc/live/get-started/live-xbl-overview).
</Note>

<a id="platform-invites" />

## Convites da plataforma

Veja a seguir um fluxo de como incorporar os convites da plataforma XBOX ao PlayFab Party:

1. O *PlayerA* cria um documento de sessão do MPSD, escuta as alterações na sessão e cria uma rede do Party. Quando a criação da rede do Party for concluída, o *PlayerA* publicará o descritor de rede e um convite inicial (se necessário) no documento de sessão do MPSD.

   ```cpp theme={null}
   void
   OnSessionDocumentCreated()
   {
       // This is an asynchronous call. It will be completed when StartProcessingStateChanges generates a
       // PartyCreateNewNetworkCompletedStateChange struct
       PartyError error = PartyManager::GetSingleton().CreateNewNetwork(
           m_localPartyUser,
           &networkConfiguration,
           0,
           nullptr,
           nullptr,
           nullptr,
           nullptr,
           nullptr);
       if (FAILED(error))
       {
           DEBUGLOG("PartyManager::CreateNetwork failed! 0x%08x\n", error);
           return;
       }
   }

   void
   HandleCreateNewNetworkCompleted(
       const PartyCreateNewNetworkCompletedStateChange& createNewNetworkCompletedStateChange
       )
   {
       if (createNewNetworkCompletedStateChange.result == PartyStateChangeResult::Succeeded)
       {
           // The network was created successfully! Post the networks descriptor and invitation

           char serializedDescriptor[c_maxSerializedNetworkDescriptorStringLength + 1];
           PartyError error = PartyManager::SerializeNetworkDescriptor(
               &createNewNetworkCompletedStateChange.networkDescriptor,
               serializedDescriptor);
           if (PARTY_FAILED(error))
           {
               DEBUGLOG("PartyManager::SerializeNetworkDescriptor failed: 0x%08x\n", error);
               return;
           }

           UpdateSessionProperty(
               "PartyNetworkDescriptor", // arbitrary property name
               serializedDescriptor);
       }
       else
       {
           // The network was not created successfully.
           // Please refer to CreateNewNetwork reference documentation for retry guidance
       }
   }
   ```

2. Quando o *PlayerA* quiser convidar o *PlayerB* para a rede do Party, o *PlayerA* iniciará um convite da plataforma para o *PlayerB* por meio da interface do usuário do jogo ou do console.

3. O *PlayerB* recebe o convite da plataforma, que inclui um "identificador de convite" que o *PlayerB* pode usar para localizar o documento de sessão do MPSD do *PlayerA*.

4. O *PlayerB* ingressa no documento de sessão e escuta as alterações.

5. O *PlayerA* vê o *PlayerB* ingressar no documento de sessão. O *PlayerA* cria um novo convite para o *PlayerB* usar e publica esse convite no documento de sessão

   ```cpp theme={null}
   void
   OnUserJoinedSessionDocument(
       PartyNetwork* network,
       uint64_t newSessionMemberXboxUserId
       )
   {
       std::string newMemberIdString = std::to_string(newSessionMemberXboxUserId);

       // Specify our own invitation id so we don't have to query for it after the invitation has been created.
       // Here we will specify the invite id with the format "InviterXboxUserID_InviteeXboxUserID" so that we can
       // ensure this invitation ID doesn't clash with the invitations other members might try and create for this user.
       std::string invitationId = std::to_string(m_localXboxUserId) + "_" + newMemberIdString;

       PartyInvitationConfiguration newInvite{};
       newInvite.identifier = invitationId.c_str();
       newInvite.revocability = PartyInvitationRevocability::Creator; // must be revocable by the creator only

       // Call title-defined xuid->entityid mapping helper
       PartyString newSessionMemberEntityId = GetEntityIdFromXboxUserId(newSessionMemberXboxUserId);
       newInvite.entityIdCount = 1;
       newInvite.entityIds = &newSessionMemberEntityId;

       // Create a new invitation which includes all of the users currently in the document
       PartyInvitation* newInvitation;
       PartyError error = network->CreateInvitation(
           m_localUser,
           &newInvite,
           nullptr,
           &newInvitation);
       if (PARTY_FAILED(error))
       {
           DEBUGLOG("PartyNetwork(0x%p)::CreateInvitation failed! (error=0x%x)", network, error);
           return;
       }

       // Post the invitation to the local user's member property store in the session document, key'd by the invitee's
       // xbox user id. This will let the invitee recognize when an invitation is intended for them.
       UpdateMemberProperty(
           newMemberIdString.c_str(),
           invitationId.c_str());
   }
   ```

6. O *PlayerB* vê o convite publicado no documento de sessão e o usa para ingressar na rede do Party.

   ```cpp theme={null}
   void
   OnRemoteMemberPropertyUpdated(
       PartyString memberPropertyKey,
       PartyString memberPropertyValue
       )
   {
       // The member property update signifies a new invitation, if the remote member updated a property that matches
       // our xbox user id.
       if (memberPropertyKey == std::to_string(m_localXboxUserId))
       {
           OnUserInvitationPostedToSessionDocument(memberPropertyValue);
       }

       // ...
   }

   void
   OnUserInvitationPostedToSessionDocument(
       PartyString invitationId
       )
   {
       // The network descriptor should have already been posted to the session document before the invitation.
       // Call title-defined function to pull it from the session document.
       PartyNetworkDescriptor networkDescriptor = QueryNetworkDescriptorFromSessionDocument();

       // attempt to connect to the network
       PartyNetwork* network;
       error = PartyManager::GetSingleton().ConnectToNetwork(
           &networkDescriptor,
           nullptr,
           &network);
       if (PARTY_FAILED(error))
       {
           DEBUGLOG("PartyManager::ConnectToNetwork failed: 0x%08x\n", error);
           return;
       }

       // immediately queue an authentication on the network we've attempted to connect to.
       error = network->AuthenticateLocalUser(
           m_localUser,
           invitationId,
           nullptr);
       if (PARTY_FAILED(error))
       {
           DEBUGLOG("PartyNetwork::AuthenticateLocalUser failed: 0x%08x\n", error);
           return;
       }
   }
   ```

<Info>
  Os convites criados por meio de [PartyNetwork::CreateInvitation](/pt-BR/services/playfab/multiplayer/networking/reference/classes/PartyNetwork/methods/partynetwork_createinvitation) se tornarão inválidos se o PartyLocalUser que os criou sair da rede. Portanto, se um novo usuário se adicionar a um documento de sessão, mas o usuário que o convidou sair, é recomendável que o novo usuário se remova do documento de sessão e aguarde ser convidado novamente por outro usuário.
</Info>

## Ingresso em andamento

Ingressar em sessões de jogo em andamento é muito semelhante ao cenário de [convite da plataforma](#platform-invites). A principal diferença é que, em vez de o *PlayerA* enviar ao *PlayerB* um "identificador de convite", o *PlayerB* receberá um "identificador de ingresso" ao iniciar um ingresso em andamento pela interface do usuário da plataforma. Usando esse "identificador de ingresso", o *PlayerB* ingressará no documento de sessão e escutará as alterações. O *PlayerA* responderá criando e publicando um novo convite do Party para ele no documento de sessão. O *PlayerB* verá esse novo convite junto com o descritor de rede e o usará para ingressar na rede do Party.

<Info>
  Os convites criados por meio de [PartyNetwork::CreateInvitation](/pt-BR/services/playfab/multiplayer/networking/reference/classes/PartyNetwork/methods/partynetwork_createinvitation) se tornarão inválidos se o PartyLocalUser que os criou sair da rede. Portanto, se um novo usuário receber um convite do Party pelo fluxo de ingresso em andamento, mas não puder usá-lo porque o usuário que o criou saiu, é recomendável que o novo usuário se remova do documento de sessão e ingresse novamente mais tarde. Isso permitirá que outro membro da sessão reinicie o fluxo e gere um novo convite do Party para esse usuário.
</Info>

## Desconexões e limpeza

Se um jogador sair ou for desconectado de uma rede do Party de outra forma, ele também deverá se remover de todas as sessões do MPSD associadas a essa rede do Party. As desconexões da rede do Party não iniciadas por uma operação [PartyNetwork::LeaveNetwork](/pt-BR/services/playfab/multiplayer/networking/reference/classes/PartyNetwork/methods/partynetwork_leavenetwork) são consideradas fatais. Depois de sofrer uma desconexão fatal, um jogador pode tentar se reconectar e se autenticar novamente na rede, mas também deve ingressar novamente na sessão do MPSD.

Se a conexão de um jogador com uma sessão do MPSD for interrompida temporariamente, ele poderá ser desconectado dessa sessão. Os jogadores podem tentar ingressar novamente na sessão, mas, se não conseguirem, devem se remover voluntariamente da rede do Party chamando [PartyNetwork::LeaveNetwork](/pt-BR/services/playfab/multiplayer/networking/reference/classes/PartyNetwork/methods/partynetwork_leavenetwork).

<Note>
  Os mecanismos e as heurísticas que detectam desconexões das redes do Party e das sessões do MPSD são diferentes. Mesmo em cenários em que um jogador será desconectado da rede do Party e da sessão do MPSD, esses eventos de desconexão são independentes, e não há garantia de que ocorram próximos um do outro no tempo. Os títulos devem lidar com o cenário em que um jogador pode ser desconectado apenas da rede do Party ou apenas da sessão do MPSD.
</Note>

Se o jogo for encerrado, o jogador será desconectado automaticamente da rede do Party e do documento do MPSD, e nenhuma outra limpeza será necessária.


## Related topics

- [Requisitos do XBOX](/pt-BR/services/playfab/multiplayer/networking/xbox-requirements.md)
- [Adicionando chat usando o Microsoft Azure PlayFab Party](/pt-BR/services/xbox-services/multiplayer/chat/playfab-party-intro-chat.md)
- [Usando várias redes do PlayFab Party](/pt-BR/services/playfab/multiplayer/networking/concepts-multiple-networks.md)
- [Adicione serviços de backend com o PlayFab](/pt-BR/home/build-first-title/add-backend-services.md)
- [Migrando do MPSD para o PlayFab Multiplayer e o MPA](/pt-BR/services/xbox-services/multiplayer/mpsd/concepts/live-mpsd-to-mlp.md)
