Created
November 3, 2021 12:11
-
-
Save PumpkinPaul/6a246d040a58c279e47b0cf956c1a74b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // GENERATED BY BRUTE | |
| // PumpkinGames.Glitchangels.Platforms.XboxOne.Native.XboxOneNative | |
| #include <mscorlib/1nternal/Brute.h> | |
| #include "Glitchangels/PumpkinGames/Glitchangels/Platforms/XboxOne/Native/XboxOneNative.h" | |
| #include "Glitchangels/PumpkinGames/Glitchangels/Platforms/XboxOne/Native/XboxOneNativeStats.h" | |
| #include "Glitchangels/PumpkinGames/Glitchangels/Platforms/XboxOne/Native/XboxOneNativeLeaderboard.h" | |
| #include "mscorlib/System/Array.h" | |
| #include "mscorlib/System/Byte.h" | |
| #include "mscorlib/System/Exception.h" | |
| #include "mscorlib/System/String.h" | |
| #include "mscorlib/System/Array.inl" | |
| #include "mscorlib/System/String.inl" | |
| #include "Microsoft.Xbox.One/Microsoft/Xbox/One/Input/Gamepad.h" | |
| #include <windows.h> | |
| //#include "Paladin/Paladin/XboxEvents.h" | |
| #include <collection.h> | |
| #include <Robuffer.h> | |
| #include <xsapi/services.h> | |
| #include <xsapi/xbox_live_context_settings.h> | |
| #include <xsapi/stats_manager.h> | |
| #include "Glitchangels/PumpkinGames/Glitchangels/BaseGame.h" | |
| #include "Glitchangels/PumpkinGames/Glitchangels/ConversionHelper.h" | |
| #include "Glitchangels/PumpkinGames/Glitchangels/Menus/MenuManager.h" | |
| #include "Glitchangels/PumpkinGames/Glitchangels/Input/InputMethod.h" | |
| #include "Glitchangels/PumpkinGames/Glitchangels/Input/GamepadInputMethod.h" | |
| #include "Glitchangels/PumpkinGames/Glitchangels/ScoreItem.h" | |
| #include "Glitchangels/PumpkinGames/Glitchangels/GameServices/LeaderboardFilterType.h" | |
| #include "Glitchangels/PumpkinGames/Glitchangels/GameServices/XboxLive/XboxLiveLeaderboard.h" | |
| #include "Glitchangels/PumpkinGames/Glitchangels/Storage/StorageResult.h" | |
| using namespace Windows::ApplicationModel; | |
| using namespace Windows::ApplicationModel::Core; | |
| using namespace Windows::Foundation; | |
| using namespace Windows::System; | |
| using namespace Windows::UI::Core; | |
| using namespace Windows::UI::Popups; | |
| using namespace Windows::Xbox::System; | |
| using namespace Windows::Xbox::Services; | |
| using namespace Windows::Xbox::Storage; | |
| using namespace Windows::Xbox::UI; | |
| using namespace xbox::services; | |
| using namespace xbox::services::stats::manager; | |
| using namespace concurrency; | |
| namespace PumpkinGames { | |
| namespace Glitchangels { | |
| namespace Platforms { | |
| namespace XboxOne { | |
| namespace Native { | |
| std::shared_ptr<xbox_live_context> m_xboxLiveContext; | |
| User^ m_user = nullptr; | |
| User^ m_gamepad_user = nullptr; //Users used to check the Home->Switch User combo | |
| ConnectedStorageSpace^ m_userStorage = nullptr; | |
| // Title Info | |
| uint32_t m_titleId; | |
| std::wstring m_scid; | |
| std::vector<string_t> m_leaderboardColumnNames; | |
| Windows::Xbox::Input::IGamepad^ GetGamepadFromPlayerIndex(int playerIndex) | |
| { | |
| #if _DEBUG | |
| wchar_t temp[512]; | |
| #endif | |
| auto gamepadId = Microsoft::Xbox::One::Input::GamePad$_$S_GetGamepadIdByIndex(playerIndex); | |
| if (gamepadId == 0) | |
| { | |
| #if _DEBUG | |
| swprintf(temp, 512, L"Cannot get Gamepad->Id for playerIndex: %d!\n", playerIndex); | |
| OutputDebugString(temp); | |
| #endif | |
| return nullptr; | |
| } | |
| #if _DEBUG | |
| swprintf(temp, 512, L"Gamepad->Id for playerIndex: %d is %llu\n", playerIndex, gamepadId); | |
| OutputDebugString(temp); | |
| #endif | |
| auto gamepads = ::Windows::Xbox::Input::Gamepad::Gamepads; | |
| auto count = gamepads->Size; | |
| auto index = -1; | |
| for (auto i = 0; i < count; i++) | |
| { | |
| auto p = gamepads->GetAt(i); | |
| if (p == nullptr) | |
| continue; | |
| #if _DEBUG | |
| swprintf(temp, 512, L"Gamepad->Id at gamepads[%d] is %llu\n", i, p->Id); | |
| OutputDebugString(temp); | |
| #endif | |
| if (p->Id == gamepadId) | |
| { | |
| index = i; | |
| break; | |
| } | |
| } | |
| if (-1 == index) | |
| return nullptr; | |
| #if _DEBUG | |
| swprintf(temp, 512, L"Gamepad->Id found at index: %d\n", index); | |
| OutputDebugString(temp); | |
| #endif | |
| return gamepads->GetAt(index); | |
| } | |
| void XboxOneNative$_$S_InitializeStatsAndEvents() | |
| { | |
| //EventRegisterPUMK_2361DC0E(); | |
| CoreApplication::GetCurrentView()->CoreWindow->Activated += ref new TypedEventHandler<CoreWindow^, WindowActivatedEventArgs^>([](Platform::Object^ sender, WindowActivatedEventArgs^ args) | |
| { | |
| int playerIndex = -1; | |
| Windows::Xbox::Input::IGamepad^ pad = nullptr; | |
| switch (args->WindowActivationState) | |
| { | |
| case CoreWindowActivationState::CodeActivated: | |
| #if _DEBUG | |
| OutputDebugString(L"CoreWindow->Activated CoreWindowActivationState::CodeActivated\n"); | |
| #endif | |
| BaseGame$_ActivateGame(::PumpkinGames::Glitchangels::BaseGame$_$S_get_Instance()); | |
| if (m_user == nullptr) | |
| return; | |
| playerIndex = (int)GamepadInputMethod$_get_PrimaryControllerId_Int32(::PumpkinGames::Glitchangels::BaseGame$_$S_get_Instance()->GamepadInputMethod); | |
| pad = GetGamepadFromPlayerIndex(playerIndex); | |
| if (pad == nullptr) | |
| return; | |
| if (pad->User == nullptr) | |
| return; | |
| //Have we already tested this gamepad user? Don't want to keep showing the confirm message innit! | |
| if (m_gamepad_user && Platform::String::CompareOrdinal(m_gamepad_user->XboxUserId, pad->User->XboxUserId) == 0) | |
| return; | |
| m_gamepad_user = pad->User; | |
| if (Platform::String::CompareOrdinal(m_user->XboxUserId, pad->User->XboxUserId) != 0) | |
| { | |
| BaseGame$_RequestControllerPairingChangedMenu(::PumpkinGames::Glitchangels::BaseGame$_$S_get_Instance()); | |
| } | |
| break; | |
| case CoreWindowActivationState::Deactivated: | |
| #if _DEBUG | |
| OutputDebugString(L"CoreWindow->Activated CoreWindowActivationState::Deactivated\n"); | |
| #endif | |
| BaseGame$_DeactivateGame(::PumpkinGames::Glitchangels::BaseGame$_$S_get_Instance()); | |
| break; | |
| case CoreWindowActivationState::PointerActivated: | |
| #if _DEBUG | |
| OutputDebugString(L"CoreWindow->Activated CoreWindowActivationState::PointerActivated\n"); | |
| #endif | |
| BaseGame$_ActivateGame(::PumpkinGames::Glitchangels::BaseGame$_$S_get_Instance()); | |
| break; | |
| } | |
| }); | |
| Windows::Xbox::ApplicationModel::Core::CoreApplicationContext::CurrentUserChanged += | |
| ref new Windows::Foundation::EventHandler<Platform::Object^>( | |
| [](Platform::Object^ sender, Platform::Object^ args) | |
| { | |
| #if _DEBUG | |
| OutputDebugString(L"Windows::Xbox::ApplicationModel::Core::CoreApplicationContext::CurrentUserChanged\n"); | |
| #endif | |
| }); | |
| //m_liveResources.Initialize(); | |
| auto appConfig = xbox::services::xbox_live_app_config::get_app_config_singleton(); | |
| m_titleId = appConfig->title_id(); | |
| m_scid = appConfig->scid(); | |
| //m_leaderboardColumnNames.push_back(L"Ship"); | |
| //m_leaderboardColumnNames.push_back(L"Ticks"); | |
| m_leaderboardColumnNames.push_back(L"Level"); | |
| } | |
| static void GetSessionData(LPGUID& sessionId) | |
| { | |
| sessionId = new GUID(); | |
| ZeroMemory(sessionId, sizeof(GUID)); | |
| } | |
| static void GetSessionData(PCWSTR& userId, LPGUID& sessionId) | |
| { | |
| userId = &(XboxOneNative$_$S_get_UserId()->start_char); | |
| sessionId = new GUID(); | |
| ZeroMemory(sessionId, sizeof(GUID)); | |
| } | |
| void StoreUser(Windows::Xbox::Input::IGamepad^ pad, Windows::Foundation::IAsyncOperation<Windows::Xbox::Storage::ConnectedStorageSpace^>^ opSpace) | |
| { | |
| m_user = pad->User; | |
| m_userStorage = opSpace->GetResults(); | |
| m_xboxLiveContext = std::make_shared<xbox::services::xbox_live_context>(m_user); | |
| // Setup additional user state. | |
| auto userId = ::System::String$_$Ctor(nullptr, (wchar_t*)m_user->XboxUserId->Data()); | |
| XboxOneNative$_$S_set_UserId(userId); | |
| XboxOneNative$_$S_set_LastUserId(userId); | |
| XboxOneNative$_$S_set_GamerTag(::System::String$_$Ctor(nullptr, (wchar_t*)m_user->DisplayInfo->Gamertag->Data())); | |
| m_gamepad_user = m_user; | |
| //Stats | |
| StatsAddLocalUser(stats_manager::get_singleton_instance(), m_user); | |
| } | |
| bool XboxOneNative$_$S_SetCurrentUser(int playerIndex) | |
| { | |
| // We are completely setting a new user up. | |
| m_user = nullptr; | |
| m_userStorage = nullptr; | |
| m_xboxLiveContext.reset(); | |
| XboxOneNative$_$S_set_UserId(nullptr); | |
| XboxOneNative$_$S_set_LastUserId(nullptr); | |
| XboxOneNative$_$S_set_GamerTag(nullptr); | |
| auto pad = GetGamepadFromPlayerIndex(playerIndex); | |
| if (pad == nullptr) | |
| return false; | |
| if (pad->User == nullptr) | |
| { | |
| auto pickOp = ::Windows::Xbox::UI::SystemUI::ShowAccountPickerAsync(pad, Windows::Xbox::UI::AccountPickerOptions::None); | |
| while (true) | |
| { | |
| auto s = pickOp->Status; | |
| if (s == ::Windows::Foundation::AsyncStatus::Completed) | |
| break; | |
| if (s == ::Windows::Foundation::AsyncStatus::Canceled || | |
| s == ::Windows::Foundation::AsyncStatus::Error) | |
| { | |
| auto c = pickOp->ErrorCode; | |
| return false; | |
| } | |
| } | |
| } | |
| if (pad->User == nullptr) | |
| return false; | |
| // Get the storage space here once! | |
| auto opSpace = ::Windows::Xbox::Storage::ConnectedStorageSpace::GetForUserAsync(pad->User); | |
| while (true) | |
| { | |
| auto s = opSpace->Status; | |
| if (s == ::Windows::Foundation::AsyncStatus::Completed) | |
| break; | |
| if (s == ::Windows::Foundation::AsyncStatus::Canceled || | |
| s == ::Windows::Foundation::AsyncStatus::Error) | |
| { | |
| auto c = opSpace->ErrorCode; | |
| return false; | |
| } | |
| } | |
| // Store the user and the storage space for use later. | |
| StoreUser(pad, opSpace); | |
| return true; | |
| } | |
| bool XboxOneNative$_$S_SwitchUser(int playerIndex, ::System::String* requiredUserId) | |
| { | |
| auto pad = GetGamepadFromPlayerIndex(playerIndex); | |
| if (pad == nullptr) | |
| return false; | |
| auto pickOp = ::Windows::Xbox::UI::SystemUI::ShowAccountPickerAsync(pad, Windows::Xbox::UI::AccountPickerOptions::None); | |
| while (true) | |
| { | |
| auto s = pickOp->Status; | |
| if (s == ::Windows::Foundation::AsyncStatus::Completed) | |
| { | |
| auto results = pickOp->GetResults(); | |
| // A null user is a cancled picker pick. | |
| if (results->User == nullptr) | |
| return false; | |
| // Are we looking for a particular user? | |
| if (requiredUserId != nullptr) | |
| { | |
| if (Platform::String::CompareOrdinal(::Platform::StringReference(&requiredUserId->start_char), results->User->XboxUserId) != 0) | |
| return false; | |
| } | |
| else | |
| { | |
| // Did we repick the same user? | |
| if (m_user != nullptr) | |
| { | |
| if (Platform::String::CompareOrdinal(m_user->XboxUserId, results->User->XboxUserId) == 0) | |
| return false; | |
| } | |
| } | |
| // We got a new user! | |
| break; | |
| } | |
| if (s == ::Windows::Foundation::AsyncStatus::Canceled || | |
| s == ::Windows::Foundation::AsyncStatus::Error) | |
| { | |
| auto c = pickOp->ErrorCode; | |
| return false; | |
| } | |
| } | |
| // Get the storage space here once! | |
| auto opSpace = ::Windows::Xbox::Storage::ConnectedStorageSpace::GetForUserAsync(pad->User); | |
| while (true) | |
| { | |
| auto s = opSpace->Status; | |
| if (s == ::Windows::Foundation::AsyncStatus::Completed) | |
| break; | |
| if (s == ::Windows::Foundation::AsyncStatus::Canceled || | |
| s == ::Windows::Foundation::AsyncStatus::Error) | |
| { | |
| auto c = opSpace->ErrorCode; | |
| return false; | |
| } | |
| } | |
| // Store the user and the storage space for use later. | |
| StoreUser(pad, opSpace); | |
| return true; | |
| } | |
| void UserSignedOut() | |
| { | |
| //Stats | |
| StatsRemoveLocalUser(stats_manager::get_singleton_instance(), m_gamepad_user); | |
| BaseGame$_ProfileSignedOut(::PumpkinGames::Glitchangels::BaseGame$_$S_get_Instance()); | |
| m_gamepad_user = nullptr; | |
| } | |
| void XboxOneNative$_$S_SwitchToPairedProfile() | |
| { | |
| UserSignedOut(); | |
| } | |
| void XboxOneNative$_$S_ShowProfileInfo(::System::String* uniqueIdentifier) | |
| { | |
| if (m_user == nullptr) | |
| return; | |
| if (uniqueIdentifier == nullptr) | |
| return; | |
| ::Windows::Xbox::UI::SystemUI::ShowProfileCardAsync(m_user, ::Platform::StringReference(&uniqueIdentifier->start_char)); | |
| } | |
| void OnSignOutCompleted(Platform::Object ^sender, Windows::Xbox::System::SignOutCompletedEventArgs^ args) | |
| { | |
| #if _DEBUG | |
| OutputDebugString(L"OnSignOutCompleted\n"); | |
| #endif | |
| auto result = args->Result; | |
| // No work to do if we're signed out right now. | |
| if (m_user == nullptr) | |
| return; | |
| // Skip any events for users we're not tracking. | |
| auto currentUserId = XboxOneNative$_$S_get_UserId(); | |
| if (Platform::String::CompareOrdinal(::Platform::StringReference(¤tUserId->start_char), args->User->XboxUserId) != 0) | |
| return; | |
| #if _DEBUG | |
| OutputDebugString(L"OnSignOutCompleted: Signing out!\n"); | |
| #endif | |
| UserSignedOut(); | |
| } | |
| void OnApplicationSuspending(Platform::Object ^sender, SuspendingEventArgs^ args) | |
| { | |
| #if _DEBUG | |
| OutputDebugString(L"OnApplicationSuspending\n"); | |
| #endif | |
| if (nullptr != m_xboxLiveContext) | |
| { | |
| #if _DEBUG | |
| OutputDebugString(L"OnApplicationSuspending: m_xboxLiveContext.reset()\n"); | |
| #endif | |
| m_xboxLiveContext.reset(); | |
| } | |
| #if _DEBUG | |
| OutputDebugString(L"OnApplicationSuspending: StatsRemoveLocalUser()\n"); | |
| #endif | |
| StatsRemoveLocalUser(stats_manager::get_singleton_instance(), m_user); | |
| } | |
| void OnApplicationResuming(Platform::Object ^sender, Platform::Object^ args) | |
| { | |
| #if _DEBUG | |
| wchar_t temp[512]; | |
| OutputDebugString(L"OnApplicationResuming\n"); | |
| #endif | |
| // We may or may not have gotten a DLC install event | |
| // on resuming... so check again here just in case. | |
| //RecheckForDLC(); | |
| // If we have no user then nothing more to do. | |
| if (m_user == nullptr) | |
| return; | |
| // If the user is stale try to find a fresh one. | |
| if (!m_user->IsSignedIn) | |
| { | |
| auto users = Windows::Xbox::System::User::Users; | |
| for each (auto fresh in users) | |
| { | |
| if (Platform::String::CompareOrdinal(m_user->XboxUserId, fresh->XboxUserId) == 0) | |
| { | |
| m_user = fresh; | |
| break; | |
| } | |
| } | |
| } | |
| if (!m_user->IsSignedIn) | |
| { | |
| #if _DEBUG | |
| swprintf(temp, 512, L"OnApplicationResuming - User %s could not be found!\n", m_user->XboxUserId->Data()); | |
| OutputDebugString(temp); | |
| #endif | |
| // The user is gone... let the user deal with it. | |
| m_user = nullptr; | |
| m_userStorage = nullptr; | |
| m_xboxLiveContext.reset(); | |
| UserSignedOut(); | |
| return; | |
| } | |
| // Update the user storage object at this time. | |
| auto opSpace = ::Windows::Xbox::Storage::ConnectedStorageSpace::GetForUserAsync(m_user); | |
| while (true) | |
| { | |
| auto s = opSpace->Status; | |
| if (s == ::Windows::Foundation::AsyncStatus::Completed) | |
| { | |
| m_userStorage = opSpace->GetResults(); | |
| break; | |
| } | |
| if (s == ::Windows::Foundation::AsyncStatus::Canceled || | |
| s == ::Windows::Foundation::AsyncStatus::Error) | |
| { | |
| auto c = opSpace->ErrorCode; | |
| // The storage can't be found... let the user deal with it. | |
| m_user = nullptr; | |
| m_userStorage = nullptr; | |
| m_xboxLiveContext.reset(); | |
| UserSignedOut(); | |
| return; | |
| } | |
| } | |
| #if _DEBUG | |
| OutputDebugString(L"OnApplicationResuming: create m_xboxLiveContext for user\n"); | |
| #endif | |
| m_xboxLiveContext = std::make_shared<xbox::services::xbox_live_context>(m_user); | |
| #if _DEBUG | |
| OutputDebugString(L"OnApplicationResuming: StatsAddLocalUser()\n"); | |
| #endif | |
| StatsAddLocalUser(stats_manager::get_singleton_instance(), m_user); | |
| // We have a fresh signed in user... so now we look for their controller. | |
| auto playerIndex = (int)GamepadInputMethod$_get_PrimaryControllerId_Int32(::PumpkinGames::Glitchangels::BaseGame$_$S_get_Instance()->GamepadInputMethod); | |
| auto newPlayerIndex = ::Microsoft::Xbox::One::Input::GamePad$_$S__FindIndexByXboxUserId((void*)m_user->XboxUserId->Data()); | |
| if (newPlayerIndex == playerIndex) | |
| { | |
| #if _DEBUG | |
| // The user on our controller is still the same so we're good to continue as is. | |
| swprintf(temp, 512, L"OnApplicationResuming - User %s and gamepad found!\n", m_user->XboxUserId->Data()); | |
| OutputDebugString(temp); | |
| #endif | |
| } | |
| // Show the disconnected message and let the | |
| // player select a new controller? | |
| } | |
| void XboxOneNative$_$S_InitializeUserEvents() | |
| { | |
| Windows::Xbox::System::User::SignOutCompleted += ref new Windows::Foundation::EventHandler< Windows::Xbox::System::SignOutCompletedEventArgs^ >(&OnSignOutCompleted); | |
| CoreApplication::Suspending += ref new Windows::Foundation::EventHandler< SuspendingEventArgs^ >(&OnApplicationSuspending); | |
| CoreApplication::Resuming += ref new Windows::Foundation::EventHandler< Platform::Object^ >(&OnApplicationResuming); | |
| } | |
| ::PumpkinGames::Glitchangels::Storage::StorageResult XboxOneNative$_$S_SaveData(::System::String* containerName, ::System::String* blobName, ::System::ArrayT< byte_bt, 1 >* buffer, int length) | |
| { | |
| auto space = m_userStorage; | |
| if (space == nullptr) | |
| return PumpkinGames::Glitchangels::Storage::StorageResult::ErrorUnknown; | |
| auto container = space->CreateContainer(::Platform::StringReference(&containerName->start_char)); | |
| auto writer = ref new ::Windows::Storage::Streams::DataWriter(); | |
| writer->WriteBytes(::Platform::ArrayReference<unsigned char, 1>((unsigned char*)buffer->_array, length)); | |
| auto updates = ref new Platform::Collections::Map< ::Platform::String^, ::Windows::Storage::Streams::IBuffer^>(); | |
| updates->Insert(::Platform::StringReference(&blobName->start_char), writer->DetachBuffer()); | |
| auto op = container->SubmitUpdatesAsync(updates->GetView(), nullptr); | |
| while (true) | |
| { | |
| auto s = op->Status; | |
| if (s == ::Windows::Foundation::AsyncStatus::Completed) | |
| break; | |
| if (s == ::Windows::Foundation::AsyncStatus::Canceled || | |
| s == ::Windows::Foundation::AsyncStatus::Error) | |
| { | |
| auto c = op->ErrorCode; | |
| switch (c.Value) | |
| { | |
| case (int)::Windows::Xbox::Storage::ConnectedStorageErrorStatus::NoAccess: | |
| return PumpkinGames::Glitchangels::Storage::StorageResult::ErrorNoAccess; | |
| case (int)::Windows::Xbox::Storage::ConnectedStorageErrorStatus::UpdateTooBig: | |
| return PumpkinGames::Glitchangels::Storage::StorageResult::ErrorUpdateTooBig; | |
| case (int)::Windows::Xbox::Storage::ConnectedStorageErrorStatus::QuotaExceeded: | |
| return PumpkinGames::Glitchangels::Storage::StorageResult::ErrorQuotaExceeded; | |
| case (int)::Windows::Xbox::Storage::ConnectedStorageErrorStatus::OutOfLocalStorage: | |
| return PumpkinGames::Glitchangels::Storage::StorageResult::ErrorOutOfLocalStorage; | |
| default: | |
| return PumpkinGames::Glitchangels::Storage::StorageResult::ErrorUnknown; | |
| } | |
| } | |
| } | |
| return PumpkinGames::Glitchangels::Storage::StorageResult::Ok; | |
| } | |
| bool XboxOneNative$_$S_LoadData(::System::String* containerName, ::System::String* blobName, ::System::ArrayT< byte_bt, 1 >** buffer) | |
| { | |
| *buffer = nullptr; | |
| auto space = m_userStorage; | |
| if (space == nullptr) | |
| return false; | |
| auto container = space->CreateContainer(::Platform::StringReference(&containerName->start_char)); | |
| auto reads = ref new Platform::Collections::Vector<Platform::String^>(); | |
| auto blobNameRef = ::Platform::StringReference(&blobName->start_char); | |
| reads->Append(blobNameRef); | |
| auto op = container->GetAsync(reads); | |
| while (true) | |
| { | |
| auto s = op->Status; | |
| if (s == ::Windows::Foundation::AsyncStatus::Completed) | |
| break; | |
| if (s == ::Windows::Foundation::AsyncStatus::Canceled || | |
| s == ::Windows::Foundation::AsyncStatus::Error) | |
| { | |
| auto c = op->ErrorCode; | |
| return false; | |
| } | |
| } | |
| auto blob = op->GetResults()->Lookup(blobNameRef); | |
| ::Microsoft::WRL::ComPtr<::Windows::Storage::Streams::IBufferByteAccess> bufferByteAccess; | |
| reinterpret_cast<IInspectable*>(blob)->QueryInterface(IID_PPV_ARGS(&bufferByteAccess)); | |
| unsigned char* ptr = nullptr; | |
| bufferByteAccess->Buffer(&ptr); | |
| *buffer = ::System::Internal::CreateArray< unsigned char >(blob->Length); | |
| memcpy((*buffer)->_array, ptr, blob->Length); | |
| return true; | |
| } | |
| bool XboxOneNative$_$S_DataExists(::System::String* containerName, ::System::String* blobName) | |
| { | |
| auto space = m_userStorage; | |
| if (space == nullptr) | |
| return false; | |
| auto container = space->CreateContainer(::Platform::StringReference(&containerName->start_char)); | |
| auto reads = ref new Platform::Collections::Vector<Platform::String^>(); | |
| auto blobNameRef = ::Platform::StringReference(&blobName->start_char); | |
| reads->Append(blobNameRef); | |
| auto op = container->GetAsync(reads); | |
| while (true) | |
| { | |
| auto s = op->Status; | |
| if (s == ::Windows::Foundation::AsyncStatus::Completed) | |
| break; | |
| if (s == ::Windows::Foundation::AsyncStatus::Error) | |
| { | |
| auto c = op->ErrorCode; | |
| return false; | |
| } | |
| } | |
| auto blob = op->GetResults()->Lookup(blobNameRef); | |
| ::Microsoft::WRL::ComPtr<::Windows::Storage::Streams::IBufferByteAccess> bufferByteAccess; | |
| reinterpret_cast<IInspectable*>(blob)->QueryInterface(IID_PPV_ARGS(&bufferByteAccess)); | |
| unsigned char* ptr = nullptr; | |
| bufferByteAccess->Buffer(&ptr); | |
| return true; | |
| } | |
| bool XboxOneNative$_$S_GetImageSize(unsigned int* length) | |
| { | |
| unsigned int requiredBufferSize = 1; | |
| UserPictureSize pictureSize = UserPictureSize::Small; | |
| Windows::Storage::Streams::IBuffer^ buffer = ref new Windows::Storage::Streams::Buffer(requiredBufferSize); | |
| auto op = m_user->DisplayInfo->GetGamerPictureAsync(pictureSize, buffer); | |
| while (true) | |
| { | |
| auto s = op->Status; | |
| if (s == ::Windows::Foundation::AsyncStatus::Completed) | |
| { | |
| auto result = op->GetResults(); | |
| if (result->Result.Value != E_BOUNDS) | |
| return false; | |
| requiredBufferSize = result->RequiredBufferSize; | |
| *length = requiredBufferSize; | |
| return true; | |
| } | |
| if (s == ::Windows::Foundation::AsyncStatus::Canceled || | |
| s == ::Windows::Foundation::AsyncStatus::Error) | |
| { | |
| auto c = op->ErrorCode; | |
| return false; | |
| } | |
| } | |
| return false; | |
| } | |
| byte* GetBufferData(Windows::Storage::Streams::IBuffer^ buffer) | |
| { | |
| using namespace Windows::Storage::Streams; | |
| IUnknown* unknown = reinterpret_cast<IUnknown*>(buffer); | |
| Microsoft::WRL::ComPtr<IBufferByteAccess> bufferByteAccess; | |
| HRESULT hr = unknown->QueryInterface(_uuidof(IBufferByteAccess), &bufferByteAccess); | |
| if (FAILED(hr)) | |
| return nullptr; | |
| byte* bytes = nullptr; | |
| bufferByteAccess->Buffer(&bytes); | |
| return bytes; | |
| } | |
| bool XboxOneNative$_$S_GetImageRGBA(::System::ArrayT< byte_bt, 1 >** data, unsigned int length) | |
| { | |
| *data = nullptr; | |
| UserPictureSize pictureSize = UserPictureSize::Small; | |
| Windows::Storage::Streams::IBuffer^ buffer = ref new Windows::Storage::Streams::Buffer(length); | |
| auto op = m_user->DisplayInfo->GetGamerPictureAsync(pictureSize, buffer); | |
| while (true) | |
| { | |
| auto s = op->Status; | |
| if (s == ::Windows::Foundation::AsyncStatus::Completed) | |
| { | |
| auto result = op->GetResults(); | |
| if (result->Result.Value == E_BOUNDS) | |
| return false; | |
| unsigned char* ptr = nullptr; | |
| ptr = GetBufferData(buffer); | |
| *data = ::System::Internal::CreateArray< unsigned char >(buffer->Length); | |
| memcpy((*data)->_array, ptr, buffer->Length); | |
| return true; | |
| } | |
| if (s == ::Windows::Foundation::AsyncStatus::Canceled || | |
| s == ::Windows::Foundation::AsyncStatus::Error) | |
| { | |
| auto c = op->ErrorCode; | |
| return false; | |
| } | |
| } | |
| return false; | |
| } | |
| //---------------------------------------------------------------------------------------------------- | |
| //Achievements | |
| //---------------------------------------------------------------------------------------------------- | |
| void XboxOneNative$_$S_UpdateAchievementProgress( | |
| ::System::String* name, | |
| int progress) | |
| { | |
| if (m_xboxLiveContext == nullptr) | |
| return; | |
| auto& achievementService = m_xboxLiveContext->achievement_service(); | |
| achievementService.update_achievement( | |
| m_user->XboxUserId->Data(), | |
| &name->start_char, | |
| progress | |
| ) | |
| .then([name, progress](xbox::services::xbox_live_result<void> result) | |
| { | |
| if (!result.err()) | |
| { | |
| #if _DEBUG | |
| wchar_t temp[512]; | |
| swprintf(temp, 512, L"Achievement progress updated %s: %i\n", &name->start_char, progress); | |
| OutputDebugString(temp); | |
| #endif | |
| } | |
| }); | |
| } | |
| void XboxOneNative$_$S_UnlockAchievement( | |
| ::System::String* name) | |
| { | |
| XboxOneNative$_$S_UpdateAchievementProgress( | |
| name, | |
| 100); //100 will unlock the achivement | |
| } | |
| //---------------------------------------------------------------------------------------------------- | |
| //Leaderboard | |
| //---------------------------------------------------------------------------------------------------- | |
| void XboxOneNative$_$S_UploadLeaderboardScore( | |
| ::PumpkinGames::Glitchangels::ScoreItem* scoreItem) | |
| { | |
| UploadLeaderboardScore(stats_manager::get_singleton_instance(), m_user, scoreItem); | |
| } | |
| void XboxOneNative$_$S_DownloadLeaderboardEntries( | |
| ::PumpkinGames::Glitchangels::GameServices::XboxLive::XboxLiveLeaderboard* leaderboard, | |
| ::PumpkinGames::Glitchangels::GameServices::LeaderboardFilterType filterType, | |
| int rangeStart, | |
| int rangeEnd) | |
| { | |
| GetLeaderboard(leaderboard, stats_manager::get_singleton_instance(), m_user, filterType, rangeStart, rangeEnd); | |
| } | |
| //---------------------------------------------------------------------------------------------------- | |
| //Stats | |
| //---------------------------------------------------------------------------------------------------- | |
| void XboxOneNative$_$S_SetStat( | |
| ::System::String* name, | |
| int value) | |
| { | |
| StatsSetStatAsInteger(stats_manager::get_singleton_instance(), m_user, name, value); | |
| } | |
| void XboxOneNative$_$S_FlushStats() | |
| { | |
| StatsFlushStats(stats_manager::get_singleton_instance(), m_user); | |
| } | |
| //---------------------------------------------------------------------------------------------------- | |
| //Rich Presence | |
| //---------------------------------------------------------------------------------------------------- | |
| void XboxOneNative$_$S_WriteRichPresence( | |
| ::System::String* name) | |
| { | |
| if (m_user == nullptr) | |
| return; | |
| try | |
| { | |
| auto context = ref new Microsoft::Xbox::Services::XboxLiveContext(m_user); | |
| auto presenceData = ref new Microsoft::Xbox::Services::Presence::PresenceData(context->AppConfig->ServiceConfigurationId, ::Platform::StringReference(&name->start_char)); | |
| context->Settings->DisableAssertsForXboxLiveThrottlingInDevSandboxes(Microsoft::Xbox::Services::XboxLiveContextThrottleSetting::ThisCodeNeedsToBeChangedToAvoidThrottling); | |
| auto action = context->PresenceService->SetPresenceAsync(true, presenceData); | |
| } | |
| catch (::Platform::Exception^ ex) | |
| { | |
| // I guess we are offline? | |
| return; | |
| } | |
| } | |
| //---------------------------------------------------------------------------------------------------- | |
| //Misc | |
| //---------------------------------------------------------------------------------------------------- | |
| void XboxOneNative$_$S_Update() | |
| { | |
| // Process events from the stats manager - this should be called each frame update | |
| auto statsEvents = stats_manager::get_singleton_instance()->do_work(); | |
| std::wstring text; | |
| for (const auto& evt : statsEvents) | |
| { | |
| #if _DEBUG | |
| auto err = evt; | |
| auto error_info = err.error_info(); | |
| if (err.error_info().err()) | |
| { | |
| auto errorCode = err.error_info().err().value(); | |
| auto errorMessage = err.error_info().err().message(); | |
| OutputDebugString(L"Stats Manager do work has an error\n"); | |
| wchar_t temp[512]; | |
| swprintf(temp, 512, L"Error code %i / message %hs\n", errorCode, errorMessage.c_str()); | |
| OutputDebugString(temp); | |
| } | |
| #endif | |
| switch (evt.event_type()) | |
| { | |
| case stat_event_type::local_user_added: | |
| #if _DEBUG | |
| OutputDebugString(L"Stats Manager: local user added\n"); | |
| #endif | |
| break; | |
| case stat_event_type::local_user_removed: | |
| #if _DEBUG | |
| OutputDebugString(L"Stats Manager: local user removed\n"); | |
| #endif | |
| break; | |
| case stat_event_type::stat_update_complete: | |
| #if _DEBUG | |
| OutputDebugString(L"Stats Manager: stat update complete\n"); | |
| #endif | |
| break; | |
| case stat_event_type::get_leaderboard_complete: | |
| #if _DEBUG | |
| OutputDebugString(L"Stats Manager: get leaderboard complete\n"); | |
| #endif | |
| auto getLeaderboardCompleteArgs = std::dynamic_pointer_cast<leaderboard_result_event_args>(evt.event_args()); | |
| ProcessLeaderboards(stats_manager::get_singleton_instance(), evt.local_user(), getLeaderboardCompleteArgs->result()); | |
| break; | |
| } | |
| } | |
| } | |
| void XboxOneNative$_$S_ShowHelp() | |
| { | |
| // if (m_user == nullptr) | |
| // return; | |
| // | |
| // Windows::Foundation::IAsyncAction^ helpAction = Windows::Xbox::ApplicationModel::Help::Show(m_user); | |
| // | |
| // // Optionally, specify a completion handler. | |
| // helpAction->Completed = ref new AsyncActionCompletedHandler( | |
| // [](IAsyncAction^ action, Windows::Foundation::AsyncStatus status) | |
| // { | |
| //#if _DEBUG | |
| // OutputDebugString(L"Help app has launched\n"); | |
| //#endif | |
| // }); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } // namespace PumpkinGames.Glitchangels.Platforms.XboxOne.Native | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment