> ## 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.

# Uso de PlayFab Party con MPSD

> Combine las redes de voz y datos de PlayFab Party con el Directorio de sesiones multijugador (MPSD) de XBOX para la administración de sesiones e invitaciones entre redes.

Los escenarios multijugador de XBOX se basan en el uso del servicio Directorio de sesiones multijugador (MPSD) y de los documentos MPSD. Los documentos MPSD actúan como la lista de participantes de la sesión de juego actual e impulsan las experiencias multijugador, como el emparejamiento, las invitaciones de la plataforma, las listas de jugadores recientes y la unión a partidas en curso.

En este documento se describe cómo puede incorporar PlayFab Party en los flujos multijugador comunes que requieren MPSD.

Este documento no proporciona un análisis en profundidad de MPSD y todas sus funcionalidades. Para obtener más información, consulte la [documentación de MPSD](/services/xbox-services/multiplayer/mpsd/live-mpsd-overview).

## Emparejamiento

Este es un flujo simplificado de cómo usar el emparejamiento y MPSD junto con PlayFab Party:

1. Los jugadores crearán sesiones de MPSD que representan los grupos que quieren jugar juntos en las sesiones de emparejamiento y se reunirán en ellas. Los jugadores se reunirán en estas sesiones mediante las características de invitación y unión de XBOX.

2. Esos grupos de jugadores enviarán vales al servicio de emparejamiento, que reunirá a los grupos de jugadores compatibles en una sesión de emparejamiento. Esta sesión de emparejamiento estará representada, a su vez, por un nuevo documento de sesión al que los jugadores se unirán. Los jugadores también deben escuchar los cambios de este documento de sesión.

3. Una vez que la sesión de emparejamiento se haya finalizado y la lista de participantes esté bloqueada, el título debe elegir a uno de los miembros de la sesión de emparejamiento para configurar la red de PlayFab Party. Una estrategia sencilla para seleccionar al creador de la red de Party es usar el primer miembro del documento de sesión de MPSD de emparejamiento.

