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

# Usando a API C++ do Game Chat 2

> Passo a passo da API C++ do Game Chat 2 no XBOX GDK, abrangendo a inicialização, a adição de usuários, a configuração dos canais de chat e os padrões de tratamento de erros.

Este tópico fornece um breve passo a passo do uso da API C++ do Game Chat 2 para adicionar comunicação por voz e texto ao seu jogo.

## Pré-requisitos

O Game Chat 2 exige que seu projeto tenha sido configurado para o GDK. Para obter detalhes sobre como fazer essa configuração, consulte [Introdução ao Microsoft Game Development Kit](https://learn.microsoft.com/gaming/gdk/docs/services/gdk-dev/get-started/get-started-home).

Compilar o Game Chat 2 exige incluir o cabeçalho principal *GameChat2.h*.
Para vincular corretamente, seu projeto também precisa incluir *GameChat2Impl.h* em pelo menos uma unidade de compilação (recomendamos um cabeçalho pré-compilado comum, pois essas implementações de funções stub são pequenas e fáceis para o compilador gerar como "inline").

A interface do Game Chat 2 não exige que o projeto escolha entre compilar com C++/CX ou com C++ tradicional. Ela pode ser usada com qualquer um dos dois. A implementação também não lança exceções como meio de relatar erros não fatais. Você pode consumi-la facilmente em projetos sem exceções, se preferir. No entanto, a implementação lança exceções como meio de relatar erros fatais. (Para obter mais detalhes, consulte a seção [Modelo de falhas](https://docs.xbox.com/pt-BR/services/xbox-services/multiplayer/chat/game-chat2/using-game-chat-2.md#FAILURE_MODEL) mais adiante neste tópico.)

## Inicialização

Comece a interagir com a biblioteca inicializando a instância singleton do Game Chat 2 com parâmetros que se aplicam ao tempo de vida da inicialização do singleton. A instância singleton é inicializada chamando [chat\_manager::initialize](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_initialize.md), conforme mostrado a seguir.

```cpp theme={null}
chat_manager::singleton_instance().initialize(...);
```

> [!NOTE]
>
> Você precisa se registrar para os eventos de suspensão e retomada por meio de `RegisterAppStateChangeNotification`. Na suspensão, você precisa limpar o Game Chat 2 com [chat\_manager::cleanup()](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_cleanup.md). Na retomada, você deve reinicializar o Game Chat 2. Ele pode travar se você tentar usá-lo ao longo de um ciclo de suspensão/retomada.

## Configurando usuários

### Adicionando usuários ao seu título do Microsoft Game Development Kit (GDK)

Antes de adicionar usuários à instância do Game Chat 2, verifique se eles foram adicionados ao título do GDK.
Isso é feito usando a [API XUserAddAsync](https://docs.xbox.com/pt-BR/reference/system/xuser/functions/xuseraddasync.md). Para obter mais informações sobre como usar essa API, consulte [Identidade do usuário e XUser](https://docs.xbox.com/pt-BR/build/core-features/common/user/player-identity-xuser.md).

Depois de obter o `XUserHandle` do usuário que você deseja adicionar ao Game Chat 2, você precisa obter o ID de usuário do XBOX (XUID) do usuário usando a [API XUserGetId](https://docs.xbox.com/pt-BR/reference/system/xuser/functions/xusergetid.md).
O usuário precisa estar online, e você precisa ter o consentimento do usuário para esta etapa.

[XUserGetId](https://docs.xbox.com/pt-BR/reference/system/xuser/functions/xusergetid.md) fornece o XUID como um `uint64_t`. Você precisa converter o XUID em um `std::wstring` para uso com o Game Chat 2.

Veja a seguir um exemplo de código que mostra como adicionar um usuário ao Game Chat 2 depois de obter um `XUserHandle`.
\[!NOTE] Lembre-se de que chamar [XUserResolveIssueWithUiAsync](https://docs.xbox.com/pt-BR/reference/system/xuser/functions/xuserresolveissuewithuiasync.md) exibe uma caixa de diálogo do sistema.

```cpp theme={null}
HRESULT
AddChatUserFromXUserHandle(
    _In_ XUserHandle user,
    _In_ XTaskQueueHandle queueHandle,
    _Outptr_result_maybenull_ Xs::game_chat_2::chat_user** chatUser
    )
{
    *chatUser = nullptr;
    uint64_t xuid;
    HRESULT hr = XUserGetId(user, &xuid);
    if (hr == E_GAMEUSER_RESOLVE_USER_ISSUE_REQUIRED)
    {
        XAsyncBlock* asyncBlock = new (std::nothrow) XAsyncBlock;
        if (asyncBlock != nullptr)
        {
            ZeroMemory(asyncBlock, sizeof(*asyncBlock));
            asyncBlock->queue = queueHandle;
            hr = XUserResolveIssueWithUiAsync(user, nullptr, asyncBlock);
            if (SUCCEEDED(hr))
            {
                hr = XAsyncGetStatus(asyncBlock, true);
                if (SUCCEEDED(hr))
                {
                    hr = XUserGetId(user, &xuid);
                }
            }
            delete asyncBlock;
        }
        else
        {
            hr = E_OUTOFMEMORY;
        }
    }

    if (SUCCEEDED(hr))
    {
        try
        {
            std::wstring xuidString = std::to_wstring(xuid);

            // If the user has already been added, this will return the existing user.
            *chatUser = Xs::game_chat_2::chat_manager::singleton_instance().add_local_user(xuidString.c_str());
        }
        catch (const std::bad_alloc&)
        {
            hr = E_OUTOFMEMORY;
        }
    }

    return hr;
}
```

### Adicionando usuários ao Game Chat 2

Depois que a instância for inicializada, você precisará adicionar os usuários locais à instância do Game Chat 2 usando [chat\_manager::add\_local\_user](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_add_local_user.md). Neste exemplo, o Usuário A representa um usuário local.

```cpp theme={null}
chat_user* chatUserA = chat_manager::singleton_instance().add_local_user(<user_a_xuid>);
```

Em seguida, adicione os usuários remotos e os identificadores usados para representar o "ponto de extremidade" remoto em que o usuário está.
Um *ponto de extremidade* é uma instância do aplicativo em execução em um dispositivo remoto.

Neste exemplo, o Usuário B está no ponto de extremidade X. Os Usuários C e D estão no ponto de extremidade Y.
O ponto de extremidade X recebe arbitrariamente o identificador "1". O ponto de extremidade Y recebe arbitrariamente o identificador "2".

Informe o Game Chat 2 sobre os usuários remotos com as chamadas a seguir.

```cpp theme={null}
chat_user* chatUserB = chat_manager::singleton_instance().add_remote_user(<user_b_xuid>, 1);
chat_user* chatUserC = chat_manager::singleton_instance().add_remote_user(<user_c_xuid>, 2);
chat_user* chatUserD = chat_manager::singleton_instance().add_remote_user(<user_d_xuid>, 2);
```

Em seguida, configure o relacionamento de comunicação entre cada usuário remoto e o usuário local.
Neste exemplo, suponha que o Usuário A e o Usuário B estejam na mesma equipe. A comunicação bidirecional é permitida.
`c_communicationRelationshipSendAndReceiveAll` é uma constante definida em *GameChat2.h* para representar a comunicação bidirecional.

Defina o relacionamento do Usuário A com o Usuário B usando [chat\_user\_local::set\_communication\_relationship](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_user/chat_user_local/methods/chat_user_local_set_communication_relationship.md).

```cpp theme={null}
chatUserA->local()->set_communication_relationship(chatUserB, c_communicationRelationshipSendAndReceiveAll);
```

Suponha que os Usuários C e D sejam "espectadores" e devam poder ouvir o Usuário A, mas não falar.
`c_communicationRelationshipSendAll` é uma constante definida em *GameChat2.h* para representar essa comunicação unidirecional.

Defina os relacionamentos da seguinte forma.

```cpp theme={null}
chatUserA->local()->set_communication_relationship(chatUserC, c_communicationRelationshipSendAll);
chatUserA->local()->set_communication_relationship(chatUserD, c_communicationRelationshipSendAll);
```

Para ver exemplos com as configurações de relacionamento dos quatro usuários locais, consulte a seção de [cenários](https://docs.xbox.com/pt-BR/services/xbox-services/multiplayer/chat/game-chat2/using-game-chat-2.md#scenarios) mais adiante neste tópico.

Se, em algum momento, houver usuários remotos que foram adicionados à instância singleton, mas não foram configurados para se comunicar com nenhum usuário local, não há problema.
Isso é esperado em cenários em que os usuários estão definindo as equipes ou podem trocar arbitrariamente de canal de fala.

O Game Chat 2 só armazena em cache informações (por exemplo, relacionamentos de privacidade e reputação) dos usuários que foram adicionados à instância; por isso, é útil informar o Game Chat 2 sobre todos os usuários possíveis, mesmo que eles não possam falar com nenhum usuário local em um determinado momento.

Por fim, suponha que o Usuário D tenha saído do jogo e deva ser removido da instância local do Game Chat 2.
Isso pode ser feito usando [chat\_manager::remove\_user](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_remove_user.md), conforme mostrado a seguir.

```cpp theme={null}
chat_manager::singleton_instance().remove_user(chatUserD);
```

Chamar `chat_manager::remove_user()` pode invalidar o objeto de usuário. Se você estiver usando a [manipulação de áudio em tempo real](https://docs.xbox.com/pt-BR/services/xbox-services/multiplayer/chat/game-chat2/real-time-audio-manipulation.md), consulte [Tempo de vida dos usuários do chat](https://docs.xbox.com/pt-BR/services/xbox-services/multiplayer/chat/game-chat2/real-time-audio-manipulation.md#chat-user-lifetimes) para obter mais informações. Caso contrário, o objeto de usuário é invalidado imediatamente quando `chat_manager::remove_user()` é chamado. Uma restrição sutil sobre quando os usuários podem ser removidos é detalhada na seção [Processando alterações de estado](#processing-state-changes) mais adiante neste tópico.

## Processando quadros de dados

O Game Chat 2 não tem uma camada de transporte própria. Ela precisa ser fornecida pelo aplicativo.
Esse plug-in é gerenciado pelas chamadas regulares e frequentes do aplicativo ao par de métodos [chat\_manager::start\_processing\_data\_frames()](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_start_processing_data_frames.md) e [chat\_manager::finish\_processing\_data\_frames()](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_finish_processing_data_frames.md). Esses métodos são a forma como o Game Chat 2 fornece os dados de saída ao aplicativo.

Esses métodos foram projetados para operar rapidamente. Eles podem ser consultados com frequência em uma thread de rede dedicada.
Isso oferece um lugar conveniente para recuperar todos os dados enfileirados sem se preocupar com a imprevisibilidade do tempo de rede ou com a complexidade de callbacks multithread.

Quando `chat_manager::start_processing_data_frames()` é chamado, todos os dados enfileirados são informados em uma matriz de ponteiros de estrutura [game\_chat\_data\_frame](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/structs/game_chat_data_frame.md).
Os aplicativos devem iterar pela matriz, inspecionar os pontos de extremidade de destino e usar a camada de rede do aplicativo para entregar os dados às instâncias remotas apropriadas do aplicativo.

Depois que a matriz for concluída com todas as estruturas [game\_chat\_data\_frame](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/structs/game_chat_data_frame.md), ela deverá ser passada de volta ao Game Chat 2 para liberar os recursos chamando `chat_manager:finish_processing_data_frames()`.
Isso é mostrado no exemplo a seguir.

```cpp theme={null}
uint32_t dataFrameCount;
game_chat_data_frame_array dataFrames;
chat_manager::singleton_instance().start_processing_data_frames(&dataFrameCount, &dataFrames);
for (uint32_t dataFrameIndex = 0; dataFrameIndex < dataFrameCount; ++dataFrameIndex)
{
    game_chat_data_frame const* dataFrame = dataFrames[dataFrameIndex];

    // Title-written function responsible for sending packet to remote instances of GameChat 2.
    HandleOutgoingDataFrame(
        dataFrame->packet_byte_count,
        dataFrame->packet_buffer,
        dataFrame->target_endpoint_identifier_count,
        dataFrame->target_endpoint_identifiers,
        dataFrame->transport_requirement
        );
}
chat_manager::singleton_instance().finish_processing_data_frames(dataFrames);
```

Quanto mais frequentemente os quadros de dados forem processados, menor será a latência de áudio percebida pelo usuário.
O áudio é agrupado em quadros de dados de 40 ms. Esse é o período de consulta sugerido.

## Processando alterações de estado

O Game Chat 2 fornece atualizações ao aplicativo, como mensagens de texto recebidas, por meio das chamadas regulares e frequentes do aplicativo ao par de métodos [chat\_manager::start\_processing\_state\_changes()](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_start_processing_state_changes.md) e [chat\_manager::finish\_processing\_state\_changes()](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_finish_processing_state_changes.md).
Esses métodos operam rapidamente, de modo que podem ser chamados a cada quadro gráfico no loop de renderização da interface.
Isso oferece um lugar conveniente para recuperar todas as alterações enfileiradas sem se preocupar com a imprevisibilidade do tempo de rede ou com a complexidade de callbacks multithread.

Quando `chat_manager::start_processing_state_changes()` é chamado, todas as atualizações enfileiradas são informadas em uma matriz de ponteiros de estrutura [game\_chat\_state\_change](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/structs/game_chat_state_change.md).
Os aplicativos devem iterar pela matriz, inspecionar a estrutura base para identificar seu tipo mais específico, converter a estrutura base no tipo mais detalhado correspondente e, em seguida, tratar essa atualização conforme apropriado.

Depois que a matriz for concluída com todos os objetos [game\_chat\_state\_change](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/structs/game_chat_state_change.md) disponíveis no momento, ela deverá ser passada de volta ao Game Chat 2 para liberar os recursos chamando `chat_manager::finish_processing_state_changes()`.
Isso é mostrado no exemplo a seguir.

```cpp theme={null}
uint32_t stateChangeCount;
game_chat_state_change_array gameChatStateChanges;
chat_manager::singleton_instance().start_processing_state_changes(&stateChangeCount, &gameChatStateChanges);

std::list<Xs::game_chat_2::chat_user*> usersWithPrivilegeIssues;
std::list<Xs::game_chat_2::chat_user*> usersWithPrivilegeCheckIssues;
for (uint32_t stateChangeIndex = 0; stateChangeIndex < stateChangeCount; ++stateChangeIndex)
{
    switch (gameChatStateChanges[stateChangeIndex]->state_change_type)
    {
        case game_chat_state_change_type::text_chat_received:
        {
            HandleTextChatReceived(static_cast<const game_chat_text_chat_received_state_change*>(gameChatStateChanges[stateChangeIndex]));
            break;
        }

        case Xs::game_chat_2::game_chat_state_change_type::transcribed_chat_received:
        {
            HandleTranscribedChatReceived(static_cast<const Xs::game_chat_2::game_chat_transcribed_chat_received_state_change*>(gameChatStateChanges[stateChangeIndex]));
            break;
        }
        case Xs::game_chat_2::game_chat_state_change_type::communication_relationship_adjuster_changed:
        {
            HandleAdjusterChangedStateReceived(static_cast<const Xs::game_chat_2::game_chat_communication_relationship_adjuster_changed_state_change*>(gameChatStateChanges[stateChangeIndex]), usersWithPrivilegeIssues, usersWithPrivilegeCheckIssues);
            break;
        }

        ...
    }
}
chat_manager::singleton_instance().finish_processing_state_changes(gameChatStateChanges);
```

Como `chat_manager::remove_user()` invalida imediatamente a memória associada a um objeto de usuário, e as alterações de estado podem conter ponteiros para objetos de usuário, `chat_manager::remove_user()` não pode ser chamado durante o processamento das alterações de estado.

## Chat de texto

Para enviar chat de texto, use [chat\_user::chat\_user\_local::send\_chat\_text()](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_user/chat_user_local/methods/chat_user_local_send_chat_text.md).
Isso é mostrado no exemplo a seguir.

```cpp theme={null}
chatUserA->local()->send_chat_text(L"Hello");
```

O Game Chat 2 gera um quadro de dados que contém essa mensagem. Os pontos de extremidade de destino do quadro de dados são aqueles associados aos usuários configurados para receber texto do usuário local.
Quando os dados são processados pelos pontos de extremidade remotos, a mensagem é exposta por meio de [game\_chat\_text\_chat\_received\_state\_change](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/structs/game_chat_text_chat_received_state_change.md).

Assim como no chat de voz, as restrições de privilégio e privacidade são respeitadas no chat de texto.
Se um par de usuários tiver sido configurado para permitir o chat de texto, mas restrições de privilégio ou privacidade impedirem essa comunicação, a mensagem de texto será descartada.

## Acessibilidade

A acessibilidade exige suporte à entrada e à exibição de chat de texto.

A entrada de texto é obrigatória porque, mesmo em plataformas ou gêneros de jogo que historicamente não tiveram uso difundido de teclados físicos, os usuários podem configurar o sistema para usar tecnologias assistivas de conversão de texto em fala.

Da mesma forma, a exibição de texto é obrigatória porque os usuários podem configurar o sistema para usar a conversão de fala em texto.

Essas preferências podem ser detectadas nos usuários locais chamando os métodos [chat\_user::chat\_user\_local::text\_to\_speech\_conversion\_preference\_enabled()](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_user/chat_user_local/methods/chat_user_local_text_to_speech_conversion_preference_enabled.md) e [chat\_user::chat\_user\_local::speech\_to\_text\_conversion\_preference\_enabled()](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_user/chat_user_local/methods/chat_user_local_speech_to_text_conversion_preference_enabled.md), respectivamente. Recomendamos que você habilite o texto condicionalmente, com base nas preferências do usuário.

### Conversão de texto em fala

Quando um usuário tem a conversão de texto em fala habilitada, [chat\_user::chat\_user\_local::text\_to\_speech\_conversion\_preference\_enabled()](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_user/chat_user_local/methods/chat_user_local_text_to_speech_conversion_preference_enabled.md) retorna `true`. Quando esse estado é detectado, o aplicativo precisa fornecer um método de entrada de texto.

Depois de obter a entrada de texto fornecida por um teclado real ou virtual, passe a cadeia de caracteres para o método [chat\_user::chat\_user\_local::synthesize\_text\_to\_speech()](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_user/chat_user_local/methods/chat_user_local_synthesize_text_to_speech.md). O Game Chat 2 detecta e sintetiza dados de áudio com base na cadeia de caracteres e na preferência de voz de acessibilidade do usuário.
Isso é mostrado no exemplo a seguir.

```cpp theme={null}
chat_userA->local()->synthesize_text_to_speech(L"Hello");
```

O áudio sintetizado como parte dessa operação é transportado para todos os usuários configurados para receber áudio desse usuário local.
Se `chat_user::chat_user_local::synthesize_text_to_speech()` for chamado para um usuário que não tem a conversão de texto em fala habilitada, o Game Chat 2 não fará nada.

### Conversão de fala em texto

Quando um usuário tem a conversão de fala em texto habilitada, [chat\_user::chat\_user\_local::speech\_to\_text\_conversion\_preference\_enabled()](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_user/chat_user_local/methods/chat_user_local_speech_to_text_conversion_preference_enabled.md) retorna `true`. Quando esse estado é detectado, o aplicativo precisa estar preparado para fornecer uma interface associada às mensagens de chat transcritas. O Game Chat 2 transcreve automaticamente o áudio de cada usuário remoto e o expõe por meio de uma struct [game\_chat\_transcribed\_chat\_received\_state\_change](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/structs/game_chat_transcribed_chat_received_state_change.md).

### Considerações de desempenho da conversão de fala em texto

Quando a conversão de fala em texto está habilitada, a instância do Game Chat 2 em cada dispositivo remoto inicia uma conexão WebSocket com o ponto de extremidade dos serviços de fala.
Cada cliente remoto do Game Chat 2 carrega o áudio no ponto de extremidade dos serviços de fala por meio desse WebSocket. O ponto de extremidade dos serviços de fala retorna ocasionalmente uma mensagem de transcrição ao dispositivo remoto.
Em seguida, o dispositivo remoto envia a mensagem de transcrição (ou seja, uma mensagem de texto) ao dispositivo local. A mensagem transcrita é entregue pelo Game Chat 2 ao aplicativo para renderização.

Portanto, o principal custo de desempenho da conversão de fala em texto é o uso da rede.
A maior parte do tráfego de rede é o upload do áudio codificado.
O WebSocket carrega o áudio que já foi codificado pelo Game Chat 2 no caminho "normal" do chat de voz. O aplicativo controla a taxa de bits por meio de [chat\_manager::set\_audio\_encoding\_bitrate](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_set_audio_encoding_bitrate.md).

## Interface do usuário

Recomendamos que, em todos os lugares em que a interface for mostrada aos usuários, especialmente em uma lista de gamertags, como um placar, você também exiba ícones de silenciado/falando como feedback para o usuário.
Isso é feito chamando [chat\_user::chat\_indicator()](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_user/methods/chat_user_chat_indicator.md) para recuperar uma enumeração [game\_chat\_user\_chat\_indicator](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/enums/game_chat_user_chat_indicator.md) que representa o status atual e instantâneo do chat desse usuário. O exemplo a seguir demonstra a recuperação do valor do indicador de um objeto [chat\_user](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_user/chat_user.md) apontado pela variável `chatUserA` para determinar um valor de constante de ícone específico a ser atribuído a uma variável `iconToShow`.

```cpp theme={null}
switch (chatUserA->chat_indicator())
{
   case game_chat_user_chat_indicator::silent:
   {
       iconToShow = Icon_InactiveSpeaker;
       break;
   }

   case game_chat_user_chat_indicator::talking:
   {
       iconToShow = Icon_ActiveSpeaker;
       break;
   }

   case game_chat_user_chat_indicator::local_microphone_muted:
   {
       iconToShow = Icon_MutedSpeaker;
       break;
   }
   ...
}
```

Espera-se que o valor informado por [chat\_user::chat\_indicator()](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_user/methods/chat_user_chat_indicator.md) mude com frequência, por exemplo, à medida que os jogadores começam e param de falar.
Por isso, ele foi projetado para que os aplicativos o consultem a cada quadro da interface.

## Silenciamento

O método [chat\_user::chat\_user\_local::set\_microphone\_muted()](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_user/chat_user_local/methods/chat_user_local_set_microphone_muted.md) pode ser usado para alternar o estado de silenciamento do microfone de um usuário local. Quando o microfone está silenciado, nenhum áudio desse microfone é capturado. Se o usuário estiver em um dispositivo compartilhado, como o Kinect, o estado de silenciamento se aplicará a todos os usuários.

O método [chat\_user::chat\_user\_local::microphone\_muted()](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_user/chat_user_local/methods/chat_user_local_microphone_muted.md) pode ser usado para recuperar o estado de silenciamento do microfone de um usuário local. Esse método reflete apenas se o microfone do usuário local foi silenciado no software por meio de uma chamada a `chat_user::chat_user_local::set_microphone_muted()`. Esse método não reflete um silenciamento controlado pelo hardware, por exemplo, por meio de um botão no headset do usuário.

Não há nenhum método para recuperar o estado de silenciamento por hardware do dispositivo de áudio de um usuário por meio do Game Chat 2.

O método [chat\_user::chat\_user\_local::set\_remote\_user\_muted()](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_user/chat_user_local/methods/chat_user_local_set_remote_user_muted.md) pode ser usado para alternar o estado de silenciamento de um usuário remoto em relação a um usuário local específico. Quando o usuário remoto está silenciado, o usuário local não ouve nenhum áudio nem recebe nenhuma mensagem de texto do usuário remoto.

## Silenciamento automático por má reputação

Normalmente, os usuários remotos começam sem silenciamento.
O Game Chat 2 inicia os usuários em um estado silenciado quando:

1. O usuário remoto não é amigo do usuário local.
2. O usuário remoto tem um sinalizador de má reputação.

Quando os usuários são silenciados devido a essa operação, `chat_user::chat_indicator()` retorna `game_chat_user_chat_indicator::reputation_restricted`.
Esse estado é substituído pela primeira chamada a `chat_user::chat_user_local::set_remote_user_muted()` que inclua o usuário remoto como usuário de destino.

## Privilégios e privacidade

Além do relacionamento de comunicação configurado pelo jogo, o Game Chat 2 aplica restrições de privilégio e privacidade.
O Game Chat 2 faz consultas de restrições de privilégio e privacidade quando um usuário é adicionado pela primeira vez. O `chat_user::chat_indicator()` do usuário sempre retorna `game_chat_user_chat_indicator::silent` até que essas operações sejam concluídas.

Se a comunicação com um usuário for afetada por uma restrição de privilégio ou privacidade, o `chat_user::chat_indicator()` do usuário retornará `game_chat_user_chat_indicator::platform_restricted`.
As restrições de comunicação da plataforma se aplicam tanto ao chat de voz quanto ao de texto. Nunca haverá um caso em que o chat de texto seja bloqueado por uma restrição da plataforma e o chat de voz não, ou vice-versa.

[chat\_user::chat\_user\_local::get\_effective\_communication\_relationship()](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_user/chat_user_local/methods/chat_user_local_get_effective_communication_relationship.md) pode ser usado para ajudar a distinguir quando os usuários não conseguem se comunicar devido a operações de privilégio e privacidade incompletas.
Ele retorna o relacionamento de comunicação aplicado pelo Game Chat 2 na forma de [game\_chat\_communication\_relationship\_flags](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/enums/game_chat_communication_relationship_flags.md) e o motivo pelo qual o relacionamento pode não ser igual ao relacionamento configurado, na forma de uma enumeração [game\_chat\_communication\_relationship\_adjuster](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/enums/game_chat_communication_relationship_adjuster.md).

Por exemplo, se as operações de consulta ainda estiverem em andamento, o [game\_chat\_communication\_relationship\_adjuster](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/enums/game_chat_communication_relationship_adjuster.md) será `game_chat_communication_relationship_adjuster::initializing`.
Esse método não deve ser usado para influenciar a interface. (Para obter mais informações, consulte a seção [Interface do usuário](#ui) anteriormente neste tópico.)

Se o Game Chat 2 encontrar um problema de privilégio, ele será informado na alteração de estado [communication\_relationship\_adjuster\_changed](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/structs/game_chat_stream_state_change.md).

Se o Game Chat 2 não conseguir recuperar o privilégio do usuário por um motivo irrecuperável, isso será informado como um ajustador `game_chat_communication_relationship_adjuster::privilege_check_failure`.

Se o Game Chat 2 não conseguir recuperar o privilégio do usuário por um motivo que o usuário talvez consiga resolver, isso será informado como um ajustador `game_chat_communication_relationship_adjuster::resolve_user_issue`.

Se o usuário não tiver privilégios que possam ser resolvidos com a interface, isso será informado como um ajustador `game_chat_communication_relationship_adjuster::privilege`.

Nesses casos, a comunicação será restrita.

Aqui está um exemplo de como verificar se um usuário tem um dos problemas comuns a seguir.

1. Os usuários precisam dar consentimento aos serviços do XBOX para que o Game Chat 2 verifique os privilégios.
2. A conta do usuário está configurada para negar privilégios (por exemplo, por ser uma conta de criança e, portanto, não poder usar o chat).

```cpp theme={null}
void
HandleAdjusterChangedStateReceived (
    _In_ const Xs::game_chat_2::game_chat_communication_relationship_adjuster_changed_state_change* adjusterChange,
    _Inout_ std::list<Xs::game_chat_2::chat_user*>& usersWithPrivilegeIssues,
    _Inout_ std::list<Xs::game_chat_2::chat_user*>& usersWithPrivilegeCheckIssues
    )
{
    Xs::game_chat_2::game_chat_communication_relationship_flags communicationRelationship;
    Xs::game_chat_2::game_chat_communication_relationship_adjuster communicationRelationshipAdjuster;
    adjusterChange->local_user->local()->get_effective_communication_relationship(
        adjusterChange->target_user,
        &communicationRelationship,
        &communicationRelationshipAdjuster);

    if (communicationRelationshipAdjuster == Xs::game_chat_2::game_chat_communication_relationship_adjuster::privilege)
    {
        // The local user has privilege issues.
        usersWithPrivilegeIssues.push_back(adjusterChange->local_user);
    }
    else if (communicationRelationshipAdjuster == Xs::game_chat_2::game_chat_communication_relationship_adjuster::resolve_user_issue)
    {
        // The local user has an issue checking privileges.
        usersWithPrivilegeCheckIssues.push_back(adjusterChange->local_user);
    }
}
```

Para problemas informados com o ajustador `game_chat_communication_relationship_adjuster::privilege`, você pode chamar [XUserResolvePrivilegeWithUiAsync](https://docs.xbox.com/pt-BR/reference/system/xuser/functions/xuserresolveprivilegewithuiasync.md) com `XUserPrivilegeOptions::None` e `XUserPrivilege::Communications` para tentar resolver o problema.

Para problemas informados com o ajustador `game_chat_communication_relationship_adjuster::resolve_user_issue`, você pode chamar [XUserResolveIssueWithUiAsync](https://docs.xbox.com/pt-BR/reference/system/xuser/functions/xuserresolveissuewithuiasync.md) com `nullptr` como URL para tentar resolver o problema.

Recomendamos que você mostre uma interface que indique que há um problema de privilégio. Permita que o usuário decida se deseja tentar resolver o problema, por meio do pressionamento de um botão ou de uma opção de menu.

O usuário pode não conseguir ou não querer resolver o problema.
Se o usuário resolver o problema, a solução entrará em vigor na próxima vez que o usuário for adicionado ao Game Chat 2.

> [!NOTE]
>
> [chat\_manager::remove\_user()](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_remove_user.md) não pode ser chamado durante o processamento das alterações de estado (ou seja, depois que [chat\_manager::start\_processing\_state\_changes()](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_start_processing_state_changes.md) tiver sido chamado e antes da chamada correspondente a [chat\_manager::finish\_processing\_state\_changes()](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_finish_processing_state_changes.md)). Chamar `chat_manager::remove_user()` enquanto as alterações de estado estão sendo processadas pode invalidar a memória associada ao usuário removido.
> Se você vir um ajustador `game_chat_communication_relationship_adjuster::privilege` e quiser tentar resolver os privilégios do usuário, deverá aguardar até depois do processamento das alterações de estado para fazer isso.

Para obter o `XUserHandle` a partir de um XUID, o que é necessário para chamar `XUserResolvePrivilegeWithUiAsync`, você pode usar a API [XUserFindUserById](https://docs.xbox.com/pt-BR/reference/system/xuser/functions/xuserfinduserbyid.md) para obter um novo `XUserHandle`. Como alternativa, você pode manter aquele que obteve com [XUserAddAsync](https://docs.xbox.com/pt-BR/reference/system/xuser/functions/xuseraddasync.md) e acompanhar qual XUID corresponde a ele.

Aqui está um exemplo de como resolver esses problemas.

```cpp theme={null}
// If we got an Xs::game_chat_2::game_chat_communication_relationship_adjuster::resolve_user_issue,
// we need to try and fix our issue, if we haven't already, and then remove and re-add that user.
for (Xs::game_chat_2::chat_user* localUser : usersWithPrivilegeCheckIssues)
{
    auto asyncBlock = std::make_unique<XAsyncBlock>();
    ZeroMemory(asyncBlock.get(), sizeof(*asyncBlock));
    asyncBlock->queue = g_asyncQueue;

    XUserHandle userHandle;
    hr = XUserFindUserById(localUser->local()->xbox_user_id(), &userHandle);
    if (SUCCEEDED(hr))
    {
        hr = XUserResolveIssueWithUiAsync(
            userHandle,
            nullptr,
            asyncBlock.get());
        if (SUCCEEDED(hr))
        {
            hr = XAsyncGetStatus(asyncBlock.get(), true);
            if (SUCCEEDED(hr))
            {
                // Remove and re-add the user after fixing the privileges.
                // Users must not be removed while processing state changes.
            }
            asyncBlock.release();
        }
    }
}

// If we got an Xs::game_chat_2::game_chat_communication_relationship_adjuster::resolve_user_privilege,
// we need to try and resolve the privileges, if we haven't already, and then remove and re-add that user.
for (Xs::game_chat_2::chat_user* localUser : usersWithPrivilegeIssues)
{
    auto asyncBlock = std::make_unique<XAsyncBlock>();
    ZeroMemory(asyncBlock.get(), sizeof(*asyncBlock));
    asyncBlock->queue = g_asyncQueue;

    XUserHandle userHandle;
    hr = XUserFindUserById(localUser->local()->xbox_user_id(), &userHandle);
    if (SUCCEEDED(hr))
    {
        hr = XUserResolvePrivilegeWithUiAsync(
            userHandle,
            XUserPrivilegeOptions::None,
            XUserPrivilege::Communications,
            asyncBlock.get());
        if (SUCCEEDED(hr))
        {
            hr = XAsyncGetStatus(asyncBlock.get(), true);
            if (SUCCEEDED(hr))
            {
                // Remove and re-add the user after fixing the privileges.
                // Users must not be removed while processing state changes.
            }
            asyncBlock.release();
        }
    }
}
```

## Limpeza

Quando o aplicativo não precisar mais de comunicações por meio do Game Chat 2, você deverá chamar [chat\_manager::cleanup()](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_manager/methods/chat_manager_cleanup.md).
Isso permite que o Game Chat 2 recupere os recursos alocados para gerenciar as comunicações.

## Modelo de falhas

A implementação do Game Chat 2 não lança exceções como meio de relatar erros não fatais. Você pode consumi-la facilmente em projetos sem exceções, se preferir.
No entanto, o Game Chat 2 lança exceções para informar você sobre erros fatais.

Esses erros resultam do uso indevido da API, como adicionar um usuário à instância do Game Chat antes de inicializá-la ou acessar um objeto de usuário depois que ele foi removido da instância do Game Chat 2.

Espera-se que esses erros sejam detectados no início do desenvolvimento, e eles podem ser corrigidos modificando o padrão usado para interagir com o Game Chat 2.
Quando esse erro ocorre, uma dica sobre a causa do erro é impressa no depurador antes que a exceção seja lançada.

## Como configurar cenários populares

### Pressionar para falar

O recurso de pressionar para falar deve ser implementado com [chat\_user::chat\_user\_local::set\_microphone\_muted()](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/classes/chat_user/chat_user_local/methods/chat_user_local_set_microphone_muted.md).
Chame `set_microphone_muted(false)` para permitir a fala e `set_microphone_muted(true)` para restringi-la.
Esse método oferece a resposta de menor latência do Game Chat 2.

### Equipes

Suponha que o Usuário A e o Usuário B estejam na Equipe Azul e que o Usuário C e o Usuário D estejam na Equipe Vermelha.
Cada usuário está em uma instância exclusiva do aplicativo.

No dispositivo do Usuário A:

```cpp theme={null}
chatUserA->local()->set_communication_relationship(chatUserB, c_communicationRelationshipSendAndReceiveAll);
chatUserA->local()->set_communication_relationship(chatUserC, game_chat_communication_relationship_flags::none);
chatUserA->local()->set_communication_relationship(chatUserD, game_chat_communication_relationship_flags::none);
```

No dispositivo do Usuário B:

```cpp theme={null}
chatUserB->local()->set_communication_relationship(chatUserA, c_communicationRelationshipSendAndReceiveAll);
chatUserB->local()->set_communication_relationship(chatUserC, game_chat_communication_relationship_flags::none);
chatUserB->local()->set_communication_relationship(chatUserD, game_chat_communication_relationship_flags::none);
```

No dispositivo do Usuário C:

```cpp theme={null}
chatUserC->local()->set_communication_relationship(chatUserA, game_chat_communication_relationship_flags::none);
chatUserC->local()->set_communication_relationship(chatUserB, game_chat_communication_relationship_flags::none);
chatUserC->local()->set_communication_relationship(chatUserD, c_communicationRelationshipSendAndReceiveAll);
```

No dispositivo do Usuário D:

```cpp theme={null}
chatUserD->local()->set_communication_relationship(chatUserA, game_chat_communication_relationship_flags::none);
chatUserD->local()->set_communication_relationship(chatUserB, game_chat_communication_relationship_flags::none);
chatUserD->local()->set_communication_relationship(chatUserC, c_communicationRelationshipSendAndReceiveAll);
```

### Transmissão

Suponha que o Usuário A seja o líder e esteja dando ordens. Os Usuários B, C e D só podem ouvir.
Cada jogador está em um dispositivo exclusivo.

No dispositivo do Usuário A:

```cpp theme={null}
chatUserA->local()->set_communication_relationship(chatUserB, c_communicationRelationshipSendAll);
chatUserA->local()->set_communication_relationship(chatUserC, c_communicationRelationshipSendAll);
chatUserA->local()->set_communication_relationship(chatUserD, c_communicationRelationshipSendAll);
```

No dispositivo do Usuário B:

```cpp theme={null}
chatUserB->local()->set_communication_relationship(chatUserA, c_communicationRelationshipReceiveAll);
chatUserB->local()->set_communication_relationship(chatUserC, game_chat_communication_relationship_flags::none);
chatUserB->local()->set_communication_relationship(chatUserD, game_chat_communication_relationship_flags::none);
```

No dispositivo do Usuário C:

```cpp theme={null}
chatUserC->local()->set_communication_relationship(chatUserA, c_communicationRelationshipReceiveAll);
chatUserC->local()->set_communication_relationship(chatUserB, game_chat_communication_relationship_flags::none);
chatUserC->local()->set_communication_relationship(chatUserD, game_chat_communication_relationship_flags::none);
```

No dispositivo do Usuário D:

```cpp theme={null}
chatUserD->local()->set_communication_relationship(chatUserA, c_communicationRelationshipReceiveAll);
chatUserD->local()->set_communication_relationship(chatUserB, game_chat_communication_relationship_flags::none);
chatUserD->local()->set_communication_relationship(chatUserC, game_chat_communication_relationship_flags::none);
```

## Documentação de referência da API

* [Gamechat2 (conteúdo da API)](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/gamechat2_members.md)
  * Estruturas
    * [game\_chat\_data\_frame](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/structs/game_chat_data_frame.md)
    * [game\_chat\_state\_change](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/structs/game_chat_state_change.md)
    * [game\_chat\_text\_chat\_received\_state\_change](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/structs/game_chat_text_chat_received_state_change.md)
    * [game\_chat\_transcribed\_chat\_received\_state\_change](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/structs/game_chat_transcribed_chat_received_state_change.md)
    * [communication\_relationship\_adjuster\_changed](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/structs/game_chat_stream_state_change.md)
* [xuser (conteúdo da API)](https://docs.xbox.com/pt-BR/reference/system/xuser/xuser_members.md)
  * Funções
    * [xuseraddasync](https://docs.xbox.com/pt-BR/reference/system/xuser/functions/xuseraddasync.md)
    * [xusergetid](https://docs.xbox.com/pt-BR/reference/system/xuser/functions/xusergetid.md)
    * [XUserResolveIssueWithUiAsync](https://docs.xbox.com/pt-BR/reference/system/xuser/functions/xuserresolveissuewithuiasync.md)
    * [XUserResolvePrivilegeWithUiAsync](https://docs.xbox.com/pt-BR/reference/system/xuser/functions/xuserresolveprivilegewithuiasync.md)
    * [XUserFindUserById](https://docs.xbox.com/pt-BR/reference/system/xuser/functions/xuserfinduserbyid.md)

## Confira também

[Introdução ao Game Chat 2](https://docs.xbox.com/pt-BR/services/xbox-services/multiplayer/chat/game-chat2/game-chat-2-intro.md)

[Manipulação de áudio em tempo real](https://docs.xbox.com/pt-BR/services/xbox-services/multiplayer/chat/game-chat2/real-time-audio-manipulation.md)

[Conteúdo da API (GameChat2)](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/gamechat2_members.md)

[Microsoft Game Development Kit](https://docs.xbox.com/pt-BR/services/playfab/sdks/platforms/gdk.md)


## Related topics

- [Visão geral do Game Chat 2](https://docs.xbox.com/pt-BR/services/xbox-services/multiplayer/chat/game-chat2/game-chat-2-overview.md)
- [game_chat_text_chat_received_state_change](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/structs/game_chat_text_chat_received_state_change.md)
- [game_chat_transcribed_chat_received_state_change](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/structs/game_chat_transcribed_chat_received_state_change.md)
- [game_chat_data_frame](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/structs/game_chat_data_frame.md)
- [game_chat_state_change](https://docs.xbox.com/pt-BR/reference/chat/gamechat2/structs/game_chat_state_change.md)
