Something went wrong. Try again.
the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
Something went wrong. Try again.
31 kB · 805 lines
C++
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A//// PARTICULAR PURPOSE.//////// Copyright (c) Microsoft Corporation. All rights reserved#include "stdafx.h"#include "ChatIntegrationLayer.h"#include "DQRNetworkManager.h"#include <robuffer.h>
using namespace Windows::Foundation;using namespace Windows::Xbox::System;
// To integrate the Chat DLL in your game, you can use this ChatIntegrationLayer class with modifications, // or create your own design your own class using the code in this file a guide.std::shared_ptr<ChatIntegrationLayer> GetChatIntegrationLayer(){ static std::shared_ptr<ChatIntegrationLayer> chatIntegrationLayerInstance; if (chatIntegrationLayerInstance == nullptr) { chatIntegrationLayerInstance.reset( new ChatIntegrationLayer() ); }
return chatIntegrationLayerInstance;}
ChatIntegrationLayer::ChatIntegrationLayer() { ZeroMemory( m_chatVoicePacketsStatistic, sizeof(m_chatVoicePacketsStatistic) );}
void ChatIntegrationLayer::InitializeChatManager( __in bool combineCaptureBuffersIntoSinglePacket, __in bool useKinectAsCaptureSource, __in bool applySoundEffectsToCapturedAudio, __in bool applySoundEffectsToChatRenderedAudio, DQRNetworkManager *pDQRNet ){ m_pDQRNet = pDQRNet; { Concurrency::critical_section::scoped_lock lock(m_chatPacketStatsLock); ZeroMemory( m_chatVoicePacketsStatistic, sizeof(m_chatVoicePacketsStatistic) ); }
m_chatManager = ref new Microsoft::Xbox::GameChat::ChatManager(); m_chatManager->ChatSettings->DiagnosticsTraceLevel = Microsoft::Xbox::GameChat::GameChatDiagnosticsTraceLevel::Verbose;
// Optionally, change the default settings below as desired by commenting out and editing any of the following lines // Otherwise these defaults are used. // // m_chatManager = ref new Microsoft::Xbox::GameChat::ChatManager( ChatSessionPeriod::ChatPeriodOf40Milliseconds ); // m_chatManager->ChatSettings->AudioThreadPeriodInMilliseconds = 40; // m_chatManager->ChatSettings->AudioThreadAffinityMask = XAUDIO2_DEFAULT_PROCESSOR; // <- this means is core 5, same as the default XAudio2 core // m_chatManager->ChatSettings->AudioThreadPriority = THREAD_PRIORITY_TIME_CRITICAL; // m_chatManager->ChatSettings->AudioEncodingQuality = Windows::Xbox::Chat::EncodingQuality::Normal; // m_chatManager->ChatSettings->DiagnosticsTraceLevel = Microsoft::Xbox::GameChat::GameChatDiagnosticsTraceLevel::Verbose; m_chatManager->ChatSettings->CombineCaptureBuffersIntoSinglePacket = combineCaptureBuffersIntoSinglePacket; // if unset, it defaults to TRUE m_chatManager->ChatSettings->UseKinectAsCaptureSource = useKinectAsCaptureSource; // if unset, it defaults to FALSE m_chatManager->ChatSettings->PreEncodeCallbackEnabled = applySoundEffectsToCapturedAudio; // if unset, it defaults to FALSE m_chatManager->ChatSettings->PostDecodeCallbackEnabled = applySoundEffectsToChatRenderedAudio; // if unset, it defaults to FALSE
InitializeCriticalSection(&m_csAddedUsers);
std::weak_ptr<ChatIntegrationLayer> weakPtrToThis = shared_from_this();
#ifdef PROFILE m_chatManager->ChatSettings->PerformanceCountersEnabled = true;#endif
// Upon enter constrained mode, mute everyone. // Upon leaving constrained mode, unmute everyone who was previously muted. m_tokenResourceAvailabilityChanged = Windows::ApplicationModel::Core::CoreApplication::ResourceAvailabilityChanged += ref new EventHandler< Platform::Object^ >( [weakPtrToThis] (Platform::Object^, Platform::Object^ ) { // Using a std::weak_ptr instead of 'this' to avoid dangling pointer if caller class is released. // Simply unregistering the callback in the destructor isn't enough to prevent a dangling pointer std::shared_ptr<ChatIntegrationLayer> sharedPtrToThis(weakPtrToThis.lock()); if( sharedPtrToThis != nullptr ) { if (Windows::ApplicationModel::Core::CoreApplication::ResourceAvailability == Windows::ApplicationModel::Core::ResourceAvailability::Constrained) { if( sharedPtrToThis->m_chatManager != nullptr ) { sharedPtrToThis->m_chatManager->MuteAllUsersFromAllChannels(); } } else if(Windows::ApplicationModel::Core::CoreApplication::ResourceAvailability == Windows::ApplicationModel::Core::ResourceAvailability::Full) { if( sharedPtrToThis->m_chatManager != nullptr ) { sharedPtrToThis->m_chatManager->UnmuteAllUsersFromAllChannels();
// The title should remember who was muted so when the Resume even occurs // to avoid unmuting users who has been previously muted. Simply re-mute them here } } } });
m_tokenOnDebugMessage = m_chatManager->OnDebugMessage += ref new Windows::Foundation::EventHandler<Microsoft::Xbox::GameChat::DebugMessageEventArgs^>( [weakPtrToThis] ( Platform::Object^, Microsoft::Xbox::GameChat::DebugMessageEventArgs^ args ) { // Using a std::weak_ptr instead of 'this' to avoid dangling pointer if caller class is released. // Simply unregistering the callback in the destructor isn't enough to prevent a dangling pointer std::shared_ptr<ChatIntegrationLayer> sharedPtrToThis(weakPtrToThis.lock()); if( sharedPtrToThis != nullptr ) { sharedPtrToThis->OnDebugMessageReceived(args); } });
m_tokenOnOutgoingChatPacketReady = m_chatManager->OnOutgoingChatPacketReady += ref new Windows::Foundation::EventHandler<Microsoft::Xbox::GameChat::ChatPacketEventArgs^>( [weakPtrToThis] ( Platform::Object^, Microsoft::Xbox::GameChat::ChatPacketEventArgs^ args ) { // Using a std::weak_ptr instead of 'this' to avoid dangling pointer if caller class is released. // Simply unregistering the callback in the destructor isn't enough to prevent a dangling pointer std::shared_ptr<ChatIntegrationLayer> sharedPtrToThis(weakPtrToThis.lock()); if( sharedPtrToThis != nullptr ) { sharedPtrToThis->OnOutgoingChatPacketReady(args); } });
m_tokenOnCompareUniqueConsoleIdentifiers = m_chatManager->OnCompareUniqueConsoleIdentifiers += ref new Microsoft::Xbox::GameChat::CompareUniqueConsoleIdentifiersHandler( [weakPtrToThis] ( Platform::Object^ obj1, Platform::Object^ obj2 ) { // Using a std::weak_ptr instead of 'this' to avoid dangling pointer if caller class is released. // Simply unregistering the callback in the destructor isn't enough to prevent a dangling pointer std::shared_ptr<ChatIntegrationLayer> sharedPtrToThis(weakPtrToThis.lock()); if( sharedPtrToThis != nullptr ) { return sharedPtrToThis->CompareUniqueConsoleIdentifiers(obj1, obj2); } else { return false; } });
m_tokenUserAudioDeviceAdded = WXS::User::AudioDeviceAdded += ref new Windows::Foundation::EventHandler<WXS::AudioDeviceAddedEventArgs^>( [weakPtrToThis] ( Platform::Object^, WXS::AudioDeviceAddedEventArgs^ value ) { std::shared_ptr<ChatIntegrationLayer> sharedPtrToThis(weakPtrToThis.lock()); if( sharedPtrToThis != nullptr ) { sharedPtrToThis->EvaluateDevicesForUser(value->User); } });
m_tokenUserAudioDeviceRemoved = WXS::User::AudioDeviceRemoved += ref new Windows::Foundation::EventHandler<WXS::AudioDeviceRemovedEventArgs^>( [weakPtrToThis] ( Platform::Object^, WXS::AudioDeviceRemovedEventArgs^ value ) { std::shared_ptr<ChatIntegrationLayer> sharedPtrToThis(weakPtrToThis.lock()); if( sharedPtrToThis != nullptr ) { sharedPtrToThis->EvaluateDevicesForUser(value->User); } });
m_tokenUserAudioDeviceChanged = WXS::User::AudioDeviceChanged += ref new Windows::Foundation::EventHandler<WXS::AudioDeviceChangedEventArgs^>( [weakPtrToThis] ( Platform::Object^, WXS::AudioDeviceChangedEventArgs^ value ) { std::shared_ptr<ChatIntegrationLayer> sharedPtrToThis(weakPtrToThis.lock()); if( sharedPtrToThis != nullptr ) { sharedPtrToThis->EvaluateDevicesForUser(value->User); } });
//m_tokenSuspending = Windows::ApplicationModel::Core::CoreApplication::Suspending += // ref new EventHandler< Windows::ApplicationModel::SuspendingEventArgs^ >( [weakPtrToThis] (Platform::Object^, Windows::ApplicationModel::SuspendingEventArgs^ args) //{ // // Upon Suspending, nothing needs to be done //});
//m_tokenResuming = Windows::ApplicationModel::Core::CoreApplication::Resuming += // ref new EventHandler< Platform::Object^ >( [weakPtrToThis] (Platform::Object^, Windows::ApplicationModel::SuspendingEventArgs^ args) //{ // // Upon Resuming, re-initialize the network, and reinitialize the chat session //});}
void ChatIntegrationLayer::Shutdown(){ if( m_chatManager != nullptr ) { m_chatManager->OnDebugMessage -= m_tokenOnDebugMessage; m_chatManager->OnOutgoingChatPacketReady -= m_tokenOnOutgoingChatPacketReady; m_chatManager->OnCompareUniqueConsoleIdentifiers -= m_tokenOnCompareUniqueConsoleIdentifiers; Windows::ApplicationModel::Core::CoreApplication::ResourceAvailabilityChanged -= m_tokenResourceAvailabilityChanged; if( m_chatManager->ChatSettings->PreEncodeCallbackEnabled ) { m_chatManager->OnPreEncodeAudioBuffer -= m_tokenOnPreEncodeAudioBuffer; } if( m_chatManager->ChatSettings->PostDecodeCallbackEnabled ) { m_chatManager->OnPostDecodeAudioBuffer -= m_tokenOnPostDecodeAudioBuffer; } WXS::User::AudioDeviceAdded -= m_tokenUserAudioDeviceAdded; WXS::User::AudioDeviceRemoved -= m_tokenUserAudioDeviceRemoved; WXS::User::AudioDeviceChanged -= m_tokenUserAudioDeviceChanged;
DeleteCriticalSection(&m_csAddedUsers);
m_chatManager = nullptr; }}
void ChatIntegrationLayer::OnDebugMessageReceived( __in Microsoft::Xbox::GameChat::DebugMessageEventArgs^ args ){ // To integrate the Chat DLL in your game, // change this to false and remove the LogComment calls, // or integrate with your game's own UI/debug message logging system bool outputToUI = false;
if( outputToUI ) { if (args->ErrorCode == S_OK ) { m_pDQRNet->LogComment(L"GameChat: " + args->Message); } else { m_pDQRNet->LogCommentWithError(L"GameChat: " + args->Message, args->ErrorCode); } } else { // The string appear in the Visual Studio Output window #ifndef _CONTENT_PACKAGE OutputDebugString( args->Message->Data() );#endif }}
void ChatIntegrationLayer::GameUI_RecordPacketStatistic( __in Microsoft::Xbox::GameChat::ChatMessageType messageType, __in ChatPacketType chatPacketType ){ uint32 messageTypeInt = static_cast<uint32>(messageType); if( messageType > Microsoft::Xbox::GameChat::ChatMessageType::InvalidMessage ) { return; }
{ Concurrency::critical_section::scoped_lock lock(m_chatPacketStatsLock); m_chatVoicePacketsStatistic[static_cast<int>(chatPacketType)][messageTypeInt]++; }}
int ChatIntegrationLayer::GameUI_GetPacketStatistic( __in Microsoft::Xbox::GameChat::ChatMessageType messageType, __in ChatPacketType chatPacketType ){ uint32 messageTypeInt = static_cast<uint32>(messageType); if( messageType > Microsoft::Xbox::GameChat::ChatMessageType::InvalidMessage ) { return 0; }
{ Concurrency::critical_section::scoped_lock lock(m_chatPacketStatsLock); return m_chatVoicePacketsStatistic[static_cast<int>(chatPacketType)][messageTypeInt]; }}
void ChatIntegrationLayer::OnOutgoingChatPacketReady( __in Microsoft::Xbox::GameChat::ChatPacketEventArgs^ args ){ byte *bytes; int byteCount;
GetBufferBytes(args->PacketBuffer, &bytes); byteCount = args->PacketBuffer->Length; unsigned int address = 0; if( !args->SendPacketToAllConnectedConsoles ) { address = safe_cast<unsigned int>(args->UniqueTargetConsoleIdentifier); } m_pDQRNet->SendBytesChat(address, bytes, byteCount, args->SendReliable, args->SendInOrder, args->SendPacketToAllConnectedConsoles);
GameUI_RecordPacketStatistic( args->ChatMessageType, ChatPacketType::OutgoingPacket );
}
void ChatIntegrationLayer::OnIncomingChatMessage( unsigned int sessionAddress, Platform::Array<byte>^ message ){ // To integrate the Chat DLL in your game, change the following code to use your game's network layer. // Ignore the OnChatMessageReceived event as that is specific to this sample's simple network layer. // Instead your title should upon receiving a packet, extract the chat message from it, and then call m_chatManager->ProcessIncomingChatMessage as shown below // You will need to isolate chat messages to be unique from the rest of you game's other message types.
// uniqueRemoteConsoleIdentifier is a Platform::Object^ and can be cast or unboxed to most types. // What exactly you use doesn't matter, but optimally it would be something that uniquely identifies a console on in the session. // A Windows::Xbox::Networking::SecureDeviceAssociation^ is perfect to use if you have access to it.
// This is how you would convert from byte array to a IBuffer^ // // Windows::Storage::Streams::IBuffer^ destBuffer = ref new Windows::Storage::Streams::Buffer( sourceByteBufferSize ); // byte* destBufferBytes = nullptr; // GetBufferBytes( destBuffer, &destBufferBytes ); // errno_t err = memcpy_s( destBufferBytes, destBuffer->Capacity, sourceByteBuffer, sourceByteBufferSize ); // THROW_HR_IF(err != 0, E_FAIL); // destBuffer->Length = sourceByteBufferSize;
// This is how you would convert from an int to a Platform::Object^ // Platform::Object obj = IntToPlatformObject(5);
Windows::Storage::Streams::IBuffer^ chatMessage = ArrayToBuffer(message); Platform::Object^ uniqueRemoteConsoleIdentifier = (Platform::Object^)sessionAddress;
if( m_chatManager != nullptr ) { Microsoft::Xbox::GameChat::ChatMessageType chatMessageType = m_chatManager->ProcessIncomingChatMessage(chatMessage, uniqueRemoteConsoleIdentifier);
GameUI_RecordPacketStatistic( chatMessageType, ChatPacketType::IncomingPacket ); }}
// Only add people who intend to play.void ChatIntegrationLayer::AddAllLocallySignedInUsersToChatClient( __in uint8 channelIndex, __in Windows::Foundation::Collections::IVectorView<Windows::Xbox::System::User^>^ locallySignedInUsers ){ // To integrate the Chat DLL in your game, // add all locally signed in users to the chat client for each( Windows::Xbox::System::User^ user in locallySignedInUsers ) { if( user != nullptr ) {// LogComment(L"Adding Local User to Chat Client"); AddLocalUserToChatChannel( channelIndex, user ); } }}
ChatIntegrationLayer::AddedUser::AddedUser(Windows::Xbox::System::IUser^ user, bool canCaptureAudio){ m_user = user; m_canCaptureAudio = canCaptureAudio;}
void ChatIntegrationLayer::AddLocalUser( __in Windows::Xbox::System::IUser^ user ){ // Check we haven't added already for( int i = 0; i < m_addedUsers.size(); i++ ) { if( m_addedUsers[i]->m_user->XboxUserId == user->XboxUserId ) { return; } }
bool kinectAvailable = false; Windows::Kinect::KinectSensor^ sensor = Windows::Kinect::KinectSensor::GetDefault(); if( sensor ) { sensor->Open(); if( sensor->IsAvailable ) { kinectAvailable = true; m_pDQRNet->LogComment(L"Evaluated that kinect is available\n"); } sensor->Close(); }
EnterCriticalSection(&m_csAddedUsers); // First establish whether we have an appropriate audio device at this time bool canCaptureAudio = false; for each( WXS::IAudioDeviceInfo^ audioDevice in user->AudioDevices ) { m_pDQRNet->LogComment(L"Evaluating device " + audioDevice->DeviceCategory.ToString() + L" " + audioDevice->DeviceType.ToString() + L" " + audioDevice->Id + L" " + audioDevice->Sharing.ToString() + L" " + audioDevice->IsMicrophoneMuted.ToString() + L"\n");
// Consider shared devices only if kinect is actually available - every machine seems to claim a shared device whether kinect is attached or not if( ( audioDevice->DeviceType == WXS::AudioDeviceType::Capture ) && ( kinectAvailable || ( audioDevice->Sharing != WXS::AudioDeviceSharing::Shared) ) ) { canCaptureAudio = true; } }
// If we can capture audio initially, then register with the chat session. Otherwise we'll reevaluate this situation when audio devices change if( canCaptureAudio ) { AddLocalUserToChatChannel( 0 , user ); }
// Add to vector of users that we are tracking in the chat system m_addedUsers.push_back(new AddedUser(user, canCaptureAudio)); LeaveCriticalSection(&m_csAddedUsers);}
// Remove from our list of tracked users, if the user is already therevoid ChatIntegrationLayer::RemoveLocalUser( __in Windows::Xbox::System::IUser^ user ){ EnterCriticalSection(&m_csAddedUsers); for( auto it = m_addedUsers.begin(); it != m_addedUsers.end(); it++ ) { if( (*it)->m_user->XboxUserId == user->XboxUserId ) { delete (*it); m_addedUsers.erase(it); LeaveCriticalSection(&m_csAddedUsers); return; } } LeaveCriticalSection(&m_csAddedUsers);}
// This is called when the audio devices for a user change in any way, and establishes whether we can now capture audio. Any change in this status from before will cause the user to be added/removed from the chat session.void ChatIntegrationLayer::EvaluateDevicesForUser(__in Windows::Xbox::System::IUser^ user ){ bool kinectAvailable = false; Windows::Kinect::KinectSensor^ sensor = Windows::Kinect::KinectSensor::GetDefault(); if( sensor ) { sensor->Open(); if( sensor->IsAvailable ) { kinectAvailable = true; m_pDQRNet->LogComment(L"Evaluated that kinect is available\n"); } sensor->Close(); }
EnterCriticalSection(&m_csAddedUsers); for( int i = 0; i < m_addedUsers.size(); i++ ) { AddedUser *addedUser = m_addedUsers[i]; if( addedUser->m_user->XboxUserId == user->XboxUserId ) { bool canCaptureAudio = false; for each( WXS::IAudioDeviceInfo^ audioDevice in addedUser->m_user->AudioDevices ) { // Consider shared devices only if kinect is actually available - every machine seems to claim a shared device whether kinect is attached or not if( ( audioDevice->DeviceType == WXS::AudioDeviceType::Capture ) && ( kinectAvailable || ( audioDevice->Sharing != WXS::AudioDeviceSharing::Shared) ) ) { canCaptureAudio = true; break; } } if( canCaptureAudio != addedUser->m_canCaptureAudio ) { if( canCaptureAudio ) { AddLocalUserToChatChannel(0, addedUser->m_user ); } else { RemoveUserFromChatChannel(0, addedUser->m_user ); } addedUser->m_canCaptureAudio = canCaptureAudio; LeaveCriticalSection(&m_csAddedUsers); return; } } } LeaveCriticalSection(&m_csAddedUsers);}
void ChatIntegrationLayer::AddLocalUserToChatChannel( __in uint8 channelIndex, __in Windows::Xbox::System::IUser^ user ){ // Adds a local user to a specific channel.
// This is helper function waits for the task to cm_chatManageromplete so shouldn't be called from the UI thread // Remove the .wait() and return the result of concurrency::create_task() if you want to call it from the UI thread // and chain PPL tasks together
m_pDQRNet->LogComment( L">>>>>>>>>>>>> AddLocalUserToChatChannel" ); if( m_chatManager != nullptr ) { auto asyncOp = m_chatManager->AddLocalUserToChatChannelAsync( channelIndex, user ); concurrency::create_task( asyncOp ) .then( [this] ( concurrency::task<void> t ) { // Error handling try { t.get(); } catch ( Platform::Exception^ ex ) { m_pDQRNet->LogCommentWithError( L"AddLocalUserToChatChannelAsync failed", ex->HResult ); } }) .wait(); }}
void ChatIntegrationLayer::RemoveRemoteConsole( unsigned int address ){ // uniqueConsoleIdentifier is a Platform::Object^ and can be cast or unboxed to most types. // What exactly you use doesn't matter, but optimally it would be something that uniquely identifies a console on in the session. // A Windows::Xbox::Networking::SecureDeviceAssociation^ is perfect to use if you have access to it.
// This is how you would convert from an int to a Platform::Object^ // Platform::Object obj = IntToPlatformObject(5);
// This is helper function waits for the task to complete so shouldn't be called from the UI thread // Remove the .wait() and return the result of concurrency::create_task() if you want to call it from the UI thread // and chain PPL tasks together
Platform::Object^ uniqueRemoteConsoleIdentifier = (Platform::Object^)address;
if( m_chatManager != nullptr ) { auto asyncOp = m_chatManager->RemoveRemoteConsoleAsync( uniqueRemoteConsoleIdentifier ); concurrency::create_task( asyncOp ).then( [this] ( concurrency::task<void> t ) { // Error handling try { t.get(); } catch ( Platform::Exception^ ex ) { m_pDQRNet->LogCommentWithError( L"RemoveRemoteConsoleAsync failed", ex->HResult ); } }) .wait(); }}
void ChatIntegrationLayer::RemoveUserFromChatChannel( __in uint8 channelIndex, __in Windows::Xbox::System::IUser^ user ){ if( m_chatManager != nullptr ) { // This is helper function waits for the task to complete so shouldn't be called from the UI thread // Remove the .wait() and return the result of concurrency::create_task() if you want to call it from the UI thread // and chain PPL tasks together
auto asyncOp = m_chatManager->RemoveLocalUserFromChatChannelAsync( channelIndex, user ); concurrency::create_task( asyncOp ).then( [this] ( concurrency::task<void> t ) { // Error handling try { t.get(); } catch ( Platform::Exception^ ex ) { m_pDQRNet->LogCommentWithError( L"RemoveLocalUserFromChatChannelAsync failed", ex->HResult ); } }) .wait(); }}
void ChatIntegrationLayer::OnNewSessionAddressAdded( __in unsigned int address ){ m_pDQRNet->LogCommentFormat( L">>>>>>>>>>>>> OnNewSessionAddressAdded (%d)",address ); Platform::Object^ uniqueConsoleIdentifier = (Platform::Object^)address; /// Call this when a new console connects. /// This adds this console to the chat layer if( m_chatManager != nullptr ) { m_chatManager->HandleNewRemoteConsole(uniqueConsoleIdentifier ); }}
Windows::Foundation::Collections::IVectorView<Microsoft::Xbox::GameChat::ChatUser^>^ ChatIntegrationLayer::GetChatUsers(){ if( m_chatManager != nullptr ) { return m_chatManager->GetChatUsers(); }
return nullptr;}
bool ChatIntegrationLayer::HasMicFocus(){ if( m_chatManager != nullptr ) { return m_chatManager->HasMicFocus; }
return false;}
Platform::Object^ ChatIntegrationLayer::IntToPlatformObject( __in int val ){ return (Platform::Object^)val;
// You can also do the same using a PropertyValue. //return Windows::Foundation::PropertyValue::CreateInt32(val);}
int ChatIntegrationLayer::PlatformObjectToInt( __in Platform::Object^ uniqueRemoteConsoleIdentifier ){ return safe_cast<int>( uniqueRemoteConsoleIdentifier );
// You can also do the same using a PropertyValue. //return safe_cast<Windows::Foundation::IPropertyValue^>(uniqueRemoteConsoleIdentifier)->GetInt32();}
void ChatIntegrationLayer::HandleChatChannelChanged( __in uint8 oldChatChannelIndex, __in uint8 newChatChannelIndex, __in Microsoft::Xbox::GameChat::ChatUser^ chatUser ){ // We remember if the local user was currently muted from all channels. And when we switch channels, // we ensure that the state persists. For remote users, title should implement this themselves // based on title game design if they want to persist the muting state.
bool wasUserMuted = false; IUser^ userBeingRemoved = nullptr;
if (chatUser != nullptr && chatUser->IsLocal) { wasUserMuted = chatUser->IsMuted; userBeingRemoved = chatUser->User; if (userBeingRemoved != nullptr) { RemoveUserFromChatChannel(oldChatChannelIndex, userBeingRemoved); AddLocalUserToChatChannel(newChatChannelIndex, userBeingRemoved); } }
// If the local user was muted earlier, get the latest chat users and mute him again on the newly added channel. if (wasUserMuted && userBeingRemoved != nullptr) { auto chatUsers = GetChatUsers(); if (chatUsers != nullptr ) { for (UINT chatUserIndex = 0; chatUserIndex < chatUsers->Size; chatUserIndex++) { Microsoft::Xbox::GameChat::ChatUser^ chatUser = chatUsers->GetAt(chatUserIndex); if( chatUser != nullptr && (chatUser->XboxUserId == userBeingRemoved->XboxUserId) ) { m_chatManager->MuteUserFromAllChannels(chatUser); break; } } } }}
void ChatIntegrationLayer::ChangeChatUserMuteState( __in Microsoft::Xbox::GameChat::ChatUser^ chatUser ){ /// Helper function to swap the mute state of a specific chat user if( m_chatManager != nullptr && chatUser != nullptr) { if (chatUser->IsMuted) { m_chatManager->UnmuteUserFromAllChannels(chatUser); } else { m_chatManager->MuteUserFromAllChannels(chatUser); } }}
Microsoft::Xbox::GameChat::ChatUser^ ChatIntegrationLayer::GetChatUserByXboxUserId( __in Platform::String^ xboxUserId ){ Windows::Foundation::Collections::IVectorView<Microsoft::Xbox::GameChat::ChatUser^>^ chatUsers = GetChatUsers(); for each (Microsoft::Xbox::GameChat::ChatUser^ chatUser in chatUsers) { if (chatUser != nullptr && ( chatUser->XboxUserId == xboxUserId ) ) { return chatUser; } } return nullptr;}
bool ChatIntegrationLayer::CompareUniqueConsoleIdentifiers( __in Platform::Object^ uniqueRemoteConsoleIdentifier1, __in Platform::Object^ uniqueRemoteConsoleIdentifier2 ){ if (uniqueRemoteConsoleIdentifier1 == nullptr || uniqueRemoteConsoleIdentifier2 == nullptr) { return false; }
// uniqueRemoteConsoleIdentifier is a Platform::Object^ and can be cast or unboxed to most types. // We're using XRNS addresses, which are unsigned ints unsigned int address1 = safe_cast<unsigned int>(uniqueRemoteConsoleIdentifier1); unsigned int address2 = safe_cast<unsigned int>(uniqueRemoteConsoleIdentifier2); return address1 == address2;}
Microsoft::Xbox::GameChat::ChatPerformanceCounters^ ChatIntegrationLayer::GetChatPerformanceCounters(){ if( m_chatManager != nullptr && m_chatManager->ChatSettings != nullptr && m_chatManager->ChatSettings->PerformanceCountersEnabled ) { return m_chatManager->ChatPerformanceCounters; }
return nullptr;}
void ChatIntegrationLayer::OnControllerPairingChanged( Windows::Xbox::Input::ControllerPairingChangedEventArgs^ args ){#if 0 auto controller = args->Controller; if ( controller ) { if ( controller->Type == L"Windows.Xbox.Input.Gamepad" ) { // Either add the user or sign one in User^ user = args->User; if ( user != nullptr ) { g_sampleInstance->GetLoggingUI()->LogCommentToUI("OnControllerPairingChanged: " + user->DisplayInfo->Gamertag); AddLocalUserToChatChannel( g_sampleInstance->GetUISelectionChatChannelIndex(), user ); } } }#endif}
void ChatIntegrationLayer::ToggleRenderTargetVolume(){ // Simple toggle logic to just show usage of LocalRenderTargetVolume property static bool makeRenderTargetVolumeQuiet = false; makeRenderTargetVolumeQuiet = !makeRenderTargetVolumeQuiet;
auto chatUsers = GetChatUsers(); if (chatUsers != nullptr ) { for (UINT chatUserIndex = 0; chatUserIndex < chatUsers->Size; chatUserIndex++) { Microsoft::Xbox::GameChat::ChatUser^ chatUser = chatUsers->GetAt(chatUserIndex); if( chatUser != nullptr && chatUser->IsLocal ) { chatUser->LocalRenderTargetVolume = ( makeRenderTargetVolumeQuiet ) ? 0.1f : 1.0f; } } }}
void ChatIntegrationLayer::GetBufferBytes( __in Windows::Storage::Streams::IBuffer^ buffer, __out byte** ppOut ){ if ( ppOut == nullptr || buffer == nullptr ) { throw ref new Platform::InvalidArgumentException(); }
*ppOut = nullptr;
Microsoft::WRL::ComPtr<IInspectable> srcBufferInspectable(reinterpret_cast<IInspectable*>( buffer )); Microsoft::WRL::ComPtr<Windows::Storage::Streams::IBufferByteAccess> srcBufferByteAccess; srcBufferInspectable.As(&srcBufferByteAccess); srcBufferByteAccess->Buffer(ppOut);}
Windows::Storage::Streams::IBuffer^ ChatIntegrationLayer::ArrayToBuffer( __in Platform::Array<byte>^ array ){ Windows::Storage::Streams::DataWriter^ writer = ref new Windows::Storage::Streams::DataWriter(); writer->WriteBytes(array); return writer->DetachBuffer();}