4. El miembro seleccionado creará la red con una `PartyInvitation` inicial que restringe el acceso a la red solo a los miembros de la sesión de emparejamiento. Una vez que la red se haya creado correctamente, el miembro seleccionado debe publicar el descriptor de red resultante y la invitación de Party en el documento de sesión como una propiedad de sesión para que los demás miembros la usen.

   ```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. Cuando cada miembro vea el documento de sesión actualizado, podrá usar el descriptor de red y la invitación para conectarse a la red y unirse a ella.

   ```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>
  Aquí hemos presentado un flujo para incorporar el emparejamiento y MPSD con PlayFab Party. Las ideas fundamentales de este flujo se pueden extender a otros flujos que puedan interesarle con MPSD, pero presentar todos los flujos posibles queda fuera del ámbito de esta documentación. Para obtener más información, consulte la [documentación completa de MPSD](https://learn.microsoft.com/en-us/gaming/gdk/_content/gc/live/get-started/live-xbl-overview).
</Note>

## Invitaciones de la plataforma

Este es un flujo de cómo incorporar las invitaciones de la plataforma XBOX en PlayFab Party:

1. *PlayerA* crea un documento de sesión de MPSD, escucha los cambios de la sesión y crea una red de Party. Cuando se haya completado la creación de la red de Party, \*PlayerA \*publica el descriptor de red y una invitación inicial (si es necesario) en el documento de sesión de 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. Cuando *PlayerA* quiere invitar a *PlayerB* a la red de Party, *PlayerA* inicia una invitación de la plataforma para *PlayerB* a través de la interfaz de usuario del juego o de la consola.

3. *PlayerB* recibe la invitación de la plataforma, que incluye un "invite handle" que *PlayerB* puede usar para encontrar el documento de sesión de MPSD de *PlayerA*.

4. *PlayerB* se une al documento de sesión y escucha los cambios.

5. *PlayerA* ve que *PlayerB* se une al documento de sesión. *PlayerA* crea una nueva invitación para que la use *PlayerB* y la publica en el documento de sesión.

   ```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. *PlayerB* ve la invitación publicada en el documento de sesión y la usa para unirse a la red de 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>
  Las invitaciones creadas a través de [PartyNetwork::CreateInvitation](/services/playfab/multiplayer/networking/reference/classes/PartyNetwork/methods/partynetwork_createinvitation) dejarán de ser válidas si el PartyLocalUser que las creó abandona la red. Por lo tanto, si un usuario nuevo se agrega a un documento de sesión pero el usuario que lo invitó se va, se recomienda que el usuario nuevo se quite del documento de sesión y espere a que otro usuario lo vuelva a invitar.
</Info>

## Unión a partidas en curso

Unirse a sesiones de juego en curso es muy similar al escenario de [invitación de la plataforma](#platform-invites). La diferencia fundamental es que, en lugar de que *PlayerA* envíe a *PlayerB* un "invite handle", *PlayerB* obtendrá un "join handle" cuando inicie una unión a una partida en curso desde la interfaz de usuario de la plataforma. Con este "join handle", *PlayerB* se unirá al documento de sesión y escuchará los cambios. *PlayerA* responderá creando y publicando en el documento de sesión una nueva invitación de Party para él. *PlayerB* verá esta nueva invitación junto con el descriptor de red y la usará para unirse a la red de Party.

<Info>
  Las invitaciones creadas a través de [PartyNetwork::CreateInvitation](/services/playfab/multiplayer/networking/reference/classes/PartyNetwork/methods/partynetwork_createinvitation) dejarán de ser válidas si el PartyLocalUser que las creó abandona la red. Por lo tanto, si un usuario nuevo recibe una invitación de Party del flujo de unión a una partida en curso, pero no puede usarla porque el usuario que la creó se ha ido, se recomienda que el usuario nuevo se quite del documento de sesión y se vuelva a unir más tarde. Esto permitirá que otro miembro de la sesión reinicie el flujo y genere una nueva invitación de Party para este usuario.
</Info>

## Desconexiones y limpieza

Si un jugador abandona una red de Party o se desconecta de ella por cualquier otro motivo, también debe quitarse de las sesiones de MPSD asociadas a esa red de Party. Las desconexiones de la red de Party no iniciadas por una operación [PartyNetwork::LeaveNetwork](/services/playfab/multiplayer/networking/reference/classes/PartyNetwork/methods/partynetwork_leavenetwork) se consideran irrecuperables. Después de experimentar una desconexión irrecuperable, un jugador puede intentar volver a conectarse y a autenticarse en la red, pero también debe volver a unirse a la sesión de MPSD.

Si la conexión de un jugador a una sesión de MPSD se interrumpe temporalmente, es posible que se desconecte de esa sesión. Los jugadores pueden intentar volver a unirse a la sesión pero, si no lo consiguen, deben quitarse voluntariamente de la red de Party llamando a [PartyNetwork::LeaveNetwork](/services/playfab/multiplayer/networking/reference/classes/PartyNetwork/methods/partynetwork_leavenetwork).

<Note>
  Los mecanismos y las heurísticas que detectan las desconexiones de las redes de Party y de las sesiones de MPSD son diferentes. Incluso en escenarios en los que un jugador se desconecte tanto de la red de Party como de la sesión de MPSD, estos eventos de desconexión son independientes y no se garantiza que se produzcan cerca en el tiempo. Los títulos deben controlar el escenario en el que un jugador podría desconectarse solo de la red de Party o solo de la sesión de MPSD.
</Note>

Si el juego se cierra, el jugador se desconectará automáticamente de la red de Party y del documento de MPSD, y no es necesaria ninguna limpieza adicional.


## Related topics

- [Requisitos de XBOX](/es/services/playfab/multiplayer/networking/xbox-requirements.md)
- [Uso de varias redes de PlayFab Party](/es/services/playfab/multiplayer/networking/concepts-multiple-networks.md)
- [Uso de puertos y requisitos de firewall de PlayFab Party](/es/services/playfab/multiplayer/networking/concepts-port-usage.md)
- [Uso de conexiones directas de punto a punto](/es/services/playfab/multiplayer/networking/concepts-direct-peer-connectivity.md)
- [Uso del GDK con Unity](/es/build/gdk-and-engines/unity/unity.md)
