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;
例如,chat_user::chat_indicator() 报告的值应随着玩家开始和停止说话而频繁变化。
因此,该值被设计为支持每个 UI 帧都对它进行轮询的应用。
可以使用 chat_user::chat_user_local::set_microphone_muted() 方法切换本地用户的麦克风静音状态。 将麦克风静音后,不捕获来自该麦克风的音频。 如果用户在 Kinect 等共享设备上,则静音状态应用于所有用户。
可以使用 chat_user::chat_user_local::microphone_muted() 方法检索本地用户的麦克风静音状态。 此方法通过调用 chat_user::chat_user_local::set_microphone_muted()
,只反映是否已在软件中将本地用户的麦克风静音。 不反映由硬件控制的静音,例如通过用户耳机上的按钮禁音。
没有通过游戏聊天 2 检索用户音频设备的硬件静音状态的方法。
可以使用 chat_user::chat_user_local::set_remote_user_muted() 方法切换远程用户对于某个本地用户的静音状态。 远程用户静音后,本地用户不会听到来自该远程用户的任何音频或接收到来自他的任何文本消息。
不良信誉自动静音
远程用户一开始并未静音。
游戏聊天 2 在以下情况下开始将用户禁音:
远程用户不是本地用户的好友。
远程用户拥有不良信誉标志。
用户因为此操作而被静音时,chat_user::chat_indicator()
返回 game_chat_user_chat_indicator::reputation_restricted
。
此状态将由对 chat_user::chat_user_local::set_remote_user_muted()
(其中将远程用户作为目标用户)的首次调用替代。
特权和隐私
除了由游戏配置的通信关系之外,游戏聊天 2 还强制执行特权和隐私限制。
首次添加用户时,游戏聊天 2 执行特权和隐私限制查找。 用户的 chat_user::chat_indicator()
始终返回 game_chat_user_chat_indicator::silent
,直到这些操作完成。
如果与用户的通信受到特权或隐私限制的影响,则用户的 chat_user::chat_indicator()
返回 game_chat_user_chat_indicator::platform_restricted
。
平台通信限制对语音聊天和文字聊天都适用。 绝不会有平台限制阻止文字聊天而不阻止语音聊天的实例,反之亦然。
chat_user::chat_user_local::get_effective_communication_relationship() 可用于帮助区分用户因特权和隐私操作不完整而无法通信的情况。
它返回由游戏聊天 2 强制施加的通信关系(采用 game_chat_communication_relationship_flags 形式),以及该关系可能不等于配置的关系(采用 game_chat_communication_relationship_adjuster 枚举的形式)的原因。
例如,如果查找操作仍在进行,game_chat_communication_relationship_adjuster 将为 game_chat_communication_relationship_adjuster::initializing
。
不应使用此方法来影响 UI。 (有关详细信息,请参阅本主题前面的 UI 一节。)
如果游戏聊天 2 遇到特权问题,将在 communication_relationship_adjuster_changed 状态更改中报告该问题。
如果游戏聊天 2 因不可恢复的原因未能检索用户的特权,系统会将该问题报告为 game_chat_communication_relationship_adjuster::privilege_check_failure
调节器。
如果游戏聊天 2 因用户也许能解决的问题而未能检索用户的特权,系统会将该问题报告为 game_chat_communication_relationship_adjuster::resolve_user_issue
调节器。
如果用户缺少可能可以通过 UI 解析的特权,系统会将该问题报告为 game_chat_communication_relationship_adjuster::privilege
调节器。
在这些情况下,通信将受到限制。
下面的示例说明如何检查用户是否存在以下某一个常见问题。
用户需要对 Xbox Live 予以准许,以便游戏聊天 2 检查特权。
将用户帐户配置为拒绝特权(例如,配置为子帐户,使其无法使用聊天功能)。
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);
对于使用 game_chat_communication_relationship_adjuster::privilege
调节器报告的问题,可以使用 XUserPrivilegeOptions::None
和 XUserPrivilege::Communications
调用 XUserResolvePrivilegeWithUiAsync,以尝试解决该问题。
对于通过 game_chat_communication_relationship_adjuster::resolve_user_issue
调节器报告的问题,可以通过 nullptr
对 URL 调用 XUserResolveIssueWithUiAsync 来尝试解决此问题。
我们建议你显示指示存在特权问题的 UI。 允许用户决定是否要尝试通过按下按钮或菜单选项来解决该问题。
用户可能无法或不愿意解决此问题。
如果用户确实解决了此问题,会在下一次将用户添加到游戏聊天 2 时生效。
在处理状态更改时(也就是调用 chat_manager::start_processing_state_changes() 后以及对 chat_manager::finish_processing_state_changes() 的相应调用前)不得调用 chat_manager::remove_user()。 在正在处理状态更改时调用 chat_manager\::remove_user()
会使与删除的这位用户相关联的内存无效。
如果你看到 game_chat_communication_relationship_adjuster::privilege
调节器并且希望尝试解析用户特权,应等到处理状态更改后再尝试此操作。
若要从 XUID 获取调用 XUserResolvePrivilegeWithUiAsync
所必需的 XUserHandle
,可以使用 XUserFindUserById API 获取新的 XUserHandle
。 或者,可以继续使用通过 XUserAddAsync 获取的项,并跟踪映射到它的 XUID。
下面的示例展示如何解决这些问题。
// 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();
当应用不再需要通过游戏聊天 2 进行通信时,应该调用 chat_manager::cleanup()。
这使游戏聊天 2 能够回收已分配的资源,以管理通信。
游戏聊天 2 实现不会将引发异常作为非错误报告的方式。 如果愿意,你可以从无异常项目中轻松地使用它。
但,游戏聊天 2 确实会引发异常,告诉你发生错误。
这些错误是误用 API 的结果,例如在初始化实例前将用户添加到游戏聊天实例,或者从游戏聊天 2 实例中删除用户对象后访问该用户对象。
预计在开发过程的早期捕获这些错误,并且可通过修改用于与游戏聊天 2 交互的模式来更正这些错误。
发生此类错误时,系统在引发异常前,向调试程序发送一个提示,说明导致该错误的原因。
如何配置热门场景
按下即可发言
应使用 chat_user::chat_user_local::set_microphone_muted() 实现按下即可发言。
调用 set_microphone_muted(false)
允许使用语音,调用 set_microphone_muted(true)
对其进行限制。
如果使用此方法,来自游戏聊天 2 的响应的延迟最低。
假设用户 A 和用户 B 都在蓝队中,并且用户 C 和用户 D 都在红队中。
每个用户都是应用的唯一实例。
在用户 A 的设备上:
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);
在用户 B 的设备上:
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);
在用户 C 的设备上:
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);
在用户 D 的设备上:
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);
假设用户 A 是领导,发号施令。 用户 B、C、D 只能听。
每个玩家各在一台设备上。
在用户 A 的设备上:
chatUserA->local()->set_communication_relationship(chatUserB, c_communicationRelationshipSendAll);
chatUserA->local()->set_communication_relationship(chatUserC, c_communicationRelationshipSendAll);
chatUserA->local()->set_communication_relationship(chatUserD, c_communicationRelationshipSendAll);
在用户 B 的设备上:
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);
在用户 C 的设备上:
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);
在用户 D 的设备上:
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);
游戏聊天 2 简介
实时音频操作
API 内容 (GameChat2)
Microsoft 游戏开发工具包