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. 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 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, conforme mostrado a seguir.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(). 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. Para obter mais informações sobre como usar essa API, consulte Identidade do usuário e XUser. Depois de obter oXUserHandle 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.
O usuário precisa estar online, e você precisa ter o consentimento do usuário para esta etapa.
XUserGetId 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.
Lembre-se de que chamar XUserResolveIssueWithUiAsync exibe uma caixa de diálogo do sistema.
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. Neste exemplo, o Usuário A representa um usuário local.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.
c_communicationRelationshipSendAll é uma constante definida em GameChat2.h para representar essa comunicação unidirecional.
Defina os relacionamentos da seguinte forma.
chat_manager::remove_user() pode invalidar o objeto de usuário. Se você estiver usando a manipulação de áudio em tempo real, consulte Tempo de vida dos usuários do chat 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 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() e chat_manager::finish_processing_data_frames(). 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. Quandochat_manager::start_processing_data_frames() é chamado, todos os dados enfileirados são informados em uma matriz de ponteiros de estrutura game_chat_data_frame.
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, 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.
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() e chat_manager::finish_processing_state_changes(). 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. Quandochat_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.
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 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.
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(). Isso é mostrado no exemplo a seguir.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() e chat_user::chat_user_local::speech_to_text_conversion_preference_enabled(), 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() retornatrue. 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(). 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.
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() retornatrue. 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.
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.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() para recuperar uma enumeração game_chat_user_chat_indicator 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 apontado pela variávelchatUserA para determinar um valor de constante de ícone específico a ser atribuído a uma variável iconToShow.
Silenciamento
O método chat_user::chat_user_local::set_microphone_muted() 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() 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 achat_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() 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:- O usuário remoto não é amigo do usuário local.
- O usuário remoto tem um sinalizador de má reputaçã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. Ochat_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() 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 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.
Por exemplo, se as operações de consulta ainda estiverem em andamento, o game_chat_communication_relationship_adjuster 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 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.
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.
- Os usuários precisam dar consentimento aos serviços do XBOX para que o Game Chat 2 verifique os privilégios.
- 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).
game_chat_communication_relationship_adjuster::privilege, você pode chamar XUserResolvePrivilegeWithUiAsync 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 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.
chat_manager::remove_user() não pode ser chamado durante o processamento das alterações de estado (ou seja, depois que chat_manager::start_processing_state_changes() tiver sido chamado e antes da chamada correspondente a chat_manager::finish_processing_state_changes()). 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.XUserHandle a partir de um XUID, o que é necessário para chamar XUserResolvePrivilegeWithUiAsync, você pode usar a API XUserFindUserById para obter um novo XUserHandle. Como alternativa, você pode manter aquele que obteve com XUserAddAsync e acompanhar qual XUID corresponde a ele.
Aqui está um exemplo de como resolver esses problemas.
Limpeza
Quando o aplicativo não precisar mais de comunicações por meio do Game Chat 2, você deverá chamar chat_manager::cleanup(). 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(). Chameset_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.